﻿/* ================================
   GLOBAL PAGE STYLING
   ================================ */

   /* ================================
      MINIMAL BLUE PALETTE BASE
      Used by the shared TOP HUD on every
      page EXCEPT admin.html and the topic
      chatrooms (chatcloud.html), which pin
      their own overrides locally.
      ================================ */
   :root {
     --blue-base:      #1f6fd6;   /* main HUD blue         */
     --blue-deep:      #164a8f;   /* hover / active / text */
     --blue-soft:      #e9f3ff;   /* light tint / panels   */
     --blue-line:      #c7d9f5;   /* subtle borders        */
     --blue-text:      #ffffff;   /* on-HUD text           */
     --blue-text-dim:  #dbeafe;   /* secondary on-HUD text */
   }

   body {
    margin: 0;
    font-family: Arial, sans-serif;
    background: #0d1b2a;
    color: #164a8f;
    transition: background 0.25s ease, color 0.25s ease;
  }
  
  /* ================================
      FULL BLEED ON MOBILE
      Keeping the app edge to edge, and keeping the browser's own furniture out
      of the way of it.

      viewport-fit=cover in the viewport meta is what actually lets the page
      reach under the notch and the home indicator; without it the OS letterboxes
      a notched phone and "full screen" is not achievable in CSS at all. The
      env() padding then pushes the few controls that must stay clear of the
      notch and the gesture bar back inside it.

      overscroll-behavior-y:none is the one that matters day to day. Its absence
      is why the address bar keeps reappearing over the media: dragging past the
      end of a feed rubber-bands the document, and that overscroll is what makes
      the browser show or hide its own chrome mid-swipe. Same gesture, and
      pull-to-refresh with it.

      dvh rather than vh on the app shell. 100vh on a phone is the viewport as if
      the address bar were hidden, so any element sized against it is either too
      tall or leaves a strip of background visible whenever the bar is showing.

      touch-action:manipulation keeps double-tap-to-zoom out of the way without
      taking away scrolling or pinch-zoom. Deliberately not "none": that would
      disable panning everywhere and break the chat feed, and it would also stop
      the media swipe from being able to claim the gesture at all.

      -webkit-text-size-adjust stops iOS inflating every font after a rotation,
      which reflows a layout that is already viewport-sized. */
   html {
     height: 100%;
     -webkit-text-size-adjust: 100%;
     text-size-adjust: 100%;
   }

   html,
   body {
     overscroll-behavior-y: none;
   }

   body {
     min-height: 100dvh;
     touch-action: manipulation;
   }

   /* Applied only where the notch can actually reach: the HUD strip and the
      bottom input bar, both of which sit against an edge. */
   @supports (padding: env(safe-area-inset-left)) {
     .top-hud {
       padding-left: env(safe-area-inset-left, 0px);
       padding-right: env(safe-area-inset-right, 0px);
     }

     .chatroom-body,
     .chat-input-bar {
       padding-left: env(safe-area-inset-left, 0px);
       padding-right: env(safe-area-inset-right, 0px);
     }
   }

   /* LEFT MENU (LOBBY / SIDEBAR) */
  .left-menu {
    width: 200px;
    background: white;
    border-right: 3px solid #c7d9f5;
    padding: 20px 0;
    position: fixed;
    top: 70px;
    bottom: 0;
    left: 0;
    box-shadow: 4px 0 12px rgba(0,0,0,0.1);
  }
  
  /* ================================
     ULTRA-LOW GLOBAL CHATCLOUD TOP HUD
     ================================ */
  
.top-hud {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  width: 100%;
  background: var(--blue-base, #1f6fd6);
  color: var(--blue-text, #ffffff);
  padding: 2px 12px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 22px;
  font-weight: 700;
  border-bottom: 3px solid var(--blue-deep, #164a8f);
  box-shadow: 0 3px 10px rgba(0,0,0,0.25);
  box-sizing: border-box;
  min-height: 44px;
  z-index: 1000;
}

/* Allow tooltips to appear outside the HUD */
.top-hud {
  overflow: visible !important;
  position: fixed !important; /* keep the site-wide header pinned */
  top: 0;
  left: 0;
  right: 0;
  z-index: 1000;              /* header stays above page content */
}

/* Tooltip must float above HUD */
.hud-icon {
  width: 32px;
  height: 32px;
  cursor: pointer;
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

/* Tooltip */
.hud-icon::after,
.hud-logo-wrap::after {
  content: attr(data-tip);
  position: absolute;
  bottom: -32px;
  left: 50%;
  transform: translateX(-50%);
  background: #164a8f;
  color: #fff;
  padding: 4px 10px;
  border-radius: 6px;
  font-size: 12px;
  opacity: 0;
  pointer-events: none;
  white-space: nowrap;
  transition: opacity 0.15s ease;
  box-shadow: 0 2px 6px rgba(0,0,0,0.4);
  z-index: 999999;
}

.hud-icon:hover::after,
.hud-logo-wrap:hover::after {
  opacity: 1;
}


.hud-left,
.hud-right {
    overflow: visible !important;
    position: relative !important;
}

/* TRUE CENTER */
.hud-center {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  font-size: 30px;
  font-weight: 700;
  pointer-events: none;
  white-space: nowrap;
}

/* Center topic title: show "Cloud Topic" as hover tooltip */
.hud-center #hudTopicName {
  pointer-events: auto;
  position: relative;
  cursor: default;
}

.hud-center #hudTopicName::after {
  content: attr(data-tip);
  position: absolute;
  bottom: -32px;
  left: 50%;
  transform: translateX(-50%);
  background: #164a8f;
  color: #fff;
  padding: 4px 10px;
  border-radius: 6px;
  font-size: 13px;
  font-weight: 400;
  white-space: nowrap;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.15s ease;
  box-shadow: 0 2px 6px rgba(0,0,0,0.4);
  z-index: 999999;
}

.hud-center #hudTopicName:hover::after {
  opacity: 1;
}

/* Topic love button next to center title */
#topicLoveWrap {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  margin-left: 14px;
  padding: 4px 10px;
  border-radius: 18px;
  background: rgba(255,255,255,0.2);
  cursor: pointer;
  pointer-events: auto;
  position: relative;
  transition: transform 0.15s ease, background 0.15s ease;
  user-select: none;
}

#topicLoveWrap:hover {
  transform: scale(1.08);
  background: rgba(255,255,255,0.35);
}

#topicLoveWrap .topic-love-icon {
  line-height: 1;
  transition: 0.15s ease;
}

#topicLoveWrap .topic-love-icon img {
  width: 20px;
  height: 20px;
  object-fit: contain;
  vertical-align: middle;
}

#topicLoveWrap.loved .topic-love-icon {
  animation: love-pop 0.3s ease;
}

@keyframes love-pop {
  0% { transform: scale(1); }
  50% { transform: scale(1.5); }
  100% { transform: scale(1); }
}

/* Double-tap heart.

   Spawns under the finger and flies to whichever love icon is on screen. Both
   positions arrive as custom properties holding the delta between the two, so
   the heart never needs to know the page's scroll offset or where the icon
   ended up after the layout shifted around it. */
.love-fly {
  position: fixed;
  z-index: 10001;
  font-size: 30px;
  line-height: 1;
  pointer-events: none;
  transform-origin: center center;
  animation: loveFlyToIcon 0.75s cubic-bezier(.35, 0, .3, 1) forwards;
}

@keyframes loveFlyToIcon {
  0% {
    transform: translate(0, 0) scale(.4) rotate(-12deg);
    opacity: 0;
  }
  18% {
    transform: translate(0, 0) scale(1.25) rotate(6deg);
    opacity: 1;
  }
  70% {
    transform: translate(var(--love-x), var(--love-y)) scale(1.05) rotate(0deg);
    opacity: 1;
  }
  100% {
    transform: translate(var(--love-x), var(--love-y)) scale(.2) rotate(10deg);
    opacity: 0;
  }
}

/* The icon acknowledging the heart that just landed on it. Kept separate from
   love-pop because that one is bound to the .loved class and would replay on
   every re-render instead of once, on arrival. */
.love-landed {
  animation: loveLanded 0.45s cubic-bezier(.34, 1.56, .64, 1);
}

@keyframes loveLanded {
  0% { transform: scale(1); }
  35% { transform: scale(1.75); }
  60% { transform: scale(.92); }
  100% { transform: scale(1); }
}

/* TikTok-style song love.

   A song double-tap on a phone throws one of these from under the finger and
   it rises and fades on its own. Unlike .love-fly -- a single heart aimed at a
   counter -- these are meant to be spammed: every tap spawns a fresh one, so a
   burst reads as a little column of hearts. Each carries its own sideways
   drift, spin, peak size and speed as custom properties, so no two take the
   same path. Nothing here touches the love count; the caller owns that, which
   is why the hearts keep rising even once the cap is reached. */
.love-rise {
  position: fixed;
  z-index: 10000;
  width: 34px;
  height: 34px;
  margin: -17px 0 0 -17px; /* centre the box on the point we were given */
  pointer-events: none;
  transform-origin: center center;
  will-change: transform, opacity;
  animation: loveRise var(--rise-dur, 1.4s) cubic-bezier(.22, .61, .36, 1) forwards;
}

.love-rise img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
  filter: drop-shadow(0 2px 6px rgba(255, 20, 80, .45));
}

@keyframes loveRise {
  0% {
    transform: translate(0, 0) scale(.3) rotate(0deg);
    opacity: 0;
  }
  15% {
    transform: translate(calc(var(--rise-x) * .2), calc(var(--rise-y) * .25))
      scale(1.15) rotate(calc(var(--rise-rot) * .3));
    opacity: 1;
  }
  55% {
    transform: translate(calc(var(--rise-x) * .62), calc(var(--rise-y) * .62))
      scale(var(--rise-peak, 1.2)) rotate(calc(var(--rise-rot) * .7));
    opacity: 1;
  }
  100% {
    transform: translate(var(--rise-x), var(--rise-y))
      scale(.7) rotate(var(--rise-rot));
    opacity: 0;
  }
}

#topicLoveWrap .topic-love-count {
  font-size: 14px;
  font-weight: 700;
  color: white;
}

#topicLoveWrap::after {
  content: attr(data-tip);
  position: absolute;
  bottom: -32px;
  left: 50%;
  transform: translateX(-50%);
  background: #1e1e1e;
  color: #fff;
  padding: 4px 10px;
  border-radius: 6px;
  font-size: 13px;
  font-weight: 400;
  white-space: nowrap;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.15s ease;
  box-shadow: 0 2px 6px rgba(0,0,0,0.4);
  z-index: 999999;
}

#topicLoveWrap:hover::after {
  opacity: 1;
}

/* HUD container must be relative */
.top-hud {
  position: relative;
}

/* Back button on the Invite Friends page */
.hud-return {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-right: 8px;
  padding: 6px 14px;
  background: #ffffff;
  color: #1f6fd6;
  font-size: 14px;
  font-weight: 800;
  border: 2px solid #1f6fd6;
  border-radius: 999px;
  cursor: pointer;
  user-select: none;
  white-space: nowrap;
  transition: background 0.15s ease, color 0.15s ease;
  z-index: 9999;
}

.hud-return:hover {
  background: #1f6fd6;
  color: #fff;
}

.hud-return::after {
  content: attr(data-tip);
  position: absolute;
  bottom: -32px;
  left: 50%;
  transform: translateX(-50%);
  background: #164a8f;
  color: #fff;
  padding: 4px 10px;
  border-radius: 6px;
  font-size: 12px;
  opacity: 0;
  pointer-events: none;
  white-space: nowrap;
  transition: opacity 0.15s ease;
  box-shadow: 0 2px 6px rgba(0,0,0,0.4);
  z-index: 999999;
}

.hud-return:hover::after {
  opacity: 1;
}

  
  .hud-left {
    position: relative;
    display: flex;
    align-items: center;
    gap: 8px;
  }
  
  .hud-left-core {
    display: flex;
    align-items: center;
  }
  
  .hud-logo {
    height: 32px;
    width: auto;
  }

  .hud-logo-wrap {
    position: relative;
    display: inline-flex;
    align-items: center;
    height: 32px;
    cursor: pointer;
  }
  
  .hud-alert {
    position: absolute;
    top: 50%;
    left: 24px;
    transform: translateY(-55%);
    font-size: 20px;
    color: yellow;
    font-weight: 900;
    animation: blinkSlow 1.8s infinite;
    pointer-events: auto;
    background: none;
    border: 0;
    padding: 0;
    margin: 0;
    line-height: 1;
    font-family: inherit;
    cursor: pointer;
  }

  /* Lit when someone this member follows has just come online. */
  .hud-alert.online-flash {
    color: #ff2b2b;
    animation: blinkRed 0.7s infinite;
    text-shadow: 0 0 8px rgba(255, 43, 43, 0.9);
  }
  
  @keyframes blinkSlow {
    0% { opacity: 1; }
    50% { opacity: 0.2; }
    100% { opacity: 1; }
  }

  @keyframes blinkRed {
    0%, 100% { opacity: 1; }
    50% { opacity: 0.15; }
  }

  /* Friends-online dropdown anchored under the logo. */
  .online-dropdown {
    position: absolute;
    top: 100%;
    left: 0;
    margin-top: 6px;
    width: 250px;
    max-height: 320px;
    overflow-y: auto;
    background: #fff;
    color: #164a8f;
    border-radius: 10px;
    box-shadow: 0 8px 24px rgba(0,0,0,0.28);
    padding: 6px;
    display: none;
    z-index: 10000;
  }
  .online-dropdown.show { display: block; }

  .online-dropdown-item {
    display: flex;
    align-items: center;
    gap: 9px;
    padding: 8px 9px;
    border-radius: 8px;
    cursor: pointer;
  }
  .online-dropdown-item.is-static { cursor: default; }
  .online-dropdown-item:hover { background: #eef5ff; }

  .online-dot {
    flex: 0 0 auto;
    width: 9px;
    height: 9px;
    border-radius: 50%;
    background: #37d67a;
    box-shadow: 0 0 6px #37d67a;
  }
  .online-info {
    display: flex;
    flex-direction: column;
    min-width: 0;
  }
  .online-name {
    font-size: 14px;
    font-weight: 800;
    color: #164a8f;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .online-where {
    font-size: 12px;
    color: #5a7bb0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .online-dropdown-empty {
    padding: 10px;
    font-size: 13px;
    color: #5a7bb0;
  }
  
  .hud-page-name {
    font-size: 20px;
    font-weight: 900;
    white-space: nowrap;
  }

  .topic-search-wrap {
    position: relative;
    display: flex;
    align-items: center;
    margin-left: 10px;
  }
  
  #topicSearchInput, #hudTopicSearchInput {
    padding: 6px 10px 6px 34px;
    font-size: 14px;
    border-radius: 6px;
    border: none;
    outline: none;
    background-color: #e9f3ff;
    background-image: url("img/icons/search.png");
    background-repeat: no-repeat;
    background-position: 8px center;
    background-size: 18px;
    color: #164a8f;
    width: 180px;
  }
  
  #topicSearchInput::placeholder, #hudTopicSearchInput::placeholder {
    color: #164a8f;
    opacity: 0.7;
  }
  
  .topic-suggest-menu {
    position: absolute;
    top: 36px;
    left: 0;
    width: 280px;
    max-height: 320px;
    overflow-y: auto;
    background: #fff;
    border-radius: 6px;
    box-shadow: 0 4px 12px rgba(0,0,0,0.25);
    display: none;
    z-index: 9999;
  }
  
  .topic-suggest-menu.show {
    display: block;
  }
  
  .topic-suggest-item {
    padding: 8px 10px;
    cursor: pointer;
    font-size: 14px;
    color: #164a8f;
  }
  
.topic-suggest-item:hover {
    background: #e0edff;
  }

  .music-suggest-header {
    padding: 6px 10px 3px;
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: #7b2dbf;
    border-top: 1px solid #e0edff;
    margin-top: 4px;
  }

  .music-suggest-item {
    color: #333;
  }

  .music-suggest-item:hover {
    background: #f3e9ff;
  }

  .topic-search-wrap {
    position: relative;
    display: flex;
    align-items: center;
    margin-left: 10px;
  }
  
  #topicSearchInput, #hudTopicSearchInput {
    padding: 6px 10px 6px 34px;
    font-size: 14px;
    border-radius: 6px;
    border: none;
    outline: none;
    background-color: #e9f3ff;
    background-image: url("img/icons/search.png");
    background-repeat: no-repeat;
    background-position: 8px center;
    background-size: 18px;
    color: #164a8f;
    width: 180px;
  }
  
  .topic-search-dropdown {
    position: absolute;
    top: 36px;
    left: 0;
    width: 180px;
    background: #fff;
    border-radius: 6px;
    box-shadow: 0 4px 12px rgba(0,0,0,0.25);
    display: none;
    z-index: 9999;
    padding-bottom: 6px;
  }
  
  .topic-search-dropdown.show {
    display: block;
  }
  
  .topic-section-title {
    font-size: 12px;
    font-weight: 700;
    color: #164a8f;
    padding: 6px 10px 2px 10px;
  }
  
  .topic-section {
    border-bottom: 1px solid #d0d9e8;
    padding-bottom: 4px;
  }
  
  .topic-suggest-item {
    padding: 8px 10px;
    cursor: pointer;
    font-size: 14px;
    color: #164a8f;
  }
  
  .topic-suggest-item:hover {
    background: #e0edff;
  }
  
  /* Live suggestions list */
  .topic-suggest-menu {
    padding-top: 4px;
  }
  
  .hud-avatar {
    width: 32px;
    height: 32px;
    border-radius: 50%;
    margin-right: 0;
    cursor: pointer;
  }

  .hud-invite {
    width: 32px;
    height: 32px;
    border-radius: 50%;
    cursor: pointer;
    object-fit: cover;
  }
  
  .hud-right {
    display: flex;
    align-items: center;
    gap: 10px;
    min-width: 120px;
    padding-right: 6px;
    flex-shrink: 0;
    position: relative;
  }
  
  .hud-username {
    font-size: 18px;
    font-weight: 700;
    white-space: nowrap;
  }
  
  .hud-tools {
    width: 32px;
    height: 32px;
    cursor: pointer;
    transition: transform 0.18s ease;
  }
  
  .hud-icon {
    width: 32px;
    height: 32px;
    cursor: pointer;
    position: relative;
  }
  
  /* Tooltip box */
  .hud-icon::after {
    content: attr(data-tip);
    position: absolute;
    bottom: -32px;
    left: 50%;
    transform: translateX(-50%);
    background: #1e1e1e;
    color: #fff;
    padding: 4px 10px;
    border-radius: 6px;
    font-size: 12px;
    opacity: 0;
    pointer-events: none;
    white-space: nowrap;
    transition: opacity 0.15s ease;
    box-shadow: 0 2px 6px rgba(0,0,0,0.4);
  }
  
  /* Show on hover */
  .hud-icon:hover::after {
    opacity: 1;
  }
  

  .hud-icon {
    position: relative;
  }
  
  .hud-tools:hover {
    transform: rotate(14deg);
  }
  
  /* ================================
     DROPDOWN MENU
     ================================ */
  
  .tools-menu {
    position: absolute;
    top: 40px;
    right: 0;
    background: #222;
    color: #fff;
    border-radius: 12px;
    box-shadow: 0 8px 20px rgba(0,0,0,0.25);
    width: 220px;
    padding: 10px 0;
    display: none;
    opacity: 0;
    transform: translateY(-10px);
    transition: 0.25s ease;
    z-index: 999;
    max-height: 260px;
    overflow-y: auto;
    overflow-x: hidden;
    pointer-events: none;
  }
  
  .tools-menu.show {
    display: block;
    opacity: 1;
    transform: translateY(0);
    pointer-events: auto;
  }
  
  .tools-item {
    padding: 10px 18px;
    font-size: 16px;
    cursor: pointer;
    transition: 0.2s ease;
  }
  
  .tools-item:hover {
    background: #333;
    color: #4ea3ff;
  }
  
  /* ================================
     COMPACT HOST PERMISSIONS
     ================================ */
  
  .tools-item-section {
    font-weight: 900;
    font-size: 14px;
    padding: 6px 18px;
    margin-top: 6px;
    border-top: 1px solid #444;
  }
  
  .tools-item-sub {
    font-size: 13px;
    padding: 4px 18px;
    opacity: 0.8;
  }
  
  .tools-select {
    width: 85%;
    margin: 6px 18px;
    padding: 6px;
    border-radius: 6px;
    border: 1px solid #555;
    font-size: 14px;
    background: #333;
    color: #fff;
  }
  
  .compact-select {
    font-size: 13px;
    padding: 4px;
    margin-top: 4px;
  }
  
  /* ================================
     RIGHT-ALIGNED TOGGLES
     ================================ */
  
  .toggle-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 2px 18px;
  }
  
  .toggle-row span:first-child {
    flex: 1;
  }
  
  .toggle-box {
    padding: 2px 6px;
    border-radius: 4px;
    cursor: pointer;
    font-size: 12px;
    background: #e5e5e5;
    margin-left: 4px;
  }
  
  .toggle-on {
    background: #1f6fd6;
    color: white;
  }
  
  /* ================================
     CHATCLOUD CHATTING
     ================================ */
  
  .chatroom-body {
    position: fixed;
    top: 40px;
    left: 0;
    right: 0;
    bottom: 0;
    display: flex;
    flex-direction: column;
    padding: 0;
    z-index: 1;
  }
  
  #chatFeed {
    flex: 1;
    overflow-y: auto;
    padding: 10px;
  }
  
  .chat-input-bar {
    position: relative;
    padding: 10px;
    display: flex;
    justify-content: space-between;
    align-items: flex-end;
  }
  
  .input-left {
    display: flex;
    align-items: center;
    gap: 14px;
    flex: 1;
  }
  
  .send-icon {
    width: 40px;
    height: 30px;
    opacity: 0.85;
    pointer-events: none;
    flex-shrink: 0;
    margin-left: -6px;
    margin-bottom: -10px;
  }
  
  #chatInputTop {
    margin-left: 40px;
    min-height: 20px;
    max-height: 140px;
    overflow-y: auto;
    font-size: 16px;

    /* These two lines FIX the size jump */
    line-height: 20px;
    padding: 4px 10px;

    border-radius: 8px;
    border: none;
    outline: none;
    background: #ffffff;
    color: #164a8f;
    flex: 1;
    width: 80%;
    max-width: 940px;
    box-sizing: border-box;
}

  
  .input-icons {
    position: absolute;
    right: 20px;
    bottom: 20px;
    display: flex;
    gap: 12px;
    z-index: 999;
  }
  
  .comment-icon {
    font-size: 20px;
    cursor: pointer;
  }
  
  .comment-dropdown {
    position: absolute;
    right: 0;
    bottom: 50px;
    background: white;
    border-radius: 8px;
    box-shadow: 0 4px 12px rgba(0,0,0,0.25);
    padding: 6px 0;
    display: none;
    z-index: 1200;
  }
  
  .comment-dropdown.show {
    display: block;
  }
  
  .chat-row {
    display: flex;
    align-items: flex-start;
    gap: 1px;
    margin-bottom: 1px;
  }


