/* CHAT scene — palette + layout sampled from PSD/chat.png:
   black sidebar/stage, var(--hover-bg-2) panels, #141414 header, #111 input.
   Panels are fixed-width columns (room to add more), not full-width. */

.chat-shell {
  display: flex; flex-direction: column;
  height: 100vh; width: 100vw;
  background: var(--chat-stage);
}
.chat-main { flex: 1; min-height: 0; display: flex; position: relative; }

/* ---- Top bar (mockup): brand · souls · centred shelf map · clock ---- */
.chat-topbar {
  flex: none; position: relative;
  display: flex; align-items: center; gap: 16px;
  height: 44px; padding: 0 14px;
  background: var(--panel-head); border-bottom: 1px solid var(--panel-line);
}
.tb-brand { display: flex; align-items: center; gap: 2px; flex: none; }
.tb-moon { width: 18px; height: 18px; display: block; flex: none; }
.tb-word { font-family: var(--font-mono); font-size: 13px; font-weight: 700; letter-spacing: .16em; color: var(--white); margin-left: -1px; }
.tb-word b { color: var(--accent); font-weight: 700; }
.tb-souls {
  display: flex; align-items: center; gap: 7px; flex: none;
  padding: 4px 9px; border-radius: 3px; background: var(--panel-field);
  font-family: var(--font-mono); font-size: 11px; color: var(--ink-dim);
}
.tb-souls::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: var(--good); flex: none; }
.tb-souls b { color: var(--ink); font-weight: 700; }
.tb-linked { color: #7fa8d8; margin-left: 2px; }
.tb-linked b { color: #a9cbf0; }
.tb-spacer { flex: 1; min-width: 0; }
.tb-user { flex: none; font-family: var(--font-mono); font-weight: 700; font-size: 12px; letter-spacing: .04em; }
.tb-user:empty { display: none; }
.tb-time { flex: none; font-family: var(--font-mono); font-size: 12px; color: var(--ink-dim); }

/* Optional "new build" chip (design 3a) — amber advisory beside presence. */
.tb-newbuild {
  position: fixed; top: 8px; left: 50%; transform: translateX(-50%); z-index: 90000; display: flex; align-items: center; gap: 8px;
  padding: 5px 6px 5px 11px; border-radius: 4px; background: #1e1a10; border: 1px solid #4a3c18; box-shadow: 0 8px 24px rgba(0,0,0,.5);
  animation: un-slide 320ms ease both;
}
@keyframes un-slide { 0% { opacity: 0; } 100% { opacity: 1; } }
.tb-nb-dot { width: 5px; height: 5px; border-radius: 50%; background: #e0a33a; flex: none; animation: nb-pulse 2.2s ease-in-out infinite; }
.tb-nb-label { font-family: var(--font-mono); font-size: 10px; letter-spacing: .1em; color: #e0b25c; }
.tb-nb-refresh {
  font-family: var(--font-mono); font-size: 10px; letter-spacing: .1em; color: #e8c98a;
  padding: 2px 7px; border-radius: 2px; border: 1px solid #6b5520; background: transparent; cursor: pointer;
  transition: background .15s ease, border-color .15s ease, color .15s ease;
}
.tb-nb-refresh:hover { background: #3a2f16; border-color: #a3822f; color: #f0d9a4; }
.tb-nb-x {
  font-family: var(--font-mono); font-size: 11px; line-height: 1; color: #7a6634;
  padding: 0 3px; border: none; background: none; cursor: pointer; transition: color .15s ease;
}
.tb-nb-x:hover { color: #e0b25c; }

/* ---- Guest (r0dent) mode: spectator-only, yellow "sign up" locks ---- */
/* Hide the real chat composer; lockComposerForGuest() injects a .guest-composer bar in its place. */
.is-guest .chat-input-field { display: none; }
/* In the profile modal, guests can't upload avatars or use remember-me. */
.is-guest .avatar-upload, .is-guest #profile-remember, .is-guest .profile-section-label,
.is-guest .avatar-grid { display: none; }

/* Gold locked CTA shared by all guest sign-up prompts. */
.guest-lock {
  display: inline-flex; align-items: center; gap: 7px; cursor: pointer;
  padding: 7px 12px; border-radius: 4px;
  border: 1px solid #6b5520; background: linear-gradient(#241d0c, #1a1509);
  font-family: var(--font-mono); font-size: 11px; font-weight: 700; letter-spacing: .1em; color: #e8c98a;
  transition: background .15s ease, border-color .15s ease, color .15s ease;
}
.guest-lock:hover { background: #3a2f16; border-color: #a3822f; color: #f0d9a4; }
.guest-lock .fa-lock { font-size: .9em; opacity: .9; }
.guest-composer .guest-lock { white-space: nowrap; flex: none; }   /* keep "SIGN UP" on one line */

/* Solid gold guest button (top-bar "CLAIM YOUR NAME"). */
.guest-solid {
  display: inline-flex; align-items: center; cursor: pointer; white-space: nowrap;
  padding: 7px 14px; border-radius: 4px; border: 1px solid #e6ad3f;
  background: linear-gradient(#e8b24a, #d69a2f); color: #201703;
  font-family: var(--font-mono); font-size: 11px; font-weight: 700; letter-spacing: .1em;
  transition: background .15s ease, border-color .15s ease;
}
.guest-solid:hover { background: #f0bd55; border-color: #f0bd55; }

/* Guest composer bar (replaces the chat input for guests) — boxed, gold-bordered. */
.guest-composer {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  margin: 8px; padding: 9px 10px 9px 13px; border-radius: 7px;
  border: 1px solid #4a3c18; background: #14110a;
}
.guest-composer .gc-text { display: inline-flex; align-items: center; gap: 9px; font-family: var(--font-mono); font-size: 11px; line-height: 1.45; color: #cbb98a; }
.guest-composer .gc-text .fa-lock { color: #e0b25c; font-size: 12px; }

/* guest-only elements (top-bar CLAIM YOUR NAME, friends CTA) — shown only in guest mode. */
.guest-only { display: none; }
body.is-guest .guest-only { display: inline-flex; }
body.is-guest .friend-empty { display: none; }
/* Friends guest box — muted blue copy on the panel field, dashed border. No button. */
body.is-guest .friend-guest.guest-only {
  display: block; margin: 2px 10px 6px; padding: 13px; border-radius: 7px;
  border: 1px dashed var(--panel-line); background: var(--panel-field);
}
.friend-guest .fg-text { font-family: var(--font-ui); font-size: 13px; line-height: 1.5; color: var(--ink-dim); }

/* "SHELF FULL" card — striped guest panel at the cap (NOT a .chat-col). Fades + collapses in/out. */
.shelf-full-col {
  flex: 0 0 380px; align-self: stretch; display: flex; align-items: center; justify-content: center;
  border: 1px dashed #4a3c18; border-radius: 6px; overflow: hidden;
  background: repeating-linear-gradient(45deg, #14110a, #14110a 11px, #191408 11px, #191408 22px);
  transition: opacity .24s ease, flex-basis .28s ease, margin-left .28s ease;
}
.shelf-full-col.entering, .shelf-full-col.closing { opacity: 0; flex-basis: 0; margin-left: -10px; }
.shelf-full-col .sf-inner { display: flex; flex-direction: column; align-items: center; gap: 12px; text-align: center; padding: 0 22px; max-width: 300px; }
.shelf-full-col .sf-title { font-family: var(--font-mono); font-size: 12px; font-weight: 700; letter-spacing: .22em; color: #e0b25c; }
.shelf-full-col .sf-sub { font-size: 14px; line-height: 1.55; color: #cbb98a; }
.shelf-full-col .guest-lock { align-self: center; padding: 7px 18px; }   /* compact + centered */
/* Yellow signup markers mirroring the SHELF FULL card. */
.sm-tick.sm-tick-signup { cursor: pointer; border-radius: 1px; }
.myroom-item.myroom-signup { cursor: pointer; color: #e0b25c; }
.myroom-item.myroom-signup .myroom-name { color: #e0b25c; letter-spacing: .04em; }
.myroom-item.myroom-signup:hover { background: var(--hover-bg); }

/* Bottom-center transient toast (panel-cap notice, etc.). */
.tn-toast {
  position: fixed; left: 50%; bottom: 26px; transform: translate(-50%, 12px);
  z-index: 40000; max-width: 80vw; padding: 10px 16px; border-radius: 5px;
  background: #0f1420; border: 1px solid #2b4f6b; color: #dbe6f2;
  font-family: var(--font-mono); font-size: 12px; letter-spacing: .02em;
  box-shadow: 0 14px 34px -16px #000; opacity: 0; pointer-events: none;
  transition: opacity .2s ease, transform .2s ease;
}
.tn-toast.show { opacity: 1; transform: translate(-50%, 0); }

/* Shelf mini-map — one rounded box (arrows + tick track), sampled from the mockup.
   Absolutely centered over the panel viewing area (.shelf-wrap), which sits between the
   212px sidebar and the 56px right rail — so the map lines up with the panels below it,
   not with the full top bar. Offset = half the difference of those two side widths. */
.shelf-map {
  position: absolute; top: 50%; left: calc(50% + (212px - 56px) / 2);
  transform: translate(-50%, -50%); z-index: 5;
  display: flex; align-items: center; gap: 9px; padding: 4px 8px; border-radius: 4px; background: #131a26;
}
.sm-arrow {
  width: 22px; height: 22px; flex: none; display: flex; align-items: center; justify-content: center;
  border: 1px solid #1c2836; border-radius: 3px; background: transparent; cursor: pointer;
  font-family: var(--font-mono); font-size: 13px; line-height: 1; color: #3a4757;
  transition: color .15s ease, background .15s ease, border-color .15s ease;
}
.sm-arrow:not(.disabled) { border-color: #2b3d52; background: #18222f; color: #c2d3e4; }
.sm-arrow:not(.disabled):hover { border-color: #3b5a7a; background: #1d2a3a; color: #dbe9f6; }
.sm-arrow.disabled { pointer-events: none; }
.sm-track { position: relative; min-width: 24px; height: 24px; cursor: grab; touch-action: none; }
.sm-track:active { cursor: grabbing; }
.sm-tick { position: absolute; top: 5px; height: 14px; border-radius: 1px; cursor: pointer; }   /* panels full-opacity */
.sm-tick.spine { opacity: .42; }
.sm-tick.sm-tick-av { top: 3px; height: 18px; border-radius: 3px; }   /* avatar ticks (DM / crew pit) sit a little bigger */
.sm-view { position: absolute; top: 3px; bottom: 3px; border: 1px solid rgba(140,190,240,.75); border-radius: 2px; background: rgba(120,180,240,.12);
  pointer-events: none; transition: border-color .12s ease, background .12s ease, box-shadow .12s ease; }
/* While scrubbing the mini-map, the viewport outline lights up bright neon cyan. */
.sm-track.scrubbing .sm-view { border-color: #7fd8ff; background: rgba(87,182,232,.28); box-shadow: 0 0 9px rgba(87,182,232,.6); }

/* ---- Sidebar ---- */
.chat-side {
  width: 212px; flex: 0 0 212px;
  display: flex; flex-direction: column;
  padding: 2px 0 10px;                   /* no side padding — rows run flush to the edges (mockup); tight top, 10px bottom breathing room */
  background: var(--panel-side);
  border-right: 1px solid var(--panel-line);
  position: relative; z-index: 10000;   /* above a dragged panel (it tucks under) */
}
/* Wordmark: gray letters, blue leet digits — sampled from chat.png */
.side-brand { font-family: var(--font-display); font-size: 23px; letter-spacing: 1.5px; color: var(--white); line-height: 1; }
.side-brand b { color: var(--accent); font-weight: inherit; }
.side-statusline { margin-top: 0; display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
.side-souls { font-family: var(--font-mono); font-size: 11px; color: var(--ink-dim); letter-spacing: .2px; }
.side-souls b { color: var(--ink); font-weight: 700; }
.side-time { font-family: var(--font-mono); font-size: 11px; color: var(--ink-dim); letter-spacing: .2px; white-space: nowrap; }
.side-time b { color: var(--ink); font-weight: 700; }   /* h:mm bold, like the souls number */

/* Rail section headers (spec: PSD/rail-titles.html): a tinted chip glyph + colour-tinted title +
   accent rule fading to a count. Hovering anywhere on the bar tints the row and powers up the chip.
   The whole bar toggles the list. Per-section accent driven by --rail-rgb / --rail-title. */
.sec-topics  { --rail-rgb: 87, 182, 232;  --rail-title: #8fcdf0; }
.sec-games   { --rail-rgb: 166, 120, 240; --rail-title: #c3a6f0; }
.sec-friends { --rail-rgb: 75, 191, 122;  --rail-title: #7ddba4; }
.sec-extras  { --rail-rgb: 217, 143, 184;  --rail-title: #d98fb8; }
.sec-myrooms { --rail-rgb: 125, 147, 168; --rail-title: #a9bdd1; }

.side-topics-head {
  display: flex; align-items: center; gap: 10px; cursor: pointer;   /* whole header toggles the list */
  padding: 5px 12px; margin-bottom: 2px;
  transition: background 150ms ease, box-shadow 150ms ease;
}
.side-topics-head:hover { background: rgba(var(--rail-rgb), .09); box-shadow: inset 0 -1px 0 rgba(var(--rail-rgb), .55); }

.rail-chip {
  width: 30px; height: 30px; flex: none; border-radius: 6px;
  background: rgba(var(--rail-rgb), .14); border: 1px solid rgba(var(--rail-rgb), .3);
  display: flex; align-items: center; justify-content: center;
  transition: box-shadow 150ms ease, transform 150ms ease;
}
.side-topics-head:hover .rail-chip {
  box-shadow: inset 0 0 0 1px rgba(var(--rail-rgb), .6), inset 0 0 0 30px rgba(var(--rail-rgb), .13), 0 0 12px rgba(var(--rail-rgb), .4);
  transform: translateY(-1px);
}
.rail-glyph { display: block; }

.side-section {
  flex: none; white-space: nowrap; text-transform: none;
  font-family: "Barlow Condensed", "Barlow Semi Condensed", system-ui, sans-serif; font-weight: 700;
  font-size: 19px; letter-spacing: .01em; color: var(--rail-title); transition: color .15s ease;
}
.rail-rule { flex: 1 1 0; min-width: 24px; height: 1px; background: linear-gradient(90deg, rgba(var(--rail-rgb), .55), rgba(var(--rail-rgb), 0)); }
.rail-count { flex: none; font-family: var(--font-mono); font-size: 10px; color: #4d5d75; }

.topics-search {
  flex: none; background: none; border: none; padding: 0 0 0 2px; cursor: pointer;
  color: var(--ink-dim); font-size: 12px; line-height: 1; transition: color .15s ease;
}
.topics-search:hover { color: var(--ink); }

/* Three stacked sections (Room Topics / My Rooms / My Friends). My Rooms gets twice
   the vertical space; collapsing a section drops it to just its header and the
   others grow to fill (flex-grow animates the reflow). */
.side-sections { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; margin-top: 2px; }
/* Open sections share the sidebar's height EQUALLY (flex 1 1 0), but each is capped at its own content
   (max-height: max-content) so a short list isn't stretched with dead space — its unused share is
   redistributed by flexbox to the sections that DO overflow (which then scroll). Collapsed = header only. */
.side-sec { position: relative; display: flex; flex-direction: column; min-height: 0; flex: 1 1 0; max-height: max-content; }
.side-sec + .side-sec { margin-top: 14px; }
.side-sec.collapsed { flex: 0 0 auto; }   /* keeps the base max-content cap — dropping it caused a tall section to jump to full height before collapsing */
/* Scroll fades — "more below" (bottom) and "more above" (top) when the list overflows. The top fade
   sits at the list's top edge (below the section header), anchored by --list-top set from JS. */
.side-sec::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 30px; z-index: 3;
  pointer-events: none; opacity: 0; transition: opacity .18s ease;
  background: linear-gradient(to top, var(--panel-side), transparent);
}
.side-sec::before {
  content: ""; position: absolute; left: 0; right: 0; top: var(--list-top, 0); height: 22px; z-index: 3;
  pointer-events: none; opacity: 0; transition: opacity .18s ease;
  background: linear-gradient(to bottom, var(--panel-side), transparent);
}
.side-sec.more-below::after { opacity: 1; }
.side-sec.more-above::before { opacity: 1; }
.side-sec.collapsed::before, .side-sec.collapsed::after { opacity: 0; }   /* no fades on a collapsed list. .sec-scroll-cue ("more below" cue) lives in theme.css to keep this file under budget */

.side-topics-head { flex: 0 0 auto; }
.sec-list {
  flex: 1 1 auto; min-height: 0; overflow-y: auto; list-style: none;
  display: flex; flex-direction: column; gap: 1px;   /* 1px hairline between rows (mockup) */
  transition: max-height .28s ease;   /* slide up/down on collapse (max-height set from JS) */
  scrollbar-width: none; -ms-overflow-style: none;   /* no scrollbar — rows run full width; still scrolls by wheel/trackpad */
}
.sec-list::-webkit-scrollbar { width: 0; height: 0; display: none; }

.room-item {
  display: flex; align-items: center; gap: 9px;
  padding: 6px 12px; border-left: 2px solid transparent; font-size: 14px; line-height: 1.25;
  color: #9db0c4; cursor: pointer; transition: background .12s ease, color .12s ease;
}
.room-item:hover { background: var(--hover-bg); color: #c7d6e4; }
.room-item.active { color: #dce7f2; border-left-color: var(--panel-cap, var(--accent)); background: #17263f; }   /* open chat room */
#games-list .room-item.active { color: #e2dcf2; background: #211a3a; }                                          /* open game */
#games-list .room-item:not(.active):hover { background: #17112b; color: #d8c9f4; }                               /* purple hover for the Games menu (skip the already-open/highlighted one) */
#extras-list .room-item.active { color: #e6c4d9; background: #1b1826; }                                         /* open extra (navy-rose) */
#extras-list .room-item:not(.active):hover { background: #1b1826; color: #d6a6c4; }                             /* muted rose hover for Extras */
#extras-list .room-item.active { border-left-color: #d98fb8; }
#extras-list .room-count { margin-left: auto; }   /* push the live "N here" count to the right edge (bare-text items) */
.room-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* member count with a little person glyph */
.room-count { flex: 0 0 auto; display: flex; align-items: center; gap: 4px; font-family: var(--font-mono); font-size: 10px; color: #7d93a8; }
.ppl-glyph { display: block; fill: currentColor; opacity: .8; }
/* green unread pill (shared by rooms + shelf order) */
.unread-pill {
  flex: 0 0 auto; min-width: 16px; height: 16px; padding: 0 4px; box-sizing: border-box;
  display: flex; align-items: center; justify-content: center; border-radius: 8px;
  background: var(--unread-bg); color: var(--unread-fg);
  font-family: var(--font-mono); font-weight: 700; font-size: 10px;
}

/* Shelf Order — mirrors the open panels: number + cap-colour chip + ALL-CAPS title. Sits in an
   inset list, separated from the sections above by a hairline. */
.sec-myrooms { border-top: 1px solid #141b26; padding-top: 11px; margin-top: 14px; }
#myrooms-list { padding: 0 10px; gap: 2px; }
.myroom-item {
  display: flex; align-items: center; gap: 7px;
  padding: 4px 7px; border-left: 2px solid var(--panel-cap, var(--accent));
  line-height: 1.2; cursor: pointer; transition: background .12s ease, color .12s ease;
}
.myroom-item:hover { background: var(--hover-bg-2); }
.myroom-item.focused { background: #16202e; }                 /* the panel you're focused on */
/* Panel visibility fade: gradient the label bright→gray toward whichever edge it's sliding off; fully
   off = all gray (via --vis: 0%). One continuous scale — no discrete "offscreen" state. */
.myroom-item.partial-right .myroom-name,
.myroom-item.partial-left  .myroom-name {
  color: transparent; -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent;
}
/* Fade point tracks the visible fraction (--vis): bright over the on-screen part, gray over the off
   part. The left variant is the exact mirror — same stops, just flipped with `to left`. */
.myroom-item.partial-right .myroom-name { background-image: linear-gradient(90deg,  #c2d3e4 0%, #c2d3e4 calc(var(--vis, 60%) - 14%), #67788c var(--vis, 60%)); }  /* right edge off: visible(left) bright → gray */
.myroom-item.partial-left  .myroom-name { background-image: linear-gradient(270deg, #c2d3e4 0%, #c2d3e4 calc(var(--vis, 60%) - 14%), #67788c var(--vis, 60%)); }  /* left edge off:  visible(right) bright → gray */
.myroom-n { flex: 0 0 auto; width: 11px; font-family: var(--font-mono); font-size: 9px; color: var(--label); }
.myroom-name { flex: 0 1 auto; margin-right: auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-family: var(--font-mono); font-size: 10px; letter-spacing: .04em; text-transform: uppercase; color: #c2d3e4; }

/* Friends (avatar + name + activity + status dot; placeholder for now) */
.friend-item {
  display: flex; align-items: center; gap: 9px;
  padding: 5px 10px; font-size: 13px; line-height: 1.2; color: var(--ink-dim);
  cursor: pointer; transition: background .15s ease, color .15s ease;
}
.friend-item:hover { background: var(--hover-bg); color: var(--ink); }
.friend-empty { padding: 5px 12px; font-family: var(--font-mono); font-size: 10px; color: var(--ink-faint); font-style: normal; }

/* ---- Panels strip (horizontal; more panels dock here later) ---- */
/* Shelf wrapper — non-scrolling; the 10px pad here gives the margin around the viewing area
   WITHOUT touching the strip's scroll geometry (so the last panel scrolls fully into view). */
.shelf-wrap { flex: 1; min-width: 0; position: relative; display: flex; padding: 10px 0; background: var(--chat-stage); }   /* no L/R padding — panels run edge to edge under the fades */
.chat-panels {
  flex: 1; min-width: 0;
  display: flex; align-items: stretch;
  gap: 10px;                            /* panel spacing (kept in sync with JS GAP) */
  padding: 0 10px;                      /* 10px edge inset (JS EDGE) — end panels rest off the edge for breathing room */
  overflow: hidden;                     /* no scrollbar — scrolled via the arrows */
  background: var(--chat-stage);
}
/* Left / right drop-shadow fades over the shelf edges — shown when content is scrolled off. */
.shelf-fade { position: absolute; top: 10px; bottom: 10px; width: 10px; pointer-events: none; z-index: 6; opacity: 0; transition: opacity .2s ease; }
.shelf-fade-left  { left: 0;  background: linear-gradient(to right, rgba(6, 9, 14, .92) 0%, rgba(6, 9, 14, .5) 45%, transparent 100%); }
.shelf-fade-right { right: 0; background: linear-gradient(to left,  rgba(6, 9, 14, .92) 0%, rgba(6, 9, 14, .5) 45%, transparent 100%); }
.shelf-wrap.fade-left  .shelf-fade-left  { opacity: 1; }
.shelf-wrap.fade-right .shelf-fade-right { opacity: 1; }

/* Paged scroll arrows — top of the right rail, always visible (dimmed when you
   can't scroll that way). */
/* plain left/right arrows (no circle), centered in the top header band */
.rail-arrows { height: 56px; display: flex; align-items: center; gap: 14px; }
.scroll-arrow {
  background: none; border: none; color: #9aa4b4;
  font-size: 17px; line-height: 1; cursor: pointer; padding: 2px;
  transition: color .15s ease, opacity .15s ease;
}
.scroll-arrow:hover { color: #fff; }
.scroll-arrow.disabled { opacity: .25; pointer-events: none; }

/* Far-right fixed icon rail (utility actions) */
.chat-rail {
  flex: 0 0 56px; width: 56px;
  display: flex; flex-direction: column; align-items: center; gap: 14px;
  padding: 12px 0 14px; border-left: 1px solid var(--panel-line);
  background: var(--panel-side);
  position: relative; z-index: 10000;   /* a dragged panel slides underneath this */
}
/* Notifications drawer — reads as the rail widening: it sits just left of the 56px icon strip and
   slides out from behind it (right→left) over the panels; the close button slides it back. */
.rail-drawer {
  position: absolute; top: 0; bottom: 0; right: 56px; width: 320px; box-sizing: border-box;
  display: flex; flex-direction: column; background: var(--panel-side); border-left: 1px solid var(--panel-line);
  box-shadow: none;
  transform: translateX(100%); pointer-events: none; z-index: 9990;
  transition: transform .32s cubic-bezier(.2,.7,.3,1), box-shadow .32s ease;
}
.rail-drawer.open { transform: none; pointer-events: auto; box-shadow: -11px 0 22px rgba(0,0,0,.5); }
.rd-head { flex: none; display: flex; align-items: center; gap: 8px; height: 44px; padding: 0 12px 0 14px; border-bottom: 1px solid var(--panel-line); }
.rd-title { flex: 1; min-width: 0; white-space: nowrap; font-family: var(--font-mono); font-size: 10px; font-weight: 700; letter-spacing: .16em; color: #e4eef8; }
.rd-clear { flex: none; font-family: var(--font-mono); font-size: 9px; letter-spacing: .12em; color: #7fc8f0; cursor: pointer; transition: color .14s ease; }
.rd-clear:hover { color: #b9dcf5; }
.rd-clear[hidden] { display: none; }
/* Matches the panel header close button: borderless, colour-shifts to red-orange on hover. */
.rd-close { flex: none; display: flex; align-items: center; justify-content: center; cursor: pointer;
  background: none; border: none; color: var(--ink-dim); font-size: 15px; padding: 0 1px; line-height: 1; transition: color .15s ease; }
.rd-close:hover { color: #e0653c; }
.rd-scroll { flex: 1; min-height: 0; overflow-y: auto; padding-bottom: 12px; }
.rd-sec { display: flex; align-items: center; justify-content: space-between; gap: 8px;
  padding: 13px 12px 7px; font-family: var(--font-mono); font-size: 9px; letter-spacing: .2em; color: #5c6f84; }
.rd-sec-clear { flex: none; letter-spacing: .12em; color: #7fc8f0; cursor: pointer; transition: color .14s ease; }
.rd-sec-clear:hover { color: #b9dcf5; }
.rail-drawer-game .rd-sec-clear { color: #c3a6f0; }
.rail-drawer-game .rd-sec-clear:hover { color: #ddccff; }
.rd-empty { padding: 26px 14px; text-align: center; font-size: 12.5px; color: #566472; }
.rd-av { flex: none; border-radius: 4px; display: flex; align-items: center; justify-content: center;
  font-family: var(--font-mono); font-weight: 700; background-size: cover; background-position: center; }
.rd-av.has-image { color: transparent; }
/* Pending (incoming request) — green accent, ACCEPT / DECLINE */
.rd-pend { display: flex; gap: 9px; margin: 0 10px 6px; padding: 10px; background: rgba(75,191,122,.07); border-left: 2px solid #4bbf7a; }
.rd-pend .rd-av { width: 28px; height: 28px; font-size: 11px; background-color: #24402f; color: #7fe0a8; }
.rd-pbody { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 6px; }
.rd-pline { font-size: 13.5px; line-height: 1.35; color: #a9c9b7; }
.rd-pline b { font-weight: 700; cursor: pointer; }
.rd-pmsg { font-size: 12px; line-height: 1.4; color: #7d90a4; font-style: italic; }
.rd-pacts { display: flex; gap: 5px; }
.rd-btn { cursor: pointer; font-family: var(--font-mono); font-size: 9px; font-weight: 700; letter-spacing: .1em; padding: 3px 8px; background: none; border: 1px solid transparent; transition: color .14s ease, border-color .14s ease, filter .14s ease; }
.rd-btn.accept { color: #08130d; background: #4bbf7a; border-color: #8ee3b0; }
.rd-btn.accept:hover { filter: brightness(1.08); }
.rd-btn.decline { color: #9aa8b8; border-color: #39424f; }
.rd-btn.decline:hover { color: #f0917a; border-color: rgba(224,101,60,.55); }
/* Earlier (activity log) — subtle accent, timestamp, hover X to remove permanently */
.rd-earl { position: relative; display: flex; gap: 9px; padding: 9px 10px; border-left: 2px solid transparent; }
.rd-earl:hover { background: rgba(255,255,255,.02); }
.rd-earl .rd-av { width: 26px; height: 26px; font-size: 10.5px; background-color: var(--hover-bg-2); }
.rd-ebody { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; margin-right: 14px; }
.rd-eline { font-size: 13.5px; line-height: 1.35; color: #a7b8ca; }
.rd-eline b { font-weight: 700; cursor: pointer; }
.rd-etime { font-family: var(--font-mono); font-size: 9.5px; color: #55606d; }
.rd-ex { position: absolute; top: 7px; right: 7px; width: 16px; height: 16px; border: none; background: none; cursor: pointer;
  color: #46525f; font-size: 13px; line-height: 1; border-radius: 3px; opacity: 0; transition: opacity .12s ease, color .12s ease, background .12s ease; }
.rd-earl:hover .rd-ex { opacity: 1; }
.rd-ex:hover { color: #f0a08e; background: rgba(212,122,104,.14); }

.rail-avatar {
  position: relative;
  width: 34px; height: 34px; border-radius: 5px; cursor: pointer;
  display: grid; place-content: center;
  font-family: var(--font-mono); font-weight: 700; font-size: 12px; color: #9fd2f0;
  background: #16202e; border: 1px solid #2b3d52;
  background-size: cover; background-position: center;       /* when a profile image is set */
}
.rail-avatar.has-image i { display: none; }                  /* image replaces the fallback icon */
.rail-avatar:hover { border-color: #57b6e8; box-shadow: 0 0 0 2px rgba(87,182,232,.3), 0 0 12px rgba(87,182,232,.35); filter: brightness(1.08); }
.rail-avatar::after {                     /* connection dot: green connected, red dropped */
  content: ""; position: absolute; top: -5px; right: -5px;
  width: 11px; height: 11px; border-radius: 50%;
  background: #22c55e; border: 2px solid var(--panel-side);
  transition: background .2s ease;
}
.rail-avatar.offline::after { background: #ef4444; }
.rail-btn[hidden] { display: none; }
.rail-btn {
  position: relative;
  width: 34px; height: 34px; border-radius: 5px;
  display: flex; align-items: center; justify-content: center;
  background: transparent; border: 1px solid transparent; color: var(--ink-dim);   /* gray at rest, matches the panel "2 here"/"Private" text; no resting box */
  --rail-rgb: 125, 147, 168;   /* neutral (admin/broadcast); themed per-button below */
  font-size: 15px; line-height: 1; cursor: pointer;
  transition: color .15s ease, background .15s ease, border-color .15s ease, box-shadow .15s ease;
}
/* Icons are gray at rest; on hover they light to their accent + get the tinted box + ring
   (same treatment as the left-sidebar section chips). */
.rail-btn:hover {
  color: rgb(var(--rail-rgb));
  background: rgba(var(--rail-rgb), .14); border-color: rgba(var(--rail-rgb), .3);
  box-shadow: inset 0 0 0 1px rgba(var(--rail-rgb), .6), 0 0 12px rgba(var(--rail-rgb), .4);
}
/* Per-icon accent (used only on hover; the resting icon stays gray). */
#rail-gallery { --rail-rgb: 87, 182, 232; }    /* chat blue */
#rail-media   { --rail-rgb: 224, 83, 63; }     /* YouTube red */
#rail-friends { --rail-rgb: 75, 191, 122; }    /* friends green */
#rail-games   { --rail-rgb: 166, 120, 240; }   /* games purple */
.rail-badge {
  position: absolute; top: -5px; right: -5px; min-width: 16px; height: 16px; padding: 0 4px; box-sizing: border-box;
  display: flex; align-items: center; justify-content: center; border-radius: 8px;
  background: var(--good); color: #06210f; border: 1.5px solid var(--panel-side);
  font-family: var(--font-mono); font-weight: 700; font-size: 9px;
}
.rail-badge[hidden] { display: none; }

/* A COLUMN is a strip slot (default width like the mockup column). It holds one
   full-height panel, or two stacked half-height panels. Animating flex-basis grows
   the column from the left, pushing siblings right; the horizontal open/close/spine
   mechanics live here so a panel can restack without disturbing them. */
.chat-col {
  position: relative;
  flex-grow: 0; flex-shrink: 0; flex-basis: var(--col-w, 380px);   /* width is resizable per column */
  min-width: 0;            /* allow shrink to the spine width (else the fixed-width inner blocks it) */
  height: 100%;
  display: flex; flex-direction: column; gap: 10px;
  transition: margin-left .42s cubic-bezier(.22, .61, .36, 1),
              opacity    .42s cubic-bezier(.22, .61, .36, 1),
              flex-basis .35s cubic-bezier(.22, .61, .36, 1);
}
/* Two mirror-image phases, driven from JS:
   OPEN  = expand the gap (remove .collapsed) while invisible, then fade in (remove .hidden)
   CLOSE = fade out in place (add .hidden) holding the gap, then collapse it (add .collapsed) */
.chat-col.collapsed { margin-left: calc(-1 * var(--col-w, 380px) - 10px); }   /* collapse by its own width */
/* snappy while actively resizing */
.chat-panels.resizing-active .chat-col { transition: none; }
.chat-col.hidden { opacity: 0; }
/* whole column minimized to a book spine */
.chat-col.spine { flex-basis: 40px; }

/* Lifted (being dragged): its now-empty column collapses to close the slot.
   No opacity here — the floating panel is still a DOM child and opacity would hide it too. */
.chat-col.col-lifted { flex-basis: 0 !important; margin-left: 0; overflow: hidden; pointer-events: none; }

/* A single room panel fills its column; half size = half the column height so a
   second half panel can stack beneath it (the 10px gap accounts for the -5px). */
.chat-panel {
  position: relative; flex: 0 0 auto; width: 100%; height: 100%;
  overflow: hidden; outline: none;   /* tabindex-0 for shortcut routing; focus shown via `.focused`, so no native white ring */
  border: 1px solid #1b2434; border-radius: 4px; --focus-accent: #2b4f6b; --frame-base: #1b2434; box-shadow: 0 8px 22px -12px rgba(0, 0, 0, .5);
  transition: height .32s cubic-bezier(.22, .61, .36, 1), opacity .3s ease, box-shadow .18s ease, border-color .18s ease;
}
/* Focused panel: a 1px gradient frame — accent along the top, fading down the sides, back to the resting
   frame colour at the bottom (bottom edge stays "unfocused"). Masked so it follows the rounded corners. */
.chat-panel.focused { box-shadow: 0 18px 40px -24px rgba(0, 0, 0, .9); }
.chat-panel.focused::after {
  content: ""; position: absolute; inset: 0; border-radius: 3px; padding: 1px; pointer-events: none; z-index: 6; background: linear-gradient(to bottom, var(--focus-accent) 0 10%, var(--frame-base) 50%);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0); -webkit-mask-composite: xor; mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0); mask-composite: exclude;
}
/* Game canvas panels + game-chat rooms ride the purple identity — purple window framing to match the
   Game Lobby card. Canvas panels use .panel-blue; game CHAT rooms use .panel-purple (purple body too). */
.chat-panel.panel-blue, .chat-panel.panel-purple { border-color: #33285e; --focus-accent: #6b52a8; --frame-base: #33285e; }
.chat-panel.panel-blue .chat-head, .chat-panel.panel-purple .chat-head { background: #171130; border-bottom-color: #2a2350; }
.chat-panel.panel-blue.focused .chat-head, .chat-panel.panel-purple.focused .chat-head { background: #1d1640; border-bottom-color: var(--focus-accent); }
.chat-panel.panel-purple .chat-input-field:focus { border-color: #4a3a7a; }   /* purple input focus (vs the default blue) */
/* Extras "site" panels ride a cool-rose-on-NAVY identity (frame + header stay navy, not maroon). */
.chat-panel.panel-magenta { border-color: #2b2440; --focus-accent: #5c4a70; --frame-base: #2b2440; }
.chat-panel.panel-magenta .chat-head { background: #141220; border-bottom-color: #241f36; }
.chat-panel.panel-magenta.focused .chat-head { background: #1a1730; border-bottom-color: var(--focus-accent); }
.site-body { flex: 1; min-height: 0; background: #05070c; position: relative; }
.site-frame { width: 100%; height: 100%; border: 0; display: block; background: #05070c; }
.chat-panel.half { height: calc(50% - 5px); }
/* A stacked pair splits the column height by --top-frac (default 50/50), draggable. */
.chat-col:has(> section:nth-of-type(2)) > section:first-of-type { flex: 0 0 calc(var(--top-frac, .5) * (100% - 10px)); height: auto; }
.chat-col:has(> section:nth-of-type(2)) > section:last-of-type  { flex: 0 0 calc((1 - var(--top-frac, .5)) * (100% - 10px)); height: auto; }
.chat-panel.hidden { opacity: 0; }   /* fade a stacked panel out on close */

/* Blue drop square shown in a column's blank area while dragging a panel over it. */
/* All drop indicators share one look: a dashed blue box that fades in quickly. */
@keyframes dropFadeIn { from { opacity: 0; } to { opacity: 1; } }
.stack-zone {
  flex: 1 1 auto; min-height: 0;
  background: rgba(7,181,238,.16); border: 2px dashed rgba(7,181,238,.85); border-radius: 3px;
  box-shadow: inset 0 0 22px rgba(7,181,238,.18); pointer-events: none;
  animation: dropFadeIn .12s ease;
}
/* Invalid drop (e.g. a game panel can't go half-height) → dark maroon, signals "not allowed". */
.stack-zone.invalid {
  background: rgba(74,8,18,.42); border-color: #7a1420;
  box-shadow: inset 0 0 22px rgba(74,8,18,.5);
}
/* Holds a dragged stacked panel's slot open (sibling stays put). It only SHOWS its dashed highlight
   while it's the active drop target (reordering within this column); dragging over another panel
   fades it out so only that panel's highlight remains. It still occupies the slot either way. */
.chat-panel.drop-placeholder {
  background: transparent; border: 2px dashed transparent; border-radius: 3px; box-shadow: none;
  pointer-events: none; min-height: 0;
  transition: background .12s ease, border-color .12s ease, box-shadow .12s ease;
}
.chat-panel.drop-placeholder.active {
  background: rgba(7,181,238,.16); border-color: rgba(7,181,238,.85); box-shadow: inset 0 0 22px rgba(7,181,238,.18);
}

.panel-inner {
  position: relative;
  width: 100%; height: 100%;              /* fill the (resizable) column */
  display: flex; flex-direction: column;
  background: var(--panel-bg);
  transition: opacity .3s ease;
}
/* Resize handle sits in the GAP to the right of the column (not over the panel/scrollbar).
   Cursor + a blue glow line on hover/active. Lives on the column (not clipped by the panel). */
.col-resize {
  position: absolute; top: 0; bottom: 0; right: -10px; width: 10px; z-index: 6;
  cursor: ew-resize; touch-action: none;
}
.col-resize::after {
  content: ""; position: absolute; top: 0; bottom: 0; left: 50%; transform: translateX(-50%); width: 2px;
  background: transparent; transition: background .15s ease, box-shadow .15s ease;
}
.col-resize:hover::after, .col-resize.active::after {
  background: var(--neon-blue); box-shadow: 0 0 8px 1px var(--neon-blue);
}
.chat-col.spine .col-resize { display: none; }   /* no resizing a minimized spine */

/* Horizontal divider between two stacked panels (shown only when the column is stacked). */
.row-resize {
  display: none; position: absolute; left: 0; right: 0; height: 12px; z-index: 5;
  top: calc(var(--top-frac, .5) * (100% - 10px)); cursor: ns-resize; touch-action: none;
}
.chat-col:has(> section:nth-of-type(2)) .row-resize { display: block; }
.row-resize::after {
  content: ""; position: absolute; left: 0; right: 0; top: 50%; transform: translateY(-50%); height: 2px;
  background: transparent; transition: background .15s ease, box-shadow .15s ease;
}
.row-resize:hover::after, .row-resize.active::after {
  background: var(--neon-blue); box-shadow: 0 0 8px 1px var(--neon-blue);
}
/* jump-to-newest button — fades in above the input when scrolled up.
   Default = black w/ gray outline+arrow; green outline+arrow when there's unread. */
.scroll-down {
  position: absolute; left: 50%; bottom: 66px; transform: translateX(-50%) translateY(8px);
  width: 34px; height: 34px; border-radius: 50%;
  display: grid; place-content: center;
  background: var(--hover-bg-2); color: var(--ink-dim); border: 1px solid var(--panel-line); font-size: 14px; cursor: pointer;
  opacity: 0; pointer-events: none; z-index: 3;
  box-shadow: 0 4px 14px rgba(0,0,0,.45);
  transition: opacity .2s ease, transform .2s ease, color .15s ease, border-color .15s ease;
}
.scroll-down.show { opacity: 1; pointer-events: auto; transform: translateX(-50%) translateY(0); }
.scroll-down.has-new { color: var(--good); border-color: var(--good); }
.scroll-down:hover { border-color: #2b3d52; }
.scroll-down.has-new:hover { border-color: var(--good); }
.chat-panel.spine .panel-inner { opacity: 0; pointer-events: none; }

/* ---- Game-chat panel: ONE chat with a TABLE / LOBBY tab switch (purple game frame). Each tab is a
   full embedded room chat stacked in .gc-stack; only .active is shown. Inactive tab shows an unread
   dot when its room gets a message. ---- */
.gamechat-panel .gc-tabs {
  position: relative;                       /* anchor for the sliding underline */
  display: flex; padding: 8px 0 0; background: var(--panel-head);
  border-bottom: 1px solid var(--panel-line);
}
.gamechat-panel .gc-tab {
  flex: 1; display: flex; align-items: center; justify-content: center; gap: 7px;
  padding: 8px 0 9px; background: none; border: none; cursor: pointer;
  font-family: var(--font-mono); font-size: 10.5px; font-weight: 700; letter-spacing: .16em;
  color: #6b5f8a; transition: color .15s ease;
}
.gamechat-panel .gc-tab:hover { color: #a892d0; }
.gamechat-panel .gc-tab.on { color: #c3a6f0; }
/* Single underline that slides between the two tabs (each tab is 50% wide). */
.gamechat-panel .gc-tab-underline {
  position: absolute; bottom: -1px; left: 0; width: 50%; height: 2px;
  background: #a678f0; box-shadow: 0 0 8px rgba(166, 120, 240, .6);
  transition: transform .28s cubic-bezier(.4, 0, .2, 1);
}
.gamechat-panel .gc-tabs[data-active="lobby"] .gc-tab-underline { transform: translateX(100%); }
.gamechat-panel .gc-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--good); box-shadow: 0 0 6px var(--good); }
.gamechat-panel .gc-stack { position: relative; flex: 1; min-height: 0; }
.gamechat-panel .gc-mount { position: absolute; inset: 0; display: none; flex-direction: column; min-height: 0; }
.gamechat-panel .gc-mount.active { display: flex; }
.gamechat-panel .gc-mount .chat-messages { flex: 1; min-height: 0; }

/* Book-spine view (shown when minimized) — a clean vertical tab: top cap bar, centred mono
   label, unread pill floating near the top, subtle bottom shadow (mockup). */
.panel-spine {
  position: absolute; inset: 0; z-index: 2;
  display: flex; flex-direction: column;
  background: linear-gradient(to right, #0e1622, #182233 20%, #141d2b 80%, #0c1219);
  border: 1px solid #22303f; border-radius: 3px;
  box-shadow: inset 1px 0 0 rgba(255, 255, 255, .06);   /* subtle bevel highlight on the left edge */
  opacity: 0; pointer-events: none;
  transition: opacity .3s ease, box-shadow .18s ease, border-color .18s ease, background .18s ease;
  cursor: pointer; overflow: hidden;
}
.panel-spine::before {   /* 4px accent cap along the top */
  content: ""; position: absolute; top: 0; left: 0; right: 0; height: 4px; z-index: 3;
  background: var(--panel-cap, var(--accent)); border-radius: 3px 3px 0 0;
}
.panel-spine::after {    /* soft bottom shadow */
  content: ""; position: absolute; bottom: 0; left: 0; right: 0; height: 6px; pointer-events: none;
  background: linear-gradient(to right, rgba(0, 0, 0, .55), transparent);
}
.panel-spine:hover {   /* brighten + accent ring while peeking */
  background: linear-gradient(to right, #16202e, #22314a 20%, #1b2739 80%, #101927);
  border-color: #3b5a7a; box-shadow: 0 0 0 1px rgba(87, 182, 232, .3), 0 12px 30px -14px #000;
}
.chat-panel.spine .panel-spine { opacity: 1; pointer-events: auto; }
/* Top drag zone of a minimized spine (width × the open header height) — shows the move cursor. */
.spine-drag { position: absolute; top: 0; left: 0; right: 0; height: 34px; z-index: 4; cursor: move; }

/* Minimized spine cap colour by panel identity: games/game-chat = PURPLE, Extras (site) = MAGENTA. */
.chat-panel.panel-blue .panel-spine, .chat-panel.panel-purple .panel-spine { background: linear-gradient(to right, #0c0b16, #1a1430 20%, #140f24 80%, #0a0912); border-color: #2e2544; }
.chat-panel.panel-blue .panel-spine:hover, .chat-panel.panel-purple .panel-spine:hover { background: linear-gradient(to right, #141024, #241a44 20%, #1b1436 80%, #100c1e); border-color: #4a3a7a; box-shadow: 0 0 0 1px rgba(166, 120, 240, .3), 0 12px 30px -14px #000; }
.chat-panel.panel-magenta .panel-spine { background: linear-gradient(to right, #0a0d16, #1b1830 20%, #14111f 80%, #090c14); border-color: #2b2440; }
.chat-panel.panel-magenta .panel-spine:hover { background: linear-gradient(to right, #12101e, #2a2444 20%, #1d1834 80%, #0d0f1a); border-color: #40365a; box-shadow: 0 0 0 1px rgba(217, 143, 184, .3), 0 12px 30px -14px #000; }

/* 1:1 DM panels use the standard chat frame; only the header avatar + colored-bubble messages differ. */
.chat-panel.panel-dm .drag-handle::before { display: none; }   /* no left cap bar in the DM header */
.chat-panel.panel-dm .panel-icon.dm-hav { position: relative; display: flex; align-items: center; justify-content: center; flex: none;
  width: 20px; height: 20px; border-radius: 4px; background: var(--hover-bg-2); background-size: cover; background-position: center;
  font-family: var(--font-mono); font-size: 10px; font-weight: 700; overflow: visible; }
.chat-panel.panel-dm .panel-icon.dm-hav.has-image { color: transparent; }
.dm-status { position: absolute; top: -3px; right: -3px; width: 8px; height: 8px; border-radius: 50%; border: 1.5px solid #111a29; }
.dm-status.on { background: #4bbf7a; box-shadow: 0 0 5px rgba(75,191,122,.7); } .dm-status.off { background: #55606d; } .chat-panel.dm-offline .dm-status.off { background: #d64b4b; box-shadow: 0 0 5px rgba(214,75,75,.6); } .chat-panel.dm-offline .chat-input { opacity: .45; } .chat-panel.dm-offline .chat-input-field { cursor: not-allowed; }

/* DM message bubbles: name·time label over an aligned bubble; the bar + a dark tint of the sender's
   own handle colour are set inline per message, so each person's messages carry their colour. */
.chat-panel.panel-dm .chat-messages { gap: 15px; }
.dm-msg { display: flex; flex-direction: column; align-items: flex-start; gap: 5px; }
.dm-msg.mine { align-items: flex-end; }
.dm-head { font-family: var(--font-mono); font-size: 9px; padding: 0 3px; }
.dm-name { font-weight: 700; }
.dm-time { color: #4d5a70; }
.dm-bubble { max-width: 82%; padding: 5px 12px; font-size: 14px; line-height: 1.45; word-break: break-word; }
.dm-msg .game-invite { margin-top: 2px; }   /* invite card sits below the bubble, not inside the coloured box */

/* the game-chat count badge on the spine is a plain static green circle with the number (no pulse) */

.spine-head { display: none; }   /* no chevron — the whole spine is the click target */

/* body: label centred vertically; unread pill floats near the top */
.spine-body {
  flex: 1 1 auto; min-height: 0; position: relative;
  display: flex; align-items: center; justify-content: center;
  padding: 0 4px;
}
.spine-top, .spine-row { display: flex; align-items: center; justify-content: center; }
/* username + time flow as ONE vertical line (reads bottom-to-top) */
.spine-last-line {
  writing-mode: vertical-rl; transform: rotate(180deg);
  white-space: nowrap; font-family: var(--font-ui); font-weight: 700; font-size: 12.5px; letter-spacing: .5px;
}
.spine-last-user, .spine-last-time { white-space: nowrap; }
/* vertical mono room label (reads bottom-to-top) */
.spine-room {
  writing-mode: vertical-rl; transform: rotate(180deg); white-space: nowrap;
  font-family: var(--font-mono); color: #a9bccf; font-size: 11px; font-weight: 500; letter-spacing: .14em; text-transform: uppercase;
}
.panel-spine:hover .spine-room { color: #ffffff; }
/* unread → green pill badge near the top (with a soft ring, like the mockup) */
.spine-unread:not(:empty) {   /* pill floating near the top of the tab */
  position: absolute; top: 12px; left: 50%; transform: translateX(-50%);
  writing-mode: horizontal-tb; white-space: nowrap;
  min-width: 16px; height: 16px; padding: 0 4px; box-sizing: border-box;
  display: flex; align-items: center; justify-content: center;
  background: var(--good); color: #06210f; border-radius: 8px; z-index: 4;
  font-family: var(--font-mono); font-weight: 700; font-size: 10px; letter-spacing: 0;
  box-shadow: 0 0 0 3px rgba(75, 191, 122, .18);
}
.spine-last-user { color: var(--neon-cyan); }
.spine-last-time { color: #5b6270; font-weight: 600; }

/* latest speaker + time near the bottom of every minimized spine (slides in right→left) */
.spine-last-mask {
  display: block; position: absolute; left: 50%; transform: translateX(-50%); bottom: 18px;
  width: 42px; height: 150px; overflow: hidden;
}
.spine-last {
  position: absolute; left: 0; right: 0; bottom: 0;
  display: flex; flex-direction: row; gap: 3px; justify-content: center;
  transition: transform .42s cubic-bezier(.22, .61, .36, 1);
}

.spine-count { display: none; }   /* clean tab — no bottom count (matches the mockup) */

/* Spine hover-peek popover (fixed, so it escapes the panel's clip) */
.spine-peek {
  position: fixed; z-index: 22000; width: 210px; box-sizing: border-box;
  padding: 11px 12px; border-radius: 4px;
  background: #111a26; border: 1px solid #2b4f6b; box-shadow: 0 18px 40px -18px #000;
  display: flex; flex-direction: column; gap: 7px; pointer-events: none;
}
.spine-peek[hidden] { display: none; }
.sp-head { display: flex; align-items: center; gap: 7px; }
.sp-title { font-family: var(--font-mono); font-size: 10px; letter-spacing: .1em; color: #8fd0f0; text-transform: uppercase; }
.sp-new { font-family: var(--font-mono); font-size: 9px; padding: 1px 5px; border-radius: 8px; background: var(--unread-bg); color: var(--unread-fg); }
.sp-body { font-size: 12px; line-height: 1.45; color: #a9bacd; overflow: hidden; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
.sp-hint { font-family: var(--font-mono); font-size: 9px; color: var(--label); letter-spacing: .1em; }
/* Purple variant — game + game-chat spine peeks. */
.spine-peek.sp-purple { background: #171130; border-color: #4a3a7a; }
.spine-peek.sp-purple .sp-title { color: #c3a6f0; }
.spine-peek.sp-purple .sp-body { color: #b3a6cf; }

/* header action buttons (view/half/minimize/close) — centered in the header band */
.head-actions { display: flex; align-items: center; align-self: center; gap: 8px; flex: none; }
.panel-min, .panel-half, .panel-view {
  background: none; border: none; color: var(--ink-dim); font-size: 12px; line-height: 1;
  cursor: pointer; padding: 0 1px; transition: color .15s ease;
}
.panel-min:hover, .panel-half:hover, .panel-view:hover { color: var(--ink); }
.panel-half svg { display: block; }                 /* kill the inline-SVG baseline gap */
.panel-half.on { color: var(--accent-bright); }     /* panel is currently at half height */
/* Themed header icons: game panels ride purple, Extras (site) panels ride magenta — not the chat blue.
   These carry the theme colour at REST (dimmed) and brighten on hover. */
.chat-panel.game-panel .panel-min, .chat-panel.game-panel .panel-half, .chat-panel.game-panel .panel-view, .chat-panel.game-panel .panel-close,
.chat-panel.gamechat-panel .panel-min, .chat-panel.gamechat-panel .panel-half, .chat-panel.gamechat-panel .panel-view, .chat-panel.gamechat-panel .panel-close { color: #8b78ba; }
.chat-panel.game-panel .panel-min:hover, .chat-panel.game-panel .panel-half:hover, .chat-panel.game-panel .panel-view:hover, .chat-panel.game-panel .panel-close:hover,
.chat-panel.gamechat-panel .panel-min:hover, .chat-panel.gamechat-panel .panel-half:hover, .chat-panel.gamechat-panel .panel-view:hover, .chat-panel.gamechat-panel .panel-close:hover { color: #c3a6f0; }
.chat-panel.panel-purple .panel-half.on, .chat-panel.game-panel .panel-half.on { color: #c3a6f0; }

.chat-panel.site-panel .panel-min, .chat-panel.site-panel .panel-half, .chat-panel.site-panel .panel-view, .chat-panel.site-panel .panel-close { color: #9a8296; }
.chat-panel.site-panel .panel-min:hover, .chat-panel.site-panel .panel-half:hover, .chat-panel.site-panel .panel-view:hover, .chat-panel.site-panel .panel-close:hover,
.chat-panel.site-panel .panel-half.on { color: #e8b0d0; }

/* Game panel "open chat" button — reopens the table's chat. Highlights (blue) while the chat is
   docked; carries a small dot when there's unread activity while it's closed. */
.panel-chat {
  position: relative; background: none; border: none; color: var(--ink-dim);
  font-size: 12px; line-height: 1; cursor: pointer; padding: 0 1px; transition: color .15s ease;
}
.panel-chat:hover { color: #c3a6f0; }
.panel-chat.on { color: #a678f0; }
/* Unread on the TABLE chat while the chat panel is closed/minimized → the icon stays purple and
   static; the green count BADGE is what pulses + glows. */
.panel-chat.has-unread { color: #a678f0; }
.panel-chat .pc-dot {
  position: absolute; top: -6px; right: -7px; min-width: 14px; height: 14px; padding: 0 3px;
  border-radius: 7px; background: var(--good); color: #04240f;
  font-family: var(--font-mono); font-size: 9px; font-weight: 700; line-height: 14px; text-align: center;
  box-shadow: 0 0 6px var(--good);
}
.panel-chat.has-unread .pc-dot { animation: pc-badge-pulse 2.6s ease-in-out infinite; }
@keyframes pc-badge-pulse {
  0%, 100% { box-shadow: 0 0 5px var(--good); transform: scale(1); }
  50%      { box-shadow: 0 0 13px 2px var(--good); transform: scale(1.16); }
}

.chat-head {
  position: relative;
  display: flex; align-items: center; justify-content: space-between;
  height: 34px; box-sizing: border-box;
  padding: 0 10px; background: #111a29;   /* panel header — lighter than the top bar (mockup) */
  border-bottom: 1px solid var(--panel-line);
}
.chat-panel.focused .chat-head { background: #122234; border-bottom-color: var(--focus-accent); }
/* drag-to-reorder — the grab area covers the panel's left edge through the title (cap tick + icon +
   title), but NOT the count/matchup after it. Negative margin + matching padding stretch it out to
   the header's left edge (past the 10px header padding). */
.drag-handle {
  display: inline-flex; align-items: center; gap: 8px; min-width: 0; flex: 0 0 auto;
  height: 34px; cursor: move; touch-action: none;
  margin-left: -10px; padding-left: 10px;
}

/* the lifted panel: floats free over everything, following the cursor */
.chat-panel.drag-floating {
  position: fixed; z-index: 9999; margin: 0 !important;
  box-shadow: 0 22px 55px rgba(0,0,0,.6);
  transform: scale(1.015); transform-origin: top left;
  cursor: grabbing; pointer-events: none; transition: none !important;
}
.chat-panels.dragging-active { cursor: grabbing; }
.chat-panels.panning, .chat-panels.panning * { cursor: grabbing !important; user-select: none; }

/* Drop-target overlay — covers the whole panel (full-size OR minimized spine),
   fading in as a translucent blue over the panel the cursor is over mid-drag. */
.drop-overlay {
  position: absolute; inset: 0; z-index: 7;   /* above the filter-bar overlay (z 6) so the blue highlight covers it */
  background: rgba(7,181,238,.16); border: 2px dashed rgba(7,181,238,.85); border-radius: 3px;
  box-shadow: inset 0 0 22px rgba(7,181,238,.18); opacity: 0;
  pointer-events: none; transition: opacity .12s ease;
}
.chat-panel.drop-target .drop-overlay { opacity: 1; }
/* Invalid drop onto a panel (e.g. a game panel over a half) → dark maroon. */
.chat-panel.drop-invalid .drop-overlay {
  background: rgba(74,8,18,.42); border-color: #7a1420; box-shadow: inset 0 0 22px rgba(74,8,18,.5);
}
/* Panel header = [icon/image spanning ~2 lines] + [title over subtitle]. Consistent for every
   panel; the icon is an <img> (avatar / game icon) or a fallback <i> (chat bubble / gamepad). */
/* Panel header (mockup): [cap tick] [mono title] [mono subtitle …] — no icon. */
.chat-head-title { display: flex; flex-direction: row; align-items: center; gap: 8px; min-width: 0; flex: 1; }
.drag-handle::before {   /* small vertical cap tick, coloured per panel — lives inside the grab zone */
  content: ""; flex: 0 0 auto; width: 3px; height: 16px; border-radius: 2px; background: var(--panel-cap, var(--accent));
}
.panel-icon { display: none; }   /* mockup header has no icon */
.gt-text { display: flex; flex-direction: row; align-items: baseline; gap: 8px; min-width: 0; }
.chat-room { flex: 0 0 auto; font-family: var(--font-mono); font-size: 11px; font-weight: 700; letter-spacing: .1em; line-height: 1.2; color: var(--white); white-space: nowrap; text-transform: uppercase; }
.chat-count { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; font-family: var(--font-mono); font-size: 10px; font-weight: 500; line-height: 1.1; color: var(--ink-dim); white-space: nowrap; }
.chat-count:not(:empty) { cursor: pointer; }   /* click to open the room roster */
.chat-count:not(:empty):hover { color: var(--ink); }

/* ---- Room roster popover (click "N here") — matches the panel's body/header backgrounds ---- */
.room-roster {
  position: fixed; z-index: 22000; width: 214px; overflow: hidden;
  background: #0d1421; border: 1px solid #1a2130; border-radius: 6px; box-shadow: 0 18px 40px -14px #000;
  font-family: var(--font-ui);
  opacity: 0; visibility: hidden; transform: translateY(-4px);
  transition: opacity .16s ease, visibility .16s ease, transform .16s ease;
}
.room-roster.show { opacity: 1; visibility: visible; transform: none; }
.room-roster.pur { background: #0c0b16; border-color: #2e2544; }
.rr-head { display: flex; align-items: center; justify-content: space-between;
  padding: 8px 10px; background: #111a29; border-bottom: 1px solid #1a2130;
  font-family: var(--font-mono); font-size: 9px; font-weight: 700; letter-spacing: .14em; color: #8fa6bd; }
.rr-scroll { overflow-y: auto; }
.room-roster.pur .rr-head { background: #171130; border-color: #2e2544; color: #a892d0; }
.rr-x { background: none; border: none; cursor: pointer; color: #5f7488; font-size: 12px; line-height: 1; padding: 0 2px; transition: color .12s ease; }
.rr-x:hover { color: #c7d6e4; }
.rr-grp { font-family: var(--font-mono); font-size: 8.5px; font-weight: 700; letter-spacing: .14em; color: #5f7488; padding: 8px 10px 3px; text-transform: uppercase; }
.rr-grp-link { color: #6f86c0; border-top: 1px solid #1c2634; margin-top: 3px; }   /* linked-station group header */
.rr-row { display: flex; align-items: center; gap: 8px; padding: 5px 10px; cursor: pointer; }
.rr-row:hover { background: var(--hover-bg-2); }
.rr-av { width: 22px; height: 22px; flex: none; border-radius: 4px; display: flex; align-items: center; justify-content: center;
  font-family: var(--font-mono); font-size: 10px; font-weight: 700; background: var(--hover-bg-2); background-size: cover; background-position: center; }
.rr-av.has-image { color: transparent; }
.rr-nm { flex: 0 1 auto; margin-right: auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 13px; font-weight: 600; color: #c7d6e4; cursor: pointer; }
.rr-av { cursor: pointer; }
.rr-nm:hover { text-decoration: underline dotted; text-underline-offset: 2px; }
.rr-dot { width: 7px; height: 7px; flex: none; border-radius: 50%; }
.rr-dot.on { background: var(--good); } .rr-dot.off { background: #55606d; }
.rr-dot.away { background: #e8a13a; box-shadow: 0 0 5px rgba(232,161,58,.7); }   /* idle 10+ min */
.rr-tag { flex: none; font-family: var(--font-mono); font-size: 8px; font-weight: 700; letter-spacing: .08em; padding: 2px 5px; border-radius: 3px; }
.rr-tag.seat { background: rgba(75,191,122,.16); color: #7fe0a8; }
.rr-tag.you { background: rgba(87,182,232,.16); color: #7fc8f0; }
.room-roster.pur .rr-tag.you { background: rgba(166,120,240,.18); color: #c3a6f0; }
.rr-empty { padding: 14px 10px; text-align: center; font-size: 12px; color: #5f7488; }
.panel-close {
  background: none; border: none; color: var(--ink-dim); font-size: 15px; line-height: 1;
  cursor: pointer; padding: 0 1px; transition: color .15s ease;
}
.panel-close:hover { color: #e0653c; }

/* fade strip just under the header so messages dissolve as they scroll up
   (chat-history background faded to transparent) instead of a hard cut */
/* Top-of-history fade: a zero-height flex item sitting right above the messages (so it tracks the
   filter bar), with a ::after gradient that overlays DOWN on top of the first messages. */
.msg-fade { position: relative; height: 0; z-index: 3; flex: none; }
.msg-fade::after { content: ""; position: absolute; top: 0; left: 0; right: 0; height: 12px; pointer-events: none;
  background: linear-gradient(to bottom, var(--panel-bg), transparent); }
.chat-messages {
  flex: 1; min-height: 0; overflow-y: auto; overflow-x: hidden; overflow-anchor: none; position: relative; will-change: transform;   /* will-change: own GPU layer so scrolling doesn't repaint the focused panel's masked gradient frame (main-thread paint stall on weaker GPUs). overflow-anchor:none — we pin scroll ourselves. */
  /* Reserve a stable scrollbar gutter and trim the right padding by its width, so the gap on the RIGHT
     (right-aligned DM bubbles) matches the gap on the LEFT — the scrollbar no longer offsets one side. */
  scrollbar-gutter: stable; padding: 16px 15px 8px 18px;   /* right = left(18) minus scrollbar(8) plus a +5px gap */
  display: flex; flex-direction: column; gap: 8px;
}
/* Nothing in the message list may cause a horizontal scrollbar. */
/* Rows bleed 18px past the list padding on each side (for the full-width hover background), so their
   max must allow that extra 36px — otherwise the cap shifts right-aligned (DM) bubbles inward, leaving
   a big right gap. overflow-x:hidden still prevents any horizontal scrollbar. */
.chat-messages .msg { max-width: calc(100% + 36px); }
.chat-messages .msg-body, .chat-messages .msg-c-body { min-width: 0; overflow-wrap: anywhere; }
.baud-cursor { display: inline-block; width: .55em; height: 1.05em; margin-left: 1px; background: currentColor; vertical-align: text-bottom; }   /* DDial modem typewriter: block cursor trailing the letters */
/* bottom-anchor: this spacer eats free space so messages sit at the bottom (even when nearly empty); collapses once messages overflow. */
.chat-messages::before { content: ""; margin-top: auto; }
.chat-messages::-webkit-scrollbar { width: 8px; }
.chat-messages::-webkit-scrollbar-thumb { background: var(--panel-line); border-radius: 4px; }
.chat-messages::-webkit-scrollbar-track { background: transparent; } .msg-newsep { display: flex; align-items: center; gap: 10px; margin: 4px 0 2px; }   /* offline "New messages" divider */ .msg-newsep .ns-label { flex: none; font-family: var(--font-mono); font-size: 9.5px; font-weight: 700; letter-spacing: .16em; text-transform: uppercase; color: var(--good); } .msg-newsep .ns-line { flex: 1; height: 1px; background: linear-gradient(to right, transparent, var(--good)); opacity: .55; } .msg-newsep .ns-line:last-child { background: linear-gradient(to left, transparent, var(--good)); } .msg-daysep .ns-label { color: var(--ink-faint); } .msg-daysep .ns-line { background: linear-gradient(to right, transparent, var(--panel-line)); } .msg-daysep .ns-line:last-child { background: linear-gradient(to left, transparent, var(--panel-line)); }   /* day-change divider: neutral gray, not the green new-messages one */

/* Game-chat intro (game glyph + big title + meta + one-liner). It's the first item in the message
   list: it stays put and simply scrolls up with the conversation instead of vanishing on first
   message. .has-intro disables the bottom-anchor so content flows from the top. */
.chat-messages.has-intro::before { content: none; }
.chat-empty { flex: none; display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; padding: 30px 26px 22px; }
.ce-tile { width: 78px; height: 78px; box-sizing: border-box; padding: 12px; display: flex; align-items: center; justify-content: center;
  background: rgba(166,120,240,.14); border: 1px solid rgba(166,120,240,.36); color: #a678f0; margin-bottom: 20px; }
.ce-tile svg { width: 100%; height: 100%; }
.ce-grid { width: 100%; height: 100%; display: grid; grid-template-columns: repeat(3, 1fr); grid-template-rows: repeat(3, 1fr); gap: 5px; }
.ce-grid i { background: rgba(166,120,240,.2); }
.ce-grid i.on { background: #a678f0; }
/* DM intro tile — the friend's avatar (or tinted initial) instead of a game glyph */
.ce-tile.ce-av { padding: 0; overflow: hidden; border-radius: 8px; background-size: cover; background-position: center; }
.ce-tile.ce-av .ce-av-init { font-family: "Barlow Condensed", "Barlow Semi Condensed", sans-serif; font-weight: 700; font-size: 40px; line-height: 1; }
.ce-title { font-family: "Barlow Condensed", "Barlow Semi Condensed", sans-serif; font-weight: 700; font-size: 34px; line-height: 1.02; letter-spacing: .03em; color: #f1ebff; margin-bottom: 11px; }
.ce-meta { display: flex; align-items: center; flex-wrap: wrap; justify-content: center; gap: 6px; margin-bottom: 14px;
  font-family: var(--font-mono); font-size: 9.5px; font-weight: 700; letter-spacing: .12em; color: #8b7fae; }
.ce-meta em { font-style: normal; color: #3d3352; }
.ce-hot { color: #7ddba4; }
.ce-desc { font-size: 14px; line-height: 1.5; color: #93a2ba; max-width: 260px; }
/* DDial LINK STATUS in the room intro — frameless, centered text (no pill). */
.ce-linkstat { margin-top: 10px; font-family: var(--font-mono); font-size: 10px; font-weight: 700; letter-spacing: .12em; text-align: center; }
.ce-linkstat.on { color: #6fe0a0; } .ce-linkstat.off { color: #e88a7a; } .ce-linkstat b { color: inherit; }
/* Live link-status dot in the panel header (left of the half-height icon); tooltip via data-tip. */
.link-dot { width: 9px; height: 9px; border-radius: 50%; flex: none; cursor: default; }
.link-dot.on { background: #4bd486; box-shadow: 0 0 6px #4bd486; } .link-dot.off { background: #e0653c; box-shadow: 0 0 6px #e0653c; }
/* Copyable invite link inside the TABLE chat intro (sits with the table info). */
/* matches the Game panel's INVITE LINK row (.gm-link) — dark navy field, sharp corners, blue URL */
.ce-link {
  margin-top: 16px; width: 100%; max-width: 300px; display: flex; align-items: center; gap: 8px;
  padding: 7px 9px; background: #080b13; border: 1px solid #2b2450; font-family: var(--font-mono); font-size: 10px;
}
.ce-link-lbl { flex: none; letter-spacing: .18em; color: #6b5f8a; }
.ce-link-url { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; text-align: left; color: #9fd0f0; }
.ce-link-copy { flex: none; display: inline-flex; align-items: center; gap: 6px; padding: 4px 9px; cursor: pointer; border-radius: 0;
  background: rgba(166,120,240,.14); border: 1px solid rgba(166,120,240,.4); color: #c3a6f0;
  font-family: var(--font-mono); font-size: 9px; font-weight: 700; letter-spacing: .14em; transition: background .15s ease, border-color .15s ease, color .15s ease; }
.ce-link-copy:hover { background: rgba(166,120,240,.24); border-color: #a678f0; color: #d9c6fb; }
.ce-link-copy.copied { color: #7ddba4; border-color: #2f6b45; background: rgba(75,191,122,.12); }
.ce-link-copy i { font-size: 10px; }

/* ---- Message row: dark avatar tile, then colored name with time underneath,
   and the body in default gray. Tight vertical spacing. ---- */
.msg { display: flex; flex-direction: column; gap: 2px; position: relative; padding: 3px 18px; margin: 0 -18px; transition: background .12s ease, box-shadow .12s ease; }
/* Removing (trashcan / hide-for-me): fade + drift out before the row is dropped from the DOM. */
.msg.removing { opacity: 0; transform: translateX(10px); pointer-events: none; transition: opacity .24s ease, transform .24s ease; }
/* Floating-toolbar hover (PSD/Message Actions): the row lifts with a 2px cap on the left edge. */
.msg.act-hot { background: #131b28; box-shadow: inset 2px 0 0 var(--msg-cap, var(--panel-cap, var(--accent))); }
.msg.inline.act-hot { background: #131b28; }
/* Game + game-chat panels: hovered message row + its action tray use the purple theme, not blue. */
.chat-panel.panel-purple .msg.act-hot,
.chat-panel.panel-purple .msg.inline.act-hot { background: #191231; }
.chat-panel.panel-purple .msg-actions { background: #1b1433; border-color: #3a2f5a; }
.chat-panel.panel-purple .msg-actions .ma-btn:hover { background: #2a2148; }
.chat-panel.panel-purple .msg-actions .ma-div { background: #3a2f5a; }
/* Name / avatar read as clickable (open the mini profile). */
.msg-handle, .msg-c-name { cursor: pointer; }
.msg-handle:hover, .msg-c-name:hover { text-decoration: underline dotted; text-underline-offset: 2px; }
.msg-avatar { cursor: pointer; }

/* Raised action tray, overlapping the row's top-right edge. */
.msg-actions {
  position: absolute; top: -12px; right: 8px; z-index: 4;
  display: flex; align-items: center; gap: 2px; padding: 3px 5px;
  background: #131c2b; border: 1px solid #33445a; border-radius: 6px;
  box-shadow: 0 6px 16px -8px #000;
}
.msg-actions .ma-btn {
  display: inline-flex; align-items: center; justify-content: center; width: 26px; height: 22px;
  border: none; background: none; border-radius: 4px; cursor: pointer; opacity: .85;
  color: #9db0c4; font-size: 14px;   /* beefier reply/react/trash glyphs than the old thin SVGs */
  transition: background .12s ease, opacity .12s ease, color .12s ease;
}
.msg-actions .ma-btn:hover { background: #1d2a3b; opacity: 1; }
.msg-actions .ma-reply:hover { color: #cfe0f2; }
.msg-actions .ma-react { color: #8a9cb0; }
.msg-actions .ma-react:hover { color: #ffd76a; }
.msg-actions .ma-react.disabled { color: #4a5769; opacity: .5; cursor: default; pointer-events: none; }   /* already reacted */
.msg-actions .ma-trash { color: #6d7d90; }                 /* grey until moused over */
.msg-actions .ma-trash:hover { color: #ff8f77; }
.msg-actions .ma-div { width: 1px; align-self: stretch; margin: 2px 3px; background: #2b3a4d; }
/* Reaction row (swaps in over the default menu) */
.msg-actions[data-mode="react"] { gap: 1px; padding: 3px 6px; }
.msg-actions .ma-rx { border: none; background: none; cursor: pointer; font-size: 16px; line-height: 1;
  padding: 2px 4px; border-radius: 5px; transition: background .1s ease, transform .1s ease; }
.msg-actions .ma-rx:hover { background: #24344a; transform: translateY(-1px) scale(1.15); }

/* Reaction badges on a message */
.msg-reacts { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 4px; }
.msg-reacts .rx { display: inline-flex; align-items: center; gap: 3px; padding: 1px 6px 1px 5px;
  background: #182333; border: 1px solid #2b3a4d; border-radius: 999px; font-size: 12px; line-height: 1.4; }
.msg-reacts .rx-n { font-family: var(--font-mono); font-size: 10px; font-weight: 700; color: #9db0c4; }
.msg-reacts .rx { cursor: default; }
.msg-reacts .rx.pop { animation: rxPop .3s ease-out; }
@keyframes rxPop { 0% { transform: scale(.4); } 60% { transform: scale(1.25); } 100% { transform: scale(1); } }
/* After the message lands, ONLY the reaction emoji pulses larger/smaller with a glow (slow) */
.msg-reacts .rx-e { display: inline-block; }
.msg-reacts .rx.pulse .rx-e { animation: rxPulse .9s ease-in-out 3; }
@keyframes rxPulse {
  0%, 100% { transform: scale(1); filter: none; }
  50% { transform: scale(1.55); filter: drop-shadow(0 0 6px rgba(127,180,255,.85)); }
}

/* Hover a reaction badge → the list of usernames who reacted (width hugs the longest name) */
.rx-tip { position: fixed; z-index: 24000; display: none; width: max-content; max-width: 220px;
  padding: 5px 9px; background: #0d1421; border: 1px solid #2b3a4d; border-radius: 6px;
  box-shadow: 0 10px 26px -12px #000; pointer-events: none; }
.rx-tip-u { font-family: var(--font-ui); font-size: 11px; color: #c7d6e4; line-height: 1.6; white-space: nowrap; }

/* ---- Mini profile popover (hover a name / avatar) ---- */
.msg-profile {
  position: fixed; z-index: 26500; display: none; width: 262px;
  background: #131c2b; border: 1px solid #2b4f6b; border-radius: 8px;
  box-shadow: 0 18px 44px -18px #000; color: #c2d3e4; overflow: hidden;
  font-family: var(--font-ui);
  opacity: 1; transition: opacity .16s ease;
}
.msg-profile.fade-out { opacity: 0; }
.mp-head { display: flex; align-items: center; gap: 11px; padding: 13px 13px 11px; }
.mp-av { position: relative; width: 42px; height: 42px; border-radius: 8px; flex: none; background-size: cover; background-position: center; background-color: #0e1622; }
.mp-dot { position: absolute; top: -3px; right: -3px; width: 12px; height: 12px; border-radius: 50%; border: 2px solid #131c2b; }
.mp-dot.on { background: #4bbf7a; }
.mp-dot.off { background: #e0533f; }
.mp-dot.away { background: #e8a13a; }   /* idle 10+ min */
.mp-av-i { display: flex; align-items: center; justify-content: center; font-family: var(--font-mono); font-weight: 700; font-size: 18px; }
.mp-id { min-width: 0; }
.mp-name { font-family: var(--font-mono); font-weight: 700; font-size: 15px; line-height: 1.2; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mp-tag { font-family: var(--font-mono); font-size: 9px; letter-spacing: .16em; color: #5c6b7d; margin-top: 3px; }
.mp-oneliner { padding: 0 13px 10px; font-size: 12.5px; line-height: 1.4; color: #b9cadb; font-style: italic; }
.mp-stats { display: flex; gap: 6px; padding: 0 13px; }
.mp-stat { flex: 1; min-width: 0; padding: 8px 9px; border-radius: 3px; background: #101a28; display: flex; flex-direction: column; gap: 2px; }
.mp-s-l { font-family: var(--font-mono); font-size: 8px; letter-spacing: .14em; color: #5c6b7d; }
.mp-s-v { font-family: var(--font-mono); font-size: 15px; font-weight: 700; }
.mp-recent { padding: 12px 13px 6px; }
.mp-recent .mp-h { font-family: var(--font-mono); font-size: 9px; letter-spacing: .16em; color: #5c6b7d; margin-bottom: 6px; }
.mp-empty { font-size: 13px; color: #55677c; }
.mp-actions { display: flex; flex-direction: column; gap: 6px; padding: 4px 13px 13px; }
.mp-row { display: flex; gap: 6px; }
.mp-btn { flex: 1; padding: 9px 0; text-align: center; border-radius: 3px; cursor: pointer;
  font-family: var(--font-mono); font-size: 10px; font-weight: 700; letter-spacing: .1em; transition: filter .12s ease, background .12s ease; }
.mp-btn:hover { filter: brightness(1.15); }
.mp-btn.msg, .mp-btn.pm { background: #1d3b52; border: 1px solid #2b6285; color: #cfeaff; }
.mp-btn.friend { background: #16302a; border: 1px solid #2a5a44; color: #8fe0b0; }
.mp-btn.ignore { background: #1a1a20; border: 1px solid #2e2e38; color: #8f8f9c; }
.mp-btn.block { background: #1f1210; border: 1px solid #4a2018; color: #d47a68; }
/* new (live) messages ease up from the bottom — gentle fade + small rise */
@keyframes msgIn { from { opacity: 0; transform: translateY(5px); } to { opacity: 1; transform: none; } }
.msg.enter { animation: msgIn .4s ease-out; }
/* header block: icon + name/time aligned together */
.msg-head { display: flex; gap: 9px; align-items: center; }
.msg-avatar {
  flex: 0 0 24px; width: 24px; height: 24px; border-radius: 4px;
  display: grid; place-content: center;
  font-weight: 800; font-size: 12px;
  background: var(--hover-bg-2);                 /* dark default icon; initial tinted per user (inline) */
  background-size: cover; background-position: center;   /* profile picture, when present */
}
.msg-namewrap { min-width: 0; display: flex; flex-direction: column; justify-content: center; }
.msg-handle { font-family: var(--font-mono); font-weight: 700; font-size: 13px; line-height: 1.15; }
.msg-time { font-family: var(--font-mono); font-size: 10px; color: var(--ink-faint); line-height: 1; margin-top: 1px; }
.msg-body {                            /* lines up under the username/time (past the 24px avatar + 9px gap) */
  margin-left: 33px;
  font-size: 14px; line-height: 1.3; color: var(--ink);
  white-space: pre-wrap; overflow-wrap: anywhere;
}

/* Inline views (minimal / compact): "name › message" flowing inline, stacked as tight
   as the text itself (inter-message gap == the text line spacing). */
.chat-messages:has(.msg.inline) { gap: 0; }
.msg.inline { display: block; font-size: 14px; line-height: 1.3; overflow-wrap: anywhere; white-space: pre-wrap; }
.msg-c-time { font-family: var(--font-mono); color: var(--ink-faint); font-size: 11px; margin-right: 7px; }
.msg-c-name { font-weight: 700; }
.msg-c-sep { color: var(--ink-faint); margin: 0 5px; font-size: 18px; line-height: 0; vertical-align: -1px; }
.msg-c-body { color: var(--ink); }

/* Private (/p) messages read like normal messages; only this marker is red.
   Sender: bold "/p" + regular target name; recipient: bold "Private". */
.pm-head { display: flex; align-items: baseline; } .pm-mark { margin-left: auto; padding-left: 10px; } .msg.inline .pm-mark { margin-left: 0; padding-left: 5px; padding-right: 2px; }   /* handle left, "/p target"/"Private" right; inline: right after the username instead (Username Private › message) */
.pm-tag { font-weight: 800; color: #ff5555; } .pm-who { color: #ff8080; }   /* /p or Private (bold red) + target name (red) */
.pm-recv-dot { position: absolute; left: 3px; top: 6px; font-size: 10px; line-height: 1; color: #ff4d4d; text-shadow: 0 0 5px rgba(255,77,77,.6); }   /* recipient: red lock left of the avatar */

/* System messages (command feedback): filled-triangle marker + lighter-gray text. */
.msg.system .sys-icon { color: var(--ink-dim); margin-right: 8px; font-size: 12px; }
.sys-body { color: var(--ink-dim); }

/* Presence system lines (join / enter / quit / leave) — colored left-accent block with avatar,
   name, action and time. Same look in game chat and regular rooms (semantic colors, per PSD). */
.msg.sysline {
  flex-direction: row; align-items: center; gap: 8px;
  margin: 0 -10px; padding: 6px 10px; border-left: 2px solid transparent;
}
.sysline-arrow { flex: none; width: 14px; text-align: center; font-size: 12px; } .view-inline .msg.sysline { margin-top: 1px; }   /* compact/minimal: 1px gap between stacked login/logout lines */
/* Avatar tile: force the profile image to fill the 22px tile. !important + background-size beats the
   per-kind background-COLOR fallbacks below (which must not reset sizing). */
.msg-avatar.sysline-av {
  width: 22px; height: 22px; flex: 0 0 22px; border-radius: 4px;
  font-size: 10px; font-weight: 700;
  background-size: cover; background-position: center; background-repeat: no-repeat;
}
.sysline-av.has-image { color: transparent; }
.sysline-body { flex: 1; min-width: 0; font-size: 13.5px; line-height: 1.35; }
.sysline-user { font-weight: 700; cursor: pointer; }
.sysline-user:hover { text-decoration: underline dotted; text-underline-offset: 2px; }
.sysline-time { flex: none; font-family: var(--font-mono); font-size: 9.5px; } .sysline-note { font-style: italic; opacity: .9; margin-top: 1px; overflow-wrap: anywhere; }   /* station entry/exit message on its own line in the box */ .msg.sysline:has(.sysline-note) { align-items: flex-start; }   /* two-line box: pin the chevron + timestamp to the top */
/* /me action: a normal message card whose action text flows after the name (in the username space).
   Top-aligned so the name/text sit at the top with the avatar; small gap above the time. */
.actmsg .msg-head { align-items: flex-start; } .actmsg .msg-namewrap { justify-content: flex-start; } .actmsg .msg-avatar { margin-top: 2px; }
.act-line1 { line-height: 1.15; } .act-txt { font-weight: 400; font-style: italic; font-size: 13px; }
.actmsg .msg-time { margin-top: 2px; }
/* join — green (took a seat) */
.msg.sysline-join  { background: rgba(75,191,122,.07);  border-left-color: #4bbf7a; }
.sysline-join  .sysline-body { color: #a9c9b7; } .sysline-join  .sysline-user { color: #7fe0a8; }
.sysline-join  .sysline-time { color: #4f6a5c; } .sysline-join  .sysline-av { background-color: #24402f; color: #7fe0a8; }
/* enter — green »» (entered / watching) */
.sysline-enter { background: rgba(75,191,122,.06); border-left-color: rgba(75,191,122,.5); }
.sysline-enter .sysline-body { color: #9dbfae; } .sysline-enter .sysline-user { color: #7fe0a8; }
.sysline-enter .sysline-time { color: #4f6a5c; } .sysline-enter .sysline-av { background-color: #24402f; color: #7fe0a8; }
.sysline-enter .sysline-arrow { color: #7fe0a8; }
/* quit — red (left the match, seat open) */
.msg.sysline-quit  { background: rgba(201,66,47,.06);  border-left-color: rgba(201,66,47,.75); }
.sysline-quit  .sysline-body { color: #d3a99c; } .sysline-quit  .sysline-user { color: #f0917a; }
.sysline-quit  .sysline-time { color: #7a544a; } .sysline-quit  .sysline-av { background-color: #3d2119; color: #f0917a; }
/* leave — amber «« (left the chat), dimmed so it recedes */
.sysline-leave { background: rgba(224,120,90,.05); border-left-color: rgba(224,120,90,.45); opacity: .82; }
.sysline-leave .sysline-body { color: #b39a90; } .sysline-leave .sysline-user { color: #e0a58f; }
.sysline-leave .sysline-time { color: #7a5a4a; } .sysline-leave .sysline-av { background-color: #3a2a22; color: #e0a58f; }
.sysline-leave .sysline-arrow { color: #d98a6a; }

/* In GAME chat, spectator enter/leave use blue / slate so they don't read like the green-join /
   red-quit SEAT lines. (Regular rooms keep the green »» / amber «« above.) */
.gamechat-panel .sysline-enter { background: rgba(87,182,232,.06); border-left-color: rgba(87,182,232,.5); opacity: 1; }
.gamechat-panel .sysline-enter .sysline-body { color: #93a9bf; } .gamechat-panel .sysline-enter .sysline-user { color: #7fc8f0; }
.gamechat-panel .sysline-enter .sysline-time { color: #55606d; } .gamechat-panel .sysline-enter .sysline-av { background-color: #22384d; color: #9fd8f5; }
.gamechat-panel .sysline-enter .sysline-arrow { color: #7fc8f0; }
.gamechat-panel .sysline-leave { background: rgba(120,132,150,.05); border-left-color: #4a5361; opacity: .85; }
.gamechat-panel .sysline-leave .sysline-body { color: #828d9c; } .gamechat-panel .sysline-leave .sysline-user { color: #a4b4c6; }
.gamechat-panel .sysline-leave .sysline-time { color: #55606d; } .gamechat-panel .sysline-leave .sysline-av { background-color: #242a33; color: #9aa8b8; }
.gamechat-panel .sysline-leave .sysline-arrow { color: #8794a6; }

/* Only the SEAT events (join / quit) keep the left color bar; chat enter/exit drop it (the 2px
   stays transparent so text still aligns with the seat rows). Placed last to win over the rules above. */
.msg.sysline-enter, .msg.sysline-leave { border-left-color: transparent; }
/* enter/leave lines fade out after 20s, then the row eases its height to 0 so the gap closes smoothly
   (JS pins the start height + removes the row on transitionend). */
.msg.sysline.fading { opacity: 0; overflow: hidden; padding-top: 0; padding-bottom: 0; pointer-events: none;
  transition: opacity .35s ease, max-height .4s ease, padding .4s ease; }

/* Message links: a blue link icon (opens a new tab) with a hover preview card. */
.msg-link { color: var(--neon-blue); text-decoration: none; margin: 0 3px; cursor: pointer; }
.msg-link:hover { filter: brightness(1.25); }
.msg-link i { font-size: 13px; }
/* in-app game deep-link → a rich purple invite card (spec: PSD/Join game invite). Opens the table
   locally on click, not a new tab. */
@keyframes gi-pulse { 0%, 100% { opacity: .4; } 50% { opacity: 1; } }
@keyframes gi-sheen { 0% { transform: translateX(-120%); } 100% { transform: translateX(320%); } }
.game-invite {
  display: flex; align-items: center; gap: 10px; margin: 3px 0; max-width: 340px; cursor: pointer;
  padding: 9px 11px; background: #120e1e; border: 1px solid #2e2544; border-left: 3px solid #a678f0;
}
.gi-glyph { width: 24px; height: 24px; flex: none; box-sizing: border-box; padding: 3px; display: flex; align-items: center; justify-content: center;
  background: rgba(166,120,240,.14); border: 1px solid rgba(166,120,240,.36); color: #a678f0; }
.gi-glyph svg { width: 100%; height: 100%; }
.gi-grid { width: 100%; height: 100%; display: grid; grid-template-columns: repeat(3, 1fr); grid-template-rows: repeat(3, 1fr); gap: 1.5px; }
.gi-grid i { background: rgba(166,120,240,.16); }
.gi-grid i.on { background: #a678f0; }
.gi-mid { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.gi-title { font-family: "Barlow Condensed", "Barlow Semi Condensed", sans-serif; font-weight: 700; font-size: 17px; line-height: 1.05; letter-spacing: .04em; color: #f1ebff; }
.gi-meta { display: flex; align-items: center; gap: 6px; font-family: var(--font-mono); font-size: 9.5px; letter-spacing: .12em; color: #8b7fae; }
.gi-dot { width: 5px; height: 5px; border-radius: 50%; background: #4bbf7a; animation: gi-pulse 2.2s ease-in-out infinite; }
.gi-status { color: #7fe0a8; }
.gi-sep { color: #3d3352; }
.gi-action { flex: none; display: flex; }
.gi-join { position: relative; flex: none; display: flex; align-items: center; gap: 7px; height: 30px; padding: 0 13px; box-sizing: border-box; overflow: hidden; cursor: pointer;
  appearance: none; -webkit-appearance: none; border-radius: 0; color: #fff;
  background: linear-gradient(180deg, #a678f0, #7f4fd6); border: 1px solid #b992f5; box-shadow: 0 0 18px rgba(166,120,240,.36);
  transition: filter .16s ease; }
.gi-join:hover { filter: brightness(1.09); }
.gi-join svg { position: relative; flex: none; }
.gi-join > span:last-child { position: relative; font-family: var(--font-mono); font-size: 10.5px; font-weight: 700; letter-spacing: .15em; }
.gi-sheen { position: absolute; top: 0; bottom: 0; left: 0; width: 36%; background: linear-gradient(90deg, transparent, rgba(255,255,255,.24), transparent); animation: gi-sheen 3.6s ease-in-out infinite; }

/* FULL / IN PLAY → blue dot + WATCH (spectate) button */
.game-invite[data-state="full"] .gi-dot { background: #57b6e8; animation-duration: 1.6s; }
.game-invite[data-state="full"] .gi-status { color: #7fc8f0; }
.gi-watch { flex: none; display: flex; align-items: center; gap: 7px; height: 30px; padding: 0 13px; box-sizing: border-box; cursor: pointer;
  appearance: none; -webkit-appearance: none; border-radius: 0; color: #7fc8f0;
  background: rgba(87,182,232,.09); border: 1px solid rgba(87,182,232,.45); transition: background .15s ease, border-color .15s ease; }
.gi-watch:hover { background: rgba(87,182,232,.18); border-color: #7fc8f0; }
.gi-watch svg { flex: none; }
.gi-watch > span:last-child { font-family: var(--font-mono); font-size: 10.5px; font-weight: 700; letter-spacing: .15em; }

/* ENDED / GONE → dimmed, strikethrough title, dashed disabled control */
.game-invite[data-state="ended"] { background: #0b0f16; border-color: #1a2028; border-left-color: #2a3140; }
.game-invite[data-state="ended"] .gi-glyph { opacity: .55; background: rgba(74,83,97,.16); border-color: rgba(74,83,97,.34); color: #4a5361; }
.game-invite[data-state="ended"] .gi-grid i { background: rgba(74,83,97,.16); }
.game-invite[data-state="ended"] .gi-grid i.on { background: #4a5361; }
.game-invite[data-state="ended"] .gi-title { color: #78848f; text-decoration: line-through; text-decoration-color: #39414c; }
.game-invite[data-state="ended"] .gi-meta { color: #566270; }
.game-invite[data-state="ended"] .gi-dot { background: #39414c; animation: none; }
.game-invite[data-state="ended"] { cursor: default; }
.gi-ended { display: flex; align-items: center; height: 30px; padding: 0 13px; box-sizing: border-box; cursor: not-allowed;
  border: 1px dashed #2a3140; color: #4e5966; font-family: var(--font-mono); font-size: 10.5px; font-weight: 700; letter-spacing: .15em; }
.link-preview {
  position: fixed; z-index: 22000; pointer-events: none;
  width: 280px; max-width: 88vw;
  background: #12161d; border: 1px solid #2a3550; border-radius: 10px; overflow: hidden;
  box-shadow: 0 14px 36px rgba(0,0,0,.6);
  opacity: 0; transform: translateY(6px); transition: opacity .16s ease, transform .16s ease;
  font-family: var(--font-ui);
}
.link-preview.show { opacity: 1; transform: translateY(0); }
.lp-body { padding: 10px 12px; }
.lp-title {
  font-size: 13px; font-weight: 700; color: var(--ink); line-height: 1.3;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.lp-desc {
  margin-top: 4px; font-size: 12px; color: #8a8f98; line-height: 1.4;
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;
}
.lp-desc:empty { display: none; }
.lp-img { display: none; height: 140px; background-size: cover; background-position: center; background-color: #0a0d12; }
.link-preview.has-img .lp-img { display: block; }

/* ---- Input ---- */
/* Seamless with the messages area above it (same background, no divider).
   The field itself is a lighter rounded box with a comment-bubble icon. */
.chat-input { flex: none; position: relative; padding: 6px 16px 12px; background: var(--panel-bg); }   /* never shrink — the tool bar must stay visible */
/* Editable message field (contenteditable → native caret + inline colored /p spans).
   Grows 1→3 lines, then scrolls internally (scrollbar hidden). */
.chat-input-field {
  display: block; width: 100%; box-sizing: border-box;
  padding: 9px 14px 2px; min-height: 34px; max-height: 108px; overflow-y: auto;   /* text only — the tool bar is its own row below, so scrolling never reaches the icons */
  line-height: 20px; white-space: pre-wrap; overflow-wrap: anywhere; word-break: break-word;
  background: var(--panel-field); border: 1px solid var(--panel-line); border-radius: 5px 5px 0 0; border-bottom: none; outline: none;   /* top half of the box; connects to the tool bar below */
  color: var(--ink); font-family: var(--font-ui); font-size: 14px; cursor: text;
}
.chat-input-field:focus { border-color: #2b3d52; }
.chat-input-field::-webkit-scrollbar { display: none; }
.chat-input-field.is-empty::before {
  content: attr(data-placeholder); color: var(--ink-faint); pointer-events: none;
}
.chat-input-field:focus.is-empty::before { color: var(--ink-dim); }
.ceo-cmd  { color: #ff5555; }   /* /p (red) */
.ceo-user { color: #ff8080; }   /* username (red) */
.ceo-ghost { color: #7d5555; }  /* dimmed /p autocomplete suggestion (Tab to accept) */ .ceo-ghost-at { color: color-mix(in srgb, var(--neon-cyan) 60%, transparent); }  /* @mention ghost = cyan */ .ceo-stn { color: #6a7686; font-style: italic; }   /* station hint (Tab cycles duplicates) */
/* Composer extras, image attachments + image viewer moved to composer.css. */

/* ---- Game panels ---- */
.game-panel .game-body {
  flex: 1; position: relative; min-height: 0;
  background: radial-gradient(ellipse at center, #0c1018, #05070c);
  container-type: inline-size;          /* so the popup box can scale to the panel width (cqw) */
}
.game-panel .game-canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
/* Frame the game area (left/right/bottom) in the header colour so a black board's bounding
   box stays visible against the black stage; the header supplies the top edge. */
.game-panel .game-body {
  border-left: 2px solid var(--panel-head);
  border-right: 2px solid var(--panel-head);
  border-bottom: 2px solid var(--panel-head);
}
.game-panel:focus { outline: none; }   /* focus is shown by the panel outline only (no inner border) */

/* Game overlay — one card, four states (PSD/tetris-panel-overlays): purple hairline card over a
   blurred scrim, with an eyebrow + headline always, and optional stat row / body / dots / room /
   second button. Corner brackets + soft purple glow. */
.game-modal {
  position: absolute; inset: 0; z-index: 3;
  display: flex; align-items: center; justify-content: center;
  background: rgba(7,9,14,.66); backdrop-filter: blur(3px);
}
.game-modal[hidden] { display: none; }
.gm-card {
  position: relative; width: 86%; max-width: 320px; box-sizing: border-box;
  padding: 24px 22px 22px; text-align: center;
  background: rgba(13,20,33,.96); border: 1px solid rgba(166,120,240,.5); border-radius: 10px;
  box-shadow: 0 0 0 1px rgba(166,120,240,.14), 0 22px 60px rgba(0,0,0,.7), 0 0 54px rgba(166,120,240,.14);
  animation: ovIn .32s ease both;
}
@keyframes ovIn { from { opacity: 0; transform: translateY(8px) scale(.97); } to { opacity: 1; transform: none; } }
@keyframes ovDot { 0%,100% { opacity: .25; transform: scale(.8); } 50% { opacity: 1; transform: scale(1); } }
.gm-eyebrow { display: flex; align-items: center; gap: 10px; justify-content: center; margin-bottom: 12px; }
.gm-eb-l { height: 1px; flex: 1; background: linear-gradient(90deg, transparent, rgba(166,120,240,.45)); }
.gm-eyebrow .gm-eb-l:last-child { background: linear-gradient(90deg, rgba(166,120,240,.45), transparent); }
.gm-eb-t { font-family: var(--font-mono); font-size: 10px; font-weight: 700; letter-spacing: .28em; color: #a678f0; white-space: nowrap; }
.gm-title { font-family: "Barlow Condensed", var(--font-ui); font-weight: 700; font-size: clamp(26px, 13cqw, 50px); line-height: .96; color: #f2f5fb; white-space: pre-line; }
.gm-stats { display: flex; margin: 16px 0 4px; border-top: 1px solid #1f2a3d; border-bottom: 1px solid #1f2a3d; }
.gm-stats[hidden] { display: none; }
.gm-stat { flex: 1; padding: 10px 0; }
.gm-stat + .gm-stat { border-left: 1px solid #1f2a3d; }
.gm-stat-l { font-family: var(--font-mono); font-size: 9px; letter-spacing: .2em; color: #5d6b83; }
.gm-stat-v { font-family: "Barlow Condensed", var(--font-ui); font-weight: 700; font-size: 26px; line-height: 1.1; color: #f2f5fb; margin-top: 2px; }
.gm-dots { display: flex; gap: 6px; justify-content: center; margin-top: 14px; }
.gm-dots[hidden] { display: none; }
.gm-dots i { width: 7px; height: 7px; border-radius: 50%; background: #a678f0; animation: ovDot 1.2s ease-in-out infinite; }
.gm-dots i:nth-child(2) { animation-delay: .18s; }
.gm-dots i:nth-child(3) { animation-delay: .36s; }
.gm-sub { margin-top: 14px; font-family: var(--font-mono); font-size: 11px; line-height: 1.8; color: #8b97ad; white-space: pre-line; }
.gm-sub[hidden] { display: none; }
/* Co-op seat chips (waiting): joined = solid pill w/ READY, open = dashed pill. */
.gm-seats { display: flex; gap: 8px; justify-content: center; flex-wrap: wrap; margin-top: 16px; }
.gm-seats[hidden] { display: none; }
.gm-chip { display: inline-flex; align-items: center; gap: 7px; padding: 6px 11px; border-radius: 20px;
  border: 1px solid #2a2158; background: #16123044; font-family: var(--font-mono); font-size: 11px; }
.gm-chip.open { border-style: dashed; border-color: #2a3346; color: #5d6b83; }
.gm-chip-dot { width: 6px; height: 6px; border-radius: 50%; background: #5d6b83; flex: none; }
.gm-chip-name { font-weight: 700; }
.gm-chip-ready { color: #7fe0a8; font-weight: 700; letter-spacing: .1em; font-size: 10px; }
.gm-room { display: flex; align-items: center; justify-content: center; gap: 8px; margin-top: 16px; padding: 8px 0; border-top: 1px solid #1f2a3d; border-bottom: 1px solid #1f2a3d; font-family: var(--font-mono); font-size: 11px; }
.gm-room[hidden] { display: none; }
.gm-room-lbl { letter-spacing: .2em; color: #5d6b83; }
.gm-room-c { font-weight: 700; letter-spacing: .22em; color: #e7ecf5; }
.gm-room-copy { color: #a678f0; cursor: pointer; }
/* Waiting-for-player invite link (copyable) inside the game popup */
.gm-link { display: flex; align-items: center; gap: 8px; margin-top: 10px; padding: 7px 9px; background: #080b13; border: 1px solid #2b2450; font-family: var(--font-mono); font-size: 10px; }
.gm-link[hidden] { display: none; }
.gm-link-lbl { flex: none; letter-spacing: .18em; color: #6b5f8a; }
.gm-link-c { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: #9fd0f0; }
.gm-link-copy { flex: none; display: inline-flex; align-items: center; gap: 6px; padding: 4px 9px; cursor: pointer; appearance: none; -webkit-appearance: none; border-radius: 0;
  background: rgba(166,120,240,.14); border: 1px solid rgba(166,120,240,.4); color: #c3a6f0; font-family: var(--font-mono); font-size: 9px; font-weight: 700; letter-spacing: .14em; transition: background .15s ease, border-color .15s ease, color .15s ease; }
.gm-link-copy:hover { background: rgba(166,120,240,.24); border-color: #a678f0; color: #d9c6fb; }
.gm-link-copy.copied { color: #7ddba4; border-color: #2f6b45; background: rgba(75,191,122,.12); }
.gm-link-copy i { font-size: 10px; }
.gm-actions { display: flex; gap: 10px; margin-top: 18px; }
.gm-btn { flex: 1; cursor: pointer; border: none; border-radius: 6px; background: #a678f0; color: #120a20;
  font-family: var(--font-ui); font-weight: 700; font-size: clamp(12px, 4cqw, 15px); letter-spacing: .13em; text-transform: uppercase; padding: 11px 0; transition: filter .15s ease; }
.gm-btn:hover { filter: brightness(1.12); }
.gm-btn[hidden] { display: none; }
.gm-btn.ghost, .gm-btn2 { background: transparent; border: 1px solid #2a3346; color: #8b97ad; font-weight: 600; }
.gm-btn2 { flex: none; cursor: pointer; border-radius: 6px; font-family: var(--font-ui);
  font-size: clamp(12px, 4cqw, 15px); letter-spacing: .13em; text-transform: uppercase; padding: 11px 18px; transition: filter .15s ease; }
.gm-btn2:hover { filter: brightness(1.2); }
.gm-btn2[hidden] { display: none; }
.gm-cnr { position: absolute; width: 11px; height: 11px; }
.gm-cnr.tl { top: -1px; left: -1px; border-top: 2px solid #a678f0; border-left: 2px solid #a678f0; border-radius: 10px 0 0 0; }
.gm-cnr.tr { top: -1px; right: -1px; border-top: 2px solid #a678f0; border-right: 2px solid #a678f0; border-radius: 0 10px 0 0; }
.gm-cnr.bl { bottom: -1px; left: -1px; border-bottom: 2px solid #a678f0; border-left: 2px solid #a678f0; border-radius: 0 0 0 10px; }
.gm-cnr.br { bottom: -1px; right: -1px; border-bottom: 2px solid #a678f0; border-right: 2px solid #a678f0; border-radius: 0 0 10px 0; }

/* ============================ FRIENDS ============================ */
/* Rail friend-request badge: RED circle (distinct from the green presence/unread badges). */
.rail-badge-friend { background: #ef4444; color: #fff; border-color: var(--panel-side); box-shadow: 0 0 6px rgba(239,68,68,.6); }
.rail-badge.pop { animation: friendBadgePop .42s ease; }
@keyframes friendBadgePop { 0% { transform: scale(1); } 40% { transform: scale(1.5); } 100% { transform: scale(1); } }

/* Left sidebar friends list */
.friend-list .fr-row { display: flex; align-items: center; gap: 8px; padding: 4px 12px; list-style: none; cursor: pointer; } .fr-unread { flex: none; min-width: 16px; height: 16px; padding: 0 4px; box-sizing: border-box; display: inline-flex; align-items: center; justify-content: center; border-radius: 8px; background: var(--good); color: #06120b; font-family: var(--font-mono); font-size: 9px; font-weight: 700; box-shadow: 0 0 6px rgba(75,191,122,.5); }
.friend-list .fr-row:hover { background: var(--hover-bg-2); }
.fr-av { width: 20px; height: 20px; flex: none; border-radius: 4px; display: flex; align-items: center; justify-content: center;
  font-family: var(--font-mono); font-size: 9px; font-weight: 700; background: var(--hover-bg-2); background-size: cover; background-position: center; cursor: pointer; }
.fr-av.has-image { color: transparent; }
.fr-nm { flex: 0 1 auto; margin-right: auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-size: 12.5px; font-weight: 600; color: #c7d6e4; cursor: pointer; }
.fr-nm:hover { text-decoration: underline dotted; text-underline-offset: 2px; }
.fr-dot { width: 7px; height: 7px; flex: none; border-radius: 50%; }
.fr-dot.on { background: var(--good); box-shadow: 0 0 5px var(--good); } .fr-dot.off { background: #55606d; }
.fr-dot.away { background: #e8a13a; box-shadow: 0 0 5px rgba(232,161,58,.7); }   /* idle 10+ min */


/* Friend-request toast (PSD "Friend request toast"): card + inline actions + a 10s timeline bar.
   Dismissal is driven by the bar's animationend, so pausing the bar on hover pauses the countdown. */
.friend-toasts { position: fixed; z-index: 22100; display: flex; flex-direction: column; gap: 10px; pointer-events: none; }
.friend-toast {
  pointer-events: auto; width: 250px; box-sizing: border-box;
  background: #0d1421; border: 1px solid #2b5a44; box-shadow: 0 18px 40px rgba(0,0,0,.6);
  opacity: 0; transform: translateX(14px); transition: opacity .32s cubic-bezier(.2,.7,.3,1), transform .32s cubic-bezier(.2,.7,.3,1);
}
.friend-toast.in { opacity: 1; transform: none; }
.friend-toast.out { opacity: 0; transform: translateX(14px); }
.ft-main { display: flex; gap: 9px; padding: 11px 11px 10px; }
.ft-av { width: 28px; height: 28px; flex: none; border-radius: 4px; display: flex; align-items: center; justify-content: center;
  font-family: var(--font-mono); font-size: 11px; font-weight: 700; background: #24402f; color: #7fe0a8; background-size: cover; background-position: center; }
.ft-av.has-image { color: transparent; }
.ft-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 6px; cursor: pointer; }
.ft-line { font-size: 13.5px; line-height: 1.35; color: #a9c9b7; }
.ft-msg { font-size: 12px; line-height: 1.4; color: #7d90a4; font-style: italic;
  overflow: hidden; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
.ft-acts { display: flex; gap: 5px; margin-top: 1px; }
.ft-act { cursor: pointer; font-family: var(--font-mono); font-size: 9px; font-weight: 700; letter-spacing: .1em; padding: 3px 8px;
  transition: filter .12s ease, background .12s ease, border-color .12s ease, color .12s ease; }
.ft-act.accept { color: #08130d; background: #4bbf7a; border: 1px solid #8ee3b0; }
.ft-act.accept:hover { filter: brightness(1.08); }
.ft-act.later { color: #9aa8b8; background: transparent; border: 1px solid #39424f; }
.ft-act.later:hover { color: #dbe6f2; border-color: #566172; }
.ft-x { flex: none; width: 16px; height: 16px; display: flex; align-items: center; justify-content: center; cursor: pointer;
  background: none; border: none; font-family: var(--font-mono); font-size: 11px; color: #5e7186; transition: color .12s ease; }
.ft-x:hover { color: #e0653c; }
.ft-timer { height: 2px; background: #14261d; }
.ft-timer-fill { height: 2px; width: 100%; background: #4bbf7a; transform-origin: left; animation: frToastTimer 20s linear forwards; }
@keyframes frToastTimer { from { width: 100%; } to { width: 0%; } }

/* ============================ GAME INVITES (purple sibling of FRIENDS) ============================ */
/* Rail game-invite badge: PURPLE circle (matches the game theme). */
.rail-badge-game { background: #8b5cf6; color: #fff; border-color: var(--panel-side); box-shadow: 0 0 6px rgba(139,92,246,.6); }
#rail-games .rail-btn-glyph { display: block; }
#rail-games:hover { color: #c3a6f0; }

/* Game-invites drawer — purple accents over the shared .rail-drawer chrome */
.rail-drawer-game .rd-title { color: #eee6ff; }
.rail-drawer-game .rd-clear { color: #c3a6f0; }
.rail-drawer-game .rd-clear:hover { color: #ddccff; }
.rg-inv { display: flex; gap: 9px; margin: 0 10px 6px; padding: 10px; background: rgba(139,92,246,.08); border-left: 2px solid #8b5cf6; }
.rg-glyph { flex: none; width: 30px; height: 30px; border-radius: 5px; display: flex; align-items: center; justify-content: center;
  background: #241a3d; color: #c3a6f0; font-size: 15px; }
.rg-glyph svg { width: 20px; height: 20px; }
.rg-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 4px; }
.rg-line { font-size: 13px; line-height: 1.35; color: #b9a9d6; }
.rg-line b { font-weight: 700; }
.rg-game { font-family: var(--font-mono); font-size: 11px; font-weight: 700; letter-spacing: .1em; color: #d8c9f5; }
.rg-time { font-family: var(--font-mono); font-size: 9.5px; color: #6b5f83; }
.rg-acts { display: flex; gap: 5px; margin-top: 3px; }
.rg-btn { cursor: pointer; font-family: var(--font-mono); font-size: 9px; font-weight: 700; letter-spacing: .1em; padding: 3px 9px;
  background: none; border: 1px solid transparent; transition: color .14s ease, border-color .14s ease, filter .14s ease; }
.rg-btn.play { color: #120a22; background: #a678f0; border-color: #c3a6f0; }
.rg-btn.play:hover { filter: brightness(1.09); }
.rg-btn.dismiss { color: #9a8fb2; border-color: #3c3352; }
.rg-btn.dismiss:hover { color: #d8c9f5; border-color: #6a5a92; }
/* EARLIER (expired) game invites — dimmed, with a hover ✕ */
.rg-earl { position: relative; display: flex; gap: 9px; margin: 0 10px 6px; padding: 10px;
  background: rgba(139,92,246,.04); border-left: 2px solid #4a3a6e; opacity: .78; }
.rg-earl:hover { opacity: 1; background: rgba(139,92,246,.07); }
.rg-earl .rg-glyph { background: #1e1832; color: #8f7fb8; }
.rg-ex { position: absolute; top: 7px; right: 7px; width: 16px; height: 16px; border: none; background: none; cursor: pointer;
  color: #6b5f83; font-size: 13px; line-height: 1; opacity: 0; transition: opacity .14s ease, color .14s ease, background .14s ease; border-radius: 3px; }
.rg-earl:hover .rg-ex { opacity: 1; }
.rg-ex:hover { color: #ddccff; background: rgba(139,92,246,.18); }

/* Game-invite toast — purple accent variant of .friend-toast */
.friend-toast.game { background: #120c1f; border-color: #4a3a72; }
.friend-toast.game .ft-line { color: #c1b2df; }
.friend-toast.game .ft-av.rg-glyph-av { background: #241a3d; color: #c3a6f0; }
.friend-toast.game .ft-av.rg-glyph-av svg { width: 18px; height: 18px; }
.friend-toast.game .ft-act.play { color: #120a22; background: #a678f0; border: 1px solid #c3a6f0; }
.friend-toast.game .ft-act.play:hover { filter: brightness(1.09); }
.friend-toast.game .ft-act.later { color: #9a8fb2; background: transparent; border: 1px solid #3c3352; }
.friend-toast.game .ft-act.later:hover { color: #d8c9f5; border-color: #6a5a92; }
.friend-toast.game .ft-timer { background: #201636; }
.friend-toast.game .ft-timer-fill { background: #a678f0; }

/* Invite-Friends checklist — dropped under every "Copy Game Link" */
/* the widget itself is now just a button that opens the popup */
.if-wrap { margin: 2px 0 12px; display: flex; justify-content: center; }
/* chat + game panels: give the button more breathing room above it */
.chat-empty .if-wrap, .gm-card .if-wrap { margin-top: 16px; }
/* match the panel "COPY" buttons' lavender exactly (.ce-link-copy / .gm-link-copy) */
.if-open { display: inline-flex; align-items: center; gap: 8px; cursor: pointer;
  font-family: var(--font-mono); font-size: 10px; font-weight: 700; letter-spacing: .12em;
  padding: 8px 14px; color: #c3a6f0; background: rgba(166,120,240,.16); border: 1px solid rgba(166,120,240,.4); border-radius: 6px;
  transition: background .12s ease, border-color .12s ease, color .12s ease; }
.if-open:hover { background: rgba(166,120,240,.28); border-color: #a678f0; color: #d9c6fb; }
.if-open i { font-size: 12px; color: #c3a6f0; }
.if-open.done { color: #0f1e15; background: #4bbf7a; border-color: #8ee3b0; }
.if-open.done i { color: #0f1e15; }
.if-open-count[hidden] { display: none; }
.if-open-count { min-width: 17px; height: 17px; padding: 0 4px; box-sizing: border-box; display: inline-flex; align-items: center; justify-content: center;
  font-size: 9px; border-radius: 9px; color: #120a22; background: #a678f0; }

/* selectable friend row (used inside the popup) */
.if-row { display: flex; align-items: center; gap: 8px; padding: 7px 9px; border: 1px solid transparent; border-radius: 6px;
  cursor: pointer; user-select: none; transition: background .12s ease, border-color .12s ease; }
.if-row:hover { background: rgba(139,92,246,.06); }
.if-row.on { background: rgba(139,92,246,.12); border-color: #6a4fb0; }
.if-row.invited { opacity: .6; cursor: default; }
.if-check { flex: none; width: 17px; height: 17px; border: 1px solid #4a3f66; border-radius: 4px; display: flex; align-items: center; justify-content: center;
  color: transparent; font-size: 9px; transition: background .12s ease, border-color .12s ease, color .12s ease; }
.if-row.on .if-check { background: #a678f0; border-color: #c3a6f0; color: #120a22; }
.if-row.invited .if-check { background: #4a3f66; border-color: #4a3f66; color: #c3a6f0; }
.if-invited-tag { flex: none; font-family: var(--font-mono); font-size: 8px; font-weight: 700; letter-spacing: .1em;
  color: #9a8fb2; border: 1px solid #4a3f66; border-radius: 3px; padding: 2px 5px; }
.if-av { flex: none; width: 24px; height: 24px; border-radius: 4px; background-size: cover; background-position: center; }
.if-av-ph { display: flex; align-items: center; justify-content: center; font-family: var(--font-mono); font-size: 11px; font-weight: 700; color: #120a22; }
.if-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 13px; font-weight: 600; }
.if-dot { flex: none; width: 7px; height: 7px; border-radius: 50%; background: var(--good); box-shadow: 0 0 5px var(--good); }

/* Invite-Friends popup */
.ifp-scrim { position: fixed; inset: 0; z-index: 28000; display: flex; align-items: center; justify-content: center;
  background: rgba(3,7,14,.64); opacity: 0; visibility: hidden; transition: opacity .16s ease, visibility .16s ease; }
.ifp-scrim.show { opacity: 1; visibility: visible; }
.ifp-card { width: 420px; max-width: calc(100vw - 32px); box-sizing: border-box; display: flex; flex-direction: column;
  background: #120c1f; border: 1px solid #4a3a72; box-shadow: 0 24px 60px rgba(0,0,0,.66);
  font-family: 'Barlow Semi Condensed', var(--font-ui);
  transform: translateY(8px) scale(.986); opacity: 0; transition: transform .18s cubic-bezier(.2,.7,.3,1), opacity .18s ease; }
.ifp-scrim.show .ifp-card { transform: none; opacity: 1; }
.ifp-head { display: flex; align-items: center; gap: 8px; padding: 13px 14px 11px; border-bottom: 1px solid #2a2140; }
.ifp-title { flex: none; font-family: var(--font-mono); font-size: 11px; font-weight: 700; letter-spacing: .16em; color: #d8c9f5; }
.ifp-sub { flex: 1; font-family: var(--font-mono); font-size: 9.5px; letter-spacing: .1em; color: #7a6f9a; }
.ifp-x { flex: none; width: 20px; height: 20px; display: flex; align-items: center; justify-content: center; cursor: pointer;
  background: none; border: none; font-family: var(--font-mono); font-size: 12px; color: #7a6f9a; transition: color .14s ease; }
.ifp-x:hover { color: #e0653c; }
.ifp-list { flex: 1; min-height: 0; max-height: 320px; overflow-y: auto; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 5px; padding: 10px; }
.ifp-empty { grid-column: 1 / -1; padding: 30px 14px; text-align: center; font-size: 13px; color: #6b6482; font-style: italic; }
.ifp-list .if-row { gap: 7px; padding: 6px 8px; }
.ifp-list .if-dot { display: none; }   /* every listed friend is online — drop the redundant dot to save width */
.ifp-foot { display: flex; align-items: center; gap: 10px; padding: 11px 14px; border-top: 1px solid #2a2140; }
.ifp-count { flex: 1; font-family: var(--font-mono); font-size: 10px; letter-spacing: .1em; color: #8b7fb0; }
.ifp-send { cursor: pointer; font-family: var(--font-mono); font-size: 10px; font-weight: 700; letter-spacing: .14em;
  padding: 8px 16px; color: #120a22; background: #a678f0; border: 1px solid #c3a6f0; border-radius: 5px; transition: filter .12s ease, opacity .12s ease; }
.ifp-send:hover:not(:disabled) { filter: brightness(1.09); }
.ifp-send:disabled { opacity: .4; cursor: default; }

/* Confirm / respond dialog */
.friend-dialog-scrim {
  position: fixed; inset: 0; z-index: 23000; display: flex; align-items: center; justify-content: center;
  background: rgba(3,7,14,.62); opacity: 0; visibility: hidden; transition: opacity .16s ease, visibility .16s ease;
}
.friend-dialog-scrim.show { opacity: 1; visibility: visible; }

/* PSD "Send friend request" card */
.fc-card {
  width: 360px; box-sizing: border-box; overflow: hidden;
  background: #0d1421; border: 1px solid #24405a; box-shadow: 0 24px 56px rgba(0,0,0,.6);
  font-family: 'Barlow Semi Condensed', var(--font-ui);
  transform: translateY(7px) scale(.986); opacity: 0; transition: transform .2s cubic-bezier(.2,.7,.3,1), opacity .2s ease;
}
.friend-dialog-scrim.show .fc-card { transform: none; opacity: 1; }
.fc-bar { height: 2px; }
.fc-bar.go { background: linear-gradient(90deg, #4bbf7a 0%, #57b6e8 100%); }
.fc-bar.warn { background: linear-gradient(90deg, #d3a03c 0%, #e0653c 100%); }
.fc-bar.danger { background: linear-gradient(90deg, #e0653c 0%, #b3402a 100%); }
.fc-head { display: flex; align-items: center; gap: 8px; padding: 12px 14px 10px; }
.fc-title { flex: 1; font-family: var(--font-mono); font-size: 10.5px; font-weight: 700; letter-spacing: .16em; color: #8ba6c0; }
.fc-x { width: 20px; height: 20px; display: flex; align-items: center; justify-content: center; cursor: pointer;
  background: none; border: none; font-family: var(--font-mono); font-size: 12px; color: #5e7186; transition: color .14s ease; }
.fc-x:hover { color: #e0653c; }
.fc-id { display: flex; align-items: center; gap: 11px; padding: 0 14px 14px; }
.fc-av-wrap { position: relative; width: 42px; height: 42px; flex: none; }
.fc-av { width: 42px; height: 42px; border-radius: 6px; display: flex; align-items: center; justify-content: center;
  background: #22384d; background-size: cover; background-position: center;
  font-family: var(--font-mono); font-size: 16px; font-weight: 700; color: #9fd8f5; }
.fc-av.has-image { color: transparent; }
.fc-dot { position: absolute; right: -2px; bottom: -2px; width: 9px; height: 9px; border-radius: 50%; border: 2px solid #0d1421; }
.fc-dot.on { background: #4bbf7a; } .fc-dot.off { background: #55606d; }
.fc-dot.away { background: #e8a13a; }   /* idle 10+ min */
.fc-idtext { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.fc-name { font-family: 'Barlow Condensed', var(--font-ui); font-weight: 700; font-size: 22px; line-height: 1; letter-spacing: .02em;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fc-status { font-family: var(--font-mono); font-size: 9.5px; letter-spacing: .12em; color: #7d95ad; }
.fc-div { height: 1px; background: linear-gradient(90deg, #24405a, rgba(36,64,90,.25)); }
.fc-note { padding: 14px; font-size: 13.5px; line-height: 1.45; color: #93a6ba; }
.fc-msg { display: flex; flex-direction: column; gap: 7px; padding: 14px; }
.fc-msg-head { display: flex; align-items: baseline; gap: 7px; }
.fc-msg-label { flex: 1; font-family: var(--font-mono); font-size: 9px; letter-spacing: .2em; color: #6d8099; }
.fc-msg-opt { font-family: var(--font-mono); font-size: 9px; color: #4f6070; }
.fc-msg-input { min-height: 62px; padding: 10px 11px; box-sizing: border-box; width: 100%; resize: none;
  background: #080d15; border: 1px solid #24405a; color: #cfe0f0; font-family: 'Barlow Semi Condensed', var(--font-ui);
  font-size: 13.5px; line-height: 1.45; outline: none; transition: border-color .14s ease; }
.fc-msg-input::placeholder { color: #56687c; }
.fc-msg-input:focus { border-color: #3f7bb0; }
.fc-msg-read { padding: 10px 11px; background: #080d15; border: 1px solid #24405a; color: #cfe0f0; font-size: 13.5px; line-height: 1.45; }
.fc-actions { display: flex; gap: 8px; padding: 0 14px 14px; }
.fc-btn { display: flex; align-items: center; justify-content: center; height: 36px; box-sizing: border-box; cursor: pointer;
  font-family: var(--font-mono); font-size: 10.5px; font-weight: 700; letter-spacing: .14em; transition: filter .16s ease, background .14s ease, border-color .14s ease, color .14s ease, box-shadow .16s ease; }
.fc-btn.ghost { flex: none; padding: 0 15px; color: #8fa3b8; background: transparent; border: 1px solid #26303e; }
.fc-btn.ghost:hover { color: #dbe6f2; border-color: #46536a; background: #121a25; }
.fc-btn.go { flex: 1; color: #08130d; background: #4bbf7a; border: 1px solid #8ee3b0; box-shadow: 0 0 18px rgba(75,191,122,.28); }
.fc-btn.go:hover { box-shadow: 0 0 28px rgba(75,191,122,.45); filter: brightness(1.07); }
.fc-btn.warn { flex: 1; color: #1c1206; background: #d3a03c; border: 1px solid #ecc678; box-shadow: 0 0 18px rgba(211,160,60,.26); }
.fc-btn.warn:hover { filter: brightness(1.07); }
.fc-btn.danger { flex: 1; color: #fff; background: #c0442c; border: 1px solid #e0653c; box-shadow: 0 0 18px rgba(224,101,60,.26); }
.fc-btn.danger:hover { filter: brightness(1.08); }

/* Profile friend-button relationship states */
.mp-btn.friend.is-friend { background: #2a1512; border-color: #6a2a1e; color: #f0a08e; }   /* UNFRIEND */
.mp-btn.friend.is-pending { background: #171a20; border-color: #33384a; color: #8a93a8; }   /* REQUESTED */
.mp-btn.friend.is-incoming { background: #1d3b52; border-color: #2b6285; color: #cfeaff; }   /* ACCEPT */

/* ============================ SYSTEM NOTICE (front-and-center announcement) ============================ */
.sys-notice-scrim {
  position: fixed; inset: 0; z-index: 24000; display: flex; align-items: center; justify-content: center;
  background: rgba(3,7,14,.72); backdrop-filter: blur(2px);
  opacity: 0; visibility: hidden; transition: opacity .26s ease, visibility .26s ease;
}
.sys-notice-scrim.show { opacity: 1; visibility: visible; }
.sn-card {
  position: relative; width: 440px; max-width: calc(100vw - 40px); box-sizing: border-box; overflow: hidden;
  padding: 30px 30px 26px; text-align: center;
  background: #0b1220; border: 1px solid #24405a; box-shadow: 0 30px 80px rgba(0,0,0,.7);
  font-family: 'Barlow Semi Condensed', var(--font-ui);
  transform: translateY(10px) scale(.98); transition: transform .26s cubic-bezier(.2,.7,.3,1);
}
.sys-notice-scrim.show .sn-card { transform: none; }
.sn-accent { position: absolute; top: 0; left: 0; right: 0; height: 3px; background: linear-gradient(90deg, #57b6e8, #7fd0ff); }
.sn-card .sn-glyph { font-size: 30px; color: #7fd0ff; margin-bottom: 12px; text-shadow: 0 0 18px rgba(87,182,232,.5); }
.sn-title { font-family: var(--font-mono); font-size: 15px; font-weight: 700; letter-spacing: .16em; color: #eaf4ff; margin-bottom: 10px; }
.sn-msg { font-size: 15px; line-height: 1.5; color: #b9cbe0; margin: 0 auto; max-width: 360px; }
.sn-count { margin-top: 16px; font-family: var(--font-mono); font-size: 12px; letter-spacing: .12em; color: #8ba6c0; }
.sn-count-v { font-size: 20px; color: #eaf4ff; margin-left: 4px; }
.sn-from { margin-top: 14px; font-family: var(--font-mono); font-size: 10px; letter-spacing: .14em; color: #6b7f96; }
.sn-dismiss { margin-top: 20px; cursor: pointer; font-family: var(--font-mono); font-size: 11px; font-weight: 700; letter-spacing: .14em;
  padding: 9px 22px; color: #eaf4ff; background: transparent; border: 1px solid #2b6285; transition: background .14s ease, border-color .14s ease; }
.sn-dismiss:hover { background: rgba(43,98,133,.2); border-color: #57b6e8; }
.sn-wait { margin-top: 20px; display: flex; gap: 6px; justify-content: center; }
.sn-wait .sn-dot { width: 7px; height: 7px; border-radius: 50%; background: #57b6e8; opacity: .35; animation: snPulse 1.2s ease-in-out infinite; }
.sn-wait .sn-dot:nth-child(2) { animation-delay: .2s; } .sn-wait .sn-dot:nth-child(3) { animation-delay: .4s; }
@keyframes snPulse { 0%,100% { opacity: .3; } 50% { opacity: 1; } }
/* warn = amber, restart = red + pulsing accent */
.sys-notice-scrim.lvl-warn .sn-accent { background: linear-gradient(90deg, #d3a03c, #e0b24c); }
.sys-notice-scrim.lvl-warn .sn-glyph { color: #e6b752; text-shadow: 0 0 18px rgba(211,160,60,.5); }
.sys-notice-scrim.lvl-restart .sn-accent { background: linear-gradient(90deg, #e0653c, #ff8a5c); animation: snAccentPulse 1.4s ease-in-out infinite; }
.sys-notice-scrim.lvl-restart .sn-glyph { color: #ff8a5c; text-shadow: 0 0 22px rgba(224,101,60,.6); }
@keyframes snAccentPulse { 0%,100% { opacity: 1; } 50% { opacity: .45; } }

/* ============================ SYSOP BROADCAST composer (admin only) ============================ */
.rail-btn.rail-admin { --rail-rgb: 230, 183, 82; }   /* gray at rest like the rest; gold tint + box on hover */
.bc-scrim {
  position: fixed; inset: 0; z-index: 24600; display: flex; align-items: center; justify-content: center;
  background: rgba(3,7,14,.64); opacity: 0; visibility: hidden; transition: opacity .16s ease, visibility .16s ease;
}
.bc-scrim.show { opacity: 1; visibility: visible; }
.bc-card {
  width: 400px; max-width: calc(100vw - 32px); box-sizing: border-box; padding: 0 18px 18px;
  background: #0b1220; border: 1px solid #3a3320; box-shadow: 0 24px 60px rgba(0,0,0,.66);
  font-family: 'Barlow Semi Condensed', var(--font-ui);
  transform: translateY(8px) scale(.986); opacity: 0; transition: transform .18s cubic-bezier(.2,.7,.3,1), opacity .18s ease;
}
.bc-scrim.show .bc-card { transform: none; opacity: 1; }
.bc-head { display: flex; align-items: center; gap: 9px; margin: 0 -18px 14px; padding: 13px 16px 12px;
  border-bottom: 1px solid #2a2718; color: #e6b752; }
.bc-head i { font-size: 14px; }
.bc-head span { flex: 1; font-family: var(--font-mono); font-size: 11px; font-weight: 700; letter-spacing: .16em; }
.bc-x { width: 20px; height: 20px; display: flex; align-items: center; justify-content: center; cursor: pointer;
  background: none; border: none; font-family: var(--font-mono); font-size: 12px; color: #6b7f96; transition: color .14s ease; }
.bc-x:hover { color: #e0653c; }
.bc-lbl { display: block; margin: 12px 0 5px; font-family: var(--font-mono); font-size: 9px; letter-spacing: .18em; color: #7d8ba0; }
.bc-opt { color: #55606d; letter-spacing: .06em; text-transform: none; }
.bc-levels { display: flex; gap: 6px; }
.bc-lvl { flex: 1; cursor: pointer; font-family: var(--font-mono); font-size: 10px; font-weight: 700; letter-spacing: .08em;
  padding: 7px 0; color: #9aa8b8; background: #101725; border: 1px solid #26303f; transition: all .12s ease; }
.bc-lvl:hover { border-color: #3a4658; }
.bc-lvl.on { color: #0b1220; background: #e6b752; border-color: #ffd473; }
.bc-title, .bc-msg, .bc-min {
  width: 100%; box-sizing: border-box; padding: 9px 11px; background: #0a0f1a; border: 1px solid #26303f; color: #dce8f4;
  font-family: var(--font-ui); font-size: 14px; resize: none; transition: border-color .14s ease;
}
.bc-title:focus, .bc-msg:focus, .bc-min:focus { outline: none; border-color: #57b6e8; }
.bc-actions { display: flex; gap: 8px; margin-top: 18px; }
.bc-btn { cursor: pointer; font-family: var(--font-mono); font-size: 11px; font-weight: 700; letter-spacing: .12em; padding: 10px 14px; border: 1px solid transparent; }
.bc-btn.ghost { color: #9aa8b8; background: transparent; border-color: #33384a; }
.bc-btn.ghost:hover { color: #dbe6f2; border-color: #566172; }
.bc-btn.go { flex: 1; color: #0b1220; background: #57b6e8; border-color: #7fd0ff; box-shadow: 0 0 18px rgba(87,182,232,.24); }
.bc-btn.go:hover { filter: brightness(1.08); }

/* ============================ ADMIN (full-stage, role-gated) ============================ */
.adm-scrim { position: fixed; inset: 0; z-index: 24500; display: flex; align-items: stretch; justify-content: center;
  background: rgba(3,6,12,.82); backdrop-filter: blur(3px); opacity: 0; visibility: hidden; transition: opacity .22s ease, visibility .22s ease; }
.adm-scrim.show { opacity: 1; visibility: visible; }
.adm { width: 100%; max-width: 1040px; margin: 26px 20px; display: flex; flex-direction: column; box-sizing: border-box;
  background: #0b1120; border: 1px solid #24314a; box-shadow: 0 30px 80px rgba(0,0,0,.7);
  font-family: 'Barlow Semi Condensed', var(--font-ui); transform: translateY(10px); transition: transform .22s cubic-bezier(.2,.7,.3,1); }
.adm-scrim.show .adm { transform: none; }
.adm-head { flex: none; display: flex; align-items: center; gap: 10px; padding: 14px 18px; border-bottom: 1px solid #1e2b42; color: #7fd0ff; }
.adm-head i { font-size: 15px; }
.adm-title { flex: 1; font-family: var(--font-mono); font-size: 13px; font-weight: 700; letter-spacing: .2em; color: #eaf4ff; }
.adm-close { cursor: pointer; font-family: var(--font-mono); font-size: 10px; font-weight: 700; letter-spacing: .12em; padding: 8px 13px;
  color: #9db6cf; background: transparent; border: 1px solid #2b3d57; transition: color .14s ease, border-color .14s ease, background .14s ease; }
.adm-close:hover { color: #eaf4ff; border-color: #57b6e8; background: rgba(87,182,232,.1); }
.adm-body { flex: 1; min-height: 0; display: flex; }
.adm-nav { flex: 0 0 176px; display: flex; flex-direction: column; gap: 2px; padding: 12px 10px; border-right: 1px solid #1e2b42; overflow-y: auto; }
.adm-nav-i { display: flex; align-items: center; gap: 10px; padding: 9px 11px; cursor: pointer; text-align: left;
  background: transparent; border: none; border-radius: 6px; color: #9db0c4; font-family: var(--font-ui); font-size: 14px; }
.adm-nav-i i { width: 16px; text-align: center; font-size: 13px; }
.adm-nav-i.on { background: rgba(87,182,232,.14); color: #cfeaff; }
.adm-nav-i.soon { color: #4f5f74; cursor: default; }
.adm-nav-i.soon em { margin-left: auto; font-style: normal; font-family: var(--font-mono); font-size: 8px; letter-spacing: .1em; color: #3d4b60; border: 1px solid #26324a; padding: 1px 5px; border-radius: 3px; }
.adm-main { flex: 1; min-width: 0; padding: 16px 20px 22px; overflow-y: auto; }
.adm-sec-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 14px; }
.adm-sec-title { font-family: 'Barlow Condensed', var(--font-ui); font-weight: 700; font-size: 26px; letter-spacing: .02em; color: #eaf4ff; }
.adm-new { cursor: pointer; display: inline-flex; align-items: center; gap: 7px; padding: 8px 13px; font-family: var(--font-mono); font-size: 10px; font-weight: 700; letter-spacing: .12em;
  color: #0b1220; background: #57b6e8; border: 1px solid #7fd0ff; box-shadow: 0 0 16px rgba(87,182,232,.22); }
.adm-new:hover { filter: brightness(1.08); }
.adm-nav-i.act { background: rgba(87,182,232,.14); color: #cfeaff; } .adm-empty { padding: 34px; text-align: center; color: #63748c; font-size: 14px; }
.adm-note { max-width: 560px; color: #8fa3ba; font-size: 13px; line-height: 1.6; }
/* room rows */
.adm-rooms { display: flex; flex-direction: column; border: 1px solid #1e2b42; }
.adm-room { display: flex; align-items: center; gap: 12px; padding: 10px 12px; border-bottom: 1px solid #16223500; border-top: 1px solid #17233a; cursor: pointer; }
.adm-room:first-child { border-top: none; }
.adm-room:hover { background: rgba(87,182,232,.06); }
.adm-thumb { flex: none; width: 40px; height: 40px; border-radius: 8px; background: #16233a; background-size: cover; background-position: center;
  display: flex; align-items: center; justify-content: center; color: #57b6e8; }
.adm-thumb.ph i { font-size: 15px; opacity: .7; }
.adm-room-b { flex: 1; min-width: 0; }
.adm-room-n { font-size: 15px; font-weight: 500; color: #e4eef8; }
.adm-room-m { font-family: var(--font-mono); font-size: 10px; letter-spacing: .06em; color: #6b7f97; }
.adm-room-slug { color: #4f6480; }
.adm-vis { flex: none; font-family: var(--font-mono); font-size: 9px; font-weight: 700; letter-spacing: .1em; padding: 3px 9px; border-radius: 20px; }
.adm-vis.pub { color: #7ddba4; background: rgba(75,191,122,.12); }
.adm-vis.priv { color: #e6b752; background: rgba(211,160,60,.12); }
.adm-edit { flex: none; width: 30px; height: 30px; cursor: pointer; background: transparent; border: none; color: #6b7f97; font-size: 13px; }
.adm-edit:hover { color: #cfeaff; }
/* editor */
.adm-ed { display: none; margin-top: 16px; padding: 16px; border: 1px solid #24314a; background: #0a0f1c; }
.adm-ed.show { display: block; }
.adm-ed-head { font-family: var(--font-mono); font-size: 11px; font-weight: 700; letter-spacing: .12em; color: #8ba6c0; margin-bottom: 14px; }
.adm-ed-top { display: flex; gap: 14px; margin-bottom: 12px; }
.adm-img { flex: 0 0 96px; cursor: pointer; }
.adm-img-box { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 5px; width: 96px; height: 96px; border-radius: 12px;
  border: 1px dashed #3a4c68; background-size: cover; background-position: center; color: #63748c; font-size: 11px; }
.adm-img-box i { font-size: 20px; }
.adm-img:hover .adm-img-box { border-color: #57b6e8; color: #9db6cf; }
.adm-ed-fields { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 9px; }
.adm-ed input[type=text], .adm-ed input[type=number], .adm-ed textarea { width: 100%; box-sizing: border-box; padding: 9px 11px;
  background: #0d1626; border: 1px solid #26344d; color: #dce8f4; font-family: var(--font-ui); font-size: 14px; resize: none; }
.adm-ed input:focus, .adm-ed textarea:focus { outline: none; border-color: #57b6e8; }
.adm-ed-row { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; margin-bottom: 14px; }
.adm-f-cat { flex: 1; min-width: 140px; }
.adm-f-sort { flex: 0 0 74px; }
.adm-f-hist { display: inline-flex; align-items: center; gap: 6px; flex: none; color: #9db0c4; font-size: 11px; font-family: var(--font-mono); cursor: pointer; }
.adm-vis-toggle { display: inline-flex; border: 1px solid #2b3d57; }
.adm-vis-toggle button { cursor: pointer; padding: 8px 14px; background: transparent; border: none; color: #9db0c4; font-family: var(--font-mono); font-size: 10px; font-weight: 700; letter-spacing: .1em; }
.adm-vis-toggle button.on { background: rgba(87,182,232,.16); color: #cfeaff; }
.adm-ed-actions { display: flex; align-items: center; justify-content: space-between; }
.adm-ed-right { display: flex; gap: 8px; }
.adm-del { cursor: pointer; display: inline-flex; align-items: center; gap: 6px; padding: 8px 13px; background: transparent; border: 1px solid #5a2a2a; color: #e08a7a; font-family: var(--font-mono); font-size: 10px; font-weight: 700; letter-spacing: .1em; }
.adm-del:hover { background: rgba(224,101,60,.12); border-color: #e0653c; }
.adm-cancel { cursor: pointer; padding: 8px 15px; background: transparent; border: 1px solid #33425c; color: #9db0c4; font-family: var(--font-mono); font-size: 10px; font-weight: 700; letter-spacing: .1em; }
.adm-cancel:hover { color: #dbe6f2; border-color: #566a86; }
.adm-save { cursor: pointer; padding: 8px 20px; color: #0b1220; background: #57b6e8; border: 1px solid #7fd0ff; font-family: var(--font-mono); font-size: 10px; font-weight: 700; letter-spacing: .12em; box-shadow: 0 0 16px rgba(87,182,232,.22); }
.adm-save:hover { filter: brightness(1.08); }

/* DDial telnet link editor (inside the room editor) */
.adm-link { margin-top: 16px; padding: 14px 14px 12px; border: 1px solid #33425c; border-radius: 8px; background: rgba(18,26,40,.5); }
.adm-link-head { display: flex; align-items: center; gap: 8px; font-family: var(--font-mono); font-size: 11px; font-weight: 700; letter-spacing: .1em; color: #9db0c4; text-transform: uppercase; margin-bottom: 10px; }
.adm-link-head i { color: #57b6e8; }
.adm-link-status { margin-left: auto; text-transform: none; letter-spacing: 0; font-size: 10px; padding: 2px 9px; border-radius: 999px; border: 1px solid #33425c; color: #9db0c4; }
.adm-link-status.ok { color: #6fe0a0; border-color: #2f6a48; background: rgba(60,200,130,.1); }
.adm-link-status.warn { color: #e8c46a; border-color: #6a5a2a; background: rgba(220,190,80,.1); }
.adm-link-status.err { color: #e88a7a; border-color: #6a2f2a; background: rgba(220,90,70,.1); }
.adm-link-status.off { color: #7d8da0; }
.adm-link-en { display: flex; align-items: center; gap: 8px; font-size: 12px; color: #c3d2e2; margin-bottom: 12px; cursor: pointer; }
.adm-link-grid { display: flex; gap: 10px; margin-bottom: 10px; align-items: flex-end; }
.lk-field { display: flex; flex-direction: column; gap: 4px; }
.lk-field > span { font-family: var(--font-mono); font-size: 9px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; color: #7d8da0; }
.lk-f-host { flex: 1 1 auto; min-width: 0; }
.lk-f-port { flex: 0 0 88px; }
.lk-f-chan { flex: 0 0 108px; }
.lk-f-bcast { flex: 0 0 150px; }
.lk-f-pass { flex: 1 1 auto; min-width: 0; }
.adm-link input { width: 100%; box-sizing: border-box; padding: 9px 11px; background: #0b1220; border: 1px solid #33425c; color: #dbe6f2; font-family: var(--font-mono); font-size: 12px; border-radius: 5px; }
.adm-link input:focus { outline: none; border-color: #57b6e8; }
.adm-link-save { flex: 0 0 auto; cursor: pointer; padding: 9px 16px; color: #0b1220; background: #57b6e8; border: 1px solid #7fd0ff; font-family: var(--font-mono); font-size: 10px; font-weight: 700; letter-spacing: .1em; border-radius: 5px; }
.adm-link-save:hover { filter: brightness(1.08); }
.adm-link-note { font-size: 10px; color: #6d7d90; margin-top: 4px; }
.adm-link-ctl { display: flex; gap: 8px; margin-bottom: 8px; }
.adm-link-ctl button { cursor: pointer; display: inline-flex; align-items: center; gap: 6px; padding: 7px 13px;
  background: transparent; border: 1px solid #33425c; color: #9db0c4; font-family: var(--font-mono);
  font-size: 10px; font-weight: 700; letter-spacing: .1em; border-radius: 5px; }
.adm-link-open:hover { color: #6fe0a0; border-color: #2f6a48; background: rgba(60,200,130,.1); }
.adm-link-close:hover { color: #e88a7a; border-color: #6a2f2a; background: rgba(220,90,70,.1); }

/* Subtle station tag after the handle for messages from a DDial link (e.g. "MAGVIZ.CA") */
.msg-link-badge { display: inline-block; margin-left: 7px; font-family: var(--font-mono); font-size: 8.5px;
  font-weight: 600; letter-spacing: .08em; text-transform: uppercase; color: #566579; vertical-align: middle; }
.msg-link-badge::before { content: "› "; color: #3f4b5c; }

/* ============================ ONBOARDING (first-run, 2 steps) ============================ */
.ob-scrim { position: fixed; inset: 0; z-index: 24000; display: flex; align-items: center; justify-content: center;
  background: rgba(3,6,12,.72); backdrop-filter: blur(3px); opacity: 0; visibility: hidden; transition: opacity .28s ease, visibility .28s ease; }
.ob-scrim.show { opacity: 1; visibility: visible; }
.ob { position: relative; width: 460px; max-width: calc(100vw - 32px); box-sizing: border-box; padding: 26px 26px 20px; text-align: center;
  background: #0b1120; border: 1px solid #24314a; box-shadow: 0 30px 80px rgba(0,0,0,.7);
  font-family: 'Barlow Semi Condensed', var(--font-ui);
  transform: translateY(10px) scale(.98); transition: transform .28s cubic-bezier(.2,.7,.3,1); }
.ob-scrim.show .ob { transform: none; }
.ob-accent { position: absolute; top: 0; left: 0; right: 0; height: 3px; background: linear-gradient(90deg, #57b6e8, #a678f0); }
.ob-steps { display: flex; justify-content: center; gap: 7px; margin-bottom: 16px; }
.ob-dot { width: 7px; height: 7px; border-radius: 50%; background: #2a3852; transition: background .2s ease; }
.ob-dot.on { background: #57b6e8; }
.ob-title { font-family: 'Barlow Condensed', var(--font-ui); font-weight: 700; font-size: 27px; letter-spacing: .02em; color: #eaf4ff; }
.ob-sub { font-size: 14px; line-height: 1.5; color: #93a2ba; max-width: 340px; margin: 6px auto 18px; }
.ob-preview { display: flex; align-items: center; justify-content: center; height: 46px; margin-bottom: 16px;
  background: #0a0f1c; border: 1px solid #1e2b42; }
.ob-preview-name { font-family: var(--font-mono); font-weight: 700; font-size: 18px; }
.ob-grid { grid-template-columns: repeat(11, 1fr); gap: 6px; margin-bottom: 20px; }
.ob-actions { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.ob-btn { cursor: pointer; font-family: var(--font-mono); font-size: 11px; font-weight: 700; letter-spacing: .12em; padding: 10px 20px; border: 1px solid transparent; }
.ob-btn.ghost { color: #9db0c4; background: transparent; border-color: #33425c; }
.ob-btn.ghost:hover { color: #dbe6f2; border-color: #566a86; }
.ob-btn.go { color: #0b1220; background: #57b6e8; border-color: #7fd0ff; box-shadow: 0 0 16px rgba(87,182,232,.22); margin-left: auto; }
.ob-btn.go:hover { filter: brightness(1.08); }
.ob-upload { display: block; cursor: pointer; margin-bottom: 20px; }
.ob-upbox { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8px; width: 150px; height: 150px; margin: 0 auto; border-radius: 12px;
  border: 1px dashed #3a4c68; background-size: cover; background-position: center; color: #63748c; font-size: 13px; }
.ob-upbox i { font-size: 26px; }
.ob-upload:hover .ob-upbox { border-color: #57b6e8; color: #9db6cf; }
.ob-upbox.has-image { border-style: solid; border-color: #2b6285; }
