/* ── OFF THE GRID CHAT — MOBILE FIRST ── */

:root {
  /* Base palette — "warm dark" tuned for readability without the harsh
   * near-black / electric-cyan cyberpunk look. Backgrounds lifted from
   * #080a0f family to a warmer #141a26 family; accent shifted from
   * electric cyan (#00e5ff) to softer sky-blue (#38bdf8). Divinity frame
   * styles retain the original electric cyan intentionally — that neon
   * glow is part of the premium purchase. */
  --bg:      #141a26;
  --bg2:     #1a2033;
  --bg3:     #232940;
  --bg4:     #2d344d;
  --accent:  #38bdf8;
  --accent-rgb: 56,189,248;  /* for rgba() uses — keep in sync with --accent */
  --red:     #f87171;
  --green:   #4ade80;
  --amber:   #fbbf24;
  --purple:  #7c3aed;
  /* Brand secondary — OTGC platform-staff badges. Distinct from --red
     (which is reserved for danger/error UI) and pulled redder than pure
     pink to avoid the Divinity badge's magenta range. brand-2 is for
     platform owner ("OTGC") and brand-2-soft for platform mod
     ("OTGC-Mod"); the soft variant is desaturated to express role tier. */
  --brand-2:      #e63b65;
  --brand-2-soft: #e85a7a;
  --text:    #f1f5f9;
  --muted:   #94a3b8;
  --border:  rgba(var(--accent-rgb), 0.12);
  --font:    'Inter', sans-serif;
  --mono:    'JetBrains Mono', monospace;

  /* Safe areas */
  --sat: env(safe-area-inset-top, 0px);
  --sab: env(safe-area-inset-bottom, 0px);
  --sal: env(safe-area-inset-left, 0px);
  --sar: env(safe-area-inset-right, 0px);

  /* Nav heights */
  --top-nav-h: 52px;
  --bot-nav-h: 58px;
}

/* ── RESET ── */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; -webkit-tap-highlight-color: transparent; }
html {
  height: 100%;
  height: -webkit-fill-available;
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}
body {
  height: 100%;
  height: -webkit-fill-available;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font);
  overflow: hidden;
  -webkit-font-smoothing: antialiased;
}
button {
  font-family: var(--font);
  -webkit-appearance: none;
  border: none;
  cursor: pointer;
  touch-action: manipulation;
}
input {
  font-family: var(--font);
  -webkit-appearance: none;
  font-size: 16px; /* prevents iOS zoom */
  border-radius: 0;
}

/* ── APP SHELL ── */
#app {
  width: 100%;
  height: 100%;
  height: -webkit-fill-available;
  position: relative;
  overflow: hidden;
}

/* ── SCREENS ── */
.screen {
  position: absolute;
  inset: 0;
  display: none;
  overflow: hidden;
}
.screen.active { display: flex; flex-direction: column; }

/* ── AUTH SCREEN ── */
.auth-wrap {
  flex: 1;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  padding: calc(var(--sat) + 40px) 24px calc(var(--sab) + 32px);
  display: flex;
  flex-direction: column;
  gap: 20px;
  max-width: 420px;
  margin: 0 auto;
  width: 100%;
}

.auth-logo {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  margin-bottom: 8px;
}
.auth-logo-text { text-align: center; }
.auth-app-name {
  display: block;
  font-size: 22px;
  font-weight: 700;
  color: var(--text);
  letter-spacing: 2px;
}
.auth-app-sub {
  display: block;
  font-size: 10px;
  font-family: var(--mono);
  color: var(--muted);
  letter-spacing: 3px;
  margin-top: 2px;
}

.auth-tabs {
  display: flex;
  background: var(--bg3);
  border: 1px solid var(--border);
  border-radius: 10px;
  overflow: hidden;
}
.auth-tab {
  flex: 1;
  padding: 10px;
  font-size: 14px;
  font-weight: 700;
  background: transparent;
  color: var(--muted);
  transition: all .15s;
  letter-spacing: .3px;
}
.auth-tab.active { background: rgba(var(--accent-rgb),.1); color: var(--accent); }

.auth-form { display: none; flex-direction: column; gap: 14px; }
.auth-form.active { display: flex; }

.field { display: flex; flex-direction: column; gap: 5px; }
.field label {
  font-size: 11px;
  font-family: var(--mono);
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: .5px;
}
.field-hint { font-weight: 400; opacity: .7; text-transform: none; letter-spacing: 0; }
.field input {
  width: 100%;
  background: var(--bg3);
  border: 1px solid var(--border);
  border-radius: 10px;
  color: var(--text);
  padding: 12px 14px;
  font-size: 16px;
  outline: none;
  transition: border-color .15s;
}
.field input:focus { border-color: rgba(var(--accent-rgb),.4); }

.pw-wrap { position: relative; }
.pw-wrap input { padding-right: 42px; }
.pw-eye {
  position: absolute;
  right: 12px; top: 50%;
  transform: translateY(-50%);
  background: transparent;
  color: var(--muted);
  font-size: 16px;
  padding: 4px;
}

.pw-strength {
  height: 3px;
  background: var(--bg4);
  border-radius: 2px;
  overflow: hidden;
  margin-top: 4px;
}
.pw-strength #pw-bar {
  height: 100%;
  border-radius: 2px;
  width: 0;
  transition: width .3s, background .3s;
}

.forgot-link {
  font-size: 11px;
  font-family: var(--mono);
  color: var(--muted);
  background: transparent;
  text-align: right;
  text-decoration: underline;
  align-self: flex-end;
  margin-top: -6px;
}

.auth-err {
  font-size: 12px;
  font-family: var(--mono);
  color: var(--red);
  background: rgba(204,0,24,.08);
  border: 1px solid rgba(204,0,24,.2);
  border-radius: 8px;
  padding: 9px 12px;
  display: none;
  line-height: 1.5;
}
.auth-err.show { display: block; }

.auth-ok {
  font-size: 12px;
  font-family: var(--mono);
  color: var(--green);
  background: rgba(74,222,128,.08);
  border: 1px solid rgba(74,222,128,.2);
  border-radius: 8px;
  padding: 9px 12px;
  display: none;
  line-height: 1.5;
}
.auth-ok.show { display: block; }

.auth-desc {
  font-size: 13px;
  font-family: var(--mono);
  color: var(--muted);
  line-height: 1.6;
}
.auth-terms {
  font-size: 11px;
  font-family: var(--mono);
  color: var(--muted);
  text-align: center;
  line-height: 1.6;
}
.auth-terms a { color: var(--accent); cursor: pointer; }

/* ── BUTTONS ── */
.btn-primary {
  width: 100%;
  padding: 14px;
  border-radius: 12px;
  background: linear-gradient(135deg, var(--purple), var(--accent));
  color: white;
  font-size: 15px;
  font-weight: 700;
  letter-spacing: .5px;
  transition: opacity .15s;
}
.btn-primary:disabled { opacity: .4; cursor: not-allowed; }
.btn-primary:active { opacity: .85; }

.btn-ghost {
  width: 100%;
  padding: 12px;
  border-radius: 12px;
  background: transparent;
  border: 1px solid var(--border);
  color: var(--muted);
  font-size: 14px;
  font-weight: 600;
}
.btn-ghost:active { background: var(--bg3); }

/* ── ONBOARDING ── */
.onboard-wrap {
  flex: 1;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  padding: calc(var(--sat) + 32px) 24px calc(var(--sab) + 24px);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0;
  max-width: 420px;
  margin: 0 auto;
  width: 100%;
}

.onboard-progress {
  display: flex;
  gap: 8px;
  margin-bottom: 32px;
}
.ob-dot {
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--bg4);
  border: 1px solid var(--border);
  transition: all .2s;
}
.ob-dot.active { background: var(--accent); border-color: var(--accent); }
.ob-dot.done { background: var(--green); border-color: var(--green); }

.ob-step {
  display: none;
  flex-direction: column;
  align-items: center;
  gap: 16px;
  width: 100%;
  text-align: center;
}
.ob-step.active { display: flex; }
.ob-icon { font-size: 48px; }
.ob-step h2 { font-size: 22px; font-weight: 700; }
.ob-step p { font-size: 13px; font-family: var(--mono); color: var(--muted); line-height: 1.6; }

.age-ctrl {
  display: flex;
  align-items: center;
  gap: 24px;
}
.age-btn {
  width: 48px; height: 48px;
  border-radius: 50%;
  border: 2px solid rgba(var(--accent-rgb),.3);
  background: rgba(var(--accent-rgb),.08);
  color: var(--accent);
  font-size: 22px;
  font-weight: 700;
  transition: all .15s;
}
.age-btn:active { background: rgba(var(--accent-rgb),.2); }
#age-val {
  font-size: 56px;
  font-weight: 700;
  font-family: var(--mono);
  color: var(--accent);
  min-width: 80px;
  text-align: center;
}
#age-slider {
  width: 100%;
  -webkit-appearance: none;
  appearance: none;
  height: 4px;
  border-radius: 2px;
  background: var(--bg4);
  outline: none;
}
#age-slider::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 22px; height: 22px;
  border-radius: 50%;
  background: var(--accent);
  cursor: pointer;
  border: 2px solid var(--bg);
}
.age-block {
  background: rgba(204,0,24,.08);
  border: 1px solid rgba(204,0,24,.25);
  border-radius: 10px;
  padding: 12px 16px;
  font-size: 13px;
  font-family: var(--mono);
  color: var(--red);
  width: 100%;
}

.sex-opts { display: flex; gap: 12px; width: 100%; }
.sex-opt {
  flex: 1;
  padding: 18px 12px;
  border-radius: 12px;
  border: 2px solid var(--border);
  background: var(--bg3);
  color: var(--muted);
  font-size: 16px;
  font-weight: 700;
  transition: all .15s;
}
.sex-opt.selected {
  border-color: var(--accent);
  background: rgba(var(--accent-rgb),.1);
  color: var(--accent);
}

.interests-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  justify-content: center;
  width: 100%;
}
.int-chip {
  padding: 8px 14px;
  border-radius: 20px;
  border: 1px solid var(--border);
  background: var(--bg3);
  color: var(--muted);
  font-size: 13px;
  font-weight: 600;
  transition: all .15s;
}
.int-chip.on {
  border-color: var(--accent);
  background: rgba(var(--accent-rgb),.1);
  color: var(--accent);
}

/* ── MAIN APP ── */
#screen-app {
  flex-direction: column;
  background: var(--bg);
}

/* ── TOP NAV ── */
.top-nav {
  position: fixed;
  top: 0; left: 0; right: 0;
  height: calc(var(--top-nav-h) + var(--sat));
  padding-top: var(--sat);
  background: var(--bg2);
  border-bottom: 1px solid var(--border);
  /* Five-icon row with equal spacing between and around all icons. The
     wrapper divs (.top-nav-left, .top-nav-center, .top-nav-right) are
     display:contents so their children participate directly in this
     grid — no more asymmetric gaps around the centered avatar. */
  display: flex;
  align-items: center;
  justify-content: space-around;
  z-index: 50;
  padding-left: var(--sal);
  padding-right: var(--sar);
  transition: transform 0.3s ease;
}
.top-nav.hide-in-chat {
  transform: translateY(-100%);
}

.top-nav-left,
.top-nav-right,
.top-nav-center {
  /* display:contents makes these divs transparent to flex — their children
     become direct flex items of .top-nav. Keeps HTML semantic (grouped by
     role) while giving us a flat grid for visual alignment. */
  display: contents;
}
.top-nav-right {
}

/* Profile avatar in top nav */

.nav-icon-btn {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  padding: 4px 8px;
  background: transparent;
  color: var(--muted);
  border-bottom: 2px solid transparent;
  transition: all .15s;
  min-width: 48px;
  position: relative;
}
.nav-icon-btn.active { color: var(--accent); border-bottom-color: var(--accent); }
.nav-icon-btn .nav-ico { font-size: 19px; line-height: 1; }
.nav-icon-btn .nav-lbl { font-size: 9px; font-family: var(--mono); letter-spacing: .3px; }
.nav-badge {
  position: absolute;
  top: 2px; right: 6px;
  width: 8px; height: 8px;
  background: var(--red);
  border-radius: 50%;
  display: block;
}

.token-badge {
  display: flex;
  align-items: center;
  gap: 4px;
  font-size: 12px;
  font-family: var(--mono);
  color: #a78bfa;
  background: rgba(124,58,237,.15);
  border: 1px solid rgba(124,58,237,.35);
  border-radius: 8px;
  padding: 3px 9px;
  cursor: pointer;
}

/* ── VIEW HOST ── */
.view-host {
  position: fixed;
  top: calc(var(--top-nav-h) + var(--sat));
  bottom: calc(var(--bot-nav-h) + var(--sab));
  left: var(--sal);
  right: var(--sar);
  overflow: hidden;
  transition: top 0.3s ease, bottom 0.3s ease;
}

/* When in immersive chat mode, expand to full screen */
body.immersive-chat .view-host {
  top: var(--sat);
  bottom: var(--sab);
}

/* When keyboard is open, bottom nav hides and view-host fills space */
body.keyboard-open .bottom-nav {
  transform: translateY(100%);
  pointer-events: none;
}
body.keyboard-open .view-host {
  bottom: 0;
}

.view {
  position: absolute;
  inset: 0;
  display: none;
  flex-direction: column;
  overflow: hidden;
  background: var(--bg);
}
.view.active { display: flex; }

/* ── CHAT VIEW ── */
.room-bar {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 14px;
  background: var(--bg2);
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}
.back-btn {
  background: transparent;
  border: none;
  color: var(--accent);
  font-size: 24px;
  cursor: pointer;
  padding: 0 4px;
  line-height: 1;
  opacity: 0.8;
  transition: opacity 0.15s;
}
.back-btn:hover {
  opacity: 1;
}
.room-bar span:first-of-type {
  font-size: 15px;
  font-weight: 700;
  color: var(--accent);
  letter-spacing: .3px;
}
.room-online {
  font-size: 10px;
  font-family: var(--mono);
  color: var(--green);
  margin-left: auto;
}

/* Room Banner — slim text strip pinned under the room header.
   Hidden by default (display:none in HTML); applyRoomBanner() shows it
   when the room has banner text set.
   Colors are driven by inline --banner-bg / --banner-fg custom properties
   set by JS, so the same CSS works for any owner-chosen palette. */
.room-banner {
  flex-shrink: 0;
  padding: 6px 14px;
  background: var(--banner-bg, var(--bg3));
  color: var(--banner-fg, var(--text));
  border-bottom: 1px solid var(--border);
  font-family: var(--mono);
  font-size: 12px;
  line-height: 1.4;
  /* Default: short text is centered; long text scrolls (see .scrolling) */
  text-align: center;
  white-space: nowrap;
  overflow: hidden;
}

/* When the text overflows the container width, JS adds .scrolling and we
   marquee the two-copy track. Mask fades the edges so the loop seam is invisible. */
.room-banner.scrolling {
  text-align: left;
  -webkit-mask-image: linear-gradient(to right, transparent 0, black 24px, black calc(100% - 24px), transparent 100%);
          mask-image: linear-gradient(to right, transparent 0, black 24px, black calc(100% - 24px), transparent 100%);
}
.room-banner.scrolling .room-banner-track {
  /* flex with width:max-content gives the track a deterministic pixel
     width = sum(children) + gaps. The animation then translates by an
     exact pixel offset (computed in JS, exposed via the
     --banner-scroll-distance CSS variable) to land copy-2 precisely
     where copy-1 started. Avoids percentage-transform quirks on iOS. */
  display: flex;
  width: max-content;
  gap: 48px;
  animation: room-banner-scroll 18s linear infinite;
  will-change: transform;
}
.room-banner.scrolling .room-banner-inner {
  flex-shrink: 0;
  white-space: nowrap;
}
@keyframes room-banner-scroll {
  /* --banner-scroll-distance is set in JS to (copyWidth + gap) px,
     making copy 2 land exactly where copy 1 started after one cycle. */
  from { transform: translateX(0); }
  to   { transform: translateX(var(--banner-scroll-distance, -100%)); }
}
@media (prefers-reduced-motion: reduce) {
  /* Respect users who've asked for no motion — show the text statically.
     They can still see the full banner by hovering (browser tooltip on title). */
  .room-banner.scrolling .room-banner-track {
    animation: none;
  }
  .room-banner.scrolling .room-banner-inner:nth-child(2) {
    /* Second copy is decorative for the marquee — hide when not animating */
    display: none;
  }
}

.messages {
  flex: 1;
  overflow-y: scroll; /* always show scrollbar track */
  overflow-x: hidden; /* prevent horizontal scroll on mobile */
  -webkit-overflow-scrolling: touch;
  padding: 10px 12px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  overscroll-behavior: contain;
  min-height: 0; /* required for flex child to scroll */
  /* Content zone — darker than main app background so messages pop.
     Both public-room chat (.messages) and DM conversations (#dm-messages
     uses the same class) pick this up. */
  background: #0a0f1a;
}

.sys-msg {
  text-align: center;
  font-size: 11px;
  font-family: var(--mono);
  color: var(--muted);
  padding: 6px 12px;
  background: var(--bg3);
  border-radius: 8px;
  border: 1px solid var(--border);
}

.msg {
  display: flex;
  gap: 10px;
  align-items: flex-end;
  margin-bottom: 4px;
  padding: 0 8px;
  position: relative;
}
.msg.own { flex-direction: row-reverse; }

.av {
  width: 40px; height: 40px;
  border-radius: 10px;
  background: #1a1a2e;
  border: 2px solid var(--border);
  overflow: hidden;
  flex-shrink: 0;
}
.msg-av-click {
  cursor: pointer;
  transition: border-color .15s;
}
.msg-av-click:hover { border-color: var(--accent); }
.av svg { width: 40px; height: 40px; display: block; }

.msg-body {
  display: flex;
  flex-direction: column;
  gap: 2px;
  max-width: 72%;
}
.msg-meta {
  font-size: 10px;
  font-family: var(--mono);
  color: var(--muted);
  padding: 0 4px;
  margin-bottom: 2px;
}
.msg.own .msg-meta { text-align: right; }

.bubble {
  padding: 9px 14px;
  border-radius: 8px;
  font-size: 15px;
  font-weight: 400;
  line-height: 1.5;
  word-break: break-word;
  display: inline-block;
  max-width: 100%;
  /* Prevent iOS Safari context menu / callout on long press */
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  user-select: none;
}
.bubble.them {
  background: var(--bg3);
  color: var(--text);
}
.bubble.own-b {
  background: rgba(var(--accent-rgb),.22);
  color: var(--text);
}

/* ── In-bubble translation ──
   Translation lives inside the same bubble as the original message,
   appearing below it with a subtle horizontal divider. Smaller text
   and muted color signal that it's secondary content, while keeping
   both original and translation readable at a glance. Persists for
   the session — no dismiss UI needed. */
.bubble-translation {
  margin-top: 8px;
  padding-top: 8px;
  border-top: 1px solid rgba(var(--accent-rgb), 0.18);
}
.bubble-translation-label {
  font-size: 10px;
  font-family: var(--mono);
  color: var(--muted);
  letter-spacing: 0.5px;
  margin-bottom: 4px;
  text-transform: lowercase;
}
.bubble-translation-text {
  font-size: 13px;
  color: var(--muted);
  line-height: 1.5;
  font-style: italic;
}

/* ── COMPOSER ── */
.composer {
  padding: 8px 12px;
  background: var(--bg2);
  border-top: 1px solid var(--border);
  flex-shrink: 0;
  position: relative; /* needed for mention autocomplete dropdown */
}
.composer-row {
  display: flex;
  align-items: center;
  gap: 6px;
  background: var(--bg3);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 6px 8px;
  transition: border-color .15s;
}
.composer-row:focus-within { border-color: rgba(var(--accent-rgb),.35); }
.composer-row input,
.composer-row textarea {
  flex: 1;
  background: transparent;
  border: none;
  outline: none;
  color: var(--text);
  font-size: 16px;
  padding: 2px 4px;
  font-family: var(--font);
  line-height: 1.4;
  max-height: 120px;
  overflow-y: auto;
  word-break: break-word;
}
.composer-row input::placeholder,
.composer-row textarea::placeholder { color: var(--muted); }

/* Composer side buttons (camera, GIF, voice). Sized to clear WCAG AA
   tap-target minimum (24x24); 32x32 sits comfortably above that without
   crowding the textarea on a 360px viewport. Sub-ordinate to .send-btn
   in both size and color (transparent vs. gradient). */
.composer-btn {
  background: transparent;
  color: var(--muted);
  font-size: 18px;
  min-width: 32px;
  min-height: 32px;
  padding: 4px 6px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
.send-btn {
  width: 40px; height: 40px;
  border-radius: 8px;
  background: linear-gradient(135deg, var(--purple), var(--accent));
  color: white;
  font-size: 16px;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

/* ── Media popover ──
   Tapping the 📷 button reveals a vertical column of 40×40 icon buttons
   anchored above it. Photo/Video and Voice are the two options today;
   future GIF/sticker entries can slot in with no layout changes.
   Closed by outside-tap, Escape, or making a selection. */
.media-popover {
  position: absolute;
  bottom: calc(100% + 4px);
  left: 12px;
  display: none;
  flex-direction: column;
  gap: 4px;
  background: var(--bg3);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 6px;
  box-shadow: 0 6px 18px rgba(0,0,0,0.28);
  z-index: 50;
}
.media-popover.open {
  display: flex;
}
.media-popover-item {
  width: 40px;
  height: 40px;
  border-radius: 8px;
  background: transparent;
  color: var(--text);
  font-size: 20px;
  border: none;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: background-color .12s;
}
.media-popover-item:hover {
  background: rgba(var(--accent-rgb), 0.10);
}
.media-popover-item:active {
  background: rgba(var(--accent-rgb), 0.18);
}
/* Hide the voice option when applyComposerRestrictions disables voice
   for the current room. Use !important to win against the popover's
   .open display:flex on the parent. */
.media-popover-item.voice-hidden {
  display: none !important;
}

/* ── Floating recording bar ──
   Shown ABOVE the composer while voice recording is in progress.
   Composer below stays fully interactive — typing while recording is
   permitted; it just doesn't get sent with the voice clip. Cancel
   discards the recording entirely; stop sends. */
.record-bar {
  position: absolute;
  bottom: calc(100% + 4px);
  left: 12px;
  right: 12px;
  height: 36px;
  display: none;
  align-items: center;
  gap: 8px;
  background: var(--bg3);
  border: 1px solid var(--red);
  border-radius: 10px;
  padding: 0 10px;
  z-index: 51;
}
.record-bar.recording-active {
  display: flex;
}
.record-bar-btn {
  width: 28px;
  height: 28px;
  border-radius: 6px;
  background: transparent;
  border: none;
  color: var(--text);
  font-size: 14px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}
.record-bar-cancel { color: var(--muted); }
.record-bar-cancel:hover { color: var(--text); }
.record-bar-stop { color: var(--red); font-size: 16px; }
.record-bar-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--red);
  animation: rec-pulse 1.1s ease-in-out infinite;
  flex-shrink: 0;
}
@keyframes rec-pulse {
  0%, 100% { opacity: 1; transform: scale(1); }
  50%      { opacity: 0.35; transform: scale(0.85); }
}
.record-bar-timer {
  flex: 1;
  font-family: var(--mono);
  font-size: 13px;
  color: var(--text);
  letter-spacing: 0.5px;
}