.chat-reactions {
    display: flex;
    gap: 10px;
    font-size: 22px;
    user-select: none;
  
    opacity: 0;
    transform: translateY(2px);
    pointer-events: none;
    overflow: hidden;
    transition: opacity 0.15s ease, transform 0.15s ease;
  
    margin-top: -15px;     /* Ã¢â€ Â moves icons UP */
    padding-left: 15px;   /* Ã¢â€ Â moves icons LEFT */
  }
  

 /* Hover-revealed controls are scoped to real pointers. Touch browsers latch
   :hover onto the tapped element and keep it, so an unscoped
   `.chat-row:hover ...` (specificity 0,3,0) would outrank the hide rules in
   the @media (hover: none) block and leak the icons back in without the tap. */
@media (hover: hover) {
  .chat-row:hover .chat-reactions {
    opacity: 1;
    transform: translateY(0);
    pointer-events: auto;
    height: auto;
    overflow: visible;
  }
}

.chat-reactions {
  height: 22px;              /* Ã¢â€ Â reserves space */
  overflow: hidden;
}

/* Avatar styling should NOT be nested */
  .chat-avatar {
      width: 42px;
      height: 42px;
      margin-right: 15px !important;   /* â† restores the spacing */
      border-radius: 50%;
      box-sizing: border-box;
      /* Clicking an avatar opens that member's My Cloud. */
      cursor: pointer;
  }

  /* The name typed into a message opens the same My Cloud. It sits inside the
     message text, so a pointer on hover signals it without inviting a click
     mid-sentence. */
  .chat-inline-username {
    cursor: pointer;
  }

  /* Follower / Following entries on the account page open the same My Cloud. */
  .follow-item[data-username] {
    cursor: pointer;
  }

  .follow-item[data-username]:hover {
    border-color: #1f6fd6;
  }

/* Thin tier-colour ring around avatars */
.tier-ring {
    border: 2px solid transparent;
    padding: 0;
}