/* ── OTHER VIEWS ── */
.view-head {
  padding: 14px 16px 10px;
  font-size: 16px;
  font-weight: 700;
  color: var(--accent);
  letter-spacing: .5px;
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
  display: flex;
  align-items: center;
  gap: 8px;
  text-transform: uppercase;
  position: relative; /* For absolute positioned back button */
}
/* When view-head contains a back button, add extra left padding */
.view-head:has(.view-back-btn) {
  padding-left: 56px;
}

/* What's New / Settings header bar with back button */
.view-head-bar {
  padding: 14px 16px 10px;
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
}
.view-head-title {
  font-size: 16px;
  font-weight: 700;
  color: var(--accent);
  letter-spacing: .5px;
  text-transform: uppercase;
}
.view-back-btn {
  position: absolute;
  left: 12px;
  background: transparent;
  border: none;
  color: var(--accent);
  font-size: 28px;
  font-weight: 300;
  padding: 0 8px;
  cursor: pointer;
  opacity: .7;
  transition: opacity .15s;
}
.view-back-btn:hover { opacity: 1; }

.card-list {
  flex: 1;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  padding: 12px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.room-card {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 14px;
  background: var(--bg2);
  border: 1px solid var(--border);
  border-radius: 12px;
  cursor: pointer;
  transition: background .12s, border-color .2s;
}
.room-card:hover {
  border-color: rgba(56, 189, 248, 0.4);
}
.room-card:active { background: var(--bg3); }
.room-card .rc-icon { font-size: 20px; width: 26px; text-align: center; flex-shrink: 0; }
.room-card .rc-info { flex: 1; min-width: 0; }
.room-card .rc-name { font-size: 14px; font-weight: 700; color: var(--text); }
.room-card .rc-meta { font-size: 11px; font-family: var(--mono); color: var(--muted); margin-top: 2px; }
.room-card .rc-badge {
  font-size: 9px;
  font-family: var(--mono);
  padding: 2px 7px;
  border-radius: 6px;
  flex-shrink: 0;
}
.rc-badge.hot { background: rgba(251,191,36,.1); border: 1px solid rgba(251,191,36,.2); color: var(--amber); }
.rc-badge.new { background: rgba(74,222,128,.1); border: 1px solid rgba(74,222,128,.2); color: var(--green); }
.save-btn {
  background: transparent;
  border: 1px solid var(--border);
  border-radius: 7px;
  padding: 5px 8px;
  font-size: 14px;
  flex-shrink: 0;
  color: var(--muted);
  transition: all .12s;
}
.save-btn.saved { border-color: rgba(var(--accent-rgb),.3); background: rgba(var(--accent-rgb),.08); }

.shop-body, .profile-body, .settings-body, .dm-list {
  flex: 1;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  padding: 14px;
}

.empty-state {
  text-align: center;
  font-size: 13px;
  font-family: var(--mono);
  color: var(--muted);
  padding: 48px 24px;
  line-height: 1.8;
}

/* ── BOTTOM NAV ── */
.bottom-nav {
  position: fixed;
  bottom: 0; left: 0; right: 0;
  height: calc(var(--bot-nav-h) + var(--sab));
  padding-bottom: var(--sab);
  background: var(--bg2);
  border-top: 1px solid var(--border);
  display: flex;
  align-items: center;
  z-index: 50;
  padding-left: var(--sal);
  padding-right: var(--sar);
  transition: transform 0.3s ease;
}
.bottom-nav.hide-in-chat {
  transform: translateY(100%);
}

.bnav-btn {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  padding: 6px 4px;
  background: transparent;
  color: var(--muted);
  transition: color .15s;
  min-width: 0;
  position: relative;
}
.bnav-btn.active { color: var(--accent); }
.bnav-btn .nav-ico { font-size: 20px; line-height: 1; }
.bnav-btn .nav-lbl { font-size: 9px; font-family: var(--mono); white-space: nowrap; overflow: hidden; max-width: 100%; text-overflow: ellipsis; }

/* ── DRAWERS ── */
.drawer-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0,0,0,.6);
  z-index: 100;
  opacity: 0;
  pointer-events: none;
  transition: opacity .25s;
}
.drawer-overlay.open { opacity: 1; pointer-events: auto; }

.drawer {
  position: fixed;
  bottom: 0; left: 0; right: 0;
  background: var(--bg2);
  border-radius: 20px 20px 0 0;
  border-top: 1px solid var(--border);
  z-index: 101;
  transform: translateY(100%);
  transition: transform .3s cubic-bezier(.4,0,.2,1);
  max-height: 78vh;
  display: flex;
  flex-direction: column;
  padding-bottom: var(--sab);
}
.drawer.open { transform: translateY(0); }

.drawer-handle {
  width: 36px; height: 4px;
  background: var(--border);
  border-radius: 2px;
  margin: 10px auto 0;
  flex-shrink: 0;
}
.drawer-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px 16px 8px;
  flex-shrink: 0;
}
.drawer-title { font-size: 16px; font-weight: 700; color: var(--text); }
.drawer-close {
  background: transparent;
  color: var(--muted);
  font-size: 18px;
  padding: 4px 8px;
}
.drawer-body {
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  padding: 8px 12px 12px;
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.drawer-divider { height: 1px; background: var(--border); margin: 4px 0 8px; }
.drawer-section {
  font-size: 10px;
  font-family: var(--mono);
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 1.5px;
  padding: 6px 4px 4px;
}

.more-item {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  padding: 14px 14px;
  border-radius: 12px;
  background: var(--bg3);
  border: 1px solid var(--border);
  color: var(--text);
  font-size: 15px;
  font-weight: 700;
  transition: background .12s;
}
.more-item:active { background: var(--bg4); }

/* ── TOAST ── */
.toast {
  position: fixed;
  bottom: calc(var(--bot-nav-h) + var(--sab) + 12px);
  left: 50%;
  transform: translateX(-50%) translateY(20px);
  background: var(--bg3);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 10px 18px;
  font-size: 13px;
  font-family: var(--mono);
  color: var(--text);
  opacity: 0;
  transition: opacity .2s, transform .2s;
  pointer-events: none;
  white-space: nowrap;
  z-index: 200;
}
.toast.show {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}

/* ── USER POPUP ── */

/* ── DESKTOP OVERRIDES (min 769px) ── */
/* ── DESKTOP LAYOUT (769px+) ─────────────────────────────────────────────── */
@media (min-width: 769px) {

  /* Reset mobile nav heights — not used on desktop */
  :root {
    --top-nav-h: 0px;
    --bot-nav-h: 0px;
  }

  /* Auth and onboarding — center the card */
  .auth-wrap, .onboard-wrap { max-width: 480px; }

  /* Hide mobile top nav and bottom nav */
  .top-nav, .bottom-nav { display: none !important; }

  /* App screen becomes a flex row */
  #screen-app {
    flex-direction: row !important;
  }

  /* ── DESKTOP SIDEBAR ── */
  .desktop-sidebar {
    display: flex !important;
    flex-direction: column;
    width: 260px;
    min-width: 260px;
    max-width: 260px;
    height: 100%;
    background: var(--bg2);
    border-right: 1px solid var(--border);
    z-index: 50;
    flex-shrink: 0;
    overflow: hidden;
  }

  /* Header */
  .ds-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 14px 12px 10px;
    flex-shrink: 0;
    border-bottom: 1px solid var(--border);
  }
  .ds-logo {
    font-family: var(--mono);
    font-weight: 800;
    font-size: 15px;
    color: var(--accent);
    letter-spacing: .04em;
    display: flex;
    align-items: center;
    gap: 8px;
  }
  .ds-logo-img {
    width: 22px;
    height: 22px;
    border-radius: 5px;
    flex-shrink: 0;
    /* Crisp downscale on 2x screens */
    image-rendering: -webkit-optimize-contrast;
  }
  .ds-icon-btn {
    background: none; border: none;
    font-size: 16px; cursor: pointer;
    padding: 4px 6px; border-radius: 8px;
    color: var(--muted); transition: background .12s, color .12s;
  }
  .ds-icon-btn:hover { background: var(--bg3); color: var(--text); }

  /* My Chats heading */
  .ds-chats-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 10px 14px 6px;
    font-family: var(--mono);
    font-weight: 700;
    font-size: 13px;
    color: var(--text);
    flex-shrink: 0;
  }
  .ds-new-chat-btn {
    background: var(--accent);
    border: none;
    color: #000;
    font-size: 18px;
    font-weight: 700;
    width: 26px; height: 26px;
    border-radius: 50%;
    cursor: pointer;
    display: flex; align-items: center; justify-content: center;
    line-height: 1;
  }

  /* Search bar */
  .ds-chats-search {
    padding: 0 10px 8px;
    flex-shrink: 0;
  }
  .ds-chats-search input {
    width: 100%;
    background: var(--bg3);
    border: 1px solid var(--border);
    border-radius: 20px;
    padding: 7px 12px;
    color: var(--text);
    font-family: var(--mono);
    font-size: 12px;
    outline: none;
    box-sizing: border-box;
  }
  .ds-chats-search input:focus { border-color: var(--accent); }

  /* Chat list */
  .ds-chats-list {
    flex: 1;
    overflow-y: auto;
    overflow-x: hidden;
    /* Breathing room for card layout */
    padding: 8px 8px 12px;
    display: flex;
    flex-direction: column;
    gap: 6px;
  }

  /* Individual chat row — card style */
  .ds-chat-row {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 9px 12px;
    cursor: pointer;
    transition: background .12s, border-color .12s;
    background: var(--bg2);
    border: 1px solid var(--border);
    border-radius: 12px;
    min-width: 0;
  }
  .ds-chat-row:hover {
    background: var(--bg3);
    border-color: rgba(var(--accent-rgb), 0.28);
  }
  .ds-chat-row.active {
    background: rgba(var(--accent-rgb),.10);
    border-color: var(--accent);
  }
  .ds-chat-av {
    width: 42px; height: 42px;
    border-radius: 12px;
    background: var(--bg3);
    border: 2px solid var(--border);
    overflow: hidden;
    flex-shrink: 0;
    display: flex; align-items: center; justify-content: center;
    font-size: 20px;
  }
  .ds-chat-av img, .ds-chat-av svg { width: 100%; height: 100%; object-fit: cover; }
  .ds-chat-info { flex: 1; min-width: 0; }
  .ds-chat-name-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 4px;
  }
  .ds-chat-name {
    font-family: var(--mono);
    font-size: 13px;
    font-weight: 700;
    color: var(--text);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    flex: 1;
  }
  .ds-chat-time {
    font-size: 10px;
    color: var(--muted);
    flex-shrink: 0;
  }
  .ds-chat-preview {
    font-size: 11px;
    color: var(--muted);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    margin-top: 1px;
  }
  .ds-chat-badge {
    background: var(--accent);
    color: #000;
    font-size: 10px;
    font-weight: 700;
    font-family: var(--mono);
    border-radius: 10px;
    padding: 1px 6px;
    flex-shrink: 0;
  }

  /* Small activity dot for ROOM tiles with new messages since the user's
     last visit. Distinct from the DM unread treatment (.has-unread, with
     left bar and bg fill) — rooms can have constant activity, so the dot
     is informational rather than urgent. No animation, no bg change.
     Suppressed by the renderer when the room is currently active. */
  .ds-chat-activity-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--accent);
    flex-shrink: 0;
    align-self: center;
  }

  /* ── Unread DM tile state ───────────────────────────────────
     Persistent lit state: tile background tinted with accent,
     left-edge accent bar via inset box-shadow (no layout shift),
     name text brightened to full --text. Stays until unread === 0.

     Combined with .active (when the user is currently in that DM),
     .active wins on background and border to keep "active" visually
     distinct from "unread but not open." */
  .ds-chat-row.has-unread {
    background: rgba(var(--accent-rgb), 0.14);
    border-color: rgba(var(--accent-rgb), 0.35);
    box-shadow: inset 3px 0 0 var(--accent);
  }
  .ds-chat-row.has-unread .ds-chat-name {
    color: var(--text);
    font-weight: 800;
  }
  .ds-chat-row.has-unread .ds-chat-preview {
    color: var(--text);
  }
  /* Active+unread: keep the unread bar but use the active background. */
  .ds-chat-row.active.has-unread {
    background: rgba(var(--accent-rgb), 0.18);
    border-color: var(--accent);
  }

  /* One-shot pulse animation — fires when unread count INCREMENTS
     (i.e., a new message just arrived), not on every render of an
     unread tile. The .just-arrived class is added by the renderer
     when chat.unread > previous snapshot for that chat, then removed
     on animationend so a subsequent increment can re-pulse. */
  @keyframes dsChatPulse {
    0%   { transform: scale(1);    box-shadow: inset 3px 0 0 var(--accent), 0 0 0 0 rgba(var(--accent-rgb), 0.55); }
    40%  { transform: scale(1.02); box-shadow: inset 3px 0 0 var(--accent), 0 0 0 6px rgba(var(--accent-rgb), 0.18); }
    100% { transform: scale(1);    box-shadow: inset 3px 0 0 var(--accent), 0 0 0 0 rgba(var(--accent-rgb), 0); }
  }
  .ds-chat-row.just-arrived {
    animation: dsChatPulse 1.2s ease-out 1;
  }
  /* Respect users who've asked the OS to reduce motion. They still
     get the persistent lit state (bg + bar + bold), just no bounce. */
  @media (prefers-reduced-motion: reduce) {
    .ds-chat-row.just-arrived {
      animation: none;
    }
  }

  /* Footer icon row */
  .ds-footer-nav {
    display: flex;
    justify-content: space-around;
    padding: 8px 0;
    border-top: 1px solid var(--border);
    flex-shrink: 0;
  }
  .ds-foot-btn {
    background: none; border: none;
    font-size: 18px; cursor: pointer;
    padding: 6px 10px; border-radius: 10px;
    color: var(--muted); transition: background .12s, color .12s;
    position: relative;
  }
  .ds-foot-btn:hover { background: var(--bg3); color: var(--text); }
  .ds-foot-badge {
    position: absolute;
    top: 2px; right: 2px;
    background: var(--accent);
    color: #000;
    font-size: 9px;
    font-weight: 700;
    font-family: var(--mono);
    border-radius: 8px;
    padding: 1px 4px;
    min-width: 14px;
    text-align: center;
    line-height: 1.4;
  }

  .ds-header {
    padding: 18px 16px 14px;
    border-bottom: 1px solid var(--border);
    margin-bottom: 8px;
  }
  .ds-logo {
    font-family: var(--mono);
    font-size: 12px;
    color: var(--accent);
    letter-spacing: 1.5px;
    text-transform: uppercase;
    font-weight: 700;
    display: flex;
    align-items: center;
    gap: 8px;
  }
  .ds-nav {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: 0 8px;
    flex: 1;
  }
  .ds-nav-btn {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 12px;
    border-radius: 10px;
    background: transparent;
    border: none;
    color: var(--muted);
    font-size: 13px;
    font-family: var(--font);
    cursor: pointer;
    text-align: left;
    width: 100%;
    transition: background .15s, color .15s;
    position: relative;
  }
  .ds-nav-btn:hover { background: var(--bg3); color: var(--text); }
  .ds-nav-btn.active { background: var(--bg3); color: var(--accent); }
  .ds-nav-ico { font-size: 17px; width: 22px; text-align: center; flex-shrink: 0; }
  .ds-nav-lbl { font-size: 13px; flex: 1; }
  .ds-nav-badge {
    background: var(--accent); color: #000;
    font-size: 10px; font-weight: 700;
    padding: 1px 6px; border-radius: 10px;
    min-width: 18px; text-align: center;
  }
  .ds-section-lbl {
    font-size: 10px; font-family: var(--mono);
    color: var(--muted); letter-spacing: 1px;
    text-transform: uppercase;
    padding: 14px 20px 4px;
  }
  .ds-token-bar {
    margin: 8px 8px 0;
    padding: 10px 12px;
    background: var(--bg3);
    border-radius: 10px;
    border: 1px solid var(--border);
    cursor: pointer;
  }
  .ds-token-val {
    font-size: 14px; font-weight: 700;
    color: #a78bfa; font-family: var(--mono);
  }
  .ds-token-lbl {
    font-size: 10px; color: var(--muted);
    font-family: var(--mono); letter-spacing: .5px;
  }
  .ds-purge-bar {
    margin: 6px 8px 0;
    padding: 8px 12px;
    background: var(--bg3);
    border-radius: 10px;
    border: 1px solid var(--border);
    display: flex; align-items: center; gap: 6px;
    font-size: 11px; color: var(--muted);
    font-family: var(--mono);
  }

  /* ── MAIN CONTENT AREA ── */
  .view-host {
    position: relative !important;
    top: 0 !important; bottom: 0 !important;
    left: 0 !important; right: 0 !important;
    flex: 1;
    height: 100%;
    overflow: hidden;
  }

  /* Welcome banner full width */
  .welcome-banner {
    top: 0 !important;
  }

  /* Wider modals on desktop */
  .underage-modal, .settings-edit-modal, .create-room-modal {
    max-width: 480px !important;
  }

  /* Wider message bubbles on desktop */
  .msg-body { max-width: 60%; }

  /* Rooms drawer on desktop — full left panel next to sidebar */
  .rooms-drawer {
    position: fixed !important;
    left: 220px !important;
    top: 0 !important;
    bottom: 0 !important;
    right: auto !important;
    width: 300px !important;
    border-radius: 0 16px 16px 0 !important;
    transform: translateX(-320px) !important;
    transition: transform .25s cubic-bezier(.4,0,.2,1) !important;
    max-height: 100vh !important;
    z-index: 200 !important;
    padding-bottom: 0 !important;
  }
  .rooms-drawer.open {
    transform: translateX(0px) !important;
  }
  /* Overlay on desktop — hidden, close handled by click-outside */
  #rooms-overlay {
    display: none !important;
  }

  /* Purgatory overlay still full screen */
  .purgatory-overlay { z-index: 600; }
}

/* ── PROFILE & AVATAR SYSTEM ── */

.profile-body {
  flex: 1;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  padding: 14px;
  display: flex;
  flex-direction: column;
  gap: 0;
}

.profile-section {
  margin-bottom: 14px;
}

.av-preview-wrap {
  display: flex;
  align-items: center;
  gap: 16px;
  background: var(--bg2);
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 16px;
}

.av-preview {
  width: 120px;
  height: 120px;
  flex-shrink: 0;
  border-radius: 18px;
  overflow: hidden;
  border: 2px solid var(--border);
  background: #1a1a2e;
}

.av-preview-info { flex: 1; }
.av-preview-name {
  font-size: 20px;
  font-weight: 700;
  color: var(--text);
  margin-bottom: 2px;
}
.av-preview-type {
  font-size: 11px;
  font-family: var(--mono);
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 1px;
  margin-bottom: 8px;
}
.av-token-bal {
  font-size: 16px;
  font-family: var(--mono);
  color: #a78bfa;
  font-weight: 700;
  letter-spacing: .02em;
  transition: opacity .15s;
}
.av-token-bal:hover { opacity: .75; }

/* Customise tabs */
.cust-tabs {
  display: flex;
  background: var(--bg3);
  border: 1px solid var(--border);
  border-radius: 10px;
  overflow: hidden;
  margin-bottom: 14px;
  flex-shrink: 0;
}
.cust-tab {
  flex: 1;
  padding: 9px 6px;
  font-size: 12px;
  font-weight: 700;
  background: transparent;
  color: var(--muted);
  transition: all .15s;
  white-space: nowrap;
}
.cust-tab.active {
  background: rgba(var(--accent-rgb),.1);
  color: var(--accent);
}

.cust-panel { display: none; flex-direction: column; gap: 0; }
.cust-panel.active { display: flex; }

.cust-section-lbl {
  font-size: 10px;
  font-family: var(--mono);
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 1.5px;
  margin: 10px 0 8px;
}

/* Avatar type grid */
.av-type-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 8px;
  margin-bottom: 4px;
}

.av-type-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  padding: 8px 4px;
  background: var(--bg3);
  border: 2px solid var(--border);
  border-radius: 10px;
  cursor: pointer;
  transition: all .12s;
  position: relative;
}
.av-type-card.active {
  border-color: var(--accent);
  background: rgba(var(--accent-rgb),.08);
}
.av-type-card:active { opacity: .8; }

.av-type-svg {
  width: 54px;
  height: 54px;
  border-radius: 8px;
  overflow: hidden;
}
.av-type-lbl {
  font-size: 9px;
  font-family: var(--mono);
  color: var(--muted);
  text-align: center;
  text-transform: capitalize;
}
.av-lock {
  position: absolute;
  top: 4px;
  right: 4px;
  font-size: 8px;
  font-family: var(--mono);
  color: #a78bfa;
  background: rgba(124,58,237,.2);
  border: 1px solid rgba(124,58,237,.3);
  border-radius: 4px;
  padding: 1px 4px;
}

/* Eye style grid — same as av-type-grid */
.eye-style-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 8px;
  margin-bottom: 4px;
}

/* Option grids (accessories, scars, etc) */
.opt-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 8px;
  margin-bottom: 4px;
}

/* Colour swatches */
.colour-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 4px;
}
.colour-swatch {
  width: 32px;
  height: 32px;
  border-radius: 8px;
  border: 2px solid transparent;
  cursor: pointer;
  transition: all .12s;
  flex-shrink: 0;
}
.colour-swatch.active {
  border-color: white;
  transform: scale(1.15);
}

/* ── IMAGE AVATAR PROFILE ── */
.gender-toggle {
  display: flex;
  gap: 8px;
  margin-bottom: 14px;
  flex-shrink: 0;
}
.gender-btn {
  flex: 1;
  padding: 9px;
  border-radius: 10px;
  border: 1.5px solid var(--border);
  background: transparent;
  font-size: 13px;
  font-weight: 700;
  cursor: pointer;
  color: var(--muted);
  font-family: var(--font);
  transition: all .15s;
}
.gender-btn.active-m,
.gender-btn.active-f,
.gender-btn.gender-btn-active {
  border-color: var(--accent);
  background: rgba(var(--accent-rgb),.08);
  color: var(--accent);
}

.av-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 10px;
}

.av-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 5px;
  padding: 8px 4px;
  background: var(--bg2);
  border: 1px solid var(--border);
  border-radius: 12px;
  cursor: pointer;
  transition: all .12s;
  position: relative;
}
.av-card:hover:not(.placeholder) {
  border-color: rgba(56, 189, 248, 0.4);
}
.av-card.active {
  border-color: var(--accent);
  background: rgba(var(--accent-rgb),.06);
}
.av-card.placeholder {
  opacity: .45;
  cursor: default;
}
.av-card:active:not(.placeholder) { opacity: .8; }

.av-card-img {
  width: 72px;
  height: 72px;
  border-radius: 10px;
  overflow: hidden;
  flex-shrink: 0;
  background: #1a1a2e;
}
.av-card-img img {
  width: 72px;
  height: 72px;
  object-fit: cover;
  border-radius: 10px;
}
.av-card-name {
  font-size: 10px;
  font-family: var(--mono);
  color: var(--muted);
  text-align: center;
  text-transform: capitalize;
}
.av-card-cost {
  font-size: 9px;
  font-family: var(--mono);
  color: #a78bfa;
  background: rgba(124,58,237,.15);
  border: 1px solid rgba(124,58,237,.25);
  border-radius: 4px;
  padding: 1px 5px;
}
.av-card-soon {
  font-size: 9px;
  font-family: var(--mono);
  color: var(--muted);
  opacity: .6;
}

/* ── DIVINITY SHOP ── */
.divinity-hero {
  background: linear-gradient(135deg, #1a0a2e 0%, #0d0818 50%, #200a10 100%);
  border: 1px solid rgba(167,139,250,.3);
  border-radius: 16px;
  padding: 24px 16px 20px;
  text-align: center;
  margin-bottom: 20px;
  position: relative;
  overflow: hidden;
}
.divinity-hero::before {
  content: '';
  position: absolute;
  inset: 0;
  background: radial-gradient(ellipse at 50% 0%, rgba(167,139,250,.15) 0%, transparent 65%);
  pointer-events: none;
}
.divinity-crown {
  font-size: 28px;
  color: #a78bfa;
  margin-bottom: 6px;
}
.divinity-title {
  font-size: 28px;
  font-weight: 700;
  color: #e2d9ff;
  letter-spacing: 2px;
  text-transform: uppercase;
  font-family: var(--font);
}
.divinity-sub {
  font-size: 12px;
  font-family: var(--mono);
  color: rgba(167,139,250,.6);
  letter-spacing: 1.5px;
  margin: 6px 0 14px;
  text-transform: uppercase;
}
.divinity-price {
  font-size: 22px;
  font-weight: 700;
  color: #a78bfa;
  font-family: var(--mono);
  margin-bottom: 16px;
}
.divinity-active {
  color: #4ade80;
  font-size: 16px;
}
.divinity-btn {
  background: linear-gradient(135deg, #7c3aed, #a855f7);
  color: white;
  border: none;
  border-radius: 10px;
  padding: 12px 32px;
  font-size: 15px;
  font-weight: 700;
  font-family: var(--font);
  cursor: pointer;
  letter-spacing: .5px;
  width: 100%;
  transition: opacity .15s;
}
.divinity-btn:active { opacity: .8; }

.divinity-perks-lbl {
  font-size: 10px;
  font-family: var(--mono);
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 1.5px;
  margin-bottom: 8px;
}
.divinity-perks {
  background: var(--bg2);
  border: 1px solid var(--border);
  border-radius: 12px;
  overflow: hidden;
}
.perk-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px;
  border-bottom: 1px solid var(--border);
}
.perk-row:last-child { border-bottom: none; }
.perk-icon { font-size: 20px; flex-shrink: 0; width: 28px; text-align: center; }
.perk-body { flex: 1; }
.perk-name { font-size: 13px; font-weight: 700; color: var(--text); margin-bottom: 2px; }
.perk-desc { font-size: 11px; color: var(--muted); line-height: 1.4; }
.perk-check { color: #4ade80; font-size: 16px; font-weight: 700; flex-shrink: 0; }
.perk-lock { color: #a78bfa; font-size: 14px; flex-shrink: 0; }

/* TOKEN PACKS */
.token-packs {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 8px;
}
.token-pack {
  background: var(--bg2);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 14px 8px;
  text-align: center;
  cursor: pointer;
  transition: border-color .12s;
  position: relative;
}
.token-pack:active { opacity: .8; }
.token-pack.featured {
  border-color: #a78bfa;
  background: rgba(124,58,237,.08);
}
.tp-badge {
  position: absolute;
  top: -8px;
  left: 50%;
  transform: translateX(-50%);
  background: #7c3aed;
  color: white;
  font-size: 9px;
  font-family: var(--mono);
  padding: 2px 7px;
  border-radius: 6px;
  white-space: nowrap;
}
.tp-amount {
  font-size: 14px;
  font-weight: 700;
  color: #a78bfa;
  font-family: var(--mono);
  margin-bottom: 4px;
}
.tp-price {
  font-size: 13px;
  color: var(--muted);
  font-family: var(--mono);
}

/* ── SETTINGS ── */
.settings-section-lbl {
  font-size: 10px;
  font-family: var(--mono);
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 1.5px;
  margin: 16px 0 6px;
  padding-left: 2px;
}
.settings-card {
  background: var(--bg2);
  border: 1px solid var(--border);
  border-radius: 12px;
  overflow: hidden;
}
.settings-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 13px 14px;
  cursor: pointer;
  transition: background .1s;
}
.settings-row:active { background: var(--bg3); }
.settings-row.cmd-row { cursor: default; }
.settings-divider {
  height: 1px;
  background: var(--border);
  margin: 0 14px;
}
.sr-left { flex: 1; }
.sr-label {
  font-size: 14px;
  font-weight: 700;
  color: var(--text);
  margin-bottom: 1px;
}
.sr-value {
  font-size: 11px;
  color: var(--muted);
  font-family: var(--mono);
}
.sr-cmd {
  font-size: 13px;
  font-weight: 700;
  color: var(--accent);
  font-family: var(--mono);
  margin-bottom: 2px;
}
.sr-arrow {
  font-size: 20px;
  color: var(--muted);
  flex-shrink: 0;
}

/* TOGGLE */
.sr-toggle {
  width: 44px;
  height: 26px;
  border-radius: 13px;
  background: var(--bg3);
  border: 1px solid var(--border);
  position: relative;
  cursor: pointer;
  transition: background .2s;
  flex-shrink: 0;
}
.sr-toggle.on {
  background: var(--accent);
  border-color: var(--accent);
}
.sr-toggle-thumb {
  position: absolute;
  top: 3px;
  left: 3px;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: white;
  transition: transform .2s;
}
.sr-toggle.on .sr-toggle-thumb { transform: translateX(18px); }

/* Generic toggle — used in settings rows (notifications, privacy, etc.) */
.toggle-wrap {
  flex-shrink: 0;
  width: 44px;
  height: 26px;
  position: relative;
}
.toggle {
  width: 44px;
  height: 26px;
  border-radius: 13px;
  background: var(--bg3);
  border: 1px solid var(--border);
  position: relative;
  cursor: pointer;
  transition: background .2s, border-color .2s;
  flex-shrink: 0;
}
.toggle::after {
  content: '';
  position: absolute;
  top: 3px;
  left: 3px;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: white;
  transition: transform .2s;
}
.toggle.on {
  background: var(--accent);
  border-color: var(--accent);
}
.toggle.on::after {
  transform: translateX(18px);
}

/* RADIO GROUP */
.sr-radio-group {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}
.sr-radio {
  padding: 6px 14px;
  border-radius: 8px;
  border: 1px solid var(--border);
  font-size: 12px;
  font-family: var(--mono);
  color: var(--muted);
  cursor: pointer;
  transition: all .12s;
}
.sr-radio.active {
  border-color: var(--accent);
  background: rgba(var(--accent-rgb),.08);
  color: var(--accent);
}

/* ── DIVINITY PLANS ── */
.divinity-plans {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
  margin-bottom: 14px;
}
.divinity-plan {
  background: rgba(255,255,255,.04);
  border: 1px solid rgba(167,139,250,.2);
  border-radius: 12px;
  padding: 14px 10px;
  text-align: center;
  cursor: pointer;
  position: relative;
  transition: border-color .15s;
}
.divinity-plan:active { opacity: .8; }
.divinity-plan.featured {
  border-color: #a78bfa;
  background: rgba(124,58,237,.12);
}
.dp-badge {
  position: absolute;
  top: -9px;
  left: 50%;
  transform: translateX(-50%);
  background: #a78bfa;
  color: #0a0010;
  font-size: 9px;
  font-family: var(--mono);
  font-weight: 700;
  padding: 2px 8px;
  border-radius: 6px;
  white-space: nowrap;
}
.dp-period {
  font-size: 11px;
  font-family: var(--mono);
  color: rgba(167,139,250,.7);
  text-transform: uppercase;
  letter-spacing: 1px;
  margin-bottom: 6px;
}
.dp-price {
  font-size: 20px;
  font-weight: 700;
  color: #e2d9ff;
  font-family: var(--mono);
}
.dp-price span {
  font-size: 12px;
  opacity: .6;
}
.dp-saving {
  font-size: 10px;
  color: #4ade80;
  font-family: var(--mono);
  margin-top: 4px;
}

/* ── RANDOM DM ── */
.discover-body {
  flex: 1;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}

.rdm-wrap {
  padding: 4px 0 80px; /* extra bottom padding so content clears nav */
  display: flex;
  flex-direction: column;
  gap: 0;
  min-height: 100%;
}
.rdm-intro {
  text-align: center;
  padding: 20px 16px 24px;
}
.rdm-intro-icon { font-size: 36px; margin-bottom: 10px; }
.rdm-intro-title {
  font-size: 22px;
  font-weight: 700;
  color: var(--text);
  margin-bottom: 6px;
}
.rdm-intro-sub {
  font-size: 13px;
  color: var(--muted);
  line-height: 1.5;
  max-width: 280px;
  margin: 0 auto;
}
.rdm-section-lbl {
  font-size: 10px;
  font-family: var(--mono);
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 1.5px;
  margin: 0 0 8px;
  padding: 0 2px;
}
.rdm-gender-row {
  display: flex;
  gap: 8px;
  margin-bottom: 20px;
}
.rdm-g-btn {
  flex: 1;
  padding: 9px 6px;
  border-radius: 10px;
  border: 1.5px solid var(--border);
  background: transparent;
  font-size: 13px;
  font-weight: 700;
  color: var(--muted);
  cursor: pointer;
  text-align: center;
  font-family: var(--font);
  transition: all .12s;
}
.rdm-g-btn.active {
  border-color: var(--accent);
  background: rgba(var(--accent-rgb),.08);
  color: var(--accent);
}
.rdm-interests {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 22px;
}
.rdm-interest {
  padding: 6px 12px;
  border-radius: 20px;
  border: 1px solid var(--border);
  font-size: 12px;
  font-family: var(--mono);
  color: var(--muted);
  cursor: pointer;
  transition: all .12s;
}
.rdm-interest.active {
  border-color: var(--accent);
  background: rgba(var(--accent-rgb),.08);
  color: var(--accent);
}

/* MATCH CARD */
.rdm-match-card {
  background: var(--bg2);
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 14px;
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 16px;
  animation: fadeSlideUp .25s ease;
}
@keyframes fadeSlideUp {
  from { opacity:0; transform:translateY(10px); }
  to   { opacity:1; transform:translateY(0); }
}
.rdm-match-av {
  width: 80px;
  height: 80px;
  border-radius: 12px;
  overflow: hidden;
  flex-shrink: 0;
}
.rdm-match-info { flex: 1; min-width: 0; }
.rdm-match-name {
  font-size: 16px;
  font-weight: 700;
  color: var(--text);
  margin-bottom: 6px;
}
.rdm-match-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
  margin-bottom: 6px;
}
.rdm-tag {
  font-size: 10px;
  font-family: var(--mono);
  color: var(--accent);
  background: rgba(var(--accent-rgb),.08);
  border: 1px solid rgba(var(--accent-rgb),.2);
  border-radius: 4px;
  padding: 2px 7px;
}
.rdm-match-anon {
  font-size: 10px;
  font-family: var(--mono);
  color: var(--muted);
}
.rdm-dm-btn {
  background: var(--accent);
  color: #050a10;
  border: none;
  border-radius: 10px;
  padding: 10px 14px;
  font-size: 13px;
  font-weight: 700;
  font-family: var(--font);
  cursor: pointer;
  flex-shrink: 0;
  transition: opacity .12s;
}
.rdm-dm-btn:active { opacity: .8; }

/* SEARCH BUTTON */
.rdm-btn {
  width: 100%;
  padding: 14px;
  background: var(--bg2);
  border: 1.5px solid var(--accent);
  border-radius: 12px;
  color: var(--accent);
  font-size: 15px;
  font-weight: 700;
  font-family: var(--font);
  cursor: pointer;
  transition: all .15s;
}
.rdm-btn:active { opacity: .8; }
.rdm-btn.searching {
  border-color: var(--muted);
  color: var(--muted);
}

/* ── SPLASH SCREEN ── */
.splash-wrap {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  height: 100%;
  gap: 16px;
}
.splash-title {
  font-size: 18px;
  font-weight: 700;
  color: var(--accent);
  letter-spacing: 3px;
  font-family: var(--font);
  text-transform: uppercase;
}
/* Brand mark — inline OTGC SVG icon. Used at 32px and above only;
   below that the icon collapses to noise and we use brand-color text
   instead. The base size is 32; .brand-mark--md is 48 for splash and
   page-header surfaces; .brand-mark--lg is 96 for the splash hero. */
.brand-mark {
  width: 32px;
  height: 32px;
  display: inline-block;
  vertical-align: middle;
  flex-shrink: 0;
}
.brand-mark--md { width: 48px; height: 48px; }
.brand-mark--lg { width: 96px; height: 96px; }
.splash-dot-wrap {
  display: flex;
  gap: 8px;
  margin-top: 8px;
}
.splash-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--accent);
  opacity: .3;
  animation: splashPulse 1.2s ease-in-out infinite;
}
.splash-dot:nth-child(2) { animation-delay: .2s; }
.splash-dot:nth-child(3) { animation-delay: .4s; }
@keyframes splashPulse {
  0%, 100% { opacity: .2; transform: scale(.8); }
  50%       { opacity: 1;  transform: scale(1);  }
}

/* ── WELCOME BANNER ── */
.welcome-banner {
  position: fixed;
  top: calc(var(--top-nav-h) + var(--sat) + 10px);
  right: 12px;
  background: rgba(13,16,24,.92);
  border: 1px solid rgba(var(--accent-rgb),.25);
  border-radius: 10px;
  padding: 8px 14px;
  font-size: 13px;
  font-family: var(--mono);
  color: var(--accent);
  z-index: 200;
  opacity: 0;
  transform: translateY(-8px);
  transition: opacity .3s ease, transform .3s ease;
  pointer-events: none;
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  white-space: nowrap;
}
.welcome-banner strong { color: var(--text); }
.welcome-banner.show {
  opacity: 1;
  transform: translateY(0);
}

/* ── DM INBOX ── */
.dm-inbox { display: flex; flex-direction: column; height: 100%; }
#dm-thread-list {
  flex: 1;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  padding: 8px 10px 12px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.dm-thread-row {
  display: flex; align-items: center; gap: 12px;
  padding: 12px 14px;
  /* Card treatment matches .home-room-row — bordered rounded rectangle */
  background: var(--bg2);
  border: 1px solid var(--border);
  border-radius: 12px;
  cursor: pointer;
  transition: background .1s, border-color .12s, transform .05s;
}
.dm-thread-row:hover { border-color: rgba(var(--accent-rgb), 0.28); }
.dm-thread-row:active {
  background: var(--bg3);
  transform: scale(0.995);
}
.dm-thread-av { width: 44px; height: 44px; border-radius: 10px; overflow: hidden; flex-shrink: 0; }
.dm-thread-body { flex: 1; min-width: 0; }
.dm-thread-name { font-size: 14px; font-weight: 700; color: var(--text); margin-bottom: 2px; }
.dm-thread-preview { font-size: 12px; color: var(--muted); font-family: var(--mono); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.dm-thread-meta { display: flex; flex-direction: column; align-items: flex-end; gap: 4px; flex-shrink: 0; }
.dm-thread-time { font-size: 10px; font-family: var(--mono); color: var(--muted); }
.dm-unread {
  background: var(--accent); color: #050a10;
  font-size: 10px; font-weight: 700; font-family: var(--mono);
  border-radius: 10px; padding: 1px 6px; min-width: 18px; text-align: center;
}

/* ── DM CONVERSATION ── */
.dm-convo {
  flex-direction: column;
  height: 100%;
  display: none;
}
.dm-convo-header {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 14px;
  border-bottom: 1px solid var(--border);
  background: var(--bg2);
  flex-shrink: 0;
}
.dm-back-btn {
  font-size: 22px; color: var(--accent);
  background: none; border: none; cursor: pointer;
  padding: 0 6px 0 0; line-height: 1;
}
.dm-convo-name { flex: 1; font-size: 15px; font-weight: 700; color: var(--text); }
.dm-convo-av { width: 30px; height: 30px; border-radius: 8px; overflow: hidden; flex-shrink: 0; }

/* ── USER POPUP ── */
/* ── ACTIVE USERS PANEL ── */
.active-users-overlay {
  position: fixed; inset: 0; z-index: 180;
  background: rgba(0,0,0,.5); display: none;
}
.active-users-overlay.open { display: block; }
.active-users-panel {
  position: fixed;
  top: 0; right: -280px;
  width: 260px; height: 100%;
  background: var(--bg2);
  border-left: 1px solid var(--border);
  z-index: 181;
  transition: right .25s ease;
  display: flex; flex-direction: column;
  padding-top: calc(var(--top-nav-h) + var(--sat));
}
.active-users-panel.open { right: 0; }
.active-users-header {
  display: flex; align-items: center; justify-content: space-between;
  padding: 12px 16px;
  border-bottom: 1px solid var(--border);
}
.active-users-title { font-size: 14px; font-weight: 700; color: var(--text); }
.active-users-close {
  background: none; border: none; color: var(--muted); font-size: 16px; cursor: pointer;
}
.active-user-row {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 16px;
  border-bottom: 1px solid var(--border);
}
.active-user-av { width: 36px; height: 36px; border-radius: 8px; overflow: hidden; flex-shrink: 0; }
.active-user-name { flex: 1; font-size: 13px; font-weight: 700; color: var(--text); }
.active-user-dm {
  padding: 5px 12px; border-radius: 8px;
  background: rgba(var(--accent-rgb),.1); border: 1px solid rgba(var(--accent-rgb),.3);
  color: var(--accent); font-size: 12px; font-weight: 700;
  font-family: var(--font); cursor: pointer;
}

/* ── ROOM BAR USERS BUTTON ── */
.room-users-btn {
  background: none; border: none; font-size: 16px; cursor: pointer;
  padding: 2px 4px; color: var(--muted); margin-left: 4px;
}

/* ── TAPPABLE USERNAME IN CHAT ── */
.msg-username {
  cursor: pointer; color: var(--accent);
  text-decoration: none;
  /* Allow inline style color override for Divinity text colors */
}
.msg-username:active { opacity: .7; }

/* ── DM NAV BADGE ── */
#dm-badge {
  position: absolute; top: 4px; right: 6px;
  min-width: 16px; height: 16px;
  background: var(--red); color: white;
  font-size: 9px; font-weight: 700; font-family: var(--mono);
  border-radius: 8px; padding: 0 4px;
  display: none; align-items: center; justify-content: center;
  pointer-events: none;
}
#dm-badge[style*="block"] { display: flex !important; }

/* ── CLICKABLE AVATAR IN CHAT ── */
.msg-av-click {
  cursor: pointer;
}
.msg-av-click:active { opacity: .7; }

/* ── LEGAL VIEWS ─────────────────────────────────────────────────────────── */
.legal-body {
  flex: 1;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
  padding: 20px 16px 60px;
  font-size: 14px;
  line-height: 1.7;
  color: var(--text);
  height: 0; /* forces flex child to scroll rather than expand */
}
.legal-body h2 {
  font-family: var(--mono);
  color: var(--accent);
  font-size: 15px;
  font-weight: 700;
  letter-spacing: .5px;
  margin-bottom: 16px;
}
.legal-body h3 {
  color: var(--accent);
  font-size: 12px;
  letter-spacing: 1px;
  text-transform: uppercase;
  font-family: var(--mono);
  margin: 24px 0 8px;
  padding-bottom: 5px;
  border-bottom: 1px solid var(--border);
}
.legal-body p { margin-bottom: 12px; color: var(--text); }
.legal-body ul { padding-left: 18px; margin-bottom: 12px; }
.legal-body li { margin-bottom: 5px; }
.legal-body a { color: var(--accent); }
.legal-body strong { color: var(--text); font-weight: 600; }
.legal-body code {
  font-family: var(--mono);
  background: var(--bg2);
  border: 1px solid var(--border);
  border-radius: 3px;
  padding: 1px 5px;
  font-size: 12px;
  color: var(--accent);
}
.legal-date {
  color: var(--muted) !important;
  font-size: 12px !important;
  font-family: var(--mono);
  margin-bottom: 20px !important;
}
.legal-full-link {
  margin-top: 28px !important;
  padding-top: 16px;
  border-top: 1px solid var(--border);
}
.legal-full-link a { font-size: 13px; font-family: var(--mono); }