.tier-green { border-color: #3ecf55; }
.tier-yellow { border-color: #ffd34d; }
.tier-blue { border-color: #4ea3ff; }
.tier-gold { border-color: #ffb020; }
.tier-red { border-color: #ff4d4d; }

  
  .chat-content {
    display: flex;
    flex-direction: column;
    max-width: 80%;
  }

  .chat-actions {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
    margin-left: auto;
    padding-top: 6px;
  }

  .chat-actions .chat-follow-btn,
  .chat-actions .chat-delete-btn,
  .chat-actions .chat-report-btn {
    margin-left: 0;
  }

  .chat-actions .chat-follow-btn {
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.15s ease;
  }

  /* The follow "+" was inheriting whatever colour the row theme set, which on
     several backgrounds left it nearly invisible. Pin it white with a dark
     halo so it reads on any background. */
  .chat-actions .chat-follow-btn,
  body[data-theme] .chat-actions .chat-follow-btn {
    color: #fff;
    /* The plain .chat-follow-btn rule further down paints a blue ring; this
       selector outranks it, so restate the border to keep the icon all white. */
    border-color: rgba(255, 255, 255, 0.9);
    font-size: 18px;
    font-weight: 700;
    line-height: 1;
    text-shadow: 0 0 4px rgba(0, 0, 0, 0.85), 0 0 8px rgba(0, 0, 0, 0.55);
  }

  @media (hover: hover) {
  .chat-row:hover .chat-actions .chat-follow-btn {
    opacity: 1;
    pointer-events: auto;
  }
}
  
  .chat-username {
    font-weight: 700;
    color: #fff;
    text-shadow: 0 0 4px rgba(0, 0, 0, 0.6);
    margin-bottom: 2px;
  }
  
  .chat-text {
    /* Fully transparent. This carried a solid #1b1b21 slab (and each theme
       pinned its own: #2c2c33 light, #1a1a1f dark, a blurred glass in blue),
       which put a grey panel behind every message and stacked rows into one
       continuous block. No background and no shadow now -- the text carries its
       own legibility via the white fill and the black glow below, so a photo
       or video behind the feed shows through everywhere.

       The hover / tap highlight that used to repaint this is gone too, since a
       highlight means a background. Readability over the feed is what the glow
       is for. */
    background: transparent;
    padding: 10px 14px;
    border-radius: 12px;
    box-shadow: none;
    word-break: break-word;
    color: #fff;
    text-shadow: 0 0 4px rgba(0, 0, 0, 0.6);
  }

  .chat-image {
    display: block;
    max-width: 240px;
    max-height: 240px;
    margin-top: 8px;
    border-radius: 10px;
    border: 2px solid rgba(255, 255, 255, 0.85);
    object-fit: cover;
    cursor: pointer;
  }

  .chat-youtube {
    position: relative;
    width: 100%;
    max-width: 360px;
    aspect-ratio: 16 / 9;
    margin-top: 8px;
    border-radius: 10px;
    overflow: hidden;
    border: 2px solid rgba(255, 255, 255, 0.85);
    background: #0f1626;
  }

  .chat-youtube iframe {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    border: 0;
  }

  .chat-image-expiry {
    font-size: 11px;
    color: #6b8cbf;
    margin-top: 4px;
    opacity: 0.9;
  }

  .chat-delete-btn {
    margin-left: 6px;
    background: transparent;
    border: none;
    cursor: pointer;
    width: 20px;
    height: 20px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    padding: 2px;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.15s ease, background 0.15s ease;
    vertical-align: middle;
  }

  /* The delete bin sat at opacity 0.6 on every row forever, so a permanent
     trash icon ran down the whole feed. Treat it like the follow "+": hidden
     until the row is hovered (or its avatar tapped on touch). */
  @media (hover: hover) {
  .chat-row:hover .chat-actions .chat-delete-btn {
    opacity: 0.85;
    pointer-events: auto;
  }

  .chat-row:hover .chat-actions .chat-report-btn {
    opacity: 0.85;
    pointer-events: auto;
  }
}

  .chat-delete-btn .chat-delete-icon {
    width: 13px;
    height: 13px;
    display: block;
    pointer-events: none;
  }

  .chat-delete-btn:hover {
    opacity: 1;
    background: rgba(31, 111, 214, 0.12);
  }

  .chat-report-btn {
    margin-left: 6px;
    background: transparent;
    border: none;
    cursor: pointer;
    width: 20px;
    height: 20px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    padding: 2px;
    /* Hidden like the follow "+" and the delete bin. The flag was left at a
       standing 0.85, so every row carried a permanent report icon down the
       feed. Revealed on row hover, or by tapping the avatar on touch. */
    opacity: 0;
    pointer-events: none;
    /* Was a dark maroon (#7b241c) that vanished into the bubble background.
       White with a dark halo keeps it legible against every theme. */
    color: #fff;
    font-size: 15px;
    line-height: 1;
    text-shadow: 0 0 4px rgba(0, 0, 0, 0.85), 0 0 8px rgba(0, 0, 0, 0.55);
    transition: opacity 0.15s ease, background 0.15s ease;
    vertical-align: middle;
  }

  body[data-theme] .chat-report-btn {
    color: #fff;
  }

  .chat-report-btn:hover {
    opacity: 1;
    background: rgba(192, 57, 43, 0.12);
  }

  .report-preview {
    background: #eef5ff;
    border: 1px solid #cfe0ff;
    border-radius: 10px;
    padding: 10px 12px;
    font-size: 13px;
    color: #164a8f;
    margin-bottom: 10px;
    max-height: 90px;
    overflow-y: auto;
    word-break: break-word;
  }

  /* QUICK VOTE BANNER Ã¢â‚¬â€ docked under the HUD, below the pinned question */
  .quick-vote-banner {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    z-index: 89;
    background: linear-gradient(90deg, #5b3bb8, #37217a);
    color: #fff;
    padding: 7px 14px;
    display: flex;
    align-items: center;
    gap: 10px;
    font-size: 14px;
    box-shadow: 0 3px 10px rgba(0, 0, 0, 0.25);
  }
  .quick-vote-banner[hidden] {
    display: none !important;
  }
  .quick-vote-banner .qv-pin {
    width: 18px;
    height: 18px;
    object-fit: contain;
    flex-shrink: 0;
  }
  .quick-vote-banner .qv-text {
    font-weight: 700;
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .quick-vote-banner .qv-by {
    font-size: 12px;
    opacity: 0.9;
    flex-shrink: 0;
  }
  .quick-vote-banner .qv-actions {
    display: flex;
    align-items: center;
    gap: 6px;
    flex-shrink: 0;
  }
  .quick-vote-banner .qv-btn {
    border: none;
    border-radius: 14px;
    padding: 5px 14px;
    font-size: 13px;
    font-weight: 700;
    cursor: pointer;
    transition: 0.15s ease;
  }
  .quick-vote-banner .qv-btn.yes {
    background: #d4edda;
    color: #1e8449;
    border: 2px solid #a9dfbf;
  }
  .quick-vote-banner .qv-btn.yes.active {
    background: #1e8449;
    color: white;
  }
  .quick-vote-banner .qv-btn.no {
    background: #fce4e4;
    color: #7b241c;
    border: 2px solid #f5b7b1;
  }
  .quick-vote-banner .qv-btn.no.active {
    background: #c0392b;
    color: white;
  }
  .quick-vote-banner .qv-btn:disabled {
    opacity: 0.55;
    cursor: not-allowed;
  }
  .quick-vote-banner .qv-close {
    flex-shrink: 0;
    background: rgba(255, 255, 255, 0.18);
    border: none;
    color: #fff;
    border-radius: 50%;
    width: 22px;
    height: 22px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 13px;
    cursor: pointer;
    transition: 0.15s ease;
  }
  .quick-vote-banner .qv-close:hover {
    background: rgba(255, 255, 255, 0.38);
  }
  .quick-vote-banner .qv-close:disabled {
    opacity: 0.5;
    cursor: not-allowed;
  }
  .quick-vote-banner .qv-close-icon {
    width: 12px;
    height: 12px;
    display: block;
    pointer-events: none;
    filter: brightness(0) invert(1);
  }

  /* POLL BANNER Ã¢â‚¬â€ docked under the HUD / pinned question / quick vote */
  .poll-banner {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    z-index: 88;
    background: linear-gradient(90deg, #2e9e57, #1d6b3c);
    color: #fff;
    padding: 7px 14px;
    display: flex;
    align-items: center;
    gap: 10px;
    font-size: 14px;
    box-shadow: 0 3px 10px rgba(0, 0, 0, 0.25);
  }
  .poll-banner[hidden] {
    display: none !important;
  }
  .poll-banner .pl-pin {
    width: 18px;
    height: 18px;
    object-fit: contain;
    flex-shrink: 0;
  }
  .poll-banner .pl-text {
    font-weight: 700;
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .poll-banner .pl-by {
    font-size: 12px;
    opacity: 0.9;
    flex-shrink: 0;
  }
  .poll-banner .pl-actions {
    display: flex;
    align-items: center;
    gap: 6px;
    flex-shrink: 0;
  }
  .poll-banner .pl-btn {
    border: none;
    border-radius: 14px;
    padding: 5px 14px;
    font-size: 13px;
    font-weight: 700;
    cursor: pointer;
    transition: 0.15s ease;
    background: #fff;
    color: #1d6b3c;
  }
  .poll-banner .pl-btn.active {
    background: #1d6b3c;
    color: #fff;
  }
  .poll-banner .pl-btn:disabled {
    opacity: 0.55;
    cursor: not-allowed;
  }
  .poll-banner .pl-close {
    flex-shrink: 0;
    background: rgba(255, 255, 255, 0.18);
    border: none;
    color: #fff;
    border-radius: 50%;
    width: 22px;
    height: 22px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 13px;
    cursor: pointer;
    transition: 0.15s ease;
  }
  .poll-banner .pl-close:hover {
    background: rgba(255, 255, 255, 0.38);
  }
  .poll-banner .pl-close:disabled {
    opacity: 0.5;
    cursor: not-allowed;
  }
  .poll-banner .pl-close-icon {
    width: 12px;
    height: 12px;
    display: block;
    pointer-events: none;
    filter: brightness(0) invert(1);
  }

  .poll-options-list {
    display: flex;
    flex-direction: column;
    gap: 6px;
    margin: 2px 0 10px;
  }
  .poll-options-list .popup-input {
    margin: 0;
  }

  .vote-closed-label {
    font-size: 12px;
    font-weight: 700;
    color: #4a6fa8;
    margin-left: 6px;
  }

  .vote-modal {
    position: fixed;
    inset: 0;
    background: rgba(15, 40, 80, 0.55);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 10000;
  }

  .vote-modal-box {
    background: white;
    color: #164a8f;
    border-radius: 16px;
    box-shadow: 0 20px 60px rgba(0,0,0,0.3);
    padding: 22px;
    width: 340px;
    max-width: 90vw;
  }

  .vote-modal-title {
    font-size: 18px;
    font-weight: 800;
    color: #1f6fd6;
    margin-bottom: 12px;
  }

  .vote-modal-actions {
    display: flex;
    gap: 10px;
    margin-top: 14px;
  }

  .vote-modal-actions .popup-item {
    flex: 1;
    text-align: center;
  }

  /* The action buttons (Send / Cancel / Pin It / Post Vote ...) are plain
     .popup-item rows, so they inherited the theme's text colour -- white in the
     dark and blue themes -- on the modal's white box, making them invisible.
     Give every action a real button look so it is clear what each one does. */
  .vote-modal .vote-modal-actions .popup-item {
    flex: 1;
    justify-content: center;
    text-align: center;
    padding: 10px 14px;
    margin: 0;
    border: 1px solid #1f6fd6;
    border-radius: 10px;
    background: linear-gradient(#2e86ff, #1f6fd6);
    color: #ffffff;
    font-weight: 700;
    box-shadow: 0 2px 6px rgba(31, 111, 214, 0.35);
    transition: background 0.12s ease, box-shadow 0.12s ease;
  }

  .vote-modal .vote-modal-actions .popup-item:hover {
    background: linear-gradient(#5aa0ff, #2e86ff);
    color: #ffffff;
    box-shadow: 0 4px 12px rgba(31, 111, 214, 0.55);
  }

  .vote-modal-wide {
    width: 460px;
    max-width: 92vw;
  }

  /* Preview of the image about to be posted, shown above the caption field. */
  .image-caption-preview {
    display: block;
    width: 100%;
    max-height: 40vh;
    object-fit: contain;
    border-radius: 10px;
    background: #0f1626;
    margin-bottom: 10px;
  }

  /* Full view: shared chat images open here on click or finger tap. */
  .image-full-view {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.9);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 10001;
    padding: 16px;
    box-sizing: border-box;
  }

  .image-full-view-img {
    max-width: 100%;
    max-height: 100%;
    object-fit: contain;
    border-radius: 8px;
  }

  .image-full-view-close {
    position: absolute;
    top: 12px;
    right: 12px;
    width: 40px;
    height: 40px;
    border: none;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.9);
    color: #164a8f;
    font-size: 26px;
    line-height: 1;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
  }

  /* ================================
     GAMES LOBBY + GAME ROOMS
     ================================ */

  /* The lobby is a plain surface: no media backdrop shows through behind it. */
  body.cc-games-room #mediaBackground,
  body.cc-games-room #mediaImage,
  body.cc-games-room #mediaVideo,
  body.cc-games-room #ytbg {
    display: none !important;
  }

  /* The lobby's own backdrop is part of the full-page black block below.

     The card grid is centred in whatever column it is given, rather than
     pinned to the top: with the chat now beside it the stage is a tall
     scrolling area, and top-aligned cards left a wide empty band under the
     last row. */
  .games-lobby {
    align-content: center;
  }

  .games-lobby {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
    gap: 14px;
    padding: 16px 4px 24px;
  }

  /* The card plate is opaque on purpose. It used to be a translucent white
     over the lobby wallpaper, and the wallpaper showed through brightly enough
     behind the card that the white title was unreadable on anything but the
     darkest part of the picture. The title sits on its own surface now. */
  .games-lobby-card {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    padding: 12px 10px;
    border-radius: 14px;
    background: #14141c;
    border: 2px solid rgba(255, 255, 255, 0.18);
    text-decoration: none;
    color: #fff;
    transition: transform 0.15s ease, border-color 0.15s ease, background 0.15s ease;
    position: relative;
  }

  .games-lobby-card:hover {
    transform: translateY(-2px);
    border-color: rgba(255, 255, 255, 0.55);
    background: #22222e;
  }

  /* Fully black well: several thumbnails are transparent PNG/GIFs, and a
     see-through well let the wallpaper bleed into the artwork edges. */
  .games-lobby-thumb {
    width: 100%;
    aspect-ratio: 1 / 1;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 10px;
    background: #000;
    overflow: hidden;
    position: relative;
  }

  .games-lobby-thumb img {
    max-width: 100%;
    max-height: 100%;
    object-fit: contain;
    display: block;
  }

  .games-lobby-title {
    font-size: 14px;
    font-weight: 700;
    text-align: center;
  }

  /* Music / Games lobby card love badge (top-right) */
  .music-lobby-love,
  .games-lobby-love {
    position: absolute;
    top: 4px;
    right: 4px;
    display: inline-flex;
    align-items: center;
    gap: 3px;
    background: rgba(8, 8, 14, 0.72);
    border: 1px solid rgba(255, 255, 255, 0.28);
    border-radius: 10px;
    padding: 1px 5px;
    font-size: 10px;
    font-weight: 700;
    color: #fff;
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.8);
    z-index: 1;
    pointer-events: none;
    backdrop-filter: blur(2px);
  }
  .music-lobby-love .music-love-icon,
  .games-lobby-love .music-love-icon {
    width: 10px;
    height: 10px;
    object-fit: contain;
    display: block;
  }

  /* â”€â”€ Games rooms: full-page black, HUD keeps the colour â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€
     Both the Games lobby and the "Games - <name>" rooms run on one surface:
     true black from edge to edge, so the only colour on the page is the top
     HUD band and the artwork inside the game frame.

     This has to name every layer rather than just the body, because each one
     paints its own backdrop and the stack is layered -- body < .chatroom-body
     < #chatFeed < .chat-input-bar. Blacking only the top layer lets the
     navy phone-cell (#0a0a10) show through the gaps between and below them,
     which is what left the page looking dark navy instead of black. */
  body.cc-games-room {
    background: #000 !important;
  }

  body.cc-games-room .chatroom-body,
  body.cc-games-room #chatFeed,
  body.cc-games-room .chat-input-bar {
    background: #000 !important;
  }

  body.cc-games-room .chat-input-bar,
  body.cc-games-room .chat-input-bar * {
    background: #000 !important;
    color: #f2f2f7 !important;
  }

  /* The field carries .chat-input as well as the id, and !important, for the
     same reason the dark-theme block at the end of this file does: the inline
     <style> in chatcloud.html sets `body[data-theme="dark"] #chatInputTop`
     after this sheet, both are !important, and at equal specificity the later
     one won -- so the room fell back to the charcoal --phone-cell (#15151f)
     instead of this grey. The extra class outranks it and the field reads as a
     grey box again, with white text. */
  body.cc-games-room #chatInputTop.chat-input {
    background: #2f2f3a !important;
    color: #f2f2f7 !important;
    border: 1px solid #3d3d4a !important;
  }

  body.cc-games-room #chatInputTop.chat-input:focus {
    border-color: #4ea3ff !important;
  }

  /* The stage is the black plate the game frame sits on. */
  body.cc-games-room #gameStage,
  body.cc-games-room .game-stage-frame {
    background: #000 !important;
  }

  /* A thin gold frame around the game, inside the chat room rather than inside
     the game page.

     The game draws its own edge on its body, but that is the viewport edge of
     an iframe -- the moment the frame is scaled to its column there is a hair
     of black left outside it, and the page reads as a lit rectangle floating in
     a black room. Drawing the border here as well closes that seam and ties the
     game to the room.

     Matching the in-page frame: 2px of #ffcc00, the same gold the HUD and the
     jackpot cells already use for their own borders. */
  body.cc-game-room .game-stage-frame {
    box-sizing: border-box;
    border: 1px solid #ffcc00;
    box-shadow: 0 0 18px rgba(255, 204, 0, 0.35);
  }

  /* A game room has no room wallpaper: the game is the picture, and a stored
     topic background would tint both the black plate and the chat column. */
  body.cc-game-room #mediaBackground,
  body.cc-game-room #mediaImage,
  body.cc-game-room #mediaVideo,
  body.cc-game-room #ytbg {
    display: none !important;
  }

  /* The HUD is the one band that keeps its colour, and it is the Lobby's
     colour, not a games-specific one: solid --blue-base with the --blue-deep
     underline that .top-hud already uses in cloud.css. The Games lobby and
     the "Games - <name>" rooms should read as the same site the member just
     came from, and hard-coding a purple here made them look like a different
     product sitting one click away.

     The doubled class is not a typo. chatcloud.html carries its own
     `body:not([data-theme="blue"]) .top-hud` block in a <style> that loads
     AFTER this stylesheet, and :not() contributes the specificity of its
     argument -- so that selector also scores 0,2,1. At equal specificity with
     both rules !important, the later one in source order simply won, and the
     games rooms kept the phone-black bar no matter what was set here.
     Repeating the class lifts this to 0,3,1 and settles it on the merits
     rather than on which file happens to load last.

     Declared with the same fallbacks as the base rule so it still renders if
     the custom properties are ever unavailable. */
  body.cc-games-room.cc-games-room .top-hud {
    background: var(--blue-base, #1f6fd6) !important;
    color: var(--blue-text, #ffffff) !important;
    border-bottom: 3px solid var(--blue-deep, #164a8f) !important;
    box-shadow: 0 3px 10px rgba(0, 0, 0, 0.6) !important;
  }

  /* The HUD's own cells follow it -- hover chips and the Tools dropdown are
     blue-on-blue in the Lobby, and they were left dark here. Same specificity
     reason as the bar above. */
  body.cc-games-room.cc-games-room .cc-tip,
  body.cc-games-room.cc-games-room .hud-center #hudTopicName::after,
  body.cc-games-room.cc-games-room .tools-menu {
    background: var(--blue-deep, #164a8f) !important;
    border-color: var(--blue-base, #1f6fd6) !important;
    color: var(--blue-text, #ffffff) !important;
  }

  body.cc-games-room.cc-games-room .tools-item:hover {
    background: var(--blue-base, #1f6fd6) !important;
    color: #ffffff !important;
  }

  /* The topic-name chip is written in the phone-label grey, which is legible on
     the charcoal bar but not on solid blue. */
  body.cc-games-room.cc-games-room .hud-center,
  body.cc-games-room.cc-games-room .hud-center #hudTopicName {
    color: var(--blue-text, #ffffff) !important;
  }

  /* The lobby uses the same two-column shape as a game room -- the card grid
     on the left, the room's own chat in a fixed column on the right -- so
     moving between the lobby and a Pokie does not rearrange the page.

     The grid tracks and the chat column width are deliberately identical to
     the cc-game-room rules below: same left column, same clamp() for the
     chat, so the HUD icons, the feed and the input bar all land in exactly
     the same places in both rooms.

     The stage spans both rows (1 / 3) because the input bar belongs to the
     chat column only -- the card grid is not a chat surface and has nothing
     to put an input row under. */
  body.cc-games-room:not(.cc-game-room) .chatroom-body {
    display: grid;
    grid-template-columns: minmax(0, 1fr) clamp(260px, 22vw, 380px);
    grid-template-rows: minmax(0, 1fr) auto;
  }

  body.cc-games-room:not(.cc-game-room) #gamesStage {
    grid-column: 1;
    grid-row: 1 / 3;
    min-width: 0;
    min-height: 0;
    overflow-y: auto;
    background: url("/img/games-lobby-bg.jpg") center / cover no-repeat #000;
  }

  body.cc-games-room:not(.cc-game-room) #chatFeed {
    grid-column: 2;
    grid-row: 1;
  }

  /* Same right-padding reservation as a game room: the bottom tool icons are
     position:absolute against the room and land on top of a chat column this
     narrow otherwise. They moved up to their own row above the field (see
     "the chat field in the games column" below), so the bar keeps its normal
     10px and the field takes the width they used to reserve. */
  body.cc-games-room:not(.cc-game-room) .chat-input-bar {
    grid-column: 2;
    grid-row: 2;
    padding-bottom: calc(10px + env(safe-area-inset-bottom, 0px));
  }

  /* Hidden by default in the markup, so it must not reserve a column in the
     other rooms -- same reason as #gameStage below. */
  #gamesStage[hidden] {
    display: none !important;
  }

  .games-stage {
    min-height: 0;
  }

  /* â”€â”€ A Pokie plays in the body of its own topic â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€
     Desktop: the game takes the room and the chat sits in a fixed column on
     the right, so the game keeps roughly three quarters of the width. The
     artwork stays as the room background behind both.

     The stage is a sibling of the feed rather than a child, so posting in the
     room can never push the game out of view. */
  body.cc-game-room .chatroom-body {
    display: grid;
    grid-template-columns: minmax(0, 1fr) clamp(260px, 22vw, 380px);
    grid-template-rows: minmax(0, 1fr) auto;
  }

  body.cc-game-room #gameStage {
    grid-column: 1;
    grid-row: 1 / 3;
    min-width: 0;
    min-height: 0;
    display: flex;
    padding: 10px;
    box-sizing: border-box;
  }

  body.cc-game-room #chatFeed {
    grid-column: 2;
    grid-row: 1;
  }

  /* The bottom tool icons are position:absolute against the room, not the input
     bar. In a full-width room they land clear of the text field, but the chat
     column here is only ~313px, so they sat on top of it and made both unusable.
     They now sit on their own row above the field (see "the chat field in the
     games column" below), so the bar keeps its normal 10px and the field takes
     the width the icons used to reserve. */
  body.cc-game-room .chat-input-bar {
    grid-column: 2;
    grid-row: 2;
    padding-bottom: calc(10px + env(safe-area-inset-bottom, 0px));
  }

  body.cc-game-room .chat-input {
    width: 100%;
  }

  /* â”€â”€ The chat field in the games column â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€
     Both games rooms carry .cc-games-room -- the lobby and each game -- so one
     rule covers both, and the chat column is the only surface the field has
     there. Two things change:

     1. WIDTH -- the chat column is the only surface the field has in a games
     room, so it spans 95% of it, measured from the column itself. The bar
     drops its side padding (the 40px left indent in #chatInputTop was a
     desktop-room leftover -- there is nothing to indent past here) and the
     field takes 95% of what is left, centred, so the auto margins absorb the
     slack instead of the field growing into it. It can still shrink below
     that when a special game room shows its Start / Hint buttons, or the
     phone's send button, so those never push the field off the edge.

     2. HEIGHT -- the bar is the bottom row of the room grid and #chatFeed is
     the row above it, so every line the field adds is taken off the feed: the
     field already grows upward. What stopped it was the cap -- 200px
     (.chat-input), and only 5.4em on a phone, which put a scrollbar in the
     field after three lines. A paragraph is the unit of typing here, so the
     cap is now 45vh -- and capped at 320px so a short, wide window cannot
     starve the feed -- and the field grows up to it before it scrolls. */
  body.cc-games-room .chat-input-bar {
    padding-left: 0;
    padding-right: 0;
  }

  body.cc-games-room .typing-indicator {
    padding-left: 10px;
    padding-right: 10px;
  }

  body.cc-games-room #chatInputTop.chat-input {
    flex: 1 1 auto;
    min-width: 0;
    width: 95%;
    max-width: 95%;
    /* Auto margins both sides: the 5% the cap leaves over is split between
       them, so the field sits centred on the column instead of hugging one
       edge of it. */
    margin-left: auto;
    margin-right: auto;
    max-height: min(45vh, 320px);
    /* Tapping or clicking the field opens it up right there and then -- a
       paragraph's worth of height, before a single character is typed -- and
       it keeps growing off the feed as the paragraph fills it. Without this
       the field stayed a single line until the text outgrew it, which reads
       as "it does not expand". */
    min-height: 20px;
    transition: min-height 0.18s ease;
  }

  body.cc-games-room #chatInputTop.chat-input:focus {
    min-height: 132px;
  }

  /* The tools shared the bar with the field, and were the reason for the 74px
     right padding that kept the field at ~73% of the column. They sit on their
     own row above the field now, right-aligned -- where a phone has always had
     them -- which leaves the field the whole column to grow into. Absolute
     against the bar, so they ride up with it as the field grows. */
  body.cc-games-room #bottomRightTools {
    right: 12px;
    bottom: calc(100% + 8px);
    gap: 10px;
  }

  /* On a phone the field is the rounded capsule, the keyboard eats half the
     viewport, and the send button shares the row. So: vh is a promise the
     screen cannot keep (give the capsule a smaller ceiling), the ends square
     off (a pill cannot carry a field this tall), and the 95% gives back the
     send button's share -- .input-left wraps here, and a field at a flat 95%
     shoved the button onto its own row under it. */
  @media (max-width: 760px) {
    body.cc-games-room #chatInputTop.chat-input {
      max-height: 34vh;
      border-radius: 16px;
      max-width: calc(95% - 42px);
    }
  }

  /* â”€â”€ The column's scrollbars, and every layer of it, black â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€
     The games rooms are a black page, and the only light left in the column
     was what the browser painted of its own: #chatFeed and the field both
     scroll, and an unstyled scrollbar is a white bar with a white track --
     a pale strip down the chat column, and a pale line inside the field
     whenever a message runs past the cap. Color-scheme dark takes the native
     widgets with it (caret, selection, scrollbars); the two rules below cover
     the engines that ignore it. */
  body.cc-games-room {
    color-scheme: dark;
  }

  body.cc-games-room #chatFeed,
  body.cc-games-room #chatInputTop.chat-input {
    scrollbar-width: thin;
    scrollbar-color: #3a3a44 #000;
  }

  body.cc-games-room #chatFeed::-webkit-scrollbar,
  body.cc-games-room #chatInputTop.chat-input::-webkit-scrollbar {
    width: 8px;
  }

  body.cc-games-room #chatFeed::-webkit-scrollbar-track,
  body.cc-games-room #chatInputTop.chat-input::-webkit-scrollbar-track {
    background: #000;
  }

  body.cc-games-room #chatFeed::-webkit-scrollbar-thumb,
  body.cc-games-room #chatInputTop.chat-input::-webkit-scrollbar-thumb {
    background: #3a3a44;
    border-radius: 4px;
  }

  /* The stage is hidden by default in the markup and only filled in by
     mountGameRoom(), so it must not reserve a column in other rooms. */
  #gameStage[hidden] {
    display: none !important;
  }

  .game-stage-frame {
    width: 100%;
    height: 100%;
    border: none;
    border-radius: 12px;
    background: rgba(0, 0, 0, 0.5);
  }

  @media (max-width: 760px) {
    .games-lobby {
    grid-template-columns: repeat(auto-fill, minmax(104px, 1fr));
    gap: 10px;
    }

    .games-lobby-title {
      font-size: 12px;
    }



    /* â”€â”€ The Games lobby on a phone â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€
       The desktop layout gives the chat a fixed right column. On a phone
       there is no room for both, and squeezing the cards into whatever is
       left would drop them to two per row and push the chat off the bottom.

       So the lobby goes back to one column: the card grid scrolls in the
       space above and the chat sits under it, exactly as it did before the
       two-column layout existed. The card grid keeps its own overflow so it
       takes the room it needs rather than growing the page. */
    body.cc-games-room:not(.cc-game-room) .chatroom-body {
      display: flex;
      flex-direction: column;
    }

    body.cc-games-room:not(.cc-game-room) #gamesStage {
      flex: 1;
      min-height: 0;
      overflow-y: auto;
    }

    /* No right-hand reservation here any more: the bottom-right tools sit on
       their own row above the field in a games room, so on a phone the bar is
       the plain one above. */
  }

  /* â”€â”€ A game room on a phone â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€
     A phone has no room for two columns, so the grid collapses to one and
     the game and the chat stack: cabinet on top, chat under it. Both are
     always on screen -- there is nothing to swap between and no icon that
     would try. */
  @media (max-width: 760px) {
    body.cc-game-room .chatroom-body {
      display: flex;
      flex-direction: column;
    }

    body.cc-game-room #gameStage {
      flex: 1;
      min-height: 0;
      padding: 8px;
    }

    /* ── A game room shows the game AND the chat, one above the other ──
       On a phone this room used to be an either/or -- the cabinet hidden
       to show the chat, the chat hidden to show the cabinet, and an icon
       that swapped between the two -- which meant you could play or you
       could talk, and finding out what anyone had said meant giving up
       the game first.

       They stack instead, and nothing is hidden any more: the feed is
       capped so it cannot squeeze the cabinet off the screen, and takes
       what is left of the column on a taller phone. */
    body.cc-game-room #chatFeed {
      flex: 0 0 auto;
      max-height: 42vh;
      overflow-y: auto;
    }

    /* ── The lobbies have no chat on a phone ───────────────────────────
       The Games lobby and the Music lobby are rooms ABOUT the games and
       the songs -- a card grid you browse and tap into. On a phone they
       collapsed to a single column, which put the room's own chat under
       the whole grid: you landed on the cards and had to scroll past a
       screen of them to find out anyone had spoken.

       So on a phone the lobby is the lobby and nothing else. The chat goes
       with it, and so does the toggle that would bring it back -- the
       actual rooms keep theirs: a game room is a game plus its chat, and a
       "Music - <genre>" room is a video plus its chat. Neither of those is
       a lobby, and neither is touched here.

       Scoped with :not(.cc-game-room) so a game room keeps the rules
       above, and to max-width:760px so a desktop -- which has the width
       for both columns, and where the lobby chat is the point -- is
       unaffected. */
    body.cc-games-room:not(.cc-game-room) #chatFeed,
    body.cc-games-room:not(.cc-game-room) .chat-input-bar,
    body.cc-music-room #chatFeed,
    body.cc-music-room .chat-input-bar {
      display: none !important;
    }
  }

  /* ── A Pokie cabinet scaled to fit ───────────────────────────────────
     fitGameFrame() renders the game at its 830px design width and scales the
     frame down when the stage is narrower, so all five reels stay visible and
     the footer buttons keep their places instead of bunching at the bottom.
     The frame's layout box is still 830px wide, hence clip the stage and hold
     the scaled cabinet centred (its transform-origin is its top centre). */
  body.cc-game-frame-scaled #gameStage {
    /* flex-start, not center: the frame's layout box is the full 830px
       design width, so centring an over-wide flex item pins its middle to
       the middle of the stage and pushes the outer reels out of view on
       both sides. Left-aligning it lets the scale transform -- anchored
       top-left -- bring all five reels into the stage. */
    justify-content: flex-start;
    align-items: flex-start;
    overflow: hidden;
  }

  /* The frame must actually BE 830px wide before it is scaled down.

     It is a flex item, and a flex item's default flex-shrink is 1 -- so the
     moment cloud.js set width:830px the browser shrank it straight back to
     the stage's width, the game laid itself out for 484px instead of 830px,
     and reels four and five were never drawn in the first place. Scaling
     that already-too-narrow box just made it smaller and still clipped.
     flex:0 0 auto keeps the design width; the transform does the shrinking,
     which is the only part that is visual. */
  body.cc-game-frame-scaled #gameStage .game-stage-frame {
    flex: 0 0 auto;
  }

  /* ================================
     MUSIC LOBBY + MUSIC ROOMS
     ================================ */

  /* The Music topic is a lobby in the same shape as Games: a grid of cards
     with the room's own chat in a fixed column on the right. Every
     "Music - <genre/decade>" room keeps that same right-hand chat column, with
     its YouTube backdrop showing through on the left.

     The class is doubled on the rules that set surfaces behind the media: a
     music room applies the "blue" media theme, whose later
     `body[data-theme="blue"] ...` rules would otherwise win the tie. The extra
     class lifts these to 0,3,1 so they settle on the merits. */

  body.cc-music-room {
    background: #000 !important;
    color-scheme: dark;
  }

  body.cc-music-room.cc-music-room .chatroom-body,
  body.cc-music-room.cc-music-room .chat-input-bar {
    background: #000 !important;
  }

  body.cc-music-room.cc-music-room .chat-input-bar,
  body.cc-music-room.cc-music-room .chat-input-bar * {
    background: #000 !important;
    color: #f2f2f7 !important;
  }

  body.cc-music-room.cc-music-room #chatInputTop.chat-input {
    background: #2f2f3a !important;
    color: #f2f2f7 !important;
    border: 1px solid #3d3d4a !important;
  }

  body.cc-music-room.cc-music-room #chatInputTop.chat-input:focus {
    border-color: #b06cff !important;
  }

  /* The HUD keeps the Lobby colour, same as the games rooms. */
  body.cc-music-room.cc-music-room .top-hud {
    background: var(--blue-base, #1f6fd6) !important;
    color: var(--blue-text, #ffffff) !important;
    border-bottom: 3px solid var(--blue-deep, #164a8f) !important;
    box-shadow: 0 3px 10px rgba(0, 0, 0, 0.6) !important;
  }

  body.cc-music-room.cc-music-room .cc-tip,
  body.cc-music-room.cc-music-room .hud-center #hudTopicName::after,
  body.cc-music-room.cc-music-room .tools-menu {
    background: var(--blue-deep, #164a8f) !important;
    border-color: var(--blue-base, #1f6fd6) !important;
    color: var(--blue-text, #ffffff) !important;
  }

  body.cc-music-room.cc-music-room .tools-item:hover {
    background: var(--blue-base, #1f6fd6) !important;
    color: #ffffff !important;
  }

  body.cc-music-room.cc-music-room .hud-center,
  body.cc-music-room.cc-music-room .hud-center #hudTopicName {
    color: var(--blue-text, #ffffff) !important;
  }

  /* Two-column shape: stage / video on the left, chat on the right. The
     tracks and chat column width match the games rooms exactly, so the HUD
     icons, feed and input bar land in the same places across all four. */
  body.cc-music-room .chatroom-body {
    display: grid;
    grid-template-columns: minmax(0, 1fr) clamp(260px, 22vw, 380px);
    grid-template-rows: minmax(0, 1fr) auto;
  }

  body.cc-music-room #musicStage {
    grid-column: 1;
    grid-row: 1 / 3;
    min-width: 0;
    min-height: 0;
    overflow-y: auto;
  }

  body.cc-music-room #chatFeed {
    grid-column: 2;
    grid-row: 1;
  }

  body.cc-music-room .chat-input-bar {
    grid-column: 2;
    grid-row: 2;
    padding-bottom: calc(10px + env(safe-area-inset-bottom, 0px));
  }

  #musicStage[hidden] {
    display: none !important;
  }

  .music-stage {
    min-height: 0;
  }

  /* The chat column is opaque: the lobby is its own surface, not a video room. */
  body.cc-music-room #chatFeed {
    background: #000 !important;
  }

  /* The lobby has no player of its own, so no media backdrop behind it. */
  body.cc-music-room #mediaBackground {
    display: none !important;
  }

  /* The music lobby's own backdrop: a deep violet wash behind the cards. */
  body.cc-music-room #musicStage {
    background:
      radial-gradient(1200px 600px at 20% 0%, rgba(139, 61, 255, 0.35), transparent 60%),
      radial-gradient(900px 500px at 90% 100%, rgba(216, 27, 96, 0.28), transparent 60%),
      #06060c;
  }

  /* The chat field fills the music column exactly as it does in a games room. */
  body.cc-music-room.cc-music-room .chat-input-bar {
    padding-left: 0;
    padding-right: 0;
  }

  body.cc-music-room.cc-music-room #chatInputTop.chat-input {
    flex: 1 1 auto;
    min-width: 0;
    width: 95%;
    max-width: 95%;
    margin-left: auto;
    margin-right: auto;
    max-height: min(45vh, 320px);
    min-height: 20px;
    transition: min-height 0.18s ease;
  }

  body.cc-music-room.cc-music-room #chatInputTop.chat-input:focus {
    min-height: 132px;
  }

  body.cc-music-room.cc-music-room #bottomRightTools {
    right: 12px;
    bottom: calc(100% + 8px);
    gap: 10px;
  }

  /* The loading / empty status line inside the lobby grid spans every column. */
  .music-lobby-status {
    grid-column: 1 / -1;
    padding: 24px 8px;
    text-align: center;
    color: #cfc9e6;
    font-size: 14px;
  }

  /* â”€â”€ The Music rooms on a phone â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€
     No room for two columns, so the grid collapses back to one: the cards (or
     the video) fill the space and the chat sits under them, as it did before
     the two-column layout existed. */
  @media (max-width: 760px) {
    body.cc-music-room .chatroom-body {
      display: flex;
      flex-direction: column;
    }

    body.cc-music-room #musicStage {
      flex: 1;
      min-height: 0;
      overflow-y: auto;
    }

    /* The music lobby's own backdrop: a deep violet wash behind the cards. */
    body.cc-music-room #musicStage {
      background:
        radial-gradient(1200px 600px at 20% 0%, rgba(139, 61, 255, 0.35), transparent 60%),
        radial-gradient(900px 500px at 90% 100%, rgba(216, 27, 96, 0.28), transparent 60%),
        #06060c;
    }
  }

  .my-votes-list {
    max-height: 46vh;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    gap: 10px;
  }

  .my-votes-empty {
    text-align: center;
    color: #1d4b8f;
    padding: 18px 8px;
    font-size: 14px;
  }

  .my-vote-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    background: #eef5ff;
    border: 1px solid #cfe0ff;
    border-radius: 12px;
    padding: 10px 14px;
  }

  .my-vote-info {
    min-width: 0;
  }

  .my-vote-question {
    font-weight: 700;
    color: #164a8f;
    font-size: 14px;
  }

  .my-vote-meta {
    font-size: 12px;
    color: #6b8cbf;
    margin-top: 3px;
  }

  .my-vote-delete {
    flex-shrink: 0;
    background: transparent;
    border: 1px solid #f5b7b1;
    color: #b03a2e;
    border-radius: 14px;
    padding: 4px 8px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: 0.15s ease;
  }

  .my-vote-delete-icon {
    width: 14px;
    height: 14px;
    display: block;
    pointer-events: none;
  }

  .my-vote-delete:hover {
    background: #fdecea;
    border-color: #e6a49d;
  }

  .my-vote-delete:disabled {
    opacity: 0.55;
    cursor: not-allowed;
  }
  

  .react {
    cursor: pointer;
    transition: transform 0.15s ease;
  }

  .react .react-love-icon {
    width: 16px;
    height: 16px;
    object-fit: contain;
    vertical-align: -2px;
    margin-right: 2px;
    pointer-events: none;
  }

  .react:hover {
    transform: scale(1.3);
  }
  
  .floating-react {
    position: fixed;
    font-size: 32px;
    pointer-events: none;
    z-index: 9999;
    animation: floatToAvatar 0.9s ease-out forwards;
  }

  .floating-react img {
    width: 32px;
    height: 32px;
    object-fit: contain;
  }
  
  /* The flight: out of the corner, up, then across to the avatar.

     --float-x / --float-y are the delta from the launch corner to the avatar,
     so the 45% stop sits a fifth of the way across and a fifth of the way up,
     pulled 64px further above that straight line -- the bend that reads as
     "up out of the corner, then over to you". A single straight translate
     between the same two points slid the icon sideways out of the corner
     instead of rising out of it. The 14% stop is the pop as it appears. */
  @keyframes floatToAvatar {
    0% {
      transform: translate(0, 0) scale(0.6);
      opacity: 0;
    }
    14% {
      transform: translate(0, -10px) scale(1);
      opacity: 1;
    }
    45% {
      transform:
        translate(calc(var(--float-x) * 0.2), calc(var(--float-y) * 0.2 - 64px))
        scale(1.08);
      opacity: 1;
    }
    100% {
      transform: translate(var(--float-x), var(--float-y)) scale(1);
      opacity: 1;
    }
  }
  
  .floating-react.shrink-phase {
    animation: shrinkIntoAvatar 0.4s ease-out forwards;
  }
  
  @keyframes shrinkIntoAvatar {
    0% {
      transform: translate(var(--float-x), var(--float-y)) scale(1);
      opacity: 1;
    }
    100% {
      transform: translate(var(--float-x), var(--float-y)) scale(0.1);
      opacity: 0;
    }
  }
  
  .chat-reactions .count {
    display: inline-block;
    width: 22px;
    text-align: left;
  }
  
  /* Bottom-right toolbar */
  #bottomRightTools {
    position: absolute;
    right: 20px;
    bottom: 20px;
    display: flex;
    gap: 14px;
    z-index: 9999;
  }

  /* Cloud Deck (Images) room: the deck's own controls -- last / play / next
     and the admin "add image" button -- sit in a row just above the input
     bar, in the same bottom-right corner as this icon stack. Without the
     lift the stack painted straight over the add button (z-index 9999 over
     the row's 80), so the admin control was unreachable. The offsets are the
     measured input-bar and vote-row heights (set in cloud.js), so the column
     lands just above the row on any bar height -- a wrapped phone composer
     included -- and whichever containing block the stack resolves against. */
  body.cc-deck-room #bottomRightTools {
    bottom: calc(var(--input-bar-h, 50px) + var(--deck-row-h, 42px) + 8px);
  }
  
  .br-icon {
    width: 30px;
    height: 30px;
    cursor: pointer;
    opacity: 0.9;
    position: relative;
    transition: transform 0.18s ease, opacity 0.18s ease;
    z-index: 1;
  }
  /* Bottom HUD icons zoom to 300% on hover */
  .br-icon:hover {
    transform: scale(3);
    opacity: 1;
    z-index: 60;
  }
  /* Game action buttons in the input bar (start / hint) */
  .br-icon.game-btn {
    flex-shrink: 0;
    margin-right: 4px;
  }
  .br-icon.game-btn:first-child {
    margin-left: -6px;
  }
  .br-icon.game-btn:hover {
    opacity: 1;
  }
  /* Pause + sound toggles in the input bar stay put on hover (no zoom) */
  .input-media-btn:hover {
    transform: none;
  }
  
  /* Popups */
  .br-popup {
    position: absolute;
    right: 20px;
    bottom: 70px;
    background: #222;
    color: #fff;
    padding: 12px;
    border-radius: 10px;
    width: 220px;
    display: none;
    box-shadow: 0 6px 16px rgba(0,0,0,0.25);
    z-index: 9999;
  }

  /* Popup text on the bottom HUD icons (dark blue #164a8f, like the top HUD) */
  .cc-tip {
    position: fixed;
    background: #164a8f;
    border: 1px solid #1f6fd6;
    color: #fff;
    padding: 4px 10px;
    border-radius: 6px;
    font-size: 12px;
    font-weight: 400;
    white-space: nowrap;
    box-shadow: 0 2px 6px rgba(0,0,0,0.4);
    pointer-events: none;
    opacity: 0;
    z-index: 999999;
    transition: opacity 0.15s ease;
  }
  .cc-tip.show {
    opacity: 1;
  }
  
  .br-popup.show {
    display: block;
  }
  
  .popup-item {
    padding: 8px 0;
    cursor: pointer;
    display: flex;
    align-items: center;
    gap: 8px;
  }

  .popup-item-icon {
    width: 18px;
    height: 18px;
    object-fit: contain;
    flex-shrink: 0;
  }
  
  .popup-item:hover {
    color: #4ea3ff;
  }
  
  .popup-title {
    font-weight: bold;
    margin-bottom: 6px;
  }

  .findme-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 8px 0;
  }

  .findme-text {
    flex: 1;
    min-width: 0;
  }

  .popup-item-label {
    font-weight: 600;
    font-size: 14px;
  }

  .findme-hint {
    font-size: 11px;
    opacity: 0.7;
    margin-top: 2px;
  }

  .findme-switch {
    position: relative;
    display: inline-block;
    width: 52px;
    height: 30px;
    flex-shrink: 0;
  }

  .findme-switch input {
    opacity: 0;
    width: 0;
    height: 0;
  }

  .findme-switch .slider {
    position: absolute;
    cursor: pointer;
    inset: 0;
    background: #8a97ab;
    border-radius: 30px;
    transition: 0.2s ease;
  }

  .findme-switch .slider:before {
    content: "";
    position: absolute;
    height: 24px;
    width: 24px;
    left: 3px;
    bottom: 3px;
    background: white;
    border-radius: 50%;
    transition: 0.2s ease;
    box-shadow: 0 1px 3px rgba(0,0,0,0.3);
  }

  .findme-switch input:checked + .slider {
    background: #2e9e63;
  }

  .findme-switch input:checked + .slider:before {
    transform: translateX(22px);
  }
  
  .popup-select {
    width: 100%;
    margin-bottom: 10px;
  }

  .popup-input {
    width: 100%;
    box-sizing: border-box;
    margin: 6px 0 10px;
    padding: 8px 10px;
    font-size: 14px;
    border-radius: 8px;
    border: 1px solid #c0d4ff;
    background: white;
    color: #164a8f;
  }

  .popup-btn {
    width: 100%;
    margin-bottom: 10px;
    padding: 8px 0;
  }
  
    /* ============================
     CHATING      
     ============================ */