/* ── UNDERAGE REPORT BUTTON ──────────────────────────────────────────────── */
/* ── UNDERAGE REPORT MODAL ───────────────────────────────────────────────── */
.underage-overlay {
  position: fixed; inset: 0; z-index: 300;
  background: rgba(0,0,0,.7);
  display: none;
}
.underage-overlay.open { display: block; }
.underage-modal {
  position: fixed;
  top: 50%; left: 50%;
  transform: translate(-50%, -50%) scale(.95);
  z-index: 301;
  background: var(--bg2);
  border: 1px solid var(--border);
  border-radius: 16px;
  padding: 28px 24px 20px;
  width: calc(100% - 48px);
  max-width: 340px;
  text-align: center;
  opacity: 0;
  pointer-events: none;
  transition: opacity .18s ease, transform .18s ease;
}
.underage-modal.open {
  opacity: 1;
  pointer-events: auto;
  transform: translate(-50%, -50%) scale(1);
}
.underage-icon { font-size: 32px; margin-bottom: 10px; }
.underage-title { font-size: 16px; font-weight: 700; color: var(--red); margin-bottom: 10px; font-family: var(--font); }
.underage-body { font-size: 14px; color: var(--muted); line-height: 1.55; margin-bottom: 22px; }
.underage-body strong { color: var(--text); }
.underage-actions { display: flex; gap: 10px; }
.underage-btn-cancel {
  flex: 1; padding: 11px 0; border-radius: 10px;
  background: var(--bg); border: 1px solid var(--border);
  color: var(--muted); font-size: 14px; font-weight: 600;
  font-family: var(--font); cursor: pointer;
}
.underage-btn-confirm {
  flex: 1; padding: 11px 0; border-radius: 10px;
  background: var(--red); border: none;
  color: #fff; font-size: 14px; font-weight: 700;
  font-family: var(--font); cursor: pointer;
}
.underage-btn-confirm:active { opacity: .85; }

/* ── DM CONVO MENU ───────────────────────────────────────────────────────── */
.dm-more-btn {
  background: none; border: none; color: var(--muted);
  font-size: 20px; cursor: pointer; padding: 0 4px;
  line-height: 1; letter-spacing: 2px;
  flex-shrink: 0;
}
.dm-more-btn:hover { color: var(--text); }
.dm-menu-overlay { position: fixed; inset: 0; z-index: 250; display: none; }
.dm-menu-overlay.open { display: block; }
.dm-menu {
  position: fixed;
  top: 54px; right: 12px;
  z-index: 251;
  background: var(--bg2);
  border: 1px solid var(--border);
  border-radius: 12px;
  overflow: hidden;
  min-width: 200px;
  box-shadow: 0 8px 32px rgba(0,0,0,.5);
  opacity: 0; pointer-events: none;
  transform: translateY(-6px);
  transition: opacity .15s ease, transform .15s ease;
}
.dm-menu.open { opacity: 1; pointer-events: auto; transform: translateY(0); }
.dm-menu-item {
  display: block; width: 100%;
  padding: 14px 18px; text-align: left;
  background: none; border: none; border-bottom: 1px solid var(--border);
  color: var(--text); font-size: 14px; font-family: var(--font); cursor: pointer;
}
.dm-menu-item:last-child { border-bottom: none; }
.dm-menu-item:hover { background: var(--bg); }
.dm-menu-item.danger { color: var(--red); }