#chatFeed {
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  overflow-y: auto;
  min-height: 0;
  height: auto;
  flex: 1;
  padding: 10px;
  }

  /* The conversation reads from the bottom up, the way a phone chat does:
     new messages sit just above the input bar and older ones run off the top.

     A zero-height leading pseudo-element with margin-top:auto absorbs the
     slack, which sinks the conversation to the bottom. justify-content:flex-end
     would do the same but can push the earliest rows above the scroll origin in
     a scrolling column, where they cannot be read back. The Bot Butler rows
     carry order:-1 so they sort BEFORE that anchor and take the first row at
     the top, instead of being dragged down with the messages. */
  #chatFeed::before {
    content: "";
    margin-top: auto;
  }

  /* Bot Butler gets the reserved row directly above the bottom HUD.

     order:1 sorts it AFTER the anchor pseudo-element and every message, so it
     is the last row in the column Ã¢â‚¬â€ sitting just above the input bar with the
     conversation stacked above it. Earlier this used order:-1 with
     position:sticky, which pinned it to the TOP of the feed; combined with the
     bottom-anchored conversation that put the greeting off-screen entirely,
     which is exactly where a reader looks for it.

     No sticky and no background needed now: the row is in normal flow at the
     end, so it never overlaps the messages. */
  #chatFeed .join-bubble {
    order: 1;
  }

  /* Butler's standing row. He is done talking and this is what he leaves in
     the reserved slot above the input, so it is marked a little differently
     from the ephemeral announcements that share the slot. */
  #chatFeed .join-bubble.butler-presence .chat-text {
    font-weight: 600;
  }
    
    
    
           
    

  /* Chat bubble wrap */
  .chat-bubble {
    /* Was rgba(173, 216, 230, 0.8). Same colour, alpha dropped -- this is the
       wrapper behind every row, so leaving it translucent put a see-through
       band behind each message. */
    background: transparent;
    border-radius: 14px;
    padding: 10px 12px;
    margin: 8px 0;
  }
  
  .chat-inline-username {
    font-weight: 700;
    color: #fff;
    text-shadow: 0 0 4px rgba(0, 0, 0, 0.6);
    margin-right: 6px;
  }

  .chat-follow-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    margin-left: 6px;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    border: 2px solid #1f6fd6;
    background: transparent;
    color: #1f6fd6;
    font-size: 14px;
    font-weight: 700;
    line-height: 1;
    cursor: pointer;
    padding: 0;
    transition: all 0.2s;
    vertical-align: middle;
  }

  .chat-follow-btn:hover {
    background: #1f6fd6;
    color: white;
  }

  .chat-follow-btn.following {
    background: #1f6fd6;
    color: white;
  }

  .chat-follow-btn:disabled {
    opacity: 0.5;
    cursor: default;
  }
  
  /* ================================
     EMOJI PICKER + PNG EMOJI SIZE
     ================================ */
  
  #emojiPicker {
    width: 240px;
    padding: 10px;
  }
  
  .emoji-grid {
    display: grid;
    grid-template-columns: repeat(6, 1fr);
    gap: 6px;
  }
  
  .emoji-item-img {
    width: 32px;
    height: 32px;
    object-fit: contain;
    cursor: pointer;
    padding: 1px;
    border-radius: 1px;
  }
  
  .emoji-item-img:hover {
    background: rgba(255,255,255,0.2);
  }
  
  .chat-emoji {
    width: 28px;
    height: 28px;
    object-fit: contain;
    vertical-align: middle;
  }
  
  .chat-input {
    width: 100%;
    min-height: 40px;
    max-height: 200px;
    overflow-y: auto;
    font-size: 18px;
    padding: 10px 50px 10px 14px;
    border-radius: 8px;
    border: none;
    outline: none;
    background: #ffffff;
    color: #164a8f;
  }
  
  .chat-input:empty:before {
    content: attr(data-placeholder);
    color: #7a9cc7;
    pointer-events: none;
  }
  
  /* ================================
     THEMES
     ================================ */
  
/* -------------------------------
   LIGHT MODE Ã¢â‚¬â€ ALMOST WHITE
-------------------------------- */
body[data-theme="light"] {
  background: #fafafa;        /* page background */
  color: #111;
}

/* main chat area */
body[data-theme="light"] .chatroom-body {
  background: #fdfdfd;        /* Ã¢â€ Â almost white (soft tint) */
  color: #111;
}

/* chat bubble */
body[data-theme="light"] .chat-bubble {
  background: transparent;        /* pure white bubble */
  color: #111;
}

/* username + text strip Ã¢â‚¬â€ dark glass, because all chat text is white
   (see the ONE WHITE block below) and would vanish on a near-white bubble */
body[data-theme="light"] .chat-username,
    body[data-theme="light"] .chat-text {
      background: transparent;
      color: #fff;
    }

body[data-theme="light"] #chatInputTop {
  background: #f7f7f7 !important;   /* Ã¢â€ Â soft offÃ¢â‚¬â€˜white */
  color: #111 !important;
  border: 1px solid #ddd !important;
}


/* -------------------------------
   DARK MODE Ã¢â‚¬â€ ALMOST GRAY STRIP
-------------------------------- */
body[data-theme="dark"] {
  background: #000;
  color: #fff;
}

body[data-theme="dark"] .chatroom-body {
  background: #000;
  color: #ffffff;
}

/* chat bubble (dark charcoal) */
body[data-theme="dark"] .chat-bubble {
  background: transparent;
  color: #fff;
}

/* username + text Ã¢â‚¬â€ SAME COLOR AS BUBBLE */
body[data-theme="dark"] .chat-username,
    body[data-theme="dark"] .chat-text {
      background: transparent;
      color: #fff;
    }

body[data-theme="dark"] #chatInputTop {
  background: #3a3a3a !important;   /* Ã¢â€ Â light gray */
  color: #fff !important;           /* Ã¢â€ Â white text */
  border: 1px solid #555 !important;
}



    
/* ============================
   MEDIA MODE
   ============================ */

   body[data-theme="blue"] .chat-row {
    background: transparent !important;   /* Ã¢â€ Â row stays normal */
  }
  
  body[data-theme="blue"] .chat-bubble {
    background: transparent !important;   /* Ã¢â€ Â bubble NOT glass */
    border: none !important;
    display: inline-block !important;     /* Ã¢â€ Â bubble shrinks to text */
    width: auto !important;
    max-width: 80%;
  }
/* ONLY the text gets the glass effect */
body[data-theme="blue"] .chat-text {
      background: transparent;
      padding: 6px 10px;
      border-radius: 6px;

  display: inline-block !important;     /* Ã¢â€ Â shrink to text */
  width: auto !important;

  color: #fff !important;               /* Ã¢â€ Â readable on any media */
  text-shadow: 0 0 4px rgba(0,0,0,0.6); /* Ã¢â€ Â readability booster */
}

  
  /* username stays normal */
  body[data-theme="blue"] .chat-username {
    background: transparent !important;
    color: #fff !important;
    display: inline-block !important;
    width: auto !important;
  }
  

    
  body[data-theme="blue"] .chat-avatar {
    opacity: 0.2;                 /* Ã¢â€ Â 60% transparent */
    transition: opacity 0.15s ease;
  }

  body[data-theme="blue"] .chat-row:hover .chat-avatar {
    opacity: 1;                   /* Ã¢â€ Â full opacity on hover */
  }
  

    /* POPUP MENUS KEEP BLACK BG */
    body[data-theme="blue"] .br-popup,
    body[data-theme="blue"] .tools-menu {
      background: rgba(0,0,0,0.85) !important;
      border: 1px solid rgba(255,255,255,0.25) !important;
      box-shadow: 0 6px 16px rgba(0,0,0,0.35) !important;
    }
    
    /* REMOVE FRAMES BUT KEEP SPACING */
    body[data-theme="blue"] .chat-content,
    body[data-theme="blue"] .chat-bubble {
      background: transparent !important;
      border: none !important;
      box-shadow: none !important;
      padding: 0 !important;
    }
    
    



  /* Character counter */
.char-counter {
  font-size: 14px;
  margin-top: 4px;
  opacity: 0.7;
  transition: color 0.2s ease;
  }

  /* Ã¢â€â‚¬Ã¢â€â‚¬ TYPING INDICATOR Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬
     Sits at the top of the input bar and reads "X is typing...". It
     takes no space when nobody is typing (display:none via the empty
     :empty rule) so the bar doesn't jump around as people talk. */
  .typing-indicator {
    display: block;
    font-size: 13px;
    font-weight: 700;
    font-style: italic;
    color: var(--phone-muted, #8e8e9c);
    padding: 0 2px 6px;
    min-height: 0;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    transition: opacity 0.2s ease;
  }

  /* Nothing to say: collapse the row entirely. */
  .typing-indicator:empty {
    display: none;
  }

  /* The three-dot pulse, kept subtle so it never competes with the
     messages themselves. */
  .typing-indicator .typing-dots::after {
    content: "";
    animation: typingDots 1.2s steps(4, end) infinite;
  }

  @keyframes typingDots {
    0% { content: ""; }
    25% { content: "."; }
    50% { content: ".."; }
    75% { content: "..."; }
  }

  /* Ã¢â€â‚¬Ã¢â€â‚¬ SEND BUTTON Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬
     Global, and hidden: Enter has always been how a PC user posts, so the
     desktop bar stays exactly as it was. The phone media query flips this
     to display:flex, because Enter is unreliable on a touch keyboard and
     there'd otherwise be no way to send. */
  .chat-send-btn {
    display: none;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    border: none;
    padding: 0;
    cursor: pointer;
  }

  .chat-send-btn svg {
    width: 17px;
    height: 17px;
    fill: #fff;
    pointer-events: none;
  }
  
  .char-counter.limit-reached {
    color: #ff4444;
    font-weight: 700;
  }
  
  #chatInputTop.limit-reached {
    box-shadow: 0 0 8px rgba(255, 80, 80, 0.7);
    border: 1px solid rgba(255, 80, 80, 0.9);
  }
  
  /* ============================
     MEDIA BACKGROUND (VIDEO ONLY)
     ============================ */
  
  #mediaBackground {
    position: fixed !important;
    top: 0 !important;
    left: 0 !important;
    width: 100vw !important;
    /* dvh, not vh: this layer is the full-bleed backdrop, so it has to track
       the viewport the OS is actually giving us. 100vh is measured with the
       address bar hidden, which left a strip of bare background under the media
       whenever the bar was showing -- on exactly the phones where the bar is
       always showing. */
    height: 100dvh !important;
    z-index: 0 !important;
    overflow: hidden !important;
    pointer-events: none !important;
  }
  
  #mediaBackground video {
    position: absolute !important;
    top: 0 !important;
    left: 0 !important;
    width: 100% !important;
    height: 100% !important;
    object-fit: cover !important;
    display: block !important;
    filter: brightness(0.7);
  }

  /* Covers the gap while a YouTube embed spins up. Sits under the iframe so it
     can never sit on top of a video that is already playing. */
  #mediaLoading {
    position: absolute !important;
    top: 0 !important;
    left: 0 !important;
    width: 100% !important;
    height: 100% !important;
    background: linear-gradient(160deg, #14335f 0%, #1f4f96 45%, #2b6fc4 100%);
    opacity: 1;
    transition: opacity 0.45s ease;
  }

  /* The safety net in JS clears the inline display; this keeps the fade. */
  #mediaLoading.media-loading-done {
    opacity: 0;
  }

  /* NB: no display declaration here. It used to force display:block !important,
     which beat the inline display:none the JS sets on #mediaImage whenever the
     backdrop is a YouTube embed or a <video>. With an empty src that left the
     element visible and the browser painted a broken/not-loaded image over the
     room. Visibility is driven by the inline style instead. */
  #mediaBackground img {
    position: absolute !important;
    top: 0 !important;
    left: 0 !important;
    width: 100% !important;
    height: 100% !important;
    object-fit: cover !important;
    filter: brightness(0.7);
  }

  /* Cloud Deck slideshow: show the full image (no cropping) with the room
     background visible in the letterbox bars around it. */
  #mediaBackground img.deck-fit {
    object-fit: contain !important;
    filter: none !important;
  }

  /* Cloud Deck room only: knock the whole background to black behind the
     slideshow images. */
  #mediaBackground.deck-bg {
    background: #000 !important;
  }

  #mediaBackground #ytbg {
    position: absolute !important;
    top: 0 !important;
    left: 0 !important;
    width: 100% !important;
    height: 100% !important;
    border: 0 !important;
    overflow: hidden !important;
    pointer-events: none !important;
    user-select: none !important;
    filter: brightness(0.7);
  }

  /* ── On a phone the video fills the strip you can actually see ─────
     The HUD and the chat input are opaque and sit ON TOP of the
     backdrop, so the only part of the video anyone ever sees is the
     strip between them: --media-band-top down from the top of the
     viewport, --media-band-bottom up from its bottom (measured in JS by
     fitMediaBackdropBand, which re-measures whenever either edge moves).

     Laid out for the whole viewport, a 16:9 video letterboxes: the
     picture runs the width of the phone and floats between two black
     bars, at a third of the height it could be. Sized to the strip
     instead -- and allowed to run wider than the phone, with the sides
     cropped off-screen by #mediaBackground's overflow:hidden -- it fills
     the strip edge to edge. The crop is the point: more picture, no
     bars, and nothing else about the interface changes.

     MUSIC ONLY. This crop only reads well on the 16:9 songs the Music
     rooms play, so it is keyed off body.cc-music-subroom (cloud.js sets
     that class on "Music - <genre/decade>" rooms). Every other media
     topic keeps the plain whole-viewport embed. */
  @media (max-width: 760px) {
    body.cc-music-subroom #mediaBackground #ytbg {
      top: var(--media-band-top, 0px) !important;
      left: 50% !important;
      width: calc(
        (100dvh - var(--media-band-top, 0px) - var(--media-band-bottom, 0px)) * 16 / 9
      ) !important;
      height: calc(
        100dvh - var(--media-band-top, 0px) - var(--media-band-bottom, 0px)
      ) !important;
      transform: translateX(-50%) !important;
    }

    /* Ambient mode (the interface has auto-hidden): there is no HUD or
       input left to avoid, so the song takes the whole screen -- the top
       and bottom strips go transparent and the picture runs under where
       the chrome was. */
    body.cc-music-subroom.cc-ambient #mediaBackground #ytbg {
      top: 0 !important;
      height: 100dvh !important;
      width: calc(100dvh * 16 / 9) !important;
    }
  }

/* ============================
   MEDIA MODE Ã¢â‚¬â€ FULL TRANSPARENCY
   ============================ */

   body[data-theme="blue"] {
    background: transparent !important;
    color: #fff !important;
  }
  
  /* EVERYTHING TRANSPARENT */
  body[data-theme="blue"] .top-hud,
  body[data-theme="blue"] .chatroom-body,
  body[data-theme="blue"] .chat-row,
  body[data-theme="blue"] .chat-content,
  body[data-theme="blue"] .chat-text,
  body[data-theme="blue"] .chat-bubble,
  body[data-theme="blue"] .chat-username,
  body[data-theme="blue"] .chat-reactions {
    background: transparent !important;
    border: none !important;
    box-shadow: none !important;
  }
  

/* -- HIGHLIGHTED ROW --------------------------------------------------
   A row used to be highlighted by repainting its bubble a lighter tone --
   #35353f on hover, and the same values on the .reveal-row-icons tap --
   which is what told you which row you were on. The bubbles are now
   transparent, and a background was the only way that trick worked, so the
   tints are gone rather than left in as rules that paint nothing.

   The row icons still reveal exactly as before; only the bubble tint went.
   To get the active row back WITHOUT a background, the glow on .chat-text
   is the place to go: a stronger text-shadow on hover reads the same way and
   stays transparent over photos and video. */
@media (hover: hover) {
  .chat-row:hover .chat-text {
    background: transparent !important;
  }

  body[data-theme="dark"] .chat-row:hover .chat-text {
    background: transparent !important;
  }

  body[data-theme="light"] .chat-row:hover .chat-text {
    background: transparent !important;
  }
}

@media (hover: none) {
  .chat-row.reveal-row-icons .chat-text {
    background: transparent !important;
  }

  body[data-theme="dark"] .chat-row.reveal-row-icons .chat-text {
    background: transparent !important;
  }

body[data-theme="light"] .chat-row.reveal-row-icons .chat-text {
    background: transparent !important;
  }
}

/* Media mode Ã¢â‚¬â€ bottom HUD fully transparent */
body[data-theme="blue"] .chat-input-bar {
  background: transparent !important;
  border-top: none !important;
}

  
  /* ONLY THE INPUT BOX HAS COLOR */
  body[data-theme="blue"] #chatInputTop {
    background: rgba(0,0,0,0.35) !important;  /* gray */
    backdrop-filter: blur(8px) !important;
    border: 1px solid rgba(255,255,255,0.25) !important;
    color: #fff !important;                   /* white text */
  }
  
  /* POPUP MENUS KEEP BLACK BG */
  body[data-theme="blue"] .br-popup,
  body[data-theme="blue"] .tools-menu {
    background: rgba(0,0,0,0.85) !important; /* BLACK */
    border: 1px solid rgba(255,255,255,0.25) !important;
    box-shadow: 0 6px 16px rgba(0,0,0,0.35) !important;
  }
  

/* REMOVE ALL CHAT BUBBLE / ROW / CONTENT FRAMES */
body[data-theme="blue"] .chat-row,
body[data-theme="blue"] .chat-content,
body[data-theme="blue"] .chat-text,
body[data-theme="blue"] .chat-bubble {
  padding: 0 !important;
  margin: 0 0 2px 0 !important;
}