/* ── REPORT USER REASONS ─────────────────────────────────────────────────── */
.report-reasons { display: flex; flex-direction: column; gap: 6px; margin-top: 12px; }
.report-reason {
  padding: 10px 14px; border-radius: 8px; text-align: left;
  background: var(--bg); border: 1px solid var(--border);
  color: var(--text); font-size: 13px; font-family: var(--font);
  cursor: pointer; transition: border-color .15s, background .15s;
}
.report-reason:hover { background: var(--bg2); }
.report-reason.selected { border-color: var(--accent); color: var(--accent); background: #0a1a24; }

/* ── RDM NO MATCH ────────────────────────────────────────────────────────── */
.rdm-no-match {
  text-align: center;
  color: var(--muted);
  font-size: 14px;
  padding: 24px 16px;
  line-height: 1.6;
}

/* ── COMMAND INFO MODAL ──────────────────────────────────────────────────── */
.cmd-info-modal {
  text-align: left !important;
  padding: 0 !important;
  max-width: 380px !important;
}
.cmd-info-header {
  display: flex; align-items: center; justify-content: space-between;
  padding: 18px 20px 14px;
  border-bottom: 1px solid var(--border);
}
.cmd-info-title {
  font-family: var(--mono);
  color: var(--accent);
  font-size: 15px;
  font-weight: 700;
  letter-spacing: .5px;
}
.cmd-info-close {
  background: none; border: none; color: var(--muted);
  font-size: 16px; cursor: pointer; padding: 0;
}
.cmd-info-desc {
  padding: 14px 20px 10px;
  font-size: 14px;
  color: var(--text);
  line-height: 1.55;
}
.cmd-info-details {
  padding: 0 20px 14px 36px;
  margin: 0;
}
.cmd-info-details li {
  font-size: 13px;
  color: var(--muted);
  margin-bottom: 5px;
  line-height: 1.5;
}
.cmd-info-example-wrap {
  margin: 0 20px 20px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 10px 14px;
}
.cmd-info-example-lbl {
  font-size: 10px;
  color: var(--muted);
  letter-spacing: 1px;
  text-transform: uppercase;
  font-family: var(--mono);
  margin-bottom: 4px;
}
.cmd-info-example {
  font-family: var(--mono);
  color: var(--accent);
  font-size: 14px;
}

/* ── AVATAR CREDIT ───────────────────────────────────────────────────────── */
.av-credit {
  text-align: center;
  font-size: 11px;
  color: var(--muted);
  padding: 12px 16px 4px;
  font-family: var(--mono);
  letter-spacing: .3px;
}

/* ── SETTINGS EDIT MODAL ─────────────────────────────────────────────────── */
.settings-edit-modal {
  text-align: left !important;
  padding: 0 !important;
}
.settings-edit-header {
  display: flex; align-items: center; justify-content: space-between;
  padding: 18px 20px 14px;
  border-bottom: 1px solid var(--border);
}
.settings-edit-title {
  font-size: 15px; font-weight: 700; color: var(--text);
}
.settings-edit-body {
  padding: 16px 20px 20px;
}
.settings-edit-input {
  width: 100%;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 12px 14px;
  color: var(--text);
  font-size: 15px;
  font-family: var(--font);
  outline: none;
  -webkit-appearance: none;
}
.settings-edit-input:focus { border-color: var(--accent); }
.settings-edit-err {
  color: var(--red);
  font-size: 13px;
  min-height: 18px;
  margin: 8px 0 4px;
}
.settings-edit-actions {
  display: flex; gap: 10px; margin-top: 14px;
}

/* ── MEDIA MESSAGES ──────────────────────────────────────────────────────── */
.msg-media-img {
  max-width: min(240px, 100%);
  max-height: 240px;
  border-radius: 10px;
  display: block;
  cursor: pointer;
  object-fit: cover;
}
.msg-gif {
  max-width: min(240px, 100%);
  max-height: 200px;
  width: auto;
  height: auto;
  border-radius: 10px;
  display: block;
  cursor: pointer;
}
.msg-media-video {
  max-width: 240px;
  border-radius: 10px;
  display: block;
  background: #000;
}

/* ── MEDIA VIEWER ────────────────────────────────────────────────────────── */
.media-viewer-overlay {
  position: fixed; inset: 0; z-index: 400;
  background: rgba(0,0,0,.95);
  display: none;
  align-items: center;
  justify-content: center;
}
.media-viewer-overlay.open { display: flex; }
.media-viewer-img {
  max-width: 95vw;
  max-height: 90vh;
  object-fit: contain;
  border-radius: 8px;
}
.media-viewer-close {
  position: absolute;
  top: 16px; right: 16px;
  background: rgba(255,255,255,.1);
  border: none; color: #fff;
  font-size: 20px; width: 40px; height: 40px;
  border-radius: 50%; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
}

/* ── ONBOARDING GUIDELINES STEP ──────────────────────────────────────────── */
.ob-guidelines-scroll {
  width: 100%;
  max-height: 260px;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin: 14px 0;
  padding-right: 4px;
}
/* On mobile, the inner guidelines box does NOT scroll. iOS Safari has a
   long-standing quirk where touch scroll on a small inner overflow:auto
   element gets absorbed by the outer scrollable parent (.onboard-wrap),
   leaving the inner box stuck at the top — users can never reach the
   bottom, the scroll-gate never fires, and the agree checkbox stays
   disabled. So on phone-sized viewports we let the guidelines render
   inline at full height and rely on the OUTER page scroll to deliver
   the user to the bottom. The JS scroll gate detects which scroller is
   live and watches the right element. */
@media (max-width: 768px) {
  .ob-guidelines-scroll {
    max-height: none;
    overflow-y: visible;
  }
}
.ob-guideline-item {
  display: flex;
  gap: 12px;
  align-items: flex-start;
  background: var(--bg2);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 10px 14px;
  text-align: left;
  font-size: 13px;
  line-height: 1.5;
  color: var(--muted);
}
.ob-guideline-item strong { color: var(--text); display: block; margin-bottom: 2px; }
.ob-g-icon { font-size: 18px; flex-shrink: 0; margin-top: 1px; }
.ob-agree-row {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  margin: 12px 0 16px;
  font-size: 13px;
  color: var(--muted);
  text-align: left;
  width: 100%;
  cursor: pointer;
  transition: opacity .15s;
}
.ob-agree-row.disabled {
  /* User hasn't scrolled through guidelines yet — row is non-interactive
     until initGuidelinesScrollGate() detects a scroll-to-bottom and removes
     this class. Clicking while disabled is a no-op (guarded in
     toggleAgreeCheck). */
  opacity: 0.45;
  cursor: not-allowed;
}
.ob-scroll-hint {
  text-align: center;
  font-size: 12px;
  color: var(--muted);
  font-family: var(--mono);
  margin: 4px 0 -4px;
  animation: scrollHintPulse 2s ease-in-out infinite;
}
@keyframes scrollHintPulse {
  0%, 100% { opacity: 0.55; transform: translateY(0); }
  50%      { opacity: 1;    transform: translateY(2px); }
}
.ob-agree-row input[type="checkbox"] {
  /* Hidden — replaced by custom styled box */
  position: absolute;
  opacity: 0;
  width: 0; height: 0;
}
.ob-agree-custom {
  width: 22px; height: 22px;
  min-width: 22px;
  border-radius: 6px;
  border: 2px solid var(--border);
  background: var(--bg2);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 14px;
  transition: border-color .15s, background .15s;
  margin-top: 1px;
}
.ob-agree-row.checked .ob-agree-custom {
  border-color: var(--accent);
  background: var(--accent);
  color: #000;
}
.ob-agree-label {
  flex: 1;
  line-height: 1.5;
}

/* ── DIVINITY COMING SOON ────────────────────────────────────────────────── */
.divinity-coming-soon {
  background: linear-gradient(135deg, #0d1a2e, #1a0d2e);
  border: 1px solid var(--accent);
  border-radius: 16px;
  padding: 24px 20px;
  text-align: center;
  margin-bottom: 16px;
}
.dcs-icon {
  font-size: 32px;
  color: var(--accent);
  margin-bottom: 8px;
}
.dcs-title {
  font-family: var(--mono);
  font-size: 18px;
  font-weight: 700;
  color: var(--accent);
  letter-spacing: 2px;
  text-transform: uppercase;
  margin-bottom: 8px;
}
.dcs-body {
  font-size: 13px;
  color: var(--muted);
  line-height: 1.6;
}
/* (v15.69) Removed: .divinity-locked, .divinity-plans-disabled, and
   .divinity-btn-disabled — all three were "Stripe not yet wired" teaser
   states. Now that subscriptions work, these classes are no longer
   referenced and the rules would only cause subtle pointer-events
   issues if accidentally reapplied. */

/* ── PURGATORY OVERLAY ───────────────────────────────────────────────────── */
.purgatory-overlay {
  position: fixed; inset: 0; z-index: 500;
  background: #000;
  display: none;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 32px 24px;
}
.purgatory-overlay.open { display: flex; }
.purgatory-content {
  max-width: 400px; width: 100%;
  text-align: center;
  display: flex; flex-direction: column; align-items: center; gap: 16px;
}
.purgatory-rip {
  font-size: 64px; color: #333;
  animation: purgatory-pulse 3s ease-in-out infinite;
}
@keyframes purgatory-pulse {
  0%, 100% { opacity: .3; transform: scale(1); }
  50% { opacity: .8; transform: scale(1.05); }
}
.purgatory-title {
  font-size: 28px; font-weight: 800;
  color: var(--red); font-family: var(--mono);
  letter-spacing: 2px; text-transform: uppercase;
}
.purgatory-subtitle {
  font-size: 14px; color: #555;
  font-family: var(--mono); letter-spacing: 1px;
}
.purgatory-reason {
  font-size: 15px; color: #888;
  background: #0a0a0a; border: 1px solid #1a1a1a;
  border-radius: 10px; padding: 12px 16px;
  width: 100%; line-height: 1.6;
}
.purgatory-timer {
  font-family: var(--mono); font-size: 18px;
  color: var(--accent); letter-spacing: 1px;
}
.purgatory-appeal-btn {
  background: #0d1a2e; border: 1px solid var(--accent);
  color: var(--accent); padding: 12px 24px;
  border-radius: 10px; cursor: pointer;
  font-size: 14px; width: 100%;
}
.purgatory-appeal-section { width: 100%; }
.purgatory-appeal-label { font-size: 13px; color: #666; margin-bottom: 8px; text-align: left; }
.purgatory-appeal-input {
  width: 100%; background: #0a0a0a;
  border: 1px solid #1e2530; border-radius: 10px;
  color: var(--text); padding: 12px 14px;
  font-size: 14px; font-family: var(--font);
  resize: none; margin-bottom: 8px;
}
.purgatory-appeal-err { color: var(--red); font-size: 13px; min-height: 16px; text-align: left; }
.purgatory-appeal-submit {
  width: 100%; background: var(--accent);
  border: none; color: #000; padding: 12px;
  border-radius: 10px; cursor: pointer;
  font-size: 14px; font-weight: 700;
}

/* ── MOD BADGE ───────────────────────────────────────────────────────────── */
.msg-mod-badge {
  display: inline-block;
  background: #1a2a1a; color: #4ade80;
  border: 1px solid #4ade8044;
  border-radius: 4px; font-size: 9px;
  font-family: var(--mono); letter-spacing: .5px;
  padding: 1px 5px; margin-left: 4px;
  vertical-align: middle; text-transform: uppercase;
}
.msg-owner-badge {
  margin-left: 3px; font-size: 11px;
  vertical-align: middle;
}

/* ── USER POPUP MOD BUTTONS ──────────────────────────────────────────────── */
.user-popup-mod-btn {
  flex: 1; background: var(--bg3);
  border: 1px solid var(--border);
  color: var(--text); padding: 8px 4px;
  border-radius: 8px; cursor: pointer;
  font-size: 11px; font-family: var(--mono);
  letter-spacing: .3px;
}
.user-popup-mod-btn:hover { background: var(--bg4); }
.mod-btn-danger { border-color: var(--red) !important; color: var(--red) !important; }

/* ── MOD REPORT QUEUE ────────────────────────────────────────────────────── */
.mod-report-card {
  background: var(--bg2); border: 1px solid var(--border);
  border-radius: 12px; padding: 14px;
  margin-bottom: 10px; display: flex;
  gap: 12px; align-items: flex-start;
}
.mod-report-type {
  font-family: var(--mono); font-size: 9px;
  letter-spacing: 1px; padding: 3px 8px;
  border-radius: 4px; flex-shrink: 0;
  margin-top: 2px;
}
.mod-type-underage { background: #2a1a1a; color: var(--red); border: 1px solid var(--red)44; }
.mod-type-explicit { background: #2a1a00; color: #f59e0b; border: 1px solid #f59e0b44; }
.mod-type-violation { background: #1a1a2a; color: #818cf8; border: 1px solid #818cf844; }
.mod-report-info { flex: 1; }
.mod-report-user { font-size: 14px; color: var(--text); margin-bottom: 3px; }
.mod-report-reason { font-size: 12px; color: var(--muted); margin-bottom: 3px; }
.mod-report-meta { font-size: 11px; color: #444; margin-bottom: 4px; }
.mod-report-msg {
  font-size: 11px; color: #555; font-family: var(--mono);
  background: var(--bg); border-radius: 6px;
  padding: 6px 8px; margin-top: 4px; line-height: 1.5;
}
.mod-report-actions { display: flex; flex-direction: column; gap: 4px; flex-shrink: 0; }
.mod-action-btn {
  font-size: 11px; font-family: var(--mono);
  padding: 5px 10px; border-radius: 6px;
  border: 1px solid; cursor: pointer;
  letter-spacing: .3px;
}
.mod-btn-mute { background: #1a1a2a; color: #818cf8; border-color: #818cf844; }
.mod-btn-ban { background: #2a1a1a; color: var(--red); border-color: var(--red)44; }
.mod-btn-dismiss { background: var(--bg3); color: var(--muted); border-color: var(--border); }

/* ── MOD LOG ─────────────────────────────────────────────────────────────── */
.mod-log-row {
  display: flex; gap: 12px; align-items: flex-start;
  padding: 10px 0; border-bottom: 1px solid var(--border);
}
.mod-log-action {
  font-family: var(--mono); font-size: 9px;
  letter-spacing: 1px; padding: 3px 6px;
  border-radius: 4px; flex-shrink: 0; margin-top: 2px;
  background: var(--bg2); color: var(--muted); border: 1px solid var(--border);
}
.mod-action-ban, .mod-action-roomban { color: var(--red) !important; border-color: var(--red)44 !important; }
.mod-action-mute { color: #f59e0b !important; border-color: #f59e0b44 !important; }
.mod-action-kick { color: #818cf8 !important; border-color: #818cf844 !important; }
.mod-action-unban, .mod-action-unmute, .mod-action-appeal_approved { color: #4ade80 !important; border-color: #4ade8044 !important; }
.mod-action-modadd { color: var(--accent) !important; border-color: var(--accent)44 !important; }
.mod-log-info { flex: 1; font-size: 13px; color: var(--text); }
.mod-log-reason { font-size: 12px; color: var(--muted); margin-top: 2px; }
.mod-log-meta { font-size: 11px; color: #444; margin-top: 2px; }
.mod-log-time { font-size: 11px; color: #444; flex-shrink: 0; font-family: var(--mono); }

/* ── USER-CREATED ROOMS ──────────────────────────────────────────────────── */
.create-room-btn {
  width: 100%; background: linear-gradient(135deg, #0d1a2e, #1a0d2e);
  border: 1px solid var(--accent); border-radius: 12px;
  color: var(--accent); padding: 12px 16px;
  font-size: 14px; font-family: var(--mono);
  cursor: pointer; margin-bottom: 12px;
  display: flex; align-items: center; justify-content: center; gap: 8px;
}
.create-room-btn:hover { background: linear-gradient(135deg, #112236, #220d3a); }
.create-room-cost {
  font-size: 11px; color: var(--muted);
  background: var(--bg2); padding: 2px 7px;
  border-radius: 10px; border: 1px solid var(--border);
}
.user-room-card { border-color: #1e2a3a !important; }
.rc-manage-btn {
  background: var(--bg3); border: 1px solid var(--border);
  color: var(--muted); width: 28px; height: 28px;
  border-radius: 6px; cursor: pointer; font-size: 14px;
  display: flex; align-items: center; justify-content: center;
  flex-shrink: 0;
}
.rc-manage-btn:hover { color: var(--accent); border-color: var(--accent); }

/* ── CREATE ROOM MODAL ───────────────────────────────────────────────────── */
.create-room-modal {
  text-align: left !important;
  padding: 0 !important;
  max-height: 90vh;
  overflow-y: auto;
}
.cr-header {
  display: flex; align-items: center; justify-content: space-between;
  padding: 18px 20px 14px;
  border-bottom: 1px solid var(--border);
  position: sticky; top: 0; background: var(--bg2); z-index: 1;
}
.cr-title { font-size: 15px; font-weight: 700; color: var(--text); }
.cr-body { padding: 16px 20px 20px; }
.cr-field { margin-bottom: 14px; }
.cr-label {
  display: block; font-size: 11px; font-family: var(--mono);
  color: var(--muted); letter-spacing: 1px; text-transform: uppercase;
  margin-bottom: 6px;
}
.cr-icon-grid {
  display: flex; flex-wrap: wrap; gap: 6px;
}
.cr-icon-btn {
  width: 38px; height: 38px; border-radius: 8px;
  border: 1px solid var(--border); background: var(--bg);
  font-size: 18px; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
}
.cr-icon-btn.selected { border-color: var(--accent); background: #0d1a2e; }
.cr-cost-note {
  font-size: 12px; color: var(--muted); margin: 10px 0 14px;
  padding: 8px 12px; background: var(--bg); border-radius: 8px;
  border: 1px solid var(--border);
}
.cr-actions {
  display: flex; gap: 10px;
}

/* ── MANAGE ROOM MODAL ───────────────────────────────────────────────────── */
.mr-members-list {
  display: flex; flex-direction: column; gap: 6px;
  max-height: 200px; overflow-y: auto;
}
.mr-member-row {
  display: flex; align-items: center; justify-content: space-between;
  padding: 8px 12px; background: var(--bg);
  border: 1px solid var(--border); border-radius: 8px;
}
.mr-member-name { font-size: 13px; color: var(--text); }
.mr-member-role { font-size: 11px; color: var(--muted); font-family: var(--mono); }
.mr-member-actions { display: flex; gap: 4px; }
.mr-btn {
  font-size: 10px; font-family: var(--mono); padding: 4px 8px;
  border-radius: 5px; border: 1px solid var(--border);
  background: var(--bg2); color: var(--muted); cursor: pointer;
}
.mr-btn-mod { color: #4ade80; border-color: #4ade8044; }
.mr-invite-row { display: flex; gap: 8px; align-items: center; }

/* Max-messages selector in manage-room modal — segmented-control style.
   The native radio is visually hidden (kept on-screen for a11y/keyboard
   focus) and the surrounding label acts as the click target. The
   :has(:checked) selector flips the active label without needing JS to
   toggle a class. */
.mr-mm-row {
  display: flex;
  gap: 6px;
  font-family: var(--mono);
  font-size: 13px;
}
.mr-mm-opt {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 10px 8px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--bg2);
  color: var(--muted);
  cursor: pointer;
  user-select: none;
  transition: background .12s ease, border-color .12s ease, color .12s ease;
}
.mr-mm-opt:hover { background: var(--bg3); color: var(--text); }
.mr-mm-opt:active { transform: translateY(1px); }
.mr-mm-opt input[type="radio"] {
  /* Hidden visually but still focusable for keyboard users. */
  position: absolute;
  opacity: 0;
  pointer-events: none;
  width: 1px;
  height: 1px;
}
.mr-mm-opt:has(input:checked) {
  background: var(--accent, #00e5ff);
  border-color: var(--accent, #00e5ff);
  color: #050a10;
  font-weight: 700;
}
.mr-mm-opt:has(input:focus-visible) {
  outline: 2px solid var(--accent, #00e5ff);
  outline-offset: 2px;
}

/* ── AVATAR FRAMES ───────────────────────────────────────────────────────── */
.av-frame {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  box-sizing: border-box;
  /* Frame border sits flush against avatar — no background gap */
}
.av-frame img { border-radius: inherit; }

/* Tier 1 — Static (1,000 ⬡) */
.frame-neon   { border: 2px solid #00e5ff; box-shadow: 0 0 4px #00e5ff44; }
.frame-gold   { border: 2px solid #f59e0b; box-shadow: 0 0 4px #f59e0b44; }
.frame-blood  { border: 2px solid #cc0018; box-shadow: 0 0 4px #cc001844; }
.frame-arctic { border: 2px solid #bae6fd; box-shadow: 0 0 4px #bae6fd44; }

/* Tier 2 — Glow (2,500 ⬡) */
.frame-plasma  { border: 2px solid #00e5ff; box-shadow: 0 0 8px #00e5ff, 0 0 16px #00e5ff44; }
.frame-inferno { border: 2px solid #f97316; box-shadow: 0 0 8px #f97316, 0 0 16px #f9731644; }
.frame-void    { border: 2px solid #7c3aed; box-shadow: 0 0 8px #7c3aed, 0 0 16px #7c3aed44; }

/* Tier 3 — Animated (5,000 ⬡) */
.frame-pulse {
  border: 2px solid #00e5ff;
  animation: frame-pulse-anim 2.5s ease-in-out infinite;
}
@keyframes frame-pulse-anim {
  0%, 100% { box-shadow: 0 0 4px #00e5ff44; border-color: #00e5ff; }
  50%       { box-shadow: 0 0 14px #00e5ff, 0 0 28px #00e5ff66; border-color: #7fffff; }
}
.frame-prism {
  border: 2px solid #00e5ff;
  animation: frame-prism-anim 4s linear infinite;
}
@keyframes frame-prism-anim {
  0%   { border-color: #00e5ff; box-shadow: 0 0 8px #00e5ff; }
  25%  { border-color: #a78bfa; box-shadow: 0 0 8px #a78bfa; }
  50%  { border-color: #f59e0b; box-shadow: 0 0 8px #f59e0b; }
  75%  { border-color: #4ade80; box-shadow: 0 0 8px #4ade80; }
  100% { border-color: #00e5ff; box-shadow: 0 0 8px #00e5ff; }
}

/* ── FRAME SHOP ──────────────────────────────────────────────────────────── */
.frames-shop {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 8px;
}
.frame-tier-lbl {
  font-size: 10px;
  font-family: var(--mono);
  color: var(--muted);
  letter-spacing: 1px;
  text-transform: uppercase;
  padding: 10px 0 4px;
}
.frame-card {
  display: flex;
  align-items: center;
  gap: 12px;
  background: var(--bg2);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 12px 14px;
}
.frame-preview {
  width: 44px;
  height: 44px;
  border-radius: 10px;
  flex-shrink: 0;
}
.frame-preview-inner {
  width: 100%;
  height: 100%;
  border-radius: 8px;
  background: var(--bg3);
}
.frame-info { flex: 1; }
.frame-name {
  font-size: 13px;
  font-weight: 700;
  color: var(--text);
  margin-bottom: 2px;
}
.frame-desc {
  font-size: 11px;
  color: var(--muted);
  font-family: var(--mono);
}
.frame-btn {
  font-size: 11px;
  font-family: var(--mono);
  padding: 6px 12px;
  border-radius: 8px;
  border: 1px solid;
  cursor: pointer;
  white-space: nowrap;
  flex-shrink: 0;
}
.frame-btn-buy    { background: #0d1a2e; color: var(--accent); border-color: var(--accent)44; }
.frame-btn-equip  { background: #0d2e1a; color: #4ade80; border-color: #4ade8044; }
.frame-btn-active { background: #1a2e0d; color: #4ade80; border-color: #4ade80; }

/* ── @MENTIONS ───────────────────────────────────────────────────────────── */
.mention {
  color: var(--accent);
  font-weight: 600;
  background: rgba(var(--accent-rgb), 0.07);
  border-radius: 4px;
  padding: 0 3px;
}
.mention-me {
  color: #a78bfa;
  background: #a78bfa18;
}

/* ── PROFILE FRAMES SECTION ──────────────────────────────────────────────── */
.profile-section-lbl {
  font-size: 11px;
  font-family: var(--mono);
  color: var(--muted);
  letter-spacing: 1px;
  text-transform: uppercase;
  padding: 20px 16px 10px;
}
.profile-frames-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(80px, 1fr));
  gap: 8px;
  padding: 0 12px 8px;
}
/* Profile gifts + frames sections — display:block so both reserve their own
   vertical space independently of the parent flex column, preventing any
   overlap from flex child sizing quirks or height:0 edge cases. */
.profile-gifts-section,
.profile-frames-section {
  display: block;
  width: 100%;
  clear: both;
}
.profile-gifts-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  padding: 0 12px 12px;
}
.profile-frame-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  padding: 10px 8px;
  background: var(--bg2);
  border: 1px solid var(--border);
  border-radius: 12px;
  cursor: pointer;
  transition: border-color .15s;
}
.profile-frame-card.active {
  border-color: var(--accent);
  background: #0d1a2e;
}
.profile-frame-name {
  font-size: 11px;
  color: var(--muted);
  font-family: var(--mono);
  text-align: center;
}

/* ── FUN COMMANDS ─────────────────────────────────────────────────────────── */
.msg-action {
  color: var(--muted);
  font-style: italic;
  font-size: 13px;
}
.msg-spoiler {
  background: var(--muted);
  color: transparent;
  border-radius: 4px;
  padding: 0 4px;
  cursor: pointer;
  user-select: none;
  filter: blur(4px);
  transition: filter .2s, color .2s;
}
.msg-spoiler.revealed {
  background: transparent;
  color: inherit;
  filter: none;
}

/* ── DIVINITY EXPIRY BADGE ───────────────────────────────────────────────── */
.divinity-expiry {
  font-size: 11px;
  font-family: var(--mono);
  color: #a78bfa;
  background: rgba(167,139,250,.12);
  border: 1px solid rgba(167,139,250,.3);
  border-radius: 20px;
  padding: 4px 12px;
  margin-top: 6px;
  display: inline-block;
  letter-spacing: .5px;
}

/* ── @MENTION AUTOCOMPLETE ───────────────────────────────────────────────── */
.mention-dropdown {
  position: absolute;
  bottom: 100%;
  left: 12px; right: 12px;
  background: var(--bg2);
  border: 1px solid var(--border);
  border-radius: 12px;
  overflow: hidden;
  z-index: 200;
  box-shadow: 0 -4px 20px rgba(0,0,0,.4);
  max-height: 240px;
  overflow-y: auto;
  display: none;
}
.mention-item {
  padding: 10px 14px;
  font-size: 13px;
  color: var(--text);
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 4px;
  transition: background .1s;
}
.mention-item:hover, .mention-item.active {
  background: var(--bg3);
  color: var(--accent);
}
.mention-item-at {
  color: var(--accent);
  font-weight: 700;
  font-family: var(--mono);
}

/* ── ROOM INFO PANEL ─────────────────────────────────────────────────────── */
.room-info-panel {
  position: fixed;
  top: 50%; left: 50%;
  transform: translate(-50%, -50%) scale(.95);
  width: min(360px, 92vw);
  background: var(--bg2);
  border: 1px solid var(--border);
  border-radius: 16px;
  z-index: 500;
  opacity: 0;
  pointer-events: none;
  transition: opacity .15s, transform .15s;
  overflow: hidden;
}
.room-info-panel.open {
  opacity: 1;
  pointer-events: all;
  transform: translate(-50%, -50%) scale(1);
}
.room-info-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px 18px 12px;
  border-bottom: 1px solid var(--border);
}
.room-info-title {
  font-size: 15px;
  font-weight: 700;
  color: var(--accent);
  font-family: var(--mono);
}
.room-info-body {
  padding: 14px 18px 18px;
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.room-info-desc {
  font-size: 13px;
  color: var(--muted);
  line-height: 1.5;
  font-style: italic;
}
.room-info-section { display: flex; flex-direction: column; gap: 4px; }
.room-info-lbl {
  font-size: 10px;
  font-family: var(--mono);
  color: var(--muted);
  letter-spacing: 1px;
  text-transform: uppercase;
}
.room-info-val {
  font-size: 13px;
  color: var(--text);
  font-family: var(--mono);
}
.room-info-code-row {
  display: flex;
  align-items: center;
  gap: 8px;
}
.room-info-code {
  font-size: 11px;
  color: var(--accent);
  font-family: var(--mono);
  background: var(--bg3);
  padding: 6px 10px;
  border-radius: 8px;
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  border: 1px solid var(--border);
}
.room-info-copy-btn {
  font-size: 11px;
  font-family: var(--mono);
  background: var(--bg3);
  border: 1px solid var(--accent);
  color: var(--accent);
  padding: 6px 12px;
  border-radius: 8px;
  cursor: pointer;
  white-space: nowrap;
  flex-shrink: 0;
}
.room-info-copy-btn:hover { background: #0d1a2e; }
.room-info-mods {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
.room-info-mod-tag {
  font-size: 11px;
  font-family: var(--mono);
  background: #1a2e0d;
  color: #4ade80;
  border: 1px solid #4ade8044;
  padding: 3px 10px;
  border-radius: 20px;
}

/* ── MESSAGE FRAME WRAP ──────────────────────────────────────────────────── */
/* Wraps avatar + bubble together when user has a frame equipped */
.msg-frame-wrap {
  display: flex;
  align-items: flex-end;
  gap: 10px;
  width: 100%;
}
.msg-frame-wrap.own-wrap {
  justify-content: flex-end;
}
.msg-frame-wrap.own-wrap .own-body {
  align-items: flex-end;
}

/* Frame around avatar */
.msg-has-frame {
  padding: 3px;
  border-radius: 13px;
  display: inline-block;
  flex-shrink: 0;
}
/* Bubble frame — frame border sits flush against the bubble edge (no gap),
   so the frame + bubble read as one continuous shape instead of "bubble
   inside a picture frame." Frame and bubble share the same radius so corners
   align. Avatar frames keep the .msg-has-frame default 3px padding above —
   only the bubble-specific wrapper removes it here. */
.msg-bubble-frame.msg-has-frame {
  padding: 0;
  border-radius: 10px;
}
.msg-bubble-frame .bubble {
  display: block;
  border-radius: 10px !important;
}

/* Tier 1 — Static */
.msg-frame-wrap.msg-has-frame.frame-neon   { border: 2px solid #00e5ff; box-shadow: 0 0 6px #00e5ff44; }
.msg-frame-wrap.msg-has-frame.frame-gold   { border: 2px solid #f59e0b; box-shadow: 0 0 6px #f59e0b44; }
.msg-frame-wrap.msg-has-frame.frame-blood  { border: 2px solid #cc0018; box-shadow: 0 0 6px #cc001844; }
.msg-frame-wrap.msg-has-frame.frame-arctic { border: 2px solid #bae6fd; box-shadow: 0 0 6px #bae6fd44; }

/* Tier 2 — Glow */
.msg-frame-wrap.msg-has-frame.frame-plasma  { border: 2px solid #00e5ff; box-shadow: 0 0 10px #00e5ff, 0 0 20px #00e5ff33; }
.msg-frame-wrap.msg-has-frame.frame-inferno { border: 2px solid #f97316; box-shadow: 0 0 10px #f97316, 0 0 20px #f9731633; }
.msg-frame-wrap.msg-has-frame.frame-void    { border: 2px solid #7c3aed; box-shadow: 0 0 10px #7c3aed, 0 0 20px #7c3aed33; }

/* Tier 3 — Animated */
.msg-frame-wrap.msg-has-frame.frame-pulse {
  border: 2px solid #00e5ff;
  animation: frame-pulse-anim 2.5s ease-in-out infinite;
}
.msg-frame-wrap.msg-has-frame.frame-prism {
  border: 2px solid #00e5ff;
  animation: frame-prism-anim 4s linear infinite;
}

/* ── PROFILE AVATAR GRID UPDATES ─────────────────────────────────────────── */
.av-card-equipped {
  font-size: 10px;
  font-family: var(--mono);
  color: var(--accent);
  letter-spacing: .5px;
  padding: 2px 0;
  text-align: center;
}
.av-card-equip-btn {
  font-size: 10px;
  font-family: var(--mono);
  color: var(--muted);
  letter-spacing: .5px;
  padding: 2px 0;
  text-align: center;
  cursor: pointer;
}
.av-card-equip-btn:hover { color: var(--accent); }

/* ── PURGATORY CHAT ──────────────────────────────────────────────────────── */
.purgatory-chat-wrap {
  position: absolute;
  bottom: 0; left: 0; right: 0;
  height: 260px;
  background: #0a080f;
  border-top: 1px solid #cc001844;
  display: flex;
  flex-direction: column;
  z-index: 2;
}
.purgatory-chat-header {
  font-size: 11px;
  font-family: var(--mono);
  color: #cc0018;
  letter-spacing: 1.5px;
  text-transform: uppercase;
  padding: 8px 14px;
  border-bottom: 1px solid #cc001822;
  flex-shrink: 0;
}
.purgatory-messages {
  flex: 1;
  overflow-y: auto;
  padding: 8px 14px;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.purgatory-msg {
  font-size: 13px;
  line-height: 1.4;
  color: #9ca3af;
}
.purgatory-msg-user {
  font-family: var(--mono);
  font-size: 11px;
  color: #cc0018;
  margin-right: 4px;
}
.purgatory-msg-mine { color: #f97316; }
.purgatory-msg-content { color: #d1d5db; }
.purgatory-composer {
  display: flex;
  gap: 8px;
  padding: 8px 12px;
  border-top: 1px solid #cc001822;
  flex-shrink: 0;
}
.purgatory-composer input {
  flex: 1;
  background: #150a0a;
  border: 1px solid #cc001844;
  border-radius: 8px;
  padding: 8px 12px;
  color: #e2e8f0;
  font-size: 13px;
  outline: none;
}
.purgatory-composer button {
  background: #cc0018;
  border: none;
  border-radius: 8px;
  color: #fff;
  padding: 8px 14px;
  cursor: pointer;
  font-size: 14px;
}

/* ── PURGATORY AVATAR STAMP ──────────────────────────────────────────────── */
.av-wrap { position: relative; display: inline-block; }
.av-purgatory-stamp {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(204, 0, 24, 0.18);
  border-radius: inherit;
  overflow: hidden;
  pointer-events: none;
}
.av-purgatory-stamp::before {
  content: 'PURGATORY';
  position: absolute;
  font-family: 'Courier New', monospace;
  font-weight: 900;
  font-size: 8px;
  letter-spacing: 1px;
  color: #cc0018;
  border: 1.5px solid #cc0018;
  padding: 2px 4px;
  border-radius: 2px;
  transform: rotate(-25deg);
  opacity: 0.9;
  white-space: nowrap;
  text-transform: uppercase;
  box-shadow: 0 0 6px rgba(204,0,24,.4);
}
/* Larger stamp for bigger avatars (profile preview etc) */
.av-purgatory-stamp[style*="width:1"] {
  font-size: 12px;
}

/* Appeal code button in user popup */
.user-popup-mod-btn.mod-btn-appeal {
  background: rgba(74, 222, 128, .12);
  border: 1px solid rgba(74, 222, 128, .3);
  color: #4ade80;
  width: 100%;
  margin-top: 4px;
}
.user-popup-mod-btn.mod-btn-appeal:hover {
  background: rgba(74, 222, 128, .22);
}

/* Room share link in chat */
.room-share-link {
  display: inline-block;
  color: var(--accent);
  text-decoration: none;
  background: rgba(var(--accent-rgb),.08);
  border: 1px solid rgba(var(--accent-rgb),.2);
  padding: 4px 10px;
  border-radius: 6px;
  font-family: var(--mono);
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
  /* Defensive: in case any future variant produces a long label, wrap it
     instead of letting the bubble overflow and clip the right side. */
  word-break: break-word;
  overflow-wrap: anywhere;
  max-width: 100%;
  /* Mobile tap target: comfortable to hit without missing. */
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
}
.room-share-link:hover, .room-share-link:active {
  background: rgba(var(--accent-rgb),.15);
}

/* Room code clickable hover state */
.room-info-code:hover {
  background: rgba(var(--accent-rgb),.1);
  border-color: var(--accent);
}

/* Avatar tier label in shop grid */
.av-tier-lbl {
  grid-column: 1 / -1;
  font-size: 10px;
  font-family: var(--mono);
  color: var(--muted);
  letter-spacing: 1px;
  text-transform: uppercase;
  padding: 8px 0 4px;
  border-top: 1px solid var(--border);
  margin-top: 4px;
}
.av-tier-lbl:first-child { border-top: none; margin-top: 0; }

/* Per-tier avatar grid — inner grid only, outer container is block */
#shop-av-grid, #divinity-av-grid { display: block !important; }
.av-tier-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 10px;
  margin-bottom: 8px;
}

/* ── HOME VIEW ── */
#view-home {
  display: flex;
  flex-direction: column;
  height: 100%;
  background: var(--bg);
  overflow: hidden;
}
.home-header {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 16px 10px;
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}

.home-compose-btn {
  width: 36px;
  height: 36px;
  border-radius: 10px;
  border: 1px solid var(--border);
  background: transparent;
  color: var(--accent);
  font-size: 16px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background .15s;
}
.home-compose-btn:hover { background: rgba(var(--accent-rgb),.08); }
.home-search-wrap {
  padding: 10px 16px;
  flex-shrink: 0;
}
.home-search {
  width: 100%;
  padding: 10px 14px;
  border-radius: 12px;
  border: 1px solid var(--border);
  background: var(--bg2);
  color: var(--text);
  font-size: 14px;
  font-family: var(--font);
  outline: none;
  box-sizing: border-box;
  transition: border-color .15s;
}
.home-search:focus { border-color: var(--accent); }
.home-room-list {
  flex: 1;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  /* Cards: add breathing room around the list and consistent gap between rows */
  padding: 8px 10px 12px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.home-room-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 14px;
  /* Card treatment — bordered rounded rectangle, matches bubble shape language */
  background: var(--bg2);
  border: 1px solid var(--border);
  border-radius: 12px;
  cursor: pointer;
  transition: background .1s, border-color .12s, transform .05s;
}
.home-room-row:hover { border-color: rgba(var(--accent-rgb), 0.28); }
.home-room-row:active {
  background: var(--bg3);
  transform: scale(0.995);
}
.home-room-icon {
  width: 48px;
  height: 48px;
  border-radius: 14px;
  background: var(--bg3);
  border: 1px solid var(--border);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 22px;
  flex-shrink: 0;
}
.home-room-body { flex: 1; min-width: 0; }
.home-room-name-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  margin-bottom: 3px;
}
.home-room-name {
  font-size: 14px;
  font-weight: 700;
  font-family: var(--mono);
  color: var(--text);
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  max-width: 200px;
}
.home-room-time {
  font-size: 11px;
  color: var(--muted);
  flex-shrink: 0;
  margin-left: 8px;
}
.home-room-preview {
  font-size: 12px;
  color: var(--muted);
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}
.home-room-preview .preview-user { color: var(--accent); font-weight: 600; }
.home-unread {
  background: var(--red);
  color: #fff;
  font-size: 10px;
  font-family: var(--mono);
  font-weight: 700;
  padding: 2px 7px;
  border-radius: 20px;
  min-width: 20px;
  text-align: center;
  flex-shrink: 0;
}

/* Activity dot for room tiles on the Rooms page. Same semantics as
   .ds-chat-activity-dot in the My Chats sidebar — appears when has_new
   from the API is true and the room isn't currently active. Sits in the
   .home-room-meta column alongside the timestamp. */
.home-activity-dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--accent);
  flex-shrink: 0;
  align-self: center;
}

/* ── BUBBLE CONTEXT MENU ── */
#bubble-menu-overlay { touch-action: none; }

/* ── REPLY BANNER ── */
#reply-banner {
  padding: 8px 12px;
  background: var(--bg3);
  border-top: 2px solid var(--accent);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  font-size: 12px;
  color: var(--muted);
  flex-shrink: 0;
  animation: slideUpIn .15s ease;
}
@keyframes slideUpIn {
  from { transform: translateY(100%); opacity: 0; }
  to   { transform: translateY(0);    opacity: 1; }
}

/* ── GIFT MESSAGE ── */
.gift-msg {
  display: flex;
  align-items: center;
  gap: 10px;
  background: var(--bg3);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 8px 12px;
  max-width: 260px;
}
.gift-msg-img {
  width: 48px;
  height: 48px;
  border-radius: 8px;
  object-fit: contain;
  flex-shrink: 0;
}
.gift-msg-text {
  font-size: 12px;
  color: var(--muted);
  font-family: var(--mono);
  line-height: 1.5;
}
.gift-msg-sender  { color: var(--accent); font-weight: 700; }
.gift-msg-name    { color: var(--text);   font-weight: 700; }
.gift-msg-recipient { color: var(--accent); font-weight: 700; }

/* ── ROOM SETTINGS TOGGLES ── */
.room-setting-toggle {
  padding: 4px 14px;
  border-radius: 20px;
  border: 1px solid var(--border);
  background: var(--bg);
  color: var(--muted);
  font-size: 11px;
  font-weight: 700;
  font-family: var(--mono);
  cursor: pointer;
  transition: background .15s, color .15s, border-color .15s;
  min-width: 44px;
}
.room-setting-toggle.on {
  background: var(--accent);
  color: #000;
  border-color: var(--accent);
}
.room-setting-toggle:disabled {
  opacity: 0.35;
  cursor: not-allowed;
}

/* ── VOICE RECORD BUTTON ── */
#voice-record-btn.recording {
  color: var(--red);
  animation: pulse-rec 1s ease-in-out infinite;
}
@keyframes pulse-rec {
  0%, 100% { opacity: 1; }
  50%       { opacity: 0.4; }
}

/* ── VOICE MESSAGE CARD ── */
.voice-msg {
  display: flex;
  align-items: center;
  gap: 8px;
  background: var(--bg3);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 8px 12px;
  max-width: 240px;
}
.voice-play-btn {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: var(--accent);
  color: #000;
  border: none;
  font-size: 12px;
  cursor: pointer;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}
.voice-waveform {
  flex: 1;
  height: 4px;
  background: var(--border);
  border-radius: 2px;
  overflow: hidden;
}
.voice-progress {
  height: 100%;
  background: var(--accent);
  border-radius: 2px;
  transition: width .1s linear;
}
.voice-duration {
  font-size: 10px;
  font-family: var(--mono);
  color: var(--muted);
  flex-shrink: 0;
  min-width: 28px;
}

/* ── DM TOAST NOTIFICATION ── */
@keyframes slideDown {
  from { transform: translateX(-50%) translateY(-20px); opacity: 0; }
  to   { transform: translateX(-50%) translateY(0);    opacity: 1; }
}
@keyframes slideUpOut {
  from { transform: translateX(-50%) translateY(0);    opacity: 1; }
  to   { transform: translateX(-50%) translateY(-20px); opacity: 0; }
}

/* ── DIVINITY DM TOAST (cyberpunk hologram) ────────────────────────────
   Adds a .dm-toast-divinity modifier class on top of the base .dm-toast.
   The base toast keeps its layout (top-center, avatar+username+preview,
   close button) but gets:
     • Translucent multi-color edge (chromatic shift)
     • Subtle horizontal scanlines overlay
     • Glitch-in entrance (replaces slideDown for Divinity users)
     • Faint chromatic aberration on text (red/cyan offset shadows)
   Everything is a visual-only overlay — the click target and DOM stay
   identical to the base toast so all the existing tap-to-open behavior
   continues to work. */
.dm-toast-divinity {
  background: linear-gradient(135deg, rgba(15, 10, 25, 0.78), rgba(30, 15, 45, 0.78)) !important;
  border: 1.5px solid !important;
  /* Multi-color border: cyan → violet → magenta → amber. The gradient is
     applied via border-image so each edge picks up a slightly different
     hue, giving the chromatic-shift hologram look. */
  border-image: linear-gradient(135deg, #22d3ee, #a78bfa, #f0abfc, #f59e0b) 1 !important;
  /* Layered glow: tight inner cyan, soft violet bloom, dark drop for
     contrast against light backgrounds behind the toast. */
  box-shadow:
    0 0 0 1px rgba(34, 211, 238, 0.25),
    0 0 18px rgba(167, 139, 250, 0.35),
    0 4px 24px rgba(0, 0, 0, 0.6) !important;
  backdrop-filter: blur(4px) saturate(1.4);
  -webkit-backdrop-filter: blur(4px) saturate(1.4);
  position: relative;
  /* Override the slideDown entrance with the glitch-in. The base style
     sets animation:slideDown .2s ease via inline style; we win via the
     more-specific selector + !important so the divinity variant gets
     the materialize effect instead. */
  animation: divinityToastGlitchIn 0.45s steps(6, end) !important;
  overflow: hidden;
}

/* Subtle scanline texture — faint horizontal lines layered over the
   toast body. ::before pseudo so it doesn't interfere with the existing
   inner content layout. pointer-events:none so taps still pass through
   to the underlying toast. */
.dm-toast-divinity::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image: repeating-linear-gradient(
    to bottom,
    transparent 0,
    transparent 2px,
    rgba(34, 211, 238, 0.06) 2px,
    rgba(34, 211, 238, 0.06) 3px
  );
  pointer-events: none;
  border-radius: inherit;
  mix-blend-mode: screen;
}

/* Chromatic aberration on text — split red/cyan shadow gives the
   "this is being projected, not printed" vibe. Applied to all text
   inside the toast via descendant selector; the actual glow color
   stays cyan via the base color. */
.dm-toast-divinity > div:not(:first-child) {
  text-shadow:
    -0.5px 0 0 rgba(244, 63, 94, 0.55),
    0.5px 0 0 rgba(34, 211, 238, 0.55);
}

/* Glitch-in entrance — the toast materializes via several quick clip
   reveals + slight position jitter, simulating a CRT/hologram boot. The
   steps(6,end) timing on the animation property ensures the keyframes
   land discretely rather than smoothly interpolating, which is what
   makes it read as "glitchy" rather than "slidey." */
@keyframes divinityToastGlitchIn {
  0%   { opacity: 0; clip-path: inset(0 0 100% 0); transform: translateX(-50%) translateY(0); }
  20%  { opacity: 0.4; clip-path: inset(0 0 60% 0); transform: translateX(-49%) translateY(-2px); }
  35%  { opacity: 0.7; clip-path: inset(0 0 0 0);   transform: translateX(-51%) translateY(1px); }
  50%  { opacity: 0.4; clip-path: inset(40% 0 0 0); transform: translateX(-50%) translateY(-1px); }
  65%  { opacity: 0.85; clip-path: inset(0 0 0 0);  transform: translateX(-50%) translateY(0); }
  80%  { opacity: 0.6; clip-path: inset(0 30% 0 0); transform: translateX(-49.5%) translateY(0); }
  100% { opacity: 1; clip-path: inset(0 0 0 0);     transform: translateX(-50%) translateY(0); }
}

/* ── DIVINITY FLOATING DM ICON ─────────────────────────────────────────
   Subtle pulse — scale gently breathes between 1.0 and ~1.06, with the
   glow intensifying on the upbeat. Slow enough (2.4s) that it's a
   "premium ambient" cue rather than an alarm. */
@keyframes divinityDmPulse {
  0%, 100% {
    transform: scale(1);
    box-shadow:
      0 0 0 1px rgba(34, 211, 238, 0.3),
      0 0 14px rgba(167, 139, 250, 0.4),
      0 4px 16px rgba(0, 0, 0, 0.5);
  }
  50% {
    transform: scale(1.06);
    box-shadow:
      0 0 0 1px rgba(34, 211, 238, 0.5),
      0 0 22px rgba(167, 139, 250, 0.65),
      0 4px 18px rgba(0, 0, 0, 0.5);
  }
}

#divinity-dm-float:hover {
  /* Pause the pulse on hover so it's easier to read the badge count and
     tap precisely. The base styling (border, glow) stays as the resting
     state of the keyframe, so the icon doesn't visually "drop" on hover. */
  animation-play-state: paused;
  filter: brightness(1.15);
}

#divinity-dm-float:active {
  transform: scale(0.96);
  animation-play-state: paused;
}

/* ── REACTIONS ── */
/* The reaction bar sits inside .msg-frame-wrap as a flex sibling of .msg-body.
   own-wrap is row-reverse so the bar (inserted first) renders to the right of the
   avatar and to the left of the bubble — i.e. toward the center of the chat.
   others-wrap is row so the bar (appended last) renders to the right of the
   bubble — also toward the center. */
.reaction-bar {
  display: grid;
  grid-template-columns: repeat(2, auto);
  gap: 3px;
  align-self: flex-end;      /* sit at bottom of the flex row */
  flex-shrink: 0;
  padding-bottom: 2px;
}
.reaction-pill {
  display: flex;
  align-items: center;
  gap: 3px;
  padding: 2px 8px;
  background: var(--bg3);
  border: 1px solid var(--border);
  border-radius: 20px;
  font-size: 14px;
  cursor: pointer;
  transition: border-color .15s, background .15s, transform .1s;
  color: var(--text);
}
.reaction-pill span {
  font-size: 11px;
  font-family: var(--mono);
  color: var(--muted);
}
.reaction-pill.by-me {
  background: rgba(var(--accent-rgb),.1);
  border-color: var(--accent);
}
.reaction-pill.by-me span { color: var(--accent); }
.reaction-pill:active { transform: scale(.9); }

/* Quick heart button — floats beside bubble */
.bubble-heart {
  position: absolute;
  bottom: -8px;
  right: -8px;
  background: var(--bg2);
  border: 1.5px solid var(--border);
  border-radius: 50%;
  font-size: 12px;
  cursor: pointer;
  opacity: 0.35;
  transition: opacity .15s, transform .2s, background .15s;
  padding: 3px 4px;
  line-height: 1;
  z-index: 5;
  box-shadow: 0 2px 6px rgba(0,0,0,.4);
}
.msg:hover .bubble-heart,
.msg-body:hover .bubble-heart { opacity: 1; }
.bubble-heart:active { transform: scale(1.3); }
.bubble-heart.bubble-heart-active {
  opacity: 1;
  background: rgba(255,60,100,.2);
  border-color: rgba(255,60,100,.6);
  color: #ff3c64;
}
.msg { position: relative; }

.bubble-delete {
  position: absolute;
  top: -8px;
  right: -8px;
  background: var(--bg2);
  border: 1.5px solid var(--border);
  border-radius: 50%;
  font-size: 11px;
  cursor: pointer;
  opacity: 0.35;
  transition: opacity .15s, transform .2s, background .15s, border-color .15s, color .15s;
  padding: 3px 4px;
  line-height: 1;
  z-index: 5;
  box-shadow: 0 2px 6px rgba(0,0,0,.4);
  color: var(--muted);
}
.msg:hover .bubble-delete,
.msg-body:hover .bubble-delete { opacity: 1; }
.bubble-delete:hover {
  background: rgba(255,60,60,.15);
  border-color: rgba(255,60,60,.5);
  color: #ff6464;
}
.bubble-delete:active { transform: scale(1.15); }

/* On touch-primary devices (mobile, tablets), hover never fires so the
   icons would otherwise stay dim. Bump opacity so they're reliably
   tappable without needing a long-press to discover them. */
@media (hover: none) {
  .bubble-delete { opacity: 0.7; }
  .bubble-heart { opacity: 0.7; }
}

/* ── USER SEARCH MODAL ── */
.modal-overlay {
  position: fixed; inset: 0;
  background: rgba(0,0,0,.6);
  z-index: 450;
}
.search-modal {
  position: fixed;
  top: 60px; left: 50%; transform: translateX(-50%);
  width: min(480px, 94vw);
  background: var(--bg2);
  border: 1px solid var(--border);
  border-radius: 16px;
  z-index: 451;
  display: flex;
  flex-direction: column;
  max-height: 70vh;
  box-shadow: 0 8px 40px rgba(0,0,0,.6);
}
.search-modal-head {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 12px 14px;
  border-bottom: 1px solid var(--border);
}
.search-modal-head input {
  flex: 1;
  background: var(--bg3);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 9px 12px;
  color: var(--text);
  font-family: var(--mono);
  font-size: 14px;
  outline: none;
}
.search-modal-head input:focus { border-color: var(--accent); }
.search-close-btn {
  background: none; border: none;
  color: var(--muted); font-size: 18px; cursor: pointer; padding: 4px;
}
.search-results { overflow-y: auto; padding: 8px 0; }
.search-result-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 14px;
  cursor: pointer;
  transition: background .12s;
}
.search-result-row:hover { background: var(--bg3); }
.search-result-av {
  width: 38px; height: 38px;
  border-radius: 10px;
  background: var(--bg3);
  border: 2px solid var(--border);
  overflow: hidden; flex-shrink: 0;
}
.search-result-info { flex: 1; min-width: 0; }
.search-result-name {
  font-family: var(--mono); font-size: 13px;
  font-weight: 700; color: var(--text);
}
.search-result-meta { font-size: 11px; color: var(--muted); margin-top: 1px; }
.search-online-dot {
  width: 8px; height: 8px; border-radius: 50%;
  background: #4ade80; flex-shrink: 0;
}
.search-empty {
  text-align: center; color: var(--muted);
  font-size: 13px; padding: 28px 16px;
  font-family: var(--mono);
}

/* ── MOD DASHBOARD ── */
.moddash-tab {
  flex: 1; padding: 10px 0;
  background: none; border: none;
  color: var(--muted);
  font-family: var(--mono); font-size: 12px;
  cursor: pointer; border-bottom: 2px solid transparent;
  transition: color .15s, border-color .15s;
}
.moddash-tab.active { color: var(--accent); border-bottom-color: var(--accent); }
.md-section-lbl {
  font-family: var(--mono); font-size: 11px; font-weight: 700;
  color: var(--muted); letter-spacing: .08em;
  text-transform: uppercase; margin: 16px 0 8px;
}
.md-user-row {
  display: flex; align-items: center; gap: 10px;
  padding: 9px 10px; border-radius: 10px;
  cursor: pointer; transition: background .12s;
  border: 1px solid transparent;
}
.md-user-row:hover { background: var(--bg3); border-color: var(--border); }
.md-user-info { flex: 1; min-width: 0; }
.md-user-name { font-family: var(--mono); font-size: 13px; font-weight: 700; }
.md-user-meta { font-size: 11px; color: var(--muted); }
.md-actions { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 6px; }
.md-btn {
  padding: 5px 12px; border-radius: 8px;
  font-family: var(--mono); font-size: 11px; font-weight: 700;
  cursor: pointer; border: 1px solid var(--border);
  background: var(--bg3); color: var(--text);
  transition: background .12s;
}
.md-btn:hover { background: var(--bg2); }
.md-btn.danger { color: #f87171; border-color: #f87171; }
.md-btn.danger:hover { background: rgba(248,113,113,.1); }
.md-btn.success { color: #4ade80; border-color: #4ade80; }
.md-report-card {
  background: var(--bg3); border: 1px solid var(--border);
  border-radius: 12px; padding: 12px; margin-bottom: 8px;
}
.md-report-type {
  font-family: var(--mono); font-size: 11px; font-weight: 700;
  color: var(--accent); text-transform: uppercase; margin-bottom: 4px;
}
.md-report-detail { font-size: 12px; color: var(--muted); margin-bottom: 8px; }
.md-log-row {
  padding: 8px 10px; border-bottom: 1px solid var(--border);
  font-size: 12px; color: var(--muted); font-family: var(--mono);
}
.md-log-row strong { color: var(--text); }
.md-search-bar {
  width: 100%; padding: 9px 12px; margin-bottom: 12px;
  background: var(--bg3); border: 1px solid var(--border);
  border-radius: 10px; color: var(--text);
  font-family: var(--mono); font-size: 13px; outline: none;
  box-sizing: border-box;
}
.md-search-bar:focus { border-color: var(--accent); }
.md-owner-card {
  background: var(--bg3); border: 1px solid var(--border);
  border-radius: 12px; padding: 14px; margin-bottom: 12px;
}
.md-owner-stat { font-size: 12px; color: var(--muted); margin: 3px 0; }
.md-owner-stat strong { color: var(--text); }

/* Edited message flag */
.edited-flag {
  font-size: 10px;
  color: var(--muted);
  font-family: var(--mono);
  opacity: 0.7;
  margin-left: 4px;
  font-weight: 400;
  font-style: italic;
}

/* View back button */
/* GIF composer button */
.composer-btn[onclick*="openGiphyPicker"] {
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 800;
  color: var(--accent);
  letter-spacing: .05em;
  padding: 4px 6px;
}

/* ── REPLY QUOTE BLOCK ── */
.reply-quote {
  background: rgba(0,0,0,.25);
  border-left: 3px solid var(--accent);
  border-radius: 4px 6px 6px 4px;
  padding: 5px 9px;
  margin-bottom: 6px;
  max-width: 100%;
}
.reply-quote-author {
  font-size: 11px;
  font-weight: 700;
  color: var(--accent);
  font-family: var(--mono);
  margin-bottom: 2px;
  opacity: 0.9;
}
.reply-quote-text {
  font-size: 12px;
  color: var(--muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 240px;
  font-style: italic;
}
.reply-body {
  margin-top: 2px;
}

/* Bubbles containing media/GIFs fill their max-width naturally */
.bubble:has(.msg-gif),
.bubble:has(.msg-media-img) {
  display: block;
  padding: 4px;
}

/* High-Z pin-up icon — tint to match nav button state */
.bnav-btn #bnav-highz .nav-ico svg,
#bnav-highz .nav-ico svg path,
#bnav-highz .nav-ico svg ellipse {
  transition: opacity .15s;
}
#bnav-highz .nav-ico { display: flex; align-items: center; justify-content: center; }

/* Cyberpunk nav icons — inherit button color for active/muted states */
.bnav-btn .nav-ico svg {
  color: inherit;
}
.bnav-btn .nav-ico svg circle[fill="currentColor"] {
  fill: currentColor;
}

/* ── DIVINITY NAV — center position when active ── */
.bnav-divinity-btn {
  position: relative;
}
.bnav-divinity-btn[style*="display:flex"],
.bnav-divinity-btn:not([style*="display:none"]) {
  color: var(--accent);
}

/* ── FLOATING AVATAR in top nav ── */
.tnav-profile-btn {
  padding: 0 10px;
  min-width: unset;
  border-bottom: none !important;
  position: relative;
  z-index: 10;
}
.tnav-av {
  width: 40px;
  height: 40px;
  border-radius: 12px;
  overflow: hidden;
  border: 2px solid var(--accent);
  background: var(--bg3);
  transition: border-color .15s, transform .15s, box-shadow .15s;
  display: flex;
  align-items: center;
  justify-content: center;
  /* Sized to leave 6px breathing room inside the 52px nav. Still visibly
     larger than the 22px side icons so it reads as the anchor. */
  box-shadow: 0 3px 8px rgba(var(--accent-rgb),.22), 0 1px 4px rgba(0,0,0,.4);
  position: relative;
}
.tnav-av img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  border-radius: 10px;
}
.tnav-profile-btn:hover .tnav-av,
.tnav-profile-btn.active .tnav-av {
  border-color: var(--accent);
  box-shadow: 0 4px 14px rgba(var(--accent-rgb),.38), 0 2px 8px rgba(0,0,0,.55);
  transform: scale(1.04);
}

/* ── CUSTOMIZATIONS DRAWER ────────────────────────────────────────────
   Horizontal scroll wheels for each owned-item category. One section
   per category; each section has a label, a horizontal scroll container
   with snap points, and item cards. Active item is highlighted with
   accent border. */

.cust-section { margin: 4px 0 22px; }
.cust-section-lbl {
  font-size: 11px;
  font-weight: 700;
  font-family: var(--mono);
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: .08em;
  padding: 0 16px 8px;
}
.cust-section-sub {
  font-size: 11px;
  color: var(--muted);
  padding: 0 16px 10px;
  line-height: 1.45;
}
.cust-scroll {
  display: flex;
  gap: 10px;
  overflow-x: auto;
  overflow-y: hidden;
  -webkit-overflow-scrolling: touch;
  scroll-snap-type: x mandatory;
  padding: 4px 16px 14px;
  scrollbar-width: thin;
}
.cust-scroll::-webkit-scrollbar { height: 4px; }
.cust-scroll::-webkit-scrollbar-thumb { background: var(--bg3); border-radius: 2px; }

/* Generic item card — used by all scroll wheels for consistent sizing */
.cust-item {
  flex: 0 0 auto;
  scroll-snap-align: start;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  padding: 10px 8px;
  border-radius: 12px;
  border: 2px solid var(--border);
  background: var(--bg2);
  cursor: pointer;
  transition: border-color .15s, transform .1s, background .15s;
  min-width: 78px;
  -webkit-tap-highlight-color: transparent;
}
.cust-item:hover { border-color: rgba(var(--accent-rgb), .35); }
.cust-item:active { transform: scale(0.97); }
.cust-item.active {
  border-color: var(--accent);
  background: var(--bg3);
  box-shadow: 0 2px 10px rgba(var(--accent-rgb), .25);
}
.cust-item-preview {
  width: 56px;
  height: 56px;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
.cust-item-preview img {
  width: 56px;
  height: 56px;
  object-fit: cover;
  border-radius: 10px;
  display: block;
}
.cust-item-label {
  font-size: 10px;
  font-family: var(--mono);
  color: var(--muted);
  text-align: center;
  max-width: 72px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.cust-item.active .cust-item-label { color: var(--accent); font-weight: 700; }
.cust-item-badge {
  font-size: 9px;
  color: var(--accent);
  font-family: var(--mono);
  font-weight: 700;
  margin-top: 2px;
  opacity: 0;
  transition: opacity .15s;
}
.cust-item.active .cust-item-badge { opacity: 1; }

/* Bubble color swatch — square with gradient matching the palette */
.cust-bubble-swatch {
  width: 56px;
  height: 40px;
  border-radius: 10px;
  border: 1.5px solid var(--border);
}
/* Text color swatch — shows a sample letter in the color */
.cust-text-swatch {
  width: 56px;
  height: 40px;
  border-radius: 10px;
  background: var(--bg3);
  border: 1.5px solid var(--border);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 22px;
  font-weight: 800;
  font-family: var(--mono);
}
/* Theme swatch — circular gradient of the theme's bg + accent */
.cust-theme-swatch {
  width: 56px;
  height: 56px;
  border-radius: 50%;
  border: 1.5px solid var(--border);
  position: relative;
  overflow: hidden;
}
.cust-theme-swatch::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(135deg, var(--sw-bg) 0%, var(--sw-bg2) 60%, var(--sw-accent) 100%);
}

/* "None" / "Default" tile — dashed ring so users can tell it's the absence of a choice */
.cust-item-none .cust-item-preview,
.cust-item-none .cust-bubble-swatch,
.cust-item-none .cust-text-swatch {
  border: 1.5px dashed var(--border);
  background: var(--bg3);
  color: var(--muted);
}

/* Customize button on Profile */
.profile-customize-btn {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: calc(100% - 32px);
  margin: 0 16px 16px;
  padding: 14px 16px;
  background: var(--bg2);
  border: 1px solid var(--border);
  border-radius: 12px;
  cursor: pointer;
  transition: border-color .12s, background .12s;
  color: var(--text);
  font-family: var(--mono);
  font-size: 14px;
  font-weight: 700;
}
.profile-customize-btn:hover { border-color: rgba(var(--accent-rgb), .4); background: var(--bg3); }
.profile-customize-btn:active { transform: scale(0.99); }
.profile-customize-btn .pcb-arrow { color: var(--muted); font-size: 18px; }
.profile-customize-btn .pcb-icon { font-size: 18px; margin-right: 10px; }

/* Empty-state inside a scroll wheel */
.cust-empty {
  font-size: 11px;
  font-family: var(--mono);
  color: var(--muted);
  padding: 14px 16px 18px;
}

/* "Get more" CTA card inside a wheel */
.cust-get-more {
  flex: 0 0 auto;
  scroll-snap-align: start;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 10px 8px;
  border-radius: 12px;
  border: 1.5px dashed rgba(var(--accent-rgb), .4);
  background: transparent;
  color: var(--accent);
  cursor: pointer;
  min-width: 78px;
  font-family: var(--mono);
  font-size: 10px;
  transition: background .12s;
}
.cust-get-more:hover { background: rgba(var(--accent-rgb), .08); }
.cust-get-more-icon { font-size: 22px; line-height: 1; }

/* ── BALANCE STACK (Profile) ────────────────────────────────────────
   OTGCreds sits diagonally up-right behind Tokens at 70% opacity.
   Tokens dominate visually; cR suggests a premium layer behind.
   Only visible when the user has a non-zero cR balance (buildProfile
   conditionally renders the cR element). */
.av-balance-stack {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 6px;
  margin-top: 6px;
}
.av-balance-stack .av-token-bal {
  font-family: var(--mono);
  font-size: 14px;
  font-weight: 700;
  color: var(--text);
  background: var(--bg3);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 6px 12px;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  letter-spacing: .3px;
  transition: background .12s, border-color .12s;
}
.av-balance-stack .av-token-bal:hover {
  background: var(--bg4);
  border-color: rgba(var(--accent-rgb), .35);
}
.av-balance-stack .av-creds-bal {
  font-family: var(--mono);
  font-size: 14px;
  font-weight: 700;
  color: #fef3c7;
  background: linear-gradient(135deg, rgba(124,58,237,0.28), rgba(225,29,72,0.22));
  border: 1px solid rgba(251,191,36,0.45);
  border-radius: 10px;
  padding: 6px 12px;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  letter-spacing: .3px;
  box-shadow: 0 2px 8px rgba(124,58,237,0.18);
}
/* Currency icons in the balance pills. OTGCreds is slightly larger
   (28px vs 24px) so the premium chip reads as a hair more prominent
   without breaking the matched-pill visual balance. */
.av-balance-stack .icon-token {
  width: 24px;
  height: 24px;
  vertical-align: middle;
  flex-shrink: 0;
}
.av-balance-stack .icon-creds {
  width: 28px;
  height: 28px;
  vertical-align: middle;
  flex-shrink: 0;
}

/* ── DUAL-CURRENCY PURCHASE BUTTONS ────────────────────────────────────
   Two-button row for items payable in either ⬡ tokens or cR OTGCreds.
   The cR button gets a subtle gradient hint to signal premium currency
   without overwhelming the primary-currency button. */
.frame-btn-pair {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
  justify-content: flex-end;
}
.frame-btn-cr {
  background: linear-gradient(135deg, rgba(124,58,237,0.18), rgba(225,29,72,0.15));
  border-color: rgba(var(--accent-rgb), 0.35);
}
.frame-btn-cr:hover {
  background: linear-gradient(135deg, rgba(124,58,237,0.28), rgba(225,29,72,0.22));
}
.frame-btn-dim {
  opacity: 0.45;
  pointer-events: none;
}

/* ── OTGCREDS BUNDLES ──────────────────────────────────────────────────
   Grid of purchase tiers for the premium currency. Responsive: 2 cols
   on narrow viewports, 3 on wider. Featured tier ("Most Popular") has
   an accent ring. Each card is absolutely positioned relative to the
   wrapper so the coming-soon banner can overlay the whole grid until
   Stripe lands. */
.creds-bundle-wrap { margin-bottom: 8px; }
.creds-bundle-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 10px;
}
@media (min-width: 600px) {
  .creds-bundle-grid { grid-template-columns: repeat(3, 1fr); }
}
.creds-bundle-card {
  position: relative;
  background: var(--bg2);
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 16px 12px 14px;
  text-align: center;
  cursor: pointer;
  transition: border-color .15s, transform .1s, background .15s;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  flex: 0 0 auto;
  scroll-snap-align: start;
  min-width: 140px;
  overflow: hidden;
}
.creds-bundle-card:hover {
  border-color: rgba(56, 189, 248, 0.4);
  background: var(--bg3);
}
.creds-bundle-card:active { transform: scale(0.98); }

/* Featured tier — "Most Popular" */
.creds-bundle-featured {
  border-color: rgba(56, 189, 248, 0.5);
  background: linear-gradient(135deg, rgba(124,58,237,0.10), rgba(56,189,248,0.08)), var(--bg2);
}
.creds-bundle-badge {
  position: absolute;
  top: 6px;
  left: 50%;
  transform: translateX(-50%);
  background: var(--accent);
  color: var(--bg);
  font-size: 9px;
  font-family: var(--mono);
  font-weight: 800;
  letter-spacing: .08em;
  text-transform: uppercase;
  padding: 2px 10px;
  border-radius: 10px;
  white-space: nowrap;
}
.creds-bundle-featured .creds-bundle-amount { margin-top: 10px; }

/* Discount tag — top-right corner */
.creds-bundle-discount {
  position: absolute;
  top: 8px;
  right: 8px;
  background: linear-gradient(135deg, rgba(225,29,72,.35), rgba(124,58,237,.3));
  color: #fecaca;
  font-family: var(--mono);
  font-size: 10px;
  font-weight: 800;
  padding: 2px 7px;
  border-radius: 6px;
  border: 1px solid rgba(225,29,72,.35);
  letter-spacing: .05em;
}

/* Amount display — number + cR symbol side by side */
.creds-bundle-amount {
  display: flex;
  align-items: baseline;
  gap: 3px;
  justify-content: center;
  font-family: var(--mono);
}
.creds-bundle-num {
  font-size: 22px;
  font-weight: 800;
  color: var(--text);
  letter-spacing: -.5px;
}
.creds-bundle-sym {
  font-size: 13px;
  font-weight: 700;
  color: var(--accent);
}
.creds-bundle-price {
  font-size: 16px;
  font-weight: 700;
  color: var(--text);
  font-family: var(--mono);
  margin-top: 2px;
}
.creds-bundle-value {
  font-size: 10px;
  color: var(--muted);
  font-family: var(--mono);
  margin-top: 2px;
  letter-spacing: .03em;
}

/* Locked state: disables interaction; paired with an overlay banner */
.creds-bundle-locked {
  pointer-events: none;
  opacity: .6;
  filter: grayscale(30%);
}

/* Coming-soon banner — sits on top of the grid, centered, catches eye */
.creds-coming-soon-banner {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%) rotate(-3deg);
  background: linear-gradient(135deg, rgba(15,23,42,.94), rgba(30,41,59,.94));
  border: 2px solid var(--accent);
  color: var(--text);
  padding: 12px 22px;
  border-radius: 12px;
  font-family: var(--mono);
  font-weight: 800;
  font-size: 13px;
  letter-spacing: .06em;
  text-transform: uppercase;
  display: flex;
  align-items: center;
  gap: 10px;
  box-shadow: 0 8px 30px rgba(0,0,0,.5), 0 0 30px rgba(var(--accent-rgb), .25);
  pointer-events: none;
  z-index: 2;
  white-space: nowrap;
}
.creds-coming-soon-icon {
  font-size: 18px;
  animation: cr-banner-pulse 2.4s infinite ease-in-out;
}
@keyframes cr-banner-pulse {
  0%,100% { opacity: .5; transform: scale(1); }
  50%     { opacity: 1;  transform: scale(1.2); }
}

/* ── CURRENCY ICONS ───────────────────────────────────────────────────
   Two inline-displayable icon classes, used anywhere we want to show
   the currency images (balance displays, toasts, composer badges,
   store cards, etc.). Sized so they drop in next to text naturally at
   the current line's em-height. Use the -lg variants in larger UI
   slots (store cards, profile balance). */
.icon-token,
.icon-creds {
  display: inline-block;
  vertical-align: -0.18em;
  width: 1.1em;
  height: 1.1em;
  background-repeat: no-repeat;
  background-position: center;
  background-size: contain;
  flex-shrink: 0;
}
.icon-token { background-image: url('/assets/otgc-token.png?v=15.65'); }
.icon-creds { background-image: url('/assets/otgc-creds.png?v=15.65'); }

/* Larger variants — use these explicitly in store cards and profile.
   Scaled by font-size multipliers so they adapt to surrounding type. */
.icon-token-lg,
.icon-creds-lg {
  display: inline-block;
  width: 28px;
  height: 28px;
  background-repeat: no-repeat;
  background-position: center;
  background-size: contain;
  vertical-align: middle;
  flex-shrink: 0;
}
.icon-token-lg { background-image: url('/assets/otgc-token.png?v=15.65'); }
.icon-creds-lg { background-image: url('/assets/otgc-creds.png?v=15.65'); }

.icon-token-xl,
.icon-creds-xl {
  display: inline-block;
  width: 44px;
  height: 44px;
  background-repeat: no-repeat;
  background-position: center;
  background-size: contain;
  vertical-align: middle;
  flex-shrink: 0;
}
.icon-token-xl { background-image: url('/assets/otgc-token.png?v=15.65'); }
.icon-creds-xl { background-image: url('/assets/otgc-creds.png?v=15.65'); }

/* ── STORE BUNDLE CHIP DISPLAY ────────────────────────────────────────
   Each OTGCreds bundle card now shows the cR chip image as a large
   visual anchor with the amount overlapping its bottom-right corner.
   Replaces the previous inline-icon + number layout. */
.bundle-chip-wrap {
  position: relative;
  width: 110px;
  height: 110px;
  margin: 8px auto 6px;
  display: block;
}
.bundle-chip {
  display: block;
  width: 100%;
  height: 100%;
  background-image: url('/assets/otgc-creds.png?v=15.65');
  background-size: contain;
  background-position: center;
  background-repeat: no-repeat;
  filter: drop-shadow(0 6px 14px rgba(124, 58, 237, 0.3))
          drop-shadow(0 3px 6px rgba(0, 0, 0, 0.5));
  transition: transform 0.15s ease;
}
.creds-bundle-card:hover .bundle-chip {
  transform: scale(1.05) rotate(-2deg);
}
/* Amount label overlapping the chip at bottom-right.
   Gold-amber border + dark plate so the number is readable regardless
   of what's behind the translucent chip. Overlaps by ~25% so it looks
   like a label stuck to the chip, not floating separately. */
.bundle-chip-label {
  position: absolute;
  bottom: -6px;
  right: -8px;
  font-family: var(--mono);
  font-size: 13px;
  font-weight: 800;
  color: #fef3c7;
  background: linear-gradient(135deg, rgba(15, 23, 42, 0.94), rgba(30, 41, 59, 0.94));
  border: 1.5px solid rgba(251, 191, 36, 0.65);
  border-radius: 8px;
  padding: 4px 9px;
  letter-spacing: .3px;
  box-shadow: 0 3px 10px rgba(0, 0, 0, 0.55);
  white-space: nowrap;
  pointer-events: none;
}
/* Featured ("Most Popular") tier gets a slightly larger chip so it
   visually pops more than the others */
.creds-bundle-featured .bundle-chip-wrap {
  width: 124px;
  height: 124px;
}

/* ── BUBBLE COLOR DUAL-CURRENCY BUTTONS ────────────────────────────────
   Used in the Divinity bubble-color grid where each unowned palette
   gets a token-button + cR-button pair. Mirrors the .frame-btn-pair
   pattern but compact-sized to fit within each palette tile. */
.bubble-buy-btn {
  flex: 1;
  padding: 4px 0;
  border-radius: 6px;
  font-size: 10px;
  font-family: var(--mono);
  font-weight: 700;
  cursor: pointer;
  border: 1px solid rgba(0, 229, 255, .3);
  background: rgba(0, 229, 255, .1);
  color: var(--accent);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 4px;
  transition: background .12s, border-color .12s;
}
.bubble-buy-btn:hover { background: rgba(0, 229, 255, .18); }
.bubble-buy-btn .icon-token,
.bubble-buy-btn .icon-creds {
  width: 14px;
  height: 14px;
}
/* OTGCreds variant — premium gradient, gold edge */
.bubble-buy-btn.bubble-buy-cr {
  background: linear-gradient(135deg, rgba(124,58,237,0.18), rgba(225,29,72,0.15));
  border-color: rgba(251,191,36,0.4);
  color: #fef3c7;
}
.bubble-buy-btn.bubble-buy-cr:hover {
  background: linear-gradient(135deg, rgba(124,58,237,0.28), rgba(225,29,72,0.22));
}
/* Insufficient balance */
.bubble-buy-btn.bubble-buy-dim {
  opacity: .5;
  pointer-events: none;
}

/* ── AVATAR SHOP — TIER CONTAINERS ──────────────────────────────────────
   Collapsible rows by avatar rarity tier. Each container has:
   - A header (always visible) showing tier name, price range, count
   - An expandable body with a horizontally-scrolling list of cards
   The accent color (passed via --tier-color CSS var) tints the left
   edge and the chevron, giving each tier its own visual identity. */
.tier-container {
  border: 1px solid var(--border);
  border-left: 4px solid var(--tier-color, var(--accent));
  border-radius: 12px;
  background: var(--bg2);
  margin-bottom: 10px;
  overflow: hidden;
  transition: border-color .12s;
}
.tier-container:hover { border-color: var(--tier-color, var(--accent)); }
.tier-container.tier-empty {
  opacity: .5;
  border-left-color: var(--border);
}
.tier-container.tier-empty:hover { border-color: var(--border); }

.tier-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  padding: 14px 16px;
  background: transparent;
  border: none;
  color: var(--text);
  cursor: pointer;
  font-family: var(--mono);
  text-align: left;
  transition: background .12s;
}
.tier-header:hover { background: rgba(255, 255, 255, 0.03); }
.tier-empty .tier-header { cursor: default; }
.tier-empty .tier-header:hover { background: transparent; }

.tier-header-left {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.tier-name {
  font-size: 14px;
  font-weight: 800;
  color: var(--tier-color, var(--accent));
  letter-spacing: .06em;
  text-transform: uppercase;
}
.tier-empty .tier-name { color: var(--muted); }
.tier-range {
  font-size: 11px;
  color: var(--muted);
  letter-spacing: .03em;
}

.tier-header-right {
  display: flex;
  align-items: center;
  gap: 10px;
}
.tier-count {
  font-size: 11px;
  color: var(--muted);
  font-weight: 600;
}
.tier-chevron {
  font-size: 14px;
  color: var(--tier-color, var(--accent));
  transition: transform .18s;
  display: inline-block;
}
.tier-chevron.open { transform: rotate(90deg); }

/* Horizontal scroll container for avatar cards inside an expanded tier */
.tier-scroll {
  display: flex;
  gap: 12px;
  overflow-x: auto;
  overflow-y: hidden;
  -webkit-overflow-scrolling: touch;
  scroll-snap-type: x mandatory;
  padding: 0 16px 16px;
  scrollbar-width: thin;
}
.tier-scroll::-webkit-scrollbar { height: 4px; }
.tier-scroll::-webkit-scrollbar-thumb { background: var(--bg3); border-radius: 2px; }

/* Avatar card inside a tier scroller */
.av-tier-card {
  flex: 0 0 auto;
  scroll-snap-align: start;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  padding: 10px 8px;
  min-width: 96px;
  border-radius: 12px;
  background: var(--bg3);
  border: 2px solid var(--border);
  cursor: pointer;
  transition: border-color .12s, transform .1s;
  -webkit-tap-highlight-color: transparent;
}
.av-tier-card:hover { border-color: var(--tier-color, var(--accent)); }
.av-tier-card:active { transform: scale(0.97); }
.av-tier-card.active {
  border-color: #4ade80;
  box-shadow: 0 0 0 2px rgba(74, 222, 128, 0.25);
}
.av-tier-card.owned {
  border-color: rgba(56, 189, 248, 0.45);
}
.av-tier-card-img {
  width: 72px;
  height: 72px;
  border-radius: 50%;
  overflow: hidden;
  background: var(--bg);
}
.av-tier-card-img img,
.av-tier-card-img > div {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.av-tier-card-name {
  font-size: 11px;
  font-family: var(--mono);
  font-weight: 700;
  color: var(--text);
  letter-spacing: .04em;
  white-space: nowrap;
}
.av-tier-card-prices {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
}
.av-tier-card-price {
  font-size: 10px;
  font-family: var(--mono);
  font-weight: 700;
  color: var(--text);
  display: inline-flex;
  align-items: center;
  gap: 4px;
  white-space: nowrap;
}
.av-tier-card-price-cr {
  color: #fef3c7;
  opacity: .85;
}
.av-tier-card-price .icon-token,
.av-tier-card-price .icon-creds {
  width: 12px;
  height: 12px;
}
.av-tier-card-equipped {
  font-size: 10px;
  font-family: var(--mono);
  font-weight: 800;
  color: #4ade80;
  background: rgba(74, 222, 128, 0.12);
  border: 1px solid rgba(74, 222, 128, 0.4);
  border-radius: 6px;
  padding: 3px 8px;
  letter-spacing: .04em;
}
.av-tier-card-owned {
  font-size: 10px;
  font-family: var(--mono);
  font-weight: 700;
  color: var(--accent);
  background: rgba(56, 189, 248, 0.10);
  border: 1px solid rgba(56, 189, 248, 0.30);
  border-radius: 6px;
  padding: 3px 8px;
  letter-spacing: .04em;
}

/* ── GIFT TIER CARDS ─────────────────────────────────────────────────
   Cards inside the gift shop's .tier-scroll containers. Similar shape
   to .av-tier-card but include a description line and use a square-ish
   image (gifts are illustrated objects, not portrait avatars). */
.gift-tier-card {
  flex: 0 0 auto;
  scroll-snap-align: start;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  padding: 10px 8px;
  min-width: 96px;
  max-width: 110px;
  border-radius: 12px;
  background: var(--bg3);
  border: 1px solid var(--border);
  transition: border-color .12s, transform .1s;
  -webkit-tap-highlight-color: transparent;
}
.gift-tier-card:hover {
  border-color: rgba(56, 189, 248, 0.4);
}
.gift-tier-card-img {
  width: 64px;
  height: 64px;
  border-radius: 10px;
  /* contain — show the full image even if non-square. Prevents clipping
     when source PNGs aren't perfectly square. */
  object-fit: contain;
  display: block;
}
.gift-tier-card-name {
  font-size: 11px;
  font-family: var(--mono);
  font-weight: 700;
  color: var(--text);
  letter-spacing: .04em;
  white-space: nowrap;
  margin-top: 4px;
}
.gift-tier-card-desc {
  font-size: 9px;
  color: var(--muted);
  text-align: center;
  line-height: 1.25;
  /* allow 2 lines max so multi-word descs like "Cyber teddy bear" fit */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  min-height: 22px;
}
.gift-tier-card-price {
  font-size: 11px;
  font-family: var(--mono);
  font-weight: 700;
  color: var(--text);
  display: inline-flex;
  align-items: center;
  gap: 4px;
  white-space: nowrap;
  margin-top: 2px;
}
.gift-tier-card-price .icon-token {
  width: 12px;
  height: 12px;
}

/* ── DRAWER SEARCH INPUT ─────────────────────────────────────────────
   Sits between the drawer head and the scrollable body. Sticky-ish
   positioning is implicit because flex-shrink:0 keeps it pinned while
   the body scrolls underneath.
   Used by the rooms drawer; can be reused by other drawers if needed. */
.drawer-search-wrap {
  padding: 0 12px 8px;
  flex-shrink: 0;
}
.drawer-search-input {
  width: 100%;
  background: var(--bg3);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 8px 12px;
  color: var(--text);
  font-size: 13px;
  font-family: var(--mono);
  outline: none;
  transition: border-color .12s;
}
.drawer-search-input::placeholder { color: var(--muted); opacity: .8; }
.drawer-search-input:focus { border-color: var(--accent); }

/* ── ROOM SAVE GLOW (in drawer tile) ─────────────────────────────────
   Glowing red circuitry icon that appears next to a room name in the
   Joined section when the user has saved that room. Uses CSS keyframes
   to give it a subtle pulse so saved rooms catch the eye. */
.rc-saved-glow {
  display: inline-block;
  margin-left: 6px;
  font-size: 11px;
  color: #ff4d6d;
  text-shadow:
    0 0 4px rgba(255, 77, 109, 0.9),
    0 0 8px rgba(255, 77, 109, 0.6),
    0 0 12px rgba(255, 77, 109, 0.4);
  animation: rcSavedPulse 2.4s ease-in-out infinite;
}
@keyframes rcSavedPulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.55; }
}
.room-card.rc-saved {
  border-color: rgba(255, 77, 109, 0.35);
  background: linear-gradient(90deg, rgba(255, 77, 109, 0.06) 0%, var(--bg2) 60%);
}

/* ── CHAT HEADER SAVE BUTTON ─────────────────────────────────────────
   The ⚡ glow toggle in the chat header, sandwiched between the online
   count and the members button. Off state is muted; on state pulses
   in red same as the drawer indicator. */
.room-save-btn {
  background: transparent;
  border: 1px solid var(--border);
  border-radius: 8px;
  color: var(--muted);
  font-size: 14px;
  padding: 4px 8px;
  cursor: pointer;
  margin: 0 4px;
  transition: color 0.15s, border-color 0.15s, text-shadow 0.2s;
}
.room-save-btn:hover { color: var(--text); border-color: var(--accent); }
.room-save-btn.saved {
  color: #ff4d6d;
  border-color: rgba(255, 77, 109, 0.5);
  text-shadow:
    0 0 4px rgba(255, 77, 109, 0.9),
    0 0 8px rgba(255, 77, 109, 0.6);
  animation: rcSavedPulse 2.4s ease-in-out infinite;
}

/* ── MEMBERS PANEL ───────────────────────────────────────────────────
   Modal showing the full member list of a room. Sorted server-side
   into Creator → Enforcer → Members; each row shows avatar, badges,
   and an online dot for users currently in the room. */
/* Members panel — right-side slide-out anchored to the chat view.
   The base #members-overlay element holds both an invisible click-catcher
   that closes the panel when clicking outside, AND the panel itself.
   The panel is positioned against the right edge of the viewport with
   a slide-in animation; the chat box stays visible and usable behind
   the catcher (no full-screen dim). On mobile the panel widens to
   take a comfortable readable width without covering everything.

   IMPORTANT: this rule overrides the generic .modal-overlay full-screen
   styling specifically when the overlay is the members panel, so it
   doesn't dim the entire app. */
#members-overlay {
  position: fixed;
  inset: 0;
  background: transparent;
  z-index: 450;
  pointer-events: none; /* let clicks fall through except on the panel */
}
#members-overlay.open {
  pointer-events: auto; /* but only when open, so click-outside-to-close works */
}
.members-modal {
  position: fixed;
  top: 56px;     /* clear the top nav */
  right: 0;
  bottom: 0;
  width: min(320px, 88vw);
  max-width: 320px;
  max-height: none;  /* override the generic 85vh */
  background: var(--bg2);
  border-left: 1px solid var(--border);
  border-radius: 0;
  box-shadow: -8px 0 32px rgba(0,0,0,.4);
  display: flex;
  flex-direction: column;
  transform: translateX(100%);
  transition: transform 0.22s cubic-bezier(.2,.8,.2,1);
  z-index: 451;
}
#members-overlay.open .members-modal {
  transform: translateX(0);
}
.members-modal .modal-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 14px;
  border-bottom: 1px solid var(--border);
}
.members-modal .modal-title {
  font-family: var(--mono);
  font-weight: 700;
  font-size: 13px;
  letter-spacing: 0.05em;
  color: var(--text);
}
.members-modal .modal-close {
  background: none;
  border: none;
  color: var(--muted);
  font-size: 18px;
  cursor: pointer;
  padding: 4px 8px;
  border-radius: 6px;
  transition: background 0.12s, color 0.12s;
}
.members-modal .modal-close:hover {
  background: var(--bg3);
  color: var(--text);
}
.members-modal .modal-body {
  flex: 1;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  padding: 0 0 12px;
}
.members-summary {
  font-size: 11px;
  font-family: var(--mono);
  color: var(--muted);
  text-align: center;
  padding: 8px 12px;
  border-bottom: 1px solid var(--border);
  letter-spacing: 0.04em;
}
.member-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 16px;
  cursor: pointer;
  border-bottom: 1px solid rgba(255, 255, 255, 0.04);
  transition: background 0.1s;
}
.member-row:hover { background: var(--bg3); }
.member-av-wrap {
  position: relative;
  width: 36px;
  height: 36px;
  flex-shrink: 0;
}
.member-av-wrap img {
  width: 36px;
  height: 36px;
  border-radius: 8px;
  object-fit: cover;
}
.member-av-fallback {
  width: 36px;
  height: 36px;
  border-radius: 8px;
  background: var(--bg3);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--muted);
  font-size: 14px;
}
.member-online-dot {
  position: absolute;
  bottom: -1px;
  right: -1px;
  width: 11px;
  height: 11px;
  border-radius: 50%;
  background: #4ade80;
  box-shadow: 0 0 0 2px var(--bg2), 0 0 6px rgba(74, 222, 128, 0.6);
}
.member-info { flex: 1; min-width: 0; }
/* Inline action button for moderators on each member row. The ⋯ glyph
   sits to the right of the row content, opens a popover via
   openMemberActionMenu(). Suppressed for non-mods, the caller's own
   row, and the room owner's row (handled in JS). */
.member-action-btn {
  flex-shrink: 0;
  background: transparent;
  border: 1px solid var(--border);
  border-radius: 8px;
  width: 28px;
  height: 28px;
  font-size: 16px;
  line-height: 1;
  color: var(--muted);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  transition: background 0.12s, color 0.12s, border-color 0.12s;
}
.member-action-btn:hover {
  background: var(--bg3);
  color: var(--text);
  border-color: var(--accent);
}
/* Popover action menu — fixed-position next to the clicked button.
   Stacks above everything. Each action button is full-width within
   the menu and has a subtle hover state. Color-coded by destructive-
   ness: kick is amber, ban is red, mod toggles use the accent color. */
.member-action-menu {
  position: fixed;
  z-index: 700;
  min-width: 160px;
  background: var(--bg2);
  border: 1px solid var(--border);
  border-radius: 10px;
  box-shadow: 0 8px 24px rgba(0,0,0,0.5);
  padding: 4px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  animation: menuFadeIn 0.12s ease;
}
@keyframes menuFadeIn {
  from { opacity: 0; transform: translateY(-4px); }
  to   { opacity: 1; transform: translateY(0); }
}
.member-action-menu button {
  background: transparent;
  border: none;
  text-align: left;
  padding: 8px 12px;
  font-size: 12px;
  font-family: var(--mono);
  color: var(--text);
  border-radius: 6px;
  cursor: pointer;
  transition: background 0.1s;
}
.member-action-menu button:hover { background: var(--bg3); }
.member-action-menu .mam-mod   { color: #4ade80; }
.member-action-menu .mam-unmod { color: var(--muted); }
.member-action-menu .mam-kick  { color: #fbbf24; }
.member-action-menu .mam-ban   { color: var(--red); }
.member-name {
  font-size: 13px;
  font-weight: 700;
  color: var(--text);
  font-family: var(--mono);
  display: flex;
  align-items: center;
  gap: 4px;
  flex-wrap: wrap;
}
.member-badge {
  display: inline-block;
  font-size: 9px;
  font-family: var(--mono);
  font-weight: 800;
  padding: 2px 6px;
  border-radius: 4px;
  letter-spacing: 0.05em;
  text-transform: uppercase;
}
.member-badge-creator {
  background: rgba(251, 191, 36, 0.15);
  color: #fbbf24;
  border: 1px solid rgba(251, 191, 36, 0.4);
}
.member-badge-enforcer {
  background: rgba(56, 189, 248, 0.15);
  color: #38bdf8;
  border: 1px solid rgba(56, 189, 248, 0.4);
}
.member-badge-otgc {
  background: rgba(230, 59, 101, 0.15);
  color: var(--brand-2);
  border: 1px solid rgba(230, 59, 101, 0.4);
}
.member-badge-otgcmod {
  background: rgba(232, 90, 122, 0.13);
  color: var(--brand-2-soft);
  border: 1px solid rgba(232, 90, 122, 0.35);
}
.member-badge-divinity {
  background: rgba(236, 72, 153, 0.15);
  color: #ec4899;
  border: 1px solid rgba(236, 72, 153, 0.4);
  font-size: 11px;
  padding: 1px 5px;
}

/* ── INLINE LINKS INSIDE BUBBLES ──────────────────────────────────────
   Room-share-link (and any future inline link types) need to sit above
   the bubble's tap-to-open-menu zone so the link's own onclick fires
   cleanly. wireBubbleTap explicitly bails out when a tap lands on an
   <a> or .room-share-link, but the relative+z-index here is a CSS
   safety net in case any future structure changes affect stacking. */
.bubble {
  position: relative;
}
.bubble a,
.bubble .room-share-link {
  position: relative;
  z-index: 2;
}

/* ── BUY MODAL (Stripe Payment Element) v15.69 ────────────────────────
   Modal that hosts the embedded Stripe Payment Element. Built to feel
   continuous with the rest of OTGC's dark cyberpunk styling rather
   than looking like a Stripe-default popup. */
/* Hide by default. The .open class toggles to flex when the modal
   should be visible. The base .modal-overlay rule in this file has no
   display rule, so without this the buy modal is permanently visible
   on page load and blocks the entire app behind it. */
#buy-modal-overlay {
  display: none;
  align-items: center;
  justify-content: center;
}
#buy-modal-overlay.open {
  display: flex;
}
.buy-modal {
  width: 100%;
  max-width: 460px;
  max-height: 90vh;
  display: flex;
  flex-direction: column;
  background: var(--bg2);
  border-radius: 12px;
  overflow: hidden;
}
.buy-modal .modal-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  padding: 16px 18px 14px;
  border-bottom: 1px solid var(--border);
}
.buy-modal .modal-title {
  font-size: 16px;
  font-weight: 800;
  color: var(--text);
  font-family: var(--mono);
  letter-spacing: 0.02em;
}
.buy-modal .modal-subtitle {
  font-size: 12px;
  color: var(--muted);
  font-family: var(--mono);
  margin-top: 4px;
}
.buy-modal .modal-body {
  flex: 1;
  overflow-y: auto;
  padding: 16px 18px 20px;
}
.buy-modal-error {
  background: rgba(255, 77, 109, 0.08);
  border: 1px solid rgba(255, 77, 109, 0.3);
  color: #ff8aa3;
  padding: 10px 12px;
  border-radius: 8px;
  font-size: 12px;
  font-family: var(--mono);
  margin-bottom: 14px;
}
#buy-modal-payment-element {
  min-height: 280px;
  margin-bottom: 16px;
}
.buy-modal-submit {
  width: 100%;
  padding: 14px;
  border: none;
  border-radius: 8px;
  background: var(--accent);
  color: #000;
  font-size: 14px;
  font-weight: 800;
  font-family: var(--mono);
  letter-spacing: 0.04em;
  cursor: pointer;
  text-transform: uppercase;
  transition: opacity 0.15s, transform 0.05s;
}
.buy-modal-submit:hover { opacity: 0.92; }
.buy-modal-submit:active { transform: scale(0.98); }
.buy-modal-submit:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}
.buy-modal-trust {
  margin-top: 14px;
  text-align: center;
  font-size: 10px;
  color: var(--muted);
  font-family: var(--mono);
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

/* ── DIVINITY PLAN BUTTONS (active, replacing disabled state) ──────── */
.divinity-plan {
  position: relative;
  cursor: pointer;
  transition: transform 0.12s, border-color 0.12s;
}
.divinity-plan:hover { transform: translateY(-2px); }
.divinity-plan-btn {
  width: 100%;
  margin-top: 10px;
  padding: 10px;
  border: 1px solid rgba(var(--accent-rgb), 0.4);
  border-radius: 6px;
  background: rgba(var(--accent-rgb), 0.08);
  color: var(--accent);
  font-size: 12px;
  font-weight: 800;
  font-family: var(--mono);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  cursor: pointer;
  transition: background 0.12s, transform 0.05s;
}
.divinity-plan-btn:hover { background: rgba(var(--accent-rgb), 0.16); }
.divinity-plan-btn:active { transform: scale(0.97); }
.divinity-plan-btn-featured {
  background: var(--accent);
  color: #000;
  border-color: var(--accent);
}
.divinity-plan-btn-featured:hover {
  background: var(--accent);
  opacity: 0.92;
}

/* ── BUY CELEBRATION (small ✦ burst on success) ────────────────────── */
.buy-celebration {
  position: fixed;
  top: 0; left: 0; right: 0; bottom: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
  z-index: 10000;
}
.buy-celebration-burst {
  font-size: 96px;
  color: var(--accent);
  text-shadow:
    0 0 30px rgba(0, 229, 255, 0.9),
    0 0 60px rgba(0, 229, 255, 0.6),
    0 0 90px rgba(0, 229, 255, 0.4);
  animation: buyBurst 1.6s cubic-bezier(0.2, 0.8, 0.4, 1.0) forwards;
}
@keyframes buyBurst {
  0%   { transform: scale(0.2) rotate(0deg);   opacity: 0; }
  20%  { transform: scale(1.3) rotate(180deg); opacity: 1; }
  60%  { transform: scale(1.0) rotate(360deg); opacity: 1; }
  100% { transform: scale(1.6) rotate(540deg); opacity: 0; }
}

/* ── DIVINITY SUBSCRIPTION MANAGEMENT (v15.69 Phase 3) ────────────────
   Replaces the static "✓ Active" badge with a proper management
   panel: status badge, plan name, period end, and action buttons.
   Sits inside .divinity-hero so it inherits the cyberpunk styling.
   The two visual states (active, canceling) use accent vs warning
   color tones to give a clear at-a-glance status. */
.divinity-mgmt-loading,
.divinity-mgmt-error {
  font-size: 12px;
  font-family: var(--mono);
  color: var(--muted);
  text-align: center;
  padding: 12px;
}
.divinity-mgmt-error { color: #ff8aa3; }
.divinity-mgmt-status {
  margin-top: 10px;
  padding: 14px 16px;
  border-radius: 12px;
  border: 1px solid rgba(255, 255, 255, 0.08);
  background: rgba(0, 0, 0, 0.25);
}
.divinity-mgmt-active {
  border-color: rgba(74, 222, 128, 0.3);
  background: rgba(74, 222, 128, 0.06);
}
.divinity-mgmt-canceling {
  border-color: rgba(251, 146, 60, 0.35);
  background: rgba(251, 146, 60, 0.06);
}
.divinity-mgmt-badge {
  display: inline-block;
  padding: 3px 9px;
  border-radius: 4px;
  font-size: 10px;
  font-weight: 800;
  font-family: var(--mono);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  background: rgba(251, 146, 60, 0.18);
  color: #fb923c;
  border: 1px solid rgba(251, 146, 60, 0.4);
  margin-bottom: 10px;
}
.divinity-mgmt-badge-active {
  background: rgba(74, 222, 128, 0.18);
  color: #4ade80;
  border-color: rgba(74, 222, 128, 0.4);
}
.divinity-mgmt-plan {
  font-size: 16px;
  font-weight: 800;
  color: var(--text);
  font-family: var(--mono);
  letter-spacing: 0.02em;
  margin-bottom: 4px;
}
.divinity-mgmt-period {
  font-size: 12px;
  color: var(--muted);
  font-family: var(--mono);
  margin-bottom: 14px;
  letter-spacing: 0.04em;
}
.divinity-mgmt-actions {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.divinity-mgmt-btn {
  width: 100%;
  padding: 10px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.04);
  color: var(--text);
  font-size: 12px;
  font-weight: 700;
  font-family: var(--mono);
  letter-spacing: 0.04em;
  cursor: pointer;
  transition: background 0.12s, border-color 0.12s, transform 0.05s;
}
.divinity-mgmt-btn:hover { background: rgba(255, 255, 255, 0.08); }
.divinity-mgmt-btn:active { transform: scale(0.98); }
.divinity-mgmt-btn-primary {
  background: var(--accent);
  color: #000;
  border-color: var(--accent);
}
.divinity-mgmt-btn-primary:hover {
  background: var(--accent);
  opacity: 0.92;
}
.divinity-mgmt-btn-secondary {
  color: #ff8aa3;
  border-color: rgba(255, 77, 109, 0.3);
}
.divinity-mgmt-btn-secondary:hover {
  background: rgba(255, 77, 109, 0.08);
  border-color: rgba(255, 77, 109, 0.5);
}
.divinity-mgmt-btn-upgrade {
  background: linear-gradient(90deg, rgba(168, 85, 247, 0.15), rgba(236, 72, 153, 0.15));
  color: #d8b4fe;
  border-color: rgba(168, 85, 247, 0.4);
}
.divinity-mgmt-btn-upgrade:hover {
  background: linear-gradient(90deg, rgba(168, 85, 247, 0.25), rgba(236, 72, 153, 0.25));
}
.divinity-mgmt-foot {
  margin-top: 10px;
  font-size: 11px;
  color: var(--muted);
  font-family: var(--mono);
  line-height: 1.5;
  text-align: center;
}

/* ── DIVINITY MGMT — SCHEDULED PLAN CHANGE (v15.70) ────────────────────
   Visual treatment for the "plan change queued for renewal" state.
   Distinct from active (green) and canceling (orange) — uses purple
   to signal "neutral pending" without alarm. */
.divinity-mgmt-scheduled {
  border-color: rgba(168, 85, 247, 0.35);
  background: rgba(168, 85, 247, 0.06);
}
.divinity-mgmt-badge-scheduled {
  background: rgba(168, 85, 247, 0.18);
  color: #c4a8f8;
  border-color: rgba(168, 85, 247, 0.4);
}

/* ── BILLING VIEW (v15.71) ──────────────────────────────────────────
   Dedicated view for managing payment method and viewing purchase
   history. Failed-payment banner appears at the top when an invoice
   is past due. */
.billing-body {
  padding: 16px;
  max-width: 600px;
  margin: 0 auto;
}
.billing-error {
  font-size: 12px;
  font-family: var(--mono);
  color: #ff8aa3;
  text-align: center;
  padding: 24px;
}

.billing-failed-banner {
  display: flex;
  gap: 12px;
  align-items: flex-start;
  padding: 14px;
  margin-bottom: 16px;
  border: 1px solid rgba(255, 77, 109, 0.4);
  border-radius: 10px;
  background: rgba(255, 77, 109, 0.08);
}
.billing-failed-icon {
  font-size: 22px;
  color: #ff4d6d;
  flex-shrink: 0;
}
.billing-failed-title {
  font-size: 13px;
  font-weight: 800;
  color: #ff8aa3;
  font-family: var(--mono);
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
.billing-failed-desc {
  font-size: 12px;
  color: var(--text);
  font-family: var(--mono);
  line-height: 1.5;
  margin-top: 4px;
}

.billing-section {
  margin-bottom: 24px;
}
.billing-section-lbl {
  font-size: 11px;
  font-weight: 800;
  font-family: var(--mono);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
  padding: 0 4px 8px;
}

.billing-card {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 16px;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--bg2);
  font-family: var(--mono);
}
.billing-card-empty {
  color: var(--muted);
  font-size: 12px;
  justify-content: center;
}
.billing-card-brand {
  font-size: 13px;
  font-weight: 800;
  color: var(--text);
  letter-spacing: 0.02em;
}
.billing-card-last4 {
  font-size: 13px;
  color: var(--text);
  letter-spacing: 0.06em;
  flex: 1;
}
.billing-card-exp {
  font-size: 11px;
  color: var(--muted);
  letter-spacing: 0.04em;
}
.billing-update-btn {
  margin-top: 10px;
  width: 100%;
  padding: 10px;
  border: 1px solid rgba(var(--accent-rgb), 0.4);
  border-radius: 8px;
  background: rgba(var(--accent-rgb), 0.08);
  color: var(--accent);
  font-size: 12px;
  font-weight: 800;
  font-family: var(--mono);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  cursor: pointer;
  transition: background 0.12s, transform 0.05s;
}
.billing-update-btn:hover { background: rgba(var(--accent-rgb), 0.16); }
.billing-update-btn:active { transform: scale(0.98); }

.billing-empty {
  font-size: 12px;
  color: var(--muted);
  text-align: center;
  padding: 24px;
  font-family: var(--mono);
  border: 1px dashed var(--border);
  border-radius: 10px;
}
.billing-history {
  border: 1px solid var(--border);
  border-radius: 10px;
  overflow: hidden;
}
.billing-history-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 16px;
  border-bottom: 1px solid var(--border);
  background: var(--bg2);
}
.billing-history-row:last-child { border-bottom: none; }
.billing-history-info { flex: 1; min-width: 0; }
.billing-history-title {
  font-size: 13px;
  font-weight: 700;
  color: var(--text);
  font-family: var(--mono);
}
.billing-history-meta {
  font-size: 11px;
  color: var(--muted);
  font-family: var(--mono);
  margin-top: 2px;
  letter-spacing: 0.04em;
}
.billing-history-receipt {
  font-size: 11px;
  font-family: var(--mono);
  color: var(--accent);
  text-decoration: none;
  letter-spacing: 0.04em;
  white-space: nowrap;
  padding: 4px 8px;
  border-radius: 6px;
  border: 1px solid rgba(var(--accent-rgb), 0.3);
  transition: background 0.12s;
}
.billing-history-receipt:hover { background: rgba(var(--accent-rgb), 0.1); }

/* ── DIVINITY MGMT — BILLING LINK ──────────────────────────────────── */
.divinity-mgmt-billing-link {
  display: block;
  margin-top: 12px;
  font-size: 11px;
  color: var(--muted);
  font-family: var(--mono);
  text-align: center;
  cursor: pointer;
  letter-spacing: 0.04em;
  text-decoration: none;
  padding: 4px;
  transition: color 0.12s;
}
.divinity-mgmt-billing-link:hover { color: var(--accent); }

/* ── BUY MODAL — SAVE CARD CHECKBOX (v15.71) ──────────────────────────
   Custom checkbox row shown for bundle purchases (not subs). Hidden
   by default; .show class toggles visibility based on purchase type.
   We render this ourselves rather than using Stripe's native checkbox
   because Stripe's checkbox requires either:
     a) setup_future_usage on the PaymentIntent (forces save, no opt-out)
     b) A CustomerSession with payment_method_redisplay enabled (a
        much heavier integration)
   Our custom checkbox passes allow_redisplay to confirmPayment, which
   gives the same result without those constraints.

   IMPORTANT: We can't use a native checkbox here because the global
   `input { -webkit-appearance: none }` rule (line ~61) makes them
   invisible. Instead we hide the actual input visually and render
   a custom styled box that reflects :checked state.

   Layout: label on the left, custom box on the right. */
.buy-modal-save-row {
  display: none;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 12px 14px;
  margin-bottom: 14px;
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid var(--border);
  border-radius: 8px;
  font-size: 12px;
  font-family: var(--mono);
  color: var(--text);
  cursor: pointer;
  user-select: none;
  position: relative;
}
.buy-modal-save-row.show { display: flex; }
.buy-modal-save-row input[type="checkbox"] {
  /* Hide the actual input — the styled box reflects its state */
  position: absolute;
  opacity: 0;
  width: 0; height: 0;
  pointer-events: none;
}
.buy-modal-save-label {
  flex: 1;
  letter-spacing: 0.02em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.buy-modal-save-box {
  width: 20px;
  height: 20px;
  min-width: 20px;
  border: 1.5px solid var(--border);
  border-radius: 4px;
  background: rgba(0, 0, 0, 0.3);
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background 0.12s, border-color 0.12s;
  flex-shrink: 0;
}
.buy-modal-save-row input[type="checkbox"]:checked ~ .buy-modal-save-box {
  background: var(--accent);
  border-color: var(--accent);
}
.buy-modal-save-row input[type="checkbox"]:checked ~ .buy-modal-save-box::after {
  content: '✓';
  color: #000;
  font-size: 14px;
  font-weight: 900;
  font-family: system-ui, sans-serif;
  line-height: 1;
}