/* KEEP MENUS AS-IS (NO OVERRIDE HERE) */

  
  /* ================================
     VIDEO PICKER ITEMS
     ================================ */
  
  .video-pick {
    padding: 8px 0;
    cursor: pointer;
    color: #fff;
  }
  
  .video-pick:hover {
    color: #4ea3ff;
  }
  
  /* Volume controls */
  #vidMute, #vidUnmute, #vidVol50, #vidVol100 {
    padding: 8px 0;
    cursor: pointer;
  }
  
  #vidMute:hover,
  #vidUnmute:hover,
  #vidVol50:hover,
  #vidVol100:hover {
    color: #4ea3ff;
  }
  
  /* Fix tall popup menu */
  .br-popup {
    max-height: 60vh;
    overflow-y: auto;
    overflow-x: hidden;
  }
  
  #mediaControls {
    display: flex;
    align-items: center;
    gap: 12px;
  }
  
  .media-btn {
    width: 18px;
    height: 18px;
    cursor: pointer;
    user-select: none;
  }

  /* Pointer to the keyboard shortcuts, printed under the media buttons.
     Inherits the popup's text colour and just softens it, so it stays
     readable in both dark and blue themes. */
  .media-keys-hint {
    font-size: 11px;
    line-height: 1.4;
    margin: -2px 0 10px;
    opacity: 0.65;
  }

  .media-keys-hint b {
    opacity: 1;
  }

  /* Input-bar media controls (play / sound / vertical volume) Ã¢â‚¬â€ shown only
     while the room is in media mode playing a YouTube source */
  .input-media-btn {
    flex-shrink: 0;
  }

  .toggle-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 6px 4px;
  }
  
  .toggle-label {
    font-size: 14px;
  }
  
  .toggle-icon {
    width: 18px;
    height: 18px;
    margin-left: 6px;
    object-fit: contain;
  }

  .join-bubble {
    opacity: 0.7;
  }
  
  .join-text {
    font-style: italic;
    color: #fff;
    text-shadow: 0 0 4px rgba(0, 0, 0, 0.6);
  }

  /* ================================================================
     ONE WHITE FOR EVERY WORD IN THE CHAT Ã¢â‚¬â€ the same white the message
     body already used (#fff plus a soft black glow so it stays legible
     over Cloud Deck / media photos). Usernames, the Bot Butler's name
     and the "(topic) welcome" line no longer carry colours of their own.
     The !important and the body[data-theme] duplicates are deliberate:
     the per-theme blocks above pin .chat-text and .chat-username to
     #111 or #fff, and this has to outrank them.
     ================================================================ */

  .chat-text,
  .chat-username,
  .chat-inline-username,
  .chat-text.join-text,
  body[data-theme] .chat-text,
  body[data-theme] .chat-username,
  body[data-theme] .chat-inline-username,
  body[data-theme] .chat-text.join-text {
    color: #fff !important;
    text-shadow: 0 0 4px rgba(0, 0, 0, 0.6) !important;
  }

  /* CHAT PAUSED BANNER */
  .pause-banner {
    position: absolute;
    top: 64px;
    left: 50%;
    transform: translateX(-50%);
    z-index: 100;
    background: rgba(255, 80, 80, 0.92);
    color: #fff;
    padding: 8px 18px;
    border-radius: 999px;
    font-weight: 600;
    font-size: 14px;
    box-shadow: 0 4px 14px rgba(0, 0, 0, 0.35);
    white-space: nowrap;
  }
  .pause-banner[hidden] {
    display: none !important;
  }

  /* DEBATE ROOM Ã¢â‚¬â€ fixed banner + run clock */
  .debate-banner {
    position: absolute;
    top: 52px;
    left: 50%;
    transform: translateX(-50%);
    z-index: 120;
    min-width: min(560px, 92vw);
    max-width: 92vw;
    background: rgba(24, 12, 40, 0.72);
    color: #fff;
    border-radius: 16px;
    padding: 12px 20px 14px;
    box-shadow: 0 10px 34px rgba(0, 0, 0, 0.45);
    border: 1px solid rgba(255, 214, 102, 0.35);
  }
  .debate-banner[hidden] {
    display: none !important;
  }
  .debate-banner-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 14px;
    flex-wrap: wrap;
  }
  .debate-banner-title {
    font-size: 15px;
    font-weight: 900;
    letter-spacing: 2px;
    color: #ffd666;
    text-shadow: 0 1px 4px rgba(0, 0, 0, 0.35);
  }
  .debate-banner-clock {
    display: flex;
    gap: 10px;
    align-items: stretch;
    opacity: 0.55;
  }
  .debate-banner-clock.running {
    opacity: 1;
  }
  .debate-count-cell {
    display: flex;
    flex-direction: column;
    align-items: center;
    min-width: 54px;
    background: rgba(255, 255, 255, 0.05);
    border-radius: 12px;
    padding: 6px 5px 5px;
    box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.08);
  }
  .debate-count-value {
    font-size: 30px;
    font-weight: 900;
    line-height: 1;
    color: #ffffff;
    font-variant-numeric: tabular-nums;
  }
  .debate-count-cell small {
    font-size: 10px;
    font-weight: 800;
    letter-spacing: 1px;
    color: #ffe9a8;
    margin-top: 3px;
  }
  .debate-banner-about {
    margin-top: 10px;
    padding: 8px 12px;
    background: rgba(255, 255, 255, 0.06);
    border-left: 3px solid #ffd666;
    border-radius: 8px;
    font-size: 14px;
    font-weight: 600;
    line-height: 1.45;
    color: #fdf6e3;
    white-space: pre-wrap;
    word-break: break-word;
  }
  .debate-banner-about[hidden] {
    display: none !important;
  }
  .debate-banner-note {
    margin-top: 8px;
    font-size: 12px;
    font-weight: 700;
    letter-spacing: 0.4px;
    color: #d8cfe8;
    min-height: 15px;
  }
  .debate-banner-note.running {
    color: #9ff0a5;
  }

  /* EVENT ROOM Ã¢â‚¬â€ big countdown + host controls */
  .event-countdown {
    position: absolute;
    top: 52px;
    left: 50%;
    transform: translateX(-50%);
    z-index: 120;
    box-sizing: border-box;
    min-width: min(560px, 92vw);
    background: rgba(0, 0, 0, 0.5);
    color: #fff;
    border-radius: 16px;
    padding: 14px 22px 16px;
    box-shadow: 0 10px 34px rgba(0, 0, 0, 0.45);
    border: 1px solid rgba(255, 255, 255, 0.1);
  }
  .event-countdown[hidden] {
    display: none !important;
  }
  .event-countdown-title {
    font-size: 15px;
    font-weight: 900;
    letter-spacing: 2px;
    color: #ffd75e;
    text-shadow: 0 1px 4px rgba(0, 0, 0, 0.35);
  }
  .event-countdown-clock {
    display: flex;
    gap: 14px;
    align-items: stretch;
  }
  .event-count-cell {
    display: flex;
    flex-direction: column;
    align-items: center;
    min-width: 60px;
    background: rgba(255, 255, 255, 0.05);
    border-radius: 12px;
    padding: 8px 6px 6px;
    box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.08);
  }
  .event-count-value {
    font-size: 44px;
    font-weight: 900;
    line-height: 1;
    color: #ffffff;
    font-variant-numeric: tabular-nums;
  }
  .event-count-cell small {
    font-size: 11px;
    font-weight: 800;
    letter-spacing: 1px;
    color: #cfe4ff;
    margin-top: 4px;
  }
  .event-countdown-note {
    font-size: 13px;
    font-weight: 700;
    color: #eaf3ff;
    min-height: 16px;
  }
  .event-countdown-actions {
    display: flex;
    gap: 10px;
    margin-top: 2px;
  }
  .event-host-btn {
    border: none;
    border-radius: 999px;
    padding: 8px 22px;
    font-size: 14px;
    font-weight: 900;
    cursor: pointer;
    background: #35b44a;
    color: #ffffff;
    box-shadow: 0 3px 8px rgba(0, 0, 0, 0.3);
    transition: 0.2s ease;
  }
  .event-host-btn:hover {
    background: #2a9340;
  }
  .event-cancel-btn {
    background: #e04f4f;
  }
  .event-cancel-btn:hover {
    background: #c23d3d;
  }

  /* EVENT LOCK SCREEN Ã¢â‚¬â€ MASSIVE full-room countdown for guests */
  .event-lock-overlay {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 110;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(0, 0, 0, 0.5);
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    text-align: center;
    padding: 20px;
    box-sizing: border-box;
  }
  .event-lock-overlay[hidden] {
    display: none !important;
  }
  .event-lock-inner {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 14px;
    max-width: 92vw;
  }
  .event-lock-label {
    display: flex;
    align-items: center;
    gap: 12px;
    font-size: clamp(20px, 3.4vw, 30px);
    font-weight: 900;
    letter-spacing: 4px;
    color: #ffd75e;
    text-shadow: 0 3px 12px rgba(0, 0, 0, 0.45);
  }
  .event-lock-icon {
    width: 34px;
    height: 34px;
    filter: brightness(0) invert(1);
  }
  .event-lock-clock {
    display: flex;
    align-items: center;
    gap: clamp(6px, 1.4vw, 20px);
  }
  .event-lock-cell {
    display: flex;
    flex-direction: column;
    align-items: center;
    min-width: clamp(86px, 14vw, 170px);
    background: rgba(255, 255, 255, 0.12);
    border: 1px solid rgba(255, 255, 255, 0.28);
    border-radius: clamp(14px, 2vw, 26px);
    padding: clamp(14px, 2.2vw, 30px) 10px clamp(12px, 2vw, 24px);
    box-shadow: 0 16px 44px rgba(0, 0, 0, 0.4), inset 0 1px 0 rgba(255, 255, 255, 0.25);
  }
  .event-lock-value {
    font-size: clamp(64px, 12vw, 148px);
    font-weight: 900;
    line-height: 1;
    color: #ffffff;
    font-variant-numeric: tabular-nums;
    text-shadow: 0 6px 24px rgba(0, 0, 0, 0.5);
  }
  .event-lock-cell small {
    font-size: clamp(11px, 1.4vw, 17px);
    font-weight: 800;
    letter-spacing: 3px;
    color: #cfe4ff;
    margin-top: 10px;
  }
  .event-lock-colon {
    font-size: clamp(54px, 9vw, 120px);
    font-weight: 900;
    color: #ffd75e;
    line-height: 1;
    text-shadow: 0 6px 24px rgba(0, 0, 0, 0.5);
    animation: eventLockBlink 1s steps(2, start) infinite;
  }
  @keyframes eventLockBlink {
    to { visibility: hidden; }
  }
  .event-lock-note {
    font-size: clamp(13px, 1.5vw, 18px);
    font-weight: 700;
    color: #eaf3ff;
    text-shadow: 0 2px 8px rgba(0, 0, 0, 0.4);
  }

  /* Letting the chat scroll while an event is locked.

     The lock screen is an absolutely positioned layer covering the whole room,
     so it swallowed every touch aimed at the feed underneath: no wheel, no
     drag, no fling. Reading the room was impossible for the whole length of
     the countdown, which is a long time to stare at a timer.

     That was never the intent. The lock exists to stop people writing -- the
     input is disabled and the chat tools are hidden -- not to stop them
     reading. It just happened to block reading as a side effect of being a
     full-screen div.

     So the layer no longer takes the pointer, and the countdown card takes it
     back. A drag starting anywhere other than on the card now reaches
     #chatFeed and scrolls it. The dimming still does its job, because a
     background is not a hit area. The card keeps its pointer behaviour so
     anything added to it later stays usable.

     The host banner gets the same treatment for the same reason: below 640px it
     spans almost the full width of a phone and sits directly over the feed.
     Only the parts that are genuinely controls take the pointer back, so a
     drag across the digits or the note scrolls rather than being swallowed. */
  .event-lock-overlay {
    pointer-events: none;
  }
  .event-lock-inner {
    pointer-events: auto;
  }
  .event-countdown {
    pointer-events: none;
  }
  .event-countdown-actions,
  .event-statement {
    pointer-events: auto;
  }

  /* EVENT STATEMENT Ã¢â‚¬â€ host/admin only, shown under the countdown timer */
  .event-statement {
    width: 100%;
    margin-top: 6px;
    padding: 10px 14px;
    background: rgba(255, 255, 255, 0.12);
    border: 1px solid rgba(255, 255, 255, 0.22);
    border-radius: 12px;
    box-sizing: border-box;
  }
  .event-statement[hidden] {
    display: none !important;
  }
  .event-statement-title {
    font-size: 11px;
    font-weight: 900;
    letter-spacing: 2px;
    color: #ffd75e;
    margin-bottom: 6px;
  }
  .event-statement-text {
    font-size: 14px;
    font-weight: 700;
    color: #ffffff;
    line-height: 1.45;
    white-space: pre-wrap;
    word-break: break-word;
  }
  .event-statement-actions {
    display: flex;
    gap: 8px;
    margin-top: 10px;
  }
  .event-statement-btn {
    padding: 7px 18px;
    font-size: 13px;
  }
  .event-statement-input {
    font-family: inherit;
    font-size: 14px;
    color: #164a8f;
    background: #ffffff;
    border: 1px solid #c9d6ea;
    border-radius: 8px;
    padding: 10px;
    resize: vertical;
    box-sizing: border-box;
    width: 100%;
  }

  /* EVENT ROOM on phones.

     The lock screen is built desktop-first and does not survive a narrow
     viewport. Every size on that row has a floor that a phone cannot undercut:
     .event-lock-cell clamps min-width to 86px, .event-lock-value clamps the
     font to 64px, and .event-lock-colon clamps to 54px. Four cells plus three
     colons plus gaps is therefore ~540px of content before the overlay's own
     20px padding is counted, so the row needs roughly 580px no matter how small
     the screen gets. On a 390px phone the tail of the timer is pushed about
     190px off the side and simply cannot be read.

     min-width on a flex item stops it shrinking below that floor, which is why
     the row cannot simply squeeze to fit, and the lock overlay clips rather
     than scrolls -- so the overflow is invisible rather than merely awkward.

     Below 640px the four units become a 2x2 grid and the colons drop out. A
     stacked timer cannot overflow sideways at any phone width, and it reads
     better than four cramped boxes on a tall screen. The host panel keeps its
     single row -- four small boxes do fit there -- but the cells are allowed to
     flex and shrink so it can no longer outgrow the viewport. */
  @media (max-width: 640px) {
    .event-lock-overlay {
      padding: 16px 10px;
    }
    .event-lock-inner {
      max-width: 100%;
      width: 100%;
      gap: 10px;
    }
    .event-lock-label {
      font-size: clamp(15px, 4.4vw, 22px);
      letter-spacing: 1.5px;
      gap: 8px;
    }
    .event-lock-icon {
      width: 24px;
      height: 24px;
    }
    .event-lock-clock {
      display: grid;
      grid-template-columns: repeat(2, minmax(0, 1fr));
      gap: 10px;
      width: 100%;
    }
    .event-lock-colon {
      display: none;
    }
    .event-lock-cell {
      min-width: 0;
      padding: 12px 6px 10px;
      border-radius: 14px;
    }
    .event-lock-value {
      font-size: clamp(32px, 10.5vw, 58px);
    }
    .event-lock-cell small {
      font-size: 11px;
      letter-spacing: 1.5px;
      margin-top: 6px;
    }
    .event-lock-note {
      font-size: 13px;
    }

    .event-countdown {
      min-width: 0;
      width: calc(100% - 16px);
      padding: 11px 12px 13px;
      border-radius: 14px;
    }
    .event-countdown-title {
      font-size: 13px;
      letter-spacing: 1px;
    }
    .event-countdown-clock {
      gap: 6px;
    }
    .event-count-cell {
      min-width: 0;
      flex: 1;
      padding: 6px 3px 5px;
    }
    .event-count-value {
      font-size: clamp(22px, 7.6vw, 38px);
    }
    .event-countdown-note {
      font-size: 12px;
    }
    .event-countdown-actions,
    .event-statement-actions {
      flex-wrap: wrap;
    }
    .event-host-btn {
      flex: 1;
      min-width: 0;
      padding: 9px 12px;
    }
  }

  /* PINNED QUESTION BANNER Ã¢â‚¬â€ docked just under the HUD */
  .pinned-banner {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    z-index: 90;
    background: linear-gradient(90deg, #1f6fd6, #164a8f);
    color: #fff;
    padding: 7px 14px;
    display: flex;
    align-items: center;
    gap: 10px;
    font-size: 14px;
    box-shadow: 0 3px 10px rgba(0, 0, 0, 0.25);
  }
  .pinned-banner[hidden] {
    display: none !important;
  }
  .pinned-banner .pinned-pin {
    width: 18px;
    height: 18px;
    object-fit: contain;
    flex-shrink: 0;
  }
  .pinned-banner .pinned-text {
    font-weight: 700;
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .pinned-banner .pinned-by {
    font-size: 12px;
    opacity: 0.9;
    flex-shrink: 0;
  }
  .pinned-banner .pinned-delete {
    flex-shrink: 0;
    background: rgba(255, 255, 255, 0.18);
    border: none;
    color: #fff;
    border-radius: 50%;
    width: 22px;
    height: 22px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 13px;
    cursor: pointer;
    transition: 0.15s ease;
  }
  .pinned-banner .pinned-delete-icon {
    width: 12px;
    height: 12px;
    display: block;
    pointer-events: none;
    filter: brightness(0) invert(1);
  }
  .pinned-banner .pinned-delete:hover {
    background: rgba(255, 255, 255, 0.38);
  }
  .pinned-banner .pinned-delete:disabled {
    opacity: 0.5;
    cursor: not-allowed;
  }
  .music-now-banner {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    z-index: 90;
    background: linear-gradient(90deg, #11141d, #2a2438);
    border-bottom: 2px solid #7b2dbf;
    color: #fff;
    padding: 8px 14px;
    display: flex;
    align-items: center;
    gap: 10px;
    font-size: 14px;
    box-shadow: 0 3px 10px rgba(0, 0, 0, 0.35);
  }
  .music-now-banner[hidden] {
    display: none !important;
  }
  .music-love-btn {
    margin-left: auto;
    display: inline-flex;
    align-items: center;
    gap: 5px;
    background: rgba(255, 255, 255, 0.08);
    border: 1px solid rgba(255, 255, 255, 0.25);
    color: #fff;
    border-radius: 16px;
    padding: 3px 12px;
    font-size: 13px;
    font-weight: 700;
    cursor: pointer;
    flex-shrink: 0;
    transition: 0.15s ease;
  }
  .music-love-btn .music-love-icon {
    width: 14px;
    height: 14px;
    object-fit: contain;
    display: block;
  }
  .music-love-btn:disabled {
    opacity: 0.6;
    cursor: default;
  }

  /* In the Cloud Deck (Images) room, hide every user tool above the
     "Find Me in Topics" section. */
  #userToolsMenu.deck-tools #userToolsPreFindMe {
    display: none !important;
  }

  /* CLOUD DECK (Images room) Ã¢â‚¬â€ background slideshow bar */
  .cloud-deck-bar {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    z-index: 90;
    background: transparent;
    border-bottom: none;
    box-shadow: none;
    color: #fff;
    padding: 8px 14px;
    box-shadow: 0 3px 10px rgba(0, 0, 0, 0.35);
  }
  .cloud-deck-bar[hidden] {
    display: none !important;
  }
  .deck-layout {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
  }
  .deck-track {
    display: flex;
    align-items: baseline;
    gap: 8px;
  }
  .deck-label {
    font-size: 13px;
    font-weight: 800;
    letter-spacing: 1px;
  }
  .deck-counter {
    font-size: 12px;
    color: #bcd3f0;
  }
  .deck-btn {
    width: 30px;
    height: 30px;
    object-fit: contain;
    cursor: pointer;
    background: rgba(255, 255, 255, 0.08);
    border: 1px solid rgba(255, 255, 255, 0.25);
    border-radius: 8px;
    padding: 4px;
    flex-shrink: 0;
    transition: background 0.15s;
  }
  .deck-btn:hover {
    background: rgba(255, 255, 255, 0.22);
  }
  .deck-btn.pending {
    animation: deckPulse 1s ease-in-out infinite;
  }
  @keyframes deckPulse {
    0%, 100% { box-shadow: 0 0 0 0 rgba(255, 215, 0, 0.6); }
    50% { box-shadow: 0 0 0 6px rgba(255, 215, 0, 0); }
  }
  /* The add-image button uses the chat upload icon, which is drawn light for
     these dark surfaces already -- the old share-image icon needed invert(1),
     this one must not get it or it turns back to a dark blob. */
  .deck-cat {
    border: 1px solid rgba(255, 255, 255, 0.25);
    background: rgba(255, 255, 255, 0.08);
    color: #fff;
    border-radius: 14px;
    padding: 3px 10px;
    font-size: 14px;
    line-height: 1.4;
    cursor: pointer;
    flex-shrink: 0;
    transition: background 0.15s, border-color 0.15s;
  }
  .deck-cat:hover {
    background: rgba(255, 255, 255, 0.18);
  }
  .deck-cat.active {
    background: #2a7fff;
    border-color: #2a7fff;
  }
  .deck-cat.upload-ready {
    border-color: #ffd700;
    box-shadow: 0 0 0 2px rgba(255, 215, 0, 0.5);
  }
  .deck-space {
    flex: 1;
  }
  .cloud-deck-bar .deck-thumbs {
    display: none;
  }
  .deck-thumb {
    width: 44px;
    height: 44px;
    object-fit: cover;
    border-radius: 6px;
    border: 2px solid rgba(255, 255, 255, 0.25);
    cursor: pointer;
    flex-shrink: 0;
    transition: border-color 0.15s;
  }
  .deck-thumb:hover {
    border-color: rgba(255, 255, 255, 0.6);
  }
  .deck-thumb.active {
    border-color: #2a7fff;
    box-shadow: 0 0 0 2px #2a7fff;
  }
  .deck-empty {
    font-size: 12px;
    color: #bcd3f0;
    padding: 4px 0;
  }

  /* CLOUD DECK vote row Ã¢â‚¬â€ sits just above the chat text input. Mirrors the
     deck-bar category row so voted icons can fly "up the left side" to them. */
  .deck-vote-row {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 6px 14px;
    margin-left: 2px;
    background: rgba(0, 0, 0, 0.5);
    border-top: 1px solid rgba(255, 255, 255, 0.08);
    border-bottom: 1px solid rgba(255, 255, 255, 0.08);
    z-index: 80;
  }
  .deck-vote-row[hidden] {
    display: none !important;
  }
  .deck-vote-label {
font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.8px;
    color: #bcd3f0;
    margin-right: 2px;
    }
    /* The label only carries text when the deck is showing its default image
       ("upload more to vote"). With nothing to say it must not leave a gap in
       the vote row. */
    .deck-vote-label:empty {
    display: none;
    }
  .deck-vote-space {
    flex: 1;
  }
  .deck-vote-row .deck-btn {
    width: 26px;
    height: 26px;
    padding: 3px;
    border-radius: 7px;
  }
  .deck-vote-btn {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: 3px;
    border: 1px solid rgba(255, 255, 255, 0.22);
    background: rgba(255, 255, 255, 0.08);
    border-radius: 16px;
    padding: 2px 9px;
    cursor: pointer;
    transition: background 0.15s, border-color 0.15s, transform 0.15s;
  }
  .deck-vote-btn .deck-vote-emoji {
    font-size: 18px;
    line-height: 1.2;
  }
  .deck-vote-btn .deck-vote-count {
    font-size: 11px;
    font-weight: 700;
    color: #fff;
  }
  .deck-vote-btn:hover {
    background: rgba(255, 255, 255, 0.2);
    transform: translateY(-1px);
  }
  .deck-vote-btn.active {
    border-color: #2a7fff;
    background: rgba(42, 127, 255, 0.25);
    box-shadow: 0 0 0 2px rgba(42, 127, 255, 0.35);
  }
  .deck-vote-btn.disabled {
    opacity: 0.4;
    cursor: not-allowed;
  }
  .deck-vote-btn.disabled:hover {
    background: rgba(255, 255, 255, 0.08);
    transform: none;
  }

  /* Flying reaction icon Ã¢â‚¬â€ animates from the vote row up to the matching
     category button in the Cloud Deck bar. */
  .reaction-fly {
    position: fixed;
    z-index: 300;
    pointer-events: none;
    font-size: 30px;
    line-height: 1;
    opacity: 1;
    transform: translate(0, 0);
    filter: drop-shadow(0 0 8px rgba(0, 0, 0, 0.7));
    transition: transform 0.75s cubic-bezier(0.3, 0, 0.6, 1), opacity 0.75s ease-in;
  }

  @keyframes deckCatFlash {
    0% { transform: scale(1); box-shadow: 0 0 0 0 rgba(255, 215, 0, 0.9); }
    40% { transform: scale(1.25); box-shadow: 0 0 0 8px rgba(255, 215, 0, 0); }
    70% { transform: scale(0.95); }
    100% { transform: scale(1); }
  }
  .deck-cat.flash {
    animation: deckCatFlash 0.6s ease-out;
  }
  .deck-vote-btn.pulse {
    animation: deckCatFlash 0.5s ease-out;
  }

  /* TRIVIA QUESTION BANNER Ã¢â‚¬â€ docks at the very top while a round runs */
  .trivia-banner {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    z-index: 91;
    background: linear-gradient(90deg, #7b2dbf, #4a1a8a);
    color: #fff;
    padding: 7px 14px;
    display: flex;
    align-items: center;
    gap: 10px;
    font-size: 14px;
    box-shadow: 0 3px 10px rgba(0, 0, 0, 0.3);
  }

  /* ANTI-COPY: game text must stay inside the app so users cannot
     highlight-and-paste the question into a search engine. */
  .no-copy,
  .trivia-banner,
  .hangman-banner,
  .pinned-banner {
    -webkit-user-select: none;
    user-select: none;
    -webkit-touch-callout: none;
  }
  .trivia-banner[hidden] {
    display: none !important;
  }
  .trivia-banner .trivia-icon {
    flex-shrink: 0;
    font-size: 18px;
  }
  .trivia-banner .trivia-text {
    font-weight: 700;
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  /* TRIVIA LEADERBOARD Ã¢â‚¬â€ right-side panel (shown in trivia rooms) */
  .trivia-panel {
    position: fixed;
    top: 40px;
    right: 0;
    bottom: 0;
    width: 240px;
    z-index: 5; /* below the HUD (z-index 10) so HUD dropdowns stay reachable */
    background: rgba(30, 14, 60, 0.92);
    color: #fff;
    border-left: 1px solid rgba(255, 255, 255, 0.15);
    display: flex;
    flex-direction: column;
    box-shadow: -4px 0 16px rgba(0, 0, 0, 0.35);
    backdrop-filter: blur(4px);
  }
  .trivia-panel[hidden] {
    display: none !important;
  }
  /* Full-width game header banner (cloud-trivia.png / cloud-hangman.png) */
  .trivia-panel .trivia-panel-banner {
    flex-shrink: 0;
    padding: 8px 8px 0;
  }
  .trivia-panel .trivia-panel-banner img {
    width: 100%;
    height: auto;
    border-radius: 8px;
    object-fit: contain;
    display: block;
    background: transparent;
  }
  .trivia-panel .trivia-panel-header {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 10px 12px;
    background: linear-gradient(90deg, #7b2dbf, #4a1a8a);
    font-weight: 700;
    font-size: 14px;
    flex-shrink: 0;
  }
  .trivia-panel .trivia-panel-icon {
    width: 22px;
    height: 22px;
    border-radius: 50%;
    object-fit: cover;
  }
  .trivia-panel .trivia-panel-title {
    flex: 1;
  }
  .trivia-panel .trivia-panel-list {
    flex: 1;
    overflow-y: auto;
    padding: 8px 12px;
  }
  .trivia-panel .trivia-row {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 7px 0;
    border-bottom: 1px solid rgba(255, 255, 255, 0.08);
    font-size: 13px;
  }
  .trivia-panel .trivia-rank {
    width: 22px;
    text-align: center;
    font-weight: 700;
    color: #ffd54a;
    flex-shrink: 0;
  }
  .trivia-panel .trivia-avatar {
    width: 28px;
    height: 28px;
    border-radius: 50%;
    object-fit: cover;
    background: rgba(255, 255, 255, 0.15);
    flex-shrink: 0;
  }
  /* Bot Butler row: wide game icon banner instead of a small avatar */
  .trivia-panel .trivia-row.bot-banner {
    flex-wrap: wrap;
    padding-bottom: 10px;
  }
  .trivia-panel .trivia-row.bot-banner .trivia-rank {
    display: none;
  }
  .trivia-panel .trivia-row.bot-banner .trivia-bot-icon {
    width: 100%;
    height: auto;
    border-radius: 8px;
    object-fit: contain;
    background: transparent;
  }
  .trivia-panel .trivia-name {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .trivia-panel .trivia-score {
    flex-shrink: 0;
    font-weight: 700;
    color: #ffd54a;
    font-size: 13px;
  }
  .trivia-panel .trivia-panel-empty {
    padding: 18px 6px;
    text-align: center;
    color: rgba(255, 255, 255, 0.7);
    font-size: 13px;
    line-height: 1.5;
  }
  .trivia-panel .trivia-panel-footer {
    padding: 9px 12px;
    font-size: 12px;
    color: rgba(255, 255, 255, 0.85);
    background: rgba(0, 0, 0, 0.35);
    flex-shrink: 0;
    line-height: 1.4;
  }
  /* When the leaderboard is open, tuck the chatroom in from the right */
  .chatroom-body.has-trivia-panel {
    right: 240px;
  }

  /* HANGMAN WORD REVEAL Ã¢â‚¬â€ docks at the top while a round runs */
  .hangman-banner {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    z-index: 92;
    background: linear-gradient(90deg, #0f7b4a, #0a5231);
    color: #fff;
    padding: 7px 14px;
    display: flex;
    align-items: center;
    gap: 12px;
    font-size: 14px;
    box-shadow: 0 3px 10px rgba(0, 0, 0, 0.3);
  }
  .hangman-banner[hidden] {
    display: none !important;
  }
  .hangman-banner .hangman-icon {
    flex-shrink: 0;
    font-size: 18px;
  }
  .hangman-banner .hangman-word {
    font-family: "Courier New", monospace;
    font-weight: 800;
    font-size: 16px;
    letter-spacing: 2px;
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .hangman-banner .hangman-text {
    flex-shrink: 0;
    font-size: 12px;
    color: rgba(255, 255, 255, 0.9);
  }

  /* HANGMAN LEADERBOARD Ã¢â‚¬â€ right-side panel (mirrors trivia panel) */
  .hangman-panel {
    position: fixed;
    top: 40px;
    right: 0;
    bottom: 0;
    width: 240px;
    z-index: 5; /* below the HUD (z-index 10) so HUD dropdowns stay reachable */
    background: rgba(7, 62, 38, 0.92);
    color: #fff;
    border-left: 1px solid rgba(255, 255, 255, 0.15);
    display: flex;
    flex-direction: column;
    box-shadow: -4px 0 16px rgba(0, 0, 0, 0.35);
    backdrop-filter: blur(4px);
  }
  .hangman-panel[hidden] {
    display: none !important;
  }
  .hangman-panel .hangman-panel-header {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 10px 12px;
    background: linear-gradient(90deg, #0f7b4a, #0a5231);
    font-weight: 700;
    font-size: 14px;
    flex-shrink: 0;
  }
  .hangman-panel .hangman-panel-title {
    flex: 1;
  }

  /* Both games on: trivia panel takes the top half, hangman the bottom. */
  body.game-panels-both .trivia-panel {
    bottom: 50%;
  }
  body.game-panels-both .hangman-panel {
    top: auto;
    height: 50%;
  }
  .chatroom-body.has-hangman-panel {
    right: 240px;
  }

  /* PRIVATE (INVITE ONLY) ROOM PANEL Ã¢â‚¬â€ docks on the left */
  .private-panel {
    position: fixed;
    top: 40px;
    bottom: 0;
    left: 0;
    width: 260px;
    z-index: 5;
    background: rgba(10, 10, 40, 0.96);
    border-right: 1px solid #183a7a;
    color: #dbe6ff;
    display: flex;
    flex-direction: column;
    box-shadow: 4px 0 16px rgba(0, 0, 0, 0.35);
backdrop-filter: blur(4px);
  font-size: 13px;
  /* Animate the collapse so the phone auto-hide and the swipe both slide
     rather than snap. */
  transition: width 0.25s ease;
  }
  .private-panel[hidden] {
    display: none !important;
  }
  .private-panel .private-panel-header {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 10px 12px;
    background: linear-gradient(90deg, #183a7a, #0a0a5e);
    font-weight: 700;
    font-size: 14px;
    flex-shrink: 0;
  }
  .private-panel .private-panel-title {
    flex: 1;
  }
  .private-panel .private-panel-subtitle {
    font-size: 11px;
    font-weight: 600;
    background: rgba(255, 255, 255, 0.12);
    padding: 2px 8px;
    border-radius: 10px;
  }
  .private-panel .private-panel-section {
    padding: 10px 12px;
    border-bottom: 1px solid rgba(24, 58, 122, 0.5);
    overflow-y: auto;
    flex-shrink: 0;
  }
  .private-panel .private-panel-label {
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: #7fa7ff;
    margin-bottom: 8px;
  }
  .private-panel .private-email-input {
    width: 100%;
    box-sizing: border-box;
    margin: 4px 0 8px;
    padding: 10px 12px;
    font-size: 14px;
    min-height: 42px;
  }
  .private-panel .private-invite-go {
    flex-shrink: 0;
    padding: 8px 10px;
    font-size: 13px;
    text-align: center;
    background: #183a7a;
  }
  .private-panel .private-follow-list {
    display: flex;
    flex-direction: column;
    gap: 6px;
  }
  .private-panel .private-people-list {
    display: flex;
    flex-direction: column;
    gap: 6px;
  }
  .private-panel .private-person {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 6px 8px;
    background: rgba(24, 58, 122, 0.35);
    border-radius: 8px;
    min-width: 0;
  }
  .private-panel .private-person img {
    width: 28px;
    height: 28px;
    border-radius: 50%;
    flex-shrink: 0;
    object-fit: cover;
  }
  .private-panel .private-person .private-person-name {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-weight: 600;
  }
  .private-panel .private-person-btn {
    flex-shrink: 0;
    font-size: 11px;
    padding: 3px 8px;
    background: #183a7a;
    border-radius: 6px;
    cursor: pointer;
    user-select: none;
  }
  .private-panel .private-person-btn:hover {
    background: #2755a8;
  }
  .private-panel .private-person-btn.is-invited {
    background: transparent;
    color: #6f8fc9;
    cursor: default;
    border: 1px solid #183a7a;
  }
  .private-panel .private-empty {
    color: #6f8fc9;
    font-style: italic;
    padding: 4px 2px;
  }
  .chatroom-body.has-private-panel {
    left: 260px;
  }

  /* USER'S SETTINGS PANEL Ã¢â‚¬â€ Profile topics only. Docks on the left; when
     the room is also invite-only the private room panel slides next to it. */
  .profile-settings-panel {
    left: 0;
    z-index: 6;
  }
  .profile-settings-panel .findme-row[hidden] {
    display: none;
  }
  .profile-settings-panel .profile-about {
    font-size: 12px;
    line-height: 1.5;
    color: #7fa7ff;
  }
  .chatroom-body.has-profile-panel {
    left: 260px;
  }
  .chatroom-body.has-profile-panel > .private-panel:not(.profile-settings-panel) {
    left: 260px;
  }
  .chatroom-body.has-profile-panel.has-private-panel {
    left: 520px;
  }

  /* MINIMISE / MAXIMISE toggle for the left panels (Private Room + User's Settings) */
  .panel-toggle-btn {
    cursor: pointer;
    user-select: none;
    font-size: 15px;
    line-height: 1;
    font-weight: 700;
    color: #dbe6ff;
    background: rgba(255, 255, 255, 0.12);
    border-radius: 6px;
    padding: 3px 9px;
    flex-shrink: 0;
    transition: background 0.2s ease;
  }
  .panel-toggle-btn:hover {
    background: rgba(255, 255, 255, 0.28);
  }

  /* Extra "X" close in the panel header on a desktop, beside the bottom-right
     icon that also toggles the panel. Hidden on a phone. */
  .panel-close-btn {
    cursor: pointer;
    user-select: none;
    font-size: 15px;
    line-height: 1;
    font-weight: 700;
    color: #dbe6ff;
    background: rgba(255, 255, 255, 0.12);
    border-radius: 6px;
    padding: 3px 9px;
    flex-shrink: 0;
    transition: background 0.2s ease;
  }
  .panel-close-btn:hover {
    background: rgba(255, 255, 255, 0.28);
  }

  /* The left-panel toggles now live in the bottom-right icon stack, beside
     the other room icons. Dimmed at rest, lit while its menu is open. */
  #bottomRightTools .panel-toggle-icon {
    opacity: 0.6;
  }
  #bottomRightTools .panel-toggle-icon.active {
    opacity: 1;
    filter: drop-shadow(0 0 6px rgba(78, 163, 255, 0.9));
  }
  #bottomRightTools .panel-toggle-icon[hidden] {
    display: none !important;
  }
  .private-panel.minimized {
    width: 46px;
  }
  .private-panel.minimized .private-panel-header {
    justify-content: center;
    padding: 10px 0;
  }
  .private-panel.minimized .private-panel-title,
  .private-panel.minimized .private-panel-subtitle,
  .private-panel.minimized .private-panel-section {
    display: none;
  }
  
  /* JOIN MESSAGE FADE-AWAY */
  .join-bubble.fade-away {
    animation: fadeOut 3s forwards;
    animation-delay: 3s;
  }
  
  @keyframes fadeOut {
    0% { opacity: 1; }
    100% { opacity: 0; transform: translateY(-10px); }
  }
  
  /* TOAST NOTIFICATIONS */
  .toast-container {
    position: fixed;
    top: 60px;
    left: 50%;
    transform: translateX(-50%);
    z-index: 99999;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 10px;
    pointer-events: none;
  }

  .toast {
    min-width: 240px;
    max-width: 90vw;
    padding: 14px 22px;
    border-radius: 10px;
    font-size: 15px;
    font-weight: 600;
    text-align: center;
    color: #fff;
    box-shadow: 0 6px 18px rgba(0,0,0,0.3);
    animation: toastIn 0.3s ease forwards;
    transition: opacity 0.3s ease;
  }

  .toast-error {
    background: #d64545;
    border: 2px solid #a83232;
  }

  .toast-success {
    background: #2e9e57;
    border: 2px solid #237a43;
  }

  .toast-info {
    background: #1f6fd6;
    border: 2px solid #155aa8;
  }

  .toast-hiding {
    opacity: 0;
    transform: translateY(-10px);
  }

  /* A toast raised while ambient mode has hidden the interface. Toasts live on
     <body> so the cc-ambient selector list never reaches them; without this they
     float over the bare media. Kept in the DOM and simply faded, so a touch
     (which wakes the UI) brings the message back rather than losing it. */
  .toast.toast-ambient {
    opacity: 0;
    transition: opacity 0.45s ease;
  }

  @keyframes toastIn {
    from { opacity: 0; transform: translateY(-16px); }
    to { opacity: 1; transform: translateY(0); }
  }

/* ================================================================
   FOLLOW PROMPT MODAL Ã¢â‚¬â€ shown when you invite an email that already
   belongs to a ChatCloud member. Offers to follow them instead of
   leaving the invite as a dead end.
   ================================================================ */
.follow-prompt {
  position: fixed;
  inset: 0;
  background: rgba(4, 8, 18, 0.66);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 100001;
  padding: 20px;
}

.follow-prompt-box {
  background: #15151f;
  border: 1px solid #26263a;
  border-radius: 18px;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.55);
  padding: 24px 22px 20px;
  width: 360px;
  max-width: 92vw;
  box-sizing: border-box;
  text-align: center;
  color: #f2f2f7;
}

.follow-prompt-avatar {
  width: 64px;
  height: 64px;
  border-radius: 50%;
  object-fit: cover;
  border: 2px solid transparent;
  margin: 0 auto 12px;
  display: block;
}

.follow-prompt-title {
  font-size: 17px;
  font-weight: 800;
  color: #4ea3ff;
  margin-bottom: 6px;
}

.follow-prompt-text {
  font-size: 14px;
  line-height: 1.5;
  color: #b9b9c6;
  margin-bottom: 4px;
}

.follow-prompt-name {
  color: #f2f2f7;
  font-weight: 700;
}

.follow-prompt-sub {
  font-size: 12px;
  color: #8e8e9c;
  margin-top: 6px;
}

.follow-prompt-actions {
  display: flex;
  gap: 10px;
  margin-top: 18px;
}

.follow-prompt-btn {
  flex: 1;
  padding: 11px 0;
  border-radius: 10px;
  font-size: 14px;
  font-weight: 700;
  cursor: pointer;
  user-select: none;
  text-align: center;
  border: 1px solid transparent;
  background: #4ea3ff;
  color: #06121f;
}

.follow-prompt-btn:hover { background: #7bbcff; }

.follow-prompt-btn.soft {
  background: transparent;
  color: #4ea3ff;
  border-color: rgba(78, 163, 255, 0.5);
}

.follow-prompt-btn.soft:hover {
  background: #4ea3ff;
  color: #06121f;
}

.follow-prompt-btn:disabled {
  background: #2a2a3c;
  color: #8e8e9c;
  cursor: default;
}

.follow-prompt-btn.following {
  background: #2e9e57;
  color: #fff;
}
  
/* ================================
   LOBBY BODY Ã¢â‚¬â€ MINIMAL BLUE, CLEAN
   (lobby.html only; every selector
   below is lobby-exclusive in markup.
   admin.html and topic chatrooms never
   render these classes, so this block
   can never leak into them.)
   ================================ */

/* Lobby body background: calm soft blue instead of heavy navy */
.lobby-body {
  background: var(--blue-soft, #e9f3ff);
  color: var(--blue-deep, #164a8f);
}

/* Lobby shell: lightest tint, thin line borders, no hard navy blocks */
.row-shell,
.lobby-shell,
.shell {
  background: var(--blue-soft, #e9f3ff);
  border: 1px solid var(--blue-line, #c7d9f5);
  box-shadow: none;
}

/* LEFT + RIGHT HUD panels on the lobby: single clean white card
   separated by thin pale-blue lines (minimal, not heavy navy) */
.left-menu,
.right-menu {
  background: #ffffff;
  border: 1px solid var(--blue-line, #c7d9f5);
  box-shadow: none;
}

.main-content > .invite-hint-bar,
.invite-hint-bar {
  background: var(--blue-soft, #e9f3ff);
  border: 1px solid var(--blue-line, #c7d9f5);
  color: var(--blue-deep, #164a8f);
  border-radius: 12px;
  box-shadow: none;
}

.invite-hint-bar .invite-hint-text,
.invite-hint-icon {
  color: var(--blue-deep, #164a8f);
}

.invite-hint-bar:not(.invite-hint-about) .invite-ok-btn,
.invite-ok-btn {
  background: var(--blue-base, #1f6fd6);
  border: none;
}

.invite-hint-bar .invite-ok-btn:hover {
  background: var(--blue-deep, #164a8f);
}

/* Lobby topic cards: one light card, thin line border, soft hover */
.topic-item,
.topic-shell {
  background: #ffffff;
  border: 1px solid var(--blue-line, #c7d9f5);
  box-shadow: none;
}

.topic-item:hover,
.topic-hover:hover {
  background: var(--blue-soft, #e9f3ff);
}
/* ================================
   HUD ICONS - ALL THREE ROUND + UNIFORM
   (avatar, invite, tools: one identical
   32px circle, object-fit cover, so
   native PNG ratios can never make one
   look bigger or square again)
   ================================ */
.hud-avatar,
.hud-invite,
.hud-tools {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  object-fit: cover;
  flex: 0 0 auto;
}

.hud-avatar {
  margin-right: 0;
}

.hud-tools {
  margin-left: 0;
}

/* ====================================
   RIGHT TRIO Ã¢â‚¬â€ INVITE / PROFILE / TOOLS
   Even spacing + BLUE tooltips to match
   every other HUD popup.
   ==================================== */
#hudInviteIcon, #hudAvatarIcon, #toolsIconWrapper {
  gap: 8px;
}
#hudInviteIcon::after,
#hudAvatarIcon::after,
#toolsIconWrapper::after {
  background: #164a8f !important; /* blue, like the rest of the HUD */
  color: #ffffff;
}

/* ================================
   SITE-WIDE FIXED-HUD OFFSET
   Pages that carry the fixed top
   HUD start their content 44px
   below it. Pages without the HUD
   (and fixed-layout chat rooms) are
   unaffected.
   ================================ */
body:has(.top-hud) {
  padding-top: 44px;
}

/* Lobby MUSIC Ã¢â‚¬â€ animated GIF backdrop, shared by both button sets: the
   Start Topic bar (.location-icon) and the right-hand topic-types column
   (.topic-filter-btn, converted over from .location-icon in the phone skin). */
.location-icon[data-lobby-icon="music"],
.topic-filter-btn[data-lobby-icon="music"] {
  background-image: url("img/gif/music.gif");
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
}

.location-icon[data-lobby-icon="music"] span {
  color: #000000; /* black label, readable over the animated GIF */
}

/* The small tile becomes a clone of the Start Topic bar's music button:
   a row-pill over the GIF with the emoji and "Music" label side by side. */
.topic-filter-btn[data-lobby-icon="music"] {
  width: auto;
  height: 46px;
  padding: 0 14px;
  border: none;
  border-radius: 10px;
  flex-direction: row;
  gap: 7px;
  box-shadow: 0 3px 8px rgba(22, 74, 143, 0.35);
  box-sizing: border-box;
}

.topic-filter-btn[data-lobby-icon="music"] .topic-type-glyph {
  color: #000000;
  font-size: 16px;
  line-height: 1;
}

.topic-filter-btn[data-lobby-icon="music"] .topic-type-label {
  color: #000000;
  font-size: 13px;
  font-weight: 900;
  letter-spacing: 0.5px;
}

/* ================================
   START TOPIC THUMB STRIP
   Replaces the old Start Topic search bar: six even image cards across
   the lobby (#searchNav keeps its id so the preview/create flow works).
   Start a new topic leads, then Games, Start a Debate, Music, Cloud Deck and
   My Town.

   The cards are packed from the LEFT (flex-start) and share the row
   evenly, so the first one sits hard against the edge instead of being
   pushed in by space-between. The search field that follows takes the
   full row width, which drops it onto its own line underneath.
   ================================ */
#searchNav.lobby-thumbs {
  background: none;
  flex-wrap: wrap;
  justify-content: flex-start;
  gap: 12px;
  min-height: 0;
  padding: 0;
  border: none;
  box-shadow: none;
  border-radius: 0;
  cursor: default;
}

#searchNav.lobby-thumbs:hover {
  background: none;
  box-shadow: none;
  transform: none;
}

#searchNav.lobby-thumbs .topic-hover {
  display: none;
}

/* Full-row width forces the search field onto its own line below the cards. */
#searchNav.lobby-thumbs .search-wrapper {
  flex: 1 1 100%;
}

#searchNav.lobby-thumbs .lobby-thumb {
  flex: 1 1 0;
  min-width: 0;
  /* Six cards + five 12px gaps fill the row exactly, so no dead space
     collects at either end. */
  max-width: calc(16.667% - 10px);
  aspect-ratio: 16 / 9;
  border-radius: 14px;
  overflow: hidden;
  border: 1px solid var(--phone-cell-edge, #26263a);
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.4);
  background: #15151f;
  cursor: pointer;
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}

#searchNav.lobby-thumbs .lobby-thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

#searchNav.lobby-thumbs .lobby-thumb:hover {
  transform: translateY(-2px);
  box-shadow: 0 6px 16px rgba(0, 0, 0, 0.45);
}

/* My Town: the picture is the member's own country flag, painted as a
   background so the caption still sits over it. The <img> is only the
   fallback for a member with no country recorded, and it is hidden once a
   flag has been applied. */
#searchNav.lobby-thumbs .lobby-thumb-flag {
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
}

#searchNav.lobby-thumbs .lobby-thumb-flag.has-flag img {
  display: none;
}

/* Flags are flat colour, so the thumbnail needs a little more contrast than a
   photograph does before the caption stays readable on top of it. */
#searchNav.lobby-thumbs .lobby-thumb-flag.has-flag::before {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(
    to top,
    rgba(0, 0, 0, 0.55) 0%,
    rgba(0, 0, 0, 0.18) 55%,
    rgba(0, 0, 0, 0.05) 100%
  );
  pointer-events: none;
}

#searchNav.lobby-thumbs .lobby-thumb-flag.has-flag .lobby-thumb-label {
  z-index: 1;
}

/* Caption sitting on top of each large thumb. The text comes from the
   admin-managed lobby icon label (see lib/lobbyIcons.ts), so renaming an
   icon in the console renames the caption here too. */
#searchNav.lobby-thumbs .lobby-thumb {
  position: relative;
}

#searchNav.lobby-thumbs .lobby-thumb-label {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  padding: 14px 8px 6px;
  background: linear-gradient(
    to top,
    rgba(0, 0, 0, 0.88) 0%,
    rgba(0, 0, 0, 0.62) 45%,
    rgba(0, 0, 0, 0) 100%
  );
  color: #fff;
  font-size: 12px;
  font-weight: 800;
  letter-spacing: 0.6px;
  text-transform: uppercase;
  text-align: center;
  text-overflow: ellipsis;
  overflow: hidden;
  white-space: nowrap;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.95), 0 0 10px rgba(0, 0, 0, 0.6);
  pointer-events: none;
  user-select: none;
}

#searchNav.lobby-thumbs .lobby-thumb-label:empty {
  display: none;
}

@media (max-width: 760px) {
  #searchNav.lobby-thumbs .lobby-thumb-label {
    padding: 10px 4px 4px;
    font-size: 10px;
    letter-spacing: 0.3px;
  }
}

/* The search field the Start Topic thumb reveals sits on its own row
   underneath the thumbs. */
#searchNav.lobby-thumbs .topic-search-input {
  flex: 1 1 100%;
  width: 100%;
  margin-top: 12px;
  font-size: 16px;
  font-weight: 700;
  padding: 12px 14px 12px 42px;
  border-radius: 12px;
  border: 1px solid #2a2a3c;
  background-color: #1f1f2e;
  background-position: 14px center;
  color: var(--phone-label, #f2f2f7);
  box-sizing: border-box;
}

#searchNav.lobby-thumbs .topic-search-input::placeholder {
  color: var(--phone-muted, #8e8e9c);
}

@media (max-width: 760px) {
  #searchNav.lobby-thumbs {
    gap: 8px;
  }

  #searchNav.lobby-thumbs .lobby-thumb {
    max-width: calc(25% - 6px);
    aspect-ratio: 1 / 1; /* taller thumb targets on touch screens */
  }

  #searchNav.lobby-thumbs .topic-search-input {
    font-size: 16px;
  }
}

/* ================================
   MOBILE-FRIENDLY SHARED TOP HUD
   Applied to the HUD that injectHUD()
   stamps on every signed-in page
   (index, lobby, account, invite,
   admin, topic rooms).
   ================================ */

@media (max-width: 760px) {
  body:has(.top-hud) {
    padding-top: 48px;
  }

  .top-hud {
    min-height: 48px;
    padding: 4px 8px;
    font-size: 15px;
    gap: 6px;
  }

  .hud-logo { height: 26px; }
  .hud-logo-wrap { height: 28px; }

  .hud-avatar,
  .hud-invite,
  .hud-tools {
    width: 29px;
    height: 29px;
  }

  .hud-left { gap: 6px; }
  .hud-right { gap: 7px; min-width: 0; padding-right: 0; }
  .hud-alert { left: 20px; font-size: 16px; }

  /* Center title Ã¢â‚¬â€ smaller, and capped so it never
     pushes into the left/right icon clusters. */
  .hud-center {
    font-size: 17px;
    max-width: 38vw;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .hud-center #hudTopicName {
    max-width: 100%;
    display: inline-block;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    vertical-align: bottom;
  }

  /* Search Ã¢â‚¬â€ narrower so the whole HUD fits on a phone */
  .topic-search-wrap { margin-left: 4px; }
  #hudTopicSearchInput {
    width: 112px;
    padding: 5px 6px 5px 28px;
    font-size: 13px;
    background-position: 7px center;
    background-size: 15px;
  }
  .topic-suggest-menu { width: 230px; }

  /* Tools dropdown stays inside the viewport */
  .tools-menu { right: 0; }

  /* Invite-friends back button */
  .hud-return { padding: 5px 10px; font-size: 13px; }
}

@media (max-width: 480px) {
      /* The HUD centre used to be hidden outright on phones, which took the
         topic's love icon and count with it -- so a phone could not see or give
         a love at all. Hide the topic NAME only (it needs the width) and keep
         the heart and its count, which is all this needs to be useful.

         .hud-center is position:absolute at left:50% -- a viewport-centred
         overlay, not a row item -- so on a phone the search underneath it was
         covered by the heart and count. Static positioning puts the centre back
         into the flex row, and margin:auto centres it in the free gap between
         the search on the left and the icon cluster on the right, which is
         where it was always meant to sit. max-width/overflow are dropped too:
         at 38vw the count could clip. */
      .hud-center {
        position: static;
        left: auto;
        top: auto;
        transform: none;
        margin: 0 auto;
        max-width: none;
        overflow: visible;
        display: flex;
        align-items: center;
      }
      .hud-center #hudTopicName {
        display: none;
      }
      #topicLoveWrap {
        margin-left: 0;
        padding: 2px 6px;
        gap: 4px;
        pointer-events: auto;
      }
      #topicLoveWrap .topic-love-icon img {
        width: 17px;
        height: 17px;
      }
      #topicLoveWrap .topic-love-count {
        font-size: 12px;
      }
      #topicLoveWrap::after {
        display: none;
      }
      #hudTopicSearchInput { width: 96px; }
      .hud-left-core .hud-alert { display: none; }
    }

/* -------------------------------
   ADMIN MUSIC LIBRARY (Admin > Topics > Music)
   The search bar, genre tabs, song cards and the inline add/edit form.
-------------------------------- */
.music-search-row {
  display: flex;
  gap: 8px;
  margin: 0 0 10px;
}

.music-search-input {
  flex: 1;
  min-width: 0;
}

.music-genre-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: 0 0 12px;
}

.music-genre-tab {
  padding: 5px 10px;
  border-radius: 999px;
  border: 1px solid rgba(0, 0, 0, 0.15);
  background: rgba(255, 255, 255, 0.6);
  color: inherit;
  font-size: 12px;
  cursor: pointer;
}

.music-genre-tab.active {
  background: #2f6df6;
  border-color: #2f6df6;
  color: #fff;
}

.music-song-card .row-top {
  display: flex;
  gap: 12px;
  align-items: flex-start;
}

.music-thumb {
  width: 110px;
  height: 62px;
  object-fit: cover;
  border-radius: 6px;
  background: #000;
  flex: none;
}

.music-song-card .row-main {
  flex: 1;
  min-width: 0;
}

.music-song-card .controls {
  display: flex;
  gap: 6px;
  flex: none;
}

/* Inline add / edit form rows */
.music-form .edit-row {
  display: flex;
  gap: 8px;
  margin-bottom: 8px;
  flex-wrap: wrap;
}

.music-form .edit-row .mini-input {
  flex: 1;
  min-width: 140px;
}

.music-form .edit-row .mini-input[style*="flex:2"] {
  flex: 2;
}

.music-form-card {
  margin: 0 0 14px;
}

.music-form-title {
  font-weight: 700;
  margin-bottom: 10px;
}

.music-form-error {
  color: #d33;
  font-size: 12px;
  margin-top: 6px;
}


/* ============================================================
   AMBIENT MODE (Media / YouTube / Music rooms)
   In a viewing room the video should own the screen. After 5s of
   no mouse / touch / key activity the whole chat chrome fades
   out; any activity brings it straight back. Toggled by the
   `cc-ambient` body class from cloud.js.

   Only chrome is listed here - modals, popups and the lock
   overlay are deliberately absent so an open dialog is never
   faded out from under the user.

   `visibility: hidden` is not optional next to `opacity: 0`.
   .hud-center #hudTopicName and the HUD icon buttons both set
   `pointer-events: auto`, which overrides the parent and would
   leave invisible, clickable icons behind. visibility is
   inherited, so it kills hit-testing for the whole subtree.
   ============================================================ */

body:not(.cc-ambient) .top-hud,
  body:not(.cc-ambient) #chatFeed,
  body:not(.cc-ambient) .chat-input-bar,
  body:not(.cc-ambient) #bottomRightTools,
  body:not(.cc-ambient) .cc-tip,
body:not(.cc-ambient) #deckVoteRow,
body:not(.cc-ambient) #cloudDeckBar,
body:not(.cc-ambient) #privatePanel,
body:not(.cc-ambient) #profileSettingsPanel,
body:not(.cc-ambient) #triviaPanel,
body:not(.cc-ambient) #hangmanPanel,
body:not(.cc-ambient) #debateBanner,
body:not(.cc-ambient) .trivia-banner,
body:not(.cc-ambient) .hangman-banner,
body:not(.cc-ambient) .pinned-banner,
body:not(.cc-ambient) .quick-vote-banner,
body:not(.cc-ambient) .music-now-banner,
body:not(.cc-ambient) .poll-banner,
body:not(.cc-ambient) .pause-banner {
  /* visibility flips back instantly so the fade-in is actually seen */
  transition: opacity 0.45s ease, visibility 0s linear 0s;
}

body.cc-ambient .top-hud,
  body.cc-ambient #chatFeed,
  body.cc-ambient .chat-input-bar,
  body.cc-ambient #bottomRightTools,
  /* The tooltip label lives on document.body, so it is not covered by fading
     the icons it belongs to. Without this it stayed on screen after the rest of
     the interface had gone -- the blue label outliving the buttons. */
  body.cc-ambient .cc-tip,
body.cc-ambient #deckVoteRow,
body.cc-ambient #cloudDeckBar,
body.cc-ambient #privatePanel,
body.cc-ambient #profileSettingsPanel,
body.cc-ambient #triviaPanel,
body.cc-ambient #hangmanPanel,
body.cc-ambient #debateBanner,
body.cc-ambient .trivia-banner,
body.cc-ambient .hangman-banner,
body.cc-ambient .pinned-banner,
body.cc-ambient .quick-vote-banner,
body.cc-ambient .music-now-banner,
body.cc-ambient .poll-banner,
body.cc-ambient .pause-banner {
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  /* visibility waits for the fade to finish, otherwise the chrome
     would blink out instead of fading */
  transition: opacity 0.45s ease, visibility 0s linear 0.45s;
}

/* ================================
   TOPIC ROOM - MOBILE PASS
   chatcloud.html is the one page
   every signed-in user reaches
   from either Lobby, so it has to
   hold up on a phone as well as a
   desktop. Everything here is
   phone-only and layout-only: no
   colours change, so a phone user
   sees the exact same black cell
   phone theme as a desktop user.
   ================================ */

@media (max-width: 760px) {

  /* The room is position:fixed, so the body's 48px HUD padding does not
     apply to it -- pin it to the taller mobile HUD instead of 40px. */
  .chatroom-body {
    top: 48px;
  }

  /* Left/right docked panels overlay the chat on a phone. Squeezing the
     feed to 100px (260px + 260px) is unusable, so the panels sit on top
     and the feed keeps the full width behind them. */
  .chatroom-body.has-private-panel,
  .chatroom-body.has-profile-panel,
  .chatroom-body.has-profile-panel.has-private-panel {
    left: 0;
  }

  .chatroom-body.has-trivia-panel,
  .chatroom-body.has-hangman-panel {
    right: 0;
  }

/* Sizing for the panels that now overlay the feed, and the taller
     mobile HUD they hang from. */
  .private-panel,
  .trivia-panel,
  .hangman-panel {
    top: 48px;
  }

  /* The right-side game leaderboards (Trivia / Hangman) are desktop-only:
     on a phone they cover too much of the chat feed, so hide them here even
     while a game is running. The game itself still works in the feed. */
  .trivia-panel,
  .hangman-panel {
    display: none !important;
  }

  .private-panel {
    width: min(300px, 86vw);
    font-size: 14px;
  }

  /* The header "X" is a desktop extra; a phone closes these panels from the
     bottom-right icon stack instead. */
  .panel-close-btn {
    display: none;
  }

  .chatroom-body.has-profile-panel > .private-panel:not(.profile-settings-panel) {
    left: 0;
  }

  /* Banners and the feed need a little more room to breathe. */
  #chatFeed {
    padding: 8px 10px;
  }

  /* Avatars eat a fifth of a narrow screen; trim them so the message
     text gets the room it needs. */
  .chat-avatar {
    width: 32px;
    height: 32px;
    margin-right: 9px !important;
  }

  .chat-content {
    max-width: 100%;
    min-width: 0;
  }

  .chat-text {
    padding: 9px 11px;
  }

  .chat-image {
    max-width: 100%;
    max-height: 260px;
  }

  /* The input bar is the whole bottom of the screen on a phone: give the
     text field the full width (the 40px indent + 80% width is a desktop
     layout) and keep it clear of the home bar. */
  .chat-input-bar {
    padding: 8px 10px calc(8px + env(safe-area-inset-bottom, 0px));
  }

  .input-left {
    gap: 8px;
  }

  #chatInputTop {
    margin-left: 0;
    width: 100%;
    max-width: none;
    flex: 1 1 auto;
    min-width: 0;
  }

  /* Keep the bar's icons at a comfortable thumb size. */
  .br-icon {
    width: 30px;
    height: 30px;
  }

  /* BOTTOM TOOLS: on a phone the three tools sit stacked up the right edge,
     bottom-aligned, clear of the input field and within thumb reach. They were
     on the left for a while; the icons themselves are the same Emojis / Tools /
     Host Menu set, just mirrored to the right. */
  #bottomRightTools {
    left: auto;
    right: 10px;
    /* Sit above the input bar rather than under it. */
    bottom: calc(60px + env(safe-area-inset-bottom, 0px));
    flex-direction: column;
    align-items: center;
    gap: 12px;
  }

  /* The desktop hover zoom (scale 3) is far too large for a stacked column on
     a phone and covers the chat, so just brighten on tap instead. */
  #bottomRightTools .br-icon:hover {
    transform: scale(1.15);
  }

/* Popups span the screen on a phone instead of a fixed 220px, and get
   more of the height to scroll in. The bottom offset clears the stacked
   tool column: 60px offset + 3 icons (30px) + 2 gaps (12px) = 204px, plus a
   little breathing room so a popup never lands on top of its own button. */
  .br-popup {
    right: 8px;
    left: 8px;
    bottom: calc(238px + env(safe-area-inset-bottom, 0px));
    width: auto;
    max-height: 60vh;
  }

  /* Ã¢â€â‚¬Ã¢â€â‚¬ PHONE INPUT Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬Ã¢â€â‚¬
     The bar is the whole bottom of a phone, so the media/game buttons
     wrap onto their own row and the text field is styled as a rounded
     capsule with the send button at its right edge. The emoji button
     stays where it has always been, in the right-hand group. */
  .input-left {
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    width: 100%;
  }

  /* Media + game buttons keep their own row. */
  .input-left > .br-icon {
    flex: 0 0 auto;
  }

  .char-counter {
    order: -1;
    flex: 1 0 100%;
    text-align: right;
    margin: 0;
    font-size: 11px;
  }

  #chatInputTop {
    order: 0;
    flex: 1 1 auto;
    min-width: 0;
    margin-left: 0;
    width: auto;
    max-width: none;
    min-height: 22px;
    max-height: 5.4em;
    overflow-y: auto;
    padding: 7px 14px;
    border-radius: 999px;
    background: var(--phone-cell, #15151f);
    border: 1px solid var(--phone-cell-edge, #26263a);
    box-shadow: none;
  }

  /* The capsule is the focus indicator now, so drop the field's own ring. */
  body[data-theme="dark"] #chatInputTop:focus {
    border-color: var(--phone-cell-edge, #26263a);
  }

  .chat-send-btn {
    display: flex;
    width: 34px;
    height: 34px;
    border-radius: 50%;
    background: var(--phone-accent, #4ea3ff);
  }

  .chat-send-btn:disabled {
    opacity: 0.35;
    cursor: default;
  }
}

/* Touch devices have no hover, so the hover-revealed controls are unreachable
   if we simply hide them -- and the previous fix pinned every row's reaction bar
   and follow button open, which buried the chat under icons. Tapping the avatar
   now opens one row at a time (cloud.js adds .reveal-row-icons); tapping
   anywhere else closes it. */
@media (hover: none) {
  .chat-reactions {
    opacity: 0;
    transform: none;
    pointer-events: none;
    height: 0;
    overflow: hidden;
  }

  .chat-actions .chat-follow-btn,
  .chat-actions .chat-delete-btn,
  .chat-actions .chat-report-btn {
    opacity: 0;
    pointer-events: none;
  }

  /* .reveal-row-icons is set by the avatar tap handler. */
  .chat-row.reveal-row-icons .chat-reactions {
    opacity: 1;
    pointer-events: auto;
    height: auto;
    overflow: visible;
  }

.chat-row.reveal-row-icons .chat-actions .chat-follow-btn,
    .chat-row.reveal-row-icons .chat-actions .chat-delete-btn,
    .chat-row.reveal-row-icons .chat-actions .chat-report-btn {
      opacity: 1;
      pointer-events: auto;
    }
  }

/* ================================================================
   BOTTOM TOOLS + INPUT BAR ON DESKTOP (min-width: 761px)
   ================================================================

   The Emojis / Tools / Host Menu icons are stacked up the right edge on
   a phone, inside the max-width:760px block above. On a desktop they
   fell back to the base rule at the top of this file, which lays them out
   in a horizontal row pinned to the bottom-right corner -- so the same
   three controls sat in two different places depending on the screen, and
   on a wide monitor they ended up stranded out in the middle of nowhere
   next to the input field.

   Mirrored here rather than changing the base rule: the phone block has
   to keep winning on a phone, and it is the later of the two, so editing
   the base rule would have been undone on small screens anyway.

   The offsets are the phone values, unchanged. #bottomRightTools is
   position:absolute against the room, not the input bar, so the 60px
   lift is what keeps the column clear of the text field.
   ================================================================ */
@media (min-width: 761px) {
  #bottomRightTools {
    left: auto;
    right: 20px;
    /* Sit above the input bar rather than under it. */
    bottom: calc(60px + env(safe-area-inset-bottom, 0px));
    flex-direction: column;
    align-items: center;
    gap: 14px;
  }

  /* The desktop hover zoom (scale 3) is far too large for a stacked
     column -- it covers the chat column outright -- so just brighten,
     the same as the phone does on tap. */
  #bottomRightTools .br-icon:hover {
    transform: scale(1.15);
  }

  /* A popup opens to the LEFT of its button on a phone because the
     button is at the screen edge. Same geometry here, so it is
     unchanged apart from being pinned above the whole stacked column:
     60px offset + 3 icons (30px) + 2 gaps (14px) = 178px. */
  .br-popup {
    bottom: calc(60px + env(safe-area-inset-bottom, 0px));
  }

  /* The bar BEHIND the input is transparent, which on a room with a
     wallpaper let the photo show through under the text field and made
     the field look like it was floating on the picture. Black, so the
     field reads as sitting on a surface.

     Only the bar. The field itself keeps its own light background --
     that is what makes the typed text legible, and blacking it out too
     would leave dark-on-dark. */
  .chat-input-bar {
    background: #000;
  }

  /* The field itself stays a light surface so typed text remains legible,
     but it is currently the same near-black as the bar it sits on
     (--phone-cell, #15151f), which left the two merging into one slab.
     Lifted to a grey that is clearly a field sitting on a black bar.

     Selector carries .chat-input as well as the id, and !important, on
     purpose: chatcloud.html already sets this under
     `body[data-theme="dark"] #chatInputTop` in a <style> that loads after
     this stylesheet. Both are !important, and at equal specificity the
     later one wins, so the extra class is what makes this stick. */
  body[data-theme="dark"] #chatInputTop.chat-input {
    background: #2f2f3a !important;
    color: #f2f2f7 !important;
    border: 1px solid #3d3d4a !important;
  }

  body[data-theme="dark"] #chatInputTop.chat-input:focus {
    border-color: #4ea3ff !important;
  }

  /* ================================================================
     RIGHT-SIDE CHATS: THE COMPOSER
     ================================================================

     The Games lobby, the per-game rooms and the Music lobby run their chat
     in a column only clamp(260px, 22vw, 380px) wide, and the composer was
     still the full-width room's: a square-cornered slab with a 40px indent,
     three icons absolutely pinned on top of it, and a send button that
     exists only on a phone. At that width the icons straddled the field's
     right border and the field reserved 120px of inline padding to keep the
     typed text out from under them -- most of the box, spent.

     Rebuilt as one row: the field takes the slack, and the Emojis / Tools /
     Host Menu icons and the send button sit after it in normal flow, so
     nothing is ever painted over the field and the field reserves nothing.
     Their positions stop being CSS offsets entirely -- they are just the
     last flex items in the bar.

     The icons are still revealed by focus (Tools and Host Menu only while
     the field has it), so the resting state is a single Emojis button and
     the row does not jump when the field opens.

     The room class appears ONCE in every selector. A doubled class like
     .cc-games-room.cc-games-room only matches if <body> carries the class
     twice, and cloud.js adds it once -- nine such rules already in this file
     are dead for that reason. The !important flags below are the same
     story in reverse: several theme rules set colour and background with
     it, and within one origin an important declaration beats a plain one
     outright, whatever its specificity. */

  body.cc-games-room .chat-input-bar,
  body.cc-music-room .chat-input-bar {
    padding: 8px 10px calc(8px + env(safe-area-inset-bottom, 0px));
    background: #0b0b10 !important;
    border-top: 1px solid rgba(255, 255, 255, 0.07);
  }

  body.cc-games-room .input-left,
  body.cc-music-room .input-left {
    gap: 2px;
    padding-right: 0;
  }

  /* The field is the pill; everything else in the row hangs off its right
     edge. .chat-input-bar is the scope because the field is not in the
     feed -- it scores 1,3,1 against the theme block's 1,2,1. */
  body.cc-games-room .chat-input-bar #chatInputTop.chat-input,
  body.cc-music-room .chat-input-bar #chatInputTop.chat-input {
    /* The field's wrapper is itself a flex row, and dropping the absolute
       offsets on the icons leaves the field to be sized by its content
       rather than by the slack in the bar -- so it has to claim the slack
       itself. */
    flex: 1 1 auto;
    min-width: 0;
    width: auto;
    max-width: none;
    min-height: 38px;
    margin-left: 0;
    /* !important for the same inline-style reason as the icons: the field
       ships with padding-right:120px written into the markup to hold the
       icons clear back when they were absolutely positioned over it. The
       icons are in the flow now, so that reservation is not just
       unnecessary, it is 120px of dead width that pushes the icon row off
       the end of the bar. */
    padding: 9px 14px !important;
    /* A single long word (a URL, a @handle, no spaces at all) sets the
       content's min-content width, and a flex item will not shrink below
       that -- so the field used to shove the whole icon row off the end of
       the bar as soon as one was pasted in. Wrapping at any character gives
       the field a min-content width of a single character instead, so the
       bar keeps its shape and the text wraps inside the pill. */
    overflow-wrap: anywhere;
    word-break: break-word;
    max-width: 100%;
    /* The field is the one thing in this column that is allowed to grow,
       and only as far as this: the base cap was 45vh, which in a short
       window ate most of the feed. */
    max-height: 120px;
    overflow-y: auto;
    border-radius: 19px;
    background: #1a1a22 !important;
    color: #ececf2 !important;
    border: 1px solid #2b2b38 !important;
    box-shadow: none !important;
    font-size: 14px;
    line-height: 1.4;
    transition: border-color 0.15s ease, background 0.15s ease;
  }

  /* Focused, the pill is a slightly lighter surface with a blue edge --
     quiet, but enough to say which box the typing is going into.

     The height barely moves. The games-room rule further up opens the
     field to 132px the instant it takes focus, which is a paragraph of
     height before a character is typed and made the bar lurch every time;
     here it settles a few pixels taller and then grows with the text. */
  body.cc-games-room .chat-input-bar #chatInputTop.chat-input:focus,
  body.cc-music-room .chat-input-bar #chatInputTop.chat-input:focus {
    background: #20202a !important;
    border-color: #3d6ea8 !important;
    outline: none;
    min-height: 44px;
  }

  body.cc-games-room .chat-input:empty::before,
  body.cc-music-room .chat-input:empty::before {
    color: #6b6b7d;
  }

  /* The 40px indent was a full-width layout that reserved nothing, and the
     field's inline padding-right:120px exists only to hold the icons clear
     while they were painted on top of it. With the gutter above doing that
     job, both are dead weight -- and 120px was most of the box in a narrow
     column. */
  #chatInputTop {
    margin-left: 0;
    padding-right: 14px !important;
  }

  /* No send button on a desktop. Enter has always posted from a computer
     keyboard, which is the whole reason this rule exists (see the note
     above it in this file), and an earlier pass here turned it on in the
     chat columns. That was wrong: it crowded the icons and invited people
     to post a half-typed line with the mouse. Back to hidden on a desktop;
     the phone media query below still shows it, where a touch keyboard's
     Enter is not dependable. */

  /* The character counter is a full-width room's affordance. In a chat
     column this narrow it sits on the field, so it goes. */
  body.cc-games-room #charCounterHUD,
  body.cc-music-room #charCounterHUD {
    display: none !important;
  }

  /* ================================================================
     RIGHT-SIDE CHATS: THE MENUS
     ================================================================

     Same card as the composer: one surface, one radius, one border. The
     vertical offset is set in cloud.js (placePopupAboveBar), which measures
     the bar -- the field grows, so the offset cannot be a constant. */

  body.cc-games-room .br-popup,
  body.cc-music-room .br-popup {
    right: 10px;
    width: min(260px, calc(100vw - 40px));
    padding: 8px;
    border: 1px solid #2b2b38;
    border-radius: 14px;
    background: #17171f;
    color: #e8e8ef;
    font-size: 13px;
    box-shadow: 0 12px 32px rgba(0, 0, 0, 0.6);
  }

  body.cc-games-room .br-popup .popup-title,
  body.cc-music-room .br-popup .popup-title {
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: #8a8a9e;
    padding: 4px 8px 6px;
  }

  body.cc-games-room .br-popup .popup-item,
  body.cc-music-room .br-popup .popup-item {
    padding: 7px 8px;
    border-radius: 8px;
    color: #dcdce6;
    transition: background 0.12s ease;
  }

  @media (hover: hover) {
    body.cc-games-room .br-popup .popup-item:hover,
    body.cc-music-room .br-popup .popup-item:hover {
      background: #262633;
      color: #ffffff;
    }
  }

  body.cc-games-room .br-popup .popup-select,
  body.cc-music-room .br-popup .popup-select {
    background: #20202a;
    color: #e8e8ef;
    border: 1px solid #33333f;
    border-radius: 8px;
  }

  /* The emoji grid is a menu like any other, so it gets the same inset. */
  body.cc-games-room .emoji-grid,
  body.cc-music-room .emoji-grid {
    gap: 4px;
    padding: 2px;
  }

  body.cc-games-room .emoji-item-img,
  body.cc-music-room .emoji-item-img {
    width: 30px;
    height: 30px;
    border-radius: 6px;
  }
}

/* ================================================================
   RIGHT-SIDE CHATS: A MESSENGER-STYLE FEED
   ================================================================

   The Games lobby, the per-game rooms and the Music lobby run their chat
   in a column only clamp(260px, 22vw, 380px) wide. The feed was built for
   a full-width room over a photo or video: 42px avatars, 80%-wide content,
   every message its own slab of vertical space, white text carrying a black
   glow so it survives a moving backdrop. None of that earns its keep on a
   flat black column, and at that width it left one short message per third
   of the screen.

   So the column gets the Messenger treatment instead: a small avatar in a
   fixed gutter, the name inline and bold ahead of the message, no bubble
   behind anything, and runs of one person's messages sharing a single
   avatar with only a hairline between them. A new speaker gets real air.

   The room class is doubled throughout for the reason it is elsewhere in
   this file: the theme blocks (body[data-theme="dark"] .chat-text and
   friends) score 0,2,1 and carry !important, so a single class here would
   lose to them. Each rule instead carries #chatFeed as its scope, which
   both beats that score on its own and keeps the rule off the modals. */

body.cc-games-room #chatFeed,
body.cc-music-room #chatFeed {
  padding: 6px 10px 10px;
  line-height: 1.35;
}

body.cc-games-room #chatFeed .chat-bubble,
body.cc-music-room #chatFeed .chat-bubble {
  margin: 0;
  padding: 0;
}

/* A run of one person is tight; a change of speaker breathes. */
body.cc-games-room #chatFeed .chat-row:not(.chat-row-cont),
body.cc-music-room #chatFeed .chat-row:not(.chat-row-cont) {
  margin-top: 9px;
}

body.cc-games-room #chatFeed .chat-row,
body.cc-music-room #chatFeed .chat-row {
  display: flex;
  align-items: flex-start;
  gap: 8px;
}

/* The avatar is a 28px token in a fixed gutter, so the text of every row
   starts on the same line whether or not this row drew one. */
body.cc-games-room #chatFeed .chat-avatar,
body.cc-music-room #chatFeed .chat-avatar {
  width: 28px !important;
  height: 28px !important;
  min-width: 28px;
  margin-right: 0 !important;
  border-radius: 50%;
}

body.cc-games-room #chatFeed .chat-row-cont > .chat-avatar,
body.cc-music-room #chatFeed .chat-row-cont > .chat-avatar {
  visibility: hidden;
}

body.cc-games-room #chatFeed .chat-content,
body.cc-music-room #chatFeed .chat-content {
  flex: 1 1 auto;
  min-width: 0;
  max-width: none;
}

body.cc-games-room #chatFeed .chat-text,
body.cc-music-room #chatFeed .chat-text {
  background: transparent !important;
  box-shadow: none !important;
  padding: 0 !important;
  border-radius: 0;
  font-size: 14px;
  line-height: 1.35;
  color: #e8e8ef !important;
  text-shadow: none !important;
  word-break: break-word;
}

/* The name leads the message, in the Messenger accent.

   !important is not decoration here. The legibility block at the top of
   this file sets `body[data-theme] .chat-inline-username { color: #fff
   !important }`, and within one origin an important declaration beats a
   non-important one outright -- specificity is only consulted between
   declarations of equal weight, so a higher-scoring plain rule loses to
   it. */
body.cc-games-room #chatFeed .chat-inline-username,
body.cc-music-room #chatFeed .chat-inline-username {
  font-weight: 600;
  color: #74a9ff !important;
  text-shadow: none !important;
}

/* Reactions tuck under the message instead of floating over it. */
body.cc-games-room #chatFeed .chat-reactions,
body.cc-music-room #chatFeed .chat-reactions {
  margin-top: 3px;
  padding-left: 0;
  height: auto;
  gap: 6px;
  font-size: 15px;
}

body.cc-games-room #chatFeed .chat-image,
body.cc-music-room #chatFeed .chat-image {
  max-width: 100%;
  max-height: 220px;
  margin-top: 6px;
  border: none;
  border-radius: 10px;
}

body.cc-games-room #chatFeed .chat-youtube,
body.cc-music-room #chatFeed .chat-youtube {
  max-width: 100%;
  margin-top: 6px;
  border: none;
  border-radius: 10px;
}

/* Row controls: small, top-right, out of the way until a pointer asks. */
body.cc-games-room #chatFeed .chat-actions,
body.cc-music-room #chatFeed .chat-actions {
  flex-direction: row;
  align-items: flex-start;
  gap: 2px;
  margin-left: auto;
  padding-top: 0;
  flex-shrink: 0;
}

body.cc-games-room #chatFeed .chat-actions .chat-follow-btn,
body.cc-music-room #chatFeed .chat-actions .chat-follow-btn,
body.cc-games-room #chatFeed .chat-actions .chat-delete-btn,
body.cc-music-room #chatFeed .chat-actions .chat-delete-btn,
body.cc-games-room #chatFeed .chat-actions .chat-report-btn,
body.cc-music-room #chatFeed .chat-actions .chat-report-btn {
  font-size: 13px;
  line-height: 1;
  width: 20px;
  height: 20px;
  text-shadow: none;
}


/* ================================================================
   THE WELCOME PAGE KEEPS A TRANSPARENT HUD
   ================================================================

   The only top-HUD change left in the file. Everywhere else the HUD is
   left exactly as V0.5.7 had it: blue, with its underline, on every page
   and in every room.

   The welcome page is the exception because it is a splash -- the logo, a
   search box, a sign-in, over the site's own artwork -- and a solid band
   across the top of it reads as a stray bar rather than as chrome.

   Desktop only, as before. At phone width the HUD sits directly over the
   landing copy, so a see-through band there drops the topic line onto
   whatever is scrolling under it.

   Keyed on a class on <body>, because the page has no .top-hud in its
   markup -- injectHUD() writes it in at runtime -- so there is nothing
   static to hang a selector off. */
@media (min-width: 761px) {
  body.landing-page .top-hud {
    background: transparent !important;
  }
}

/* ================================================================
   MOBILE: A STANDARD COMPOSER, AND A TIKTOK ICON RAIL
   ================================================================

   Two things are wrong with the phone input, and they are separate.

   ── 1. The field collapsed to a sliver ───────────────────────────────
   The field was flex:1 1 auto with min-width:0. That combination means
   "take the slack, but give ground all the way" -- and when the media
   buttons (up to six of them in a music room) and the send button all
   asked for space on the same row, the field lost every pixel and rendered
   its placeholder one letter per line, as a vertical strip.

   min-width:0 was there to stop a long pasted URL widening the row, and
   it is still what does that -- but it has to be a floor low enough to
   survive an ordinary row, not zero. It is 96px now, which is about
   eight characters: the field always has somewhere to type, and a pasted
   URL still wraps inside the pill because of overflow-wrap.

   ── 2. The chat icons leave the bar ──────────────────────────────────
   Emojis / Tools / Host Menu move up the right edge of the screen in a
   vertical rail, TikTok style -- out of the bar entirely, so they stop
   competing with the field for a 360px row and stop being something you
   have to aim at between the text and the send button.

   They are position:fixed against the viewport rather than absolute
   against the bar, because the rail is meant to float over the feed: the
   offsets are from the bottom of the screen, which is where a thumb
   already is.

   !important on the geometry throughout: chatcloud.html writes
   position/right/width/height onto these icons as INLINE styles, and an
   inline declaration beats any stylesheet rule short of !important.

   Phone only. From 761px up the desktop blocks own all of this. */
@media (max-width: 760px) {

  /* ── The bar: pill + send, nothing else fighting for the row ──────── */
  .chat-input-bar {
    padding: 8px 10px calc(8px + env(safe-area-inset-bottom, 0px));
    background: #0b0b10;
    border-top: 1px solid rgba(255, 255, 255, 0.07);
    align-items: center;
  }

  .input-left {
    display: flex;
    flex-wrap: nowrap;
    align-items: center;
    gap: 6px;
    width: 100%;
    padding-right: 0;
  }

  .input-left > .br-icon {
    flex: 0 0 auto;
  }

  /* The media buttons share the row with the field, so they give up size
     rather than space. At 24px they read fine and cost 144px between
     them, which leaves the field a usable width on a 360px phone. */
  .input-left > .br-icon.game-btn {
    width: 24px !important;
    height: 24px !important;
    margin-right: 0;
  }

  /* The pill. min-width is the fix for the collapse described above --
     NOT min-width:0, which is what caused it. */
  #chatInputTop {
    flex: 1 1 auto;
    min-width: 96px;
    width: auto;
    max-width: none;
    margin-left: 0;
    min-height: 40px;
    max-height: 120px;
    overflow-y: auto;
    padding: 10px 16px !important;
    border-radius: 999px;
    background: #1a1a22 !important;
    color: #ececf2 !important;
    border: 1px solid #2b2b38 !important;
    box-shadow: none !important;
    font-size: 15px;
    line-height: 1.35;
    overflow-wrap: anywhere;
    word-break: break-word;
  }

  #chatInputTop:focus {
    border-color: #3d6ea8 !important;
    outline: none;
  }

  .chat-input:empty::before {
    color: #6b6b7d;
  }

  .chat-send-btn {
    display: flex;
    width: 34px;
    height: 34px;
    flex: 0 0 auto;
    border-radius: 50%;
    background: #2f6fd0;
    transition: background 0.15s ease, opacity 0.15s ease;
  }

  .chat-send-btn:disabled {
    opacity: 0.3;
    cursor: default;
  }

  /* The typing readout and the character counter are both full-width
     room furniture; in a column this narrow they only cost the field
     height. */
  .char-counter {
    display: none !important;
  }
}

/* ============================================================
   MUSIC TOPICS — transparent chrome + a framed backdrop
   ============================================================
   A "Music - <genre>" room plays over its own backdrop, so the chrome
   gets out of the way: the HUD, the chat column, the input bar and every
   chat row go fully transparent and the picture reads through them. The
   two things a member types into -- the chat box (#chatInputTop) and the
   HUD topic search (#hudTopicSearchInput) -- keep their own background,
   so neither field washes out over the video.

   The backdrop is framed between the HUD and the chat input instead of
   being stretched across the whole viewport. Covering the whole screen
   zoomed the picture in hard; covering just the strip -- touching the
   HUD's bottom edge and the input's top edge -- crops far less, and none
   of it is hidden behind the chrome. The strip edges arrive as
   --media-band-top / --media-band-bottom from fitMediaBackdropBand. */

/* -- chrome fully transparent -- */
body.cc-music-subroom .top-hud {
  background: transparent !important;
  border-bottom: none !important;
  box-shadow: none !important;
}

body.cc-music-subroom .chatroom-body,
body.cc-music-subroom #chatFeed,
body.cc-music-subroom .chat-input-bar {
  background: transparent !important;
  border-top: none !important;
  box-shadow: none !important;
}

body.cc-music-subroom .chat-row,
body.cc-music-subroom .chat-content,
body.cc-music-subroom .chat-text,
body.cc-music-subroom .chat-bubble,
body.cc-music-subroom .chat-username,
body.cc-music-subroom .chat-reactions {
  background: transparent !important;
  border: none !important;
  box-shadow: none !important;
}

/* The backdrop video / image fills only the strip, touching the HUD and
   the input. Phones only: on a PC the picture stays full-bleed, as it
   always was. NB: the YouTube song embed (#ytbg) is left to its own
   band-sized rule -- an <iframe> cannot be object-fitted. */
@media (max-width: 760px) {
  body.cc-music-subroom #mediaBackground video,
  body.cc-music-subroom #mediaBackground img:not(.deck-fit) {
    top: var(--media-band-top, 0px) !important;
    height: calc(
      100dvh - var(--media-band-top, 0px) - var(--media-band-bottom, 0px)
    ) !important;
    width: 100vw !important;
    object-fit: cover !important;
  }
}
