/* Extracted from chat.html. Loaded in the same position the inline
   <style> occupied, so the cascade is unchanged. */
    .ol-stage { padding-bottom: 28px; }
    .chat-shell {
      display: grid;
      grid-template-columns: 244px minmax(0, 1fr);
      gap: var(--gap);
      height: calc(100vh - 56px);
    }

    .roster { display: flex; flex-direction: column; min-height: 0; padding: 14px; }
    .roster-head {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: 8px;
      padding-bottom: 12px;
      border-bottom: 1px solid var(--line);
    }
    .roster-head h1 { font-size: 15px; }
    .dot {
      display: inline-flex;
      align-items: center;
      gap: 6px;
      color: var(--text-faint);
      font-size: 12px;
    }
    .dot::before {
      content: "";
      width: 7px;
      height: 7px;
      border-radius: 50%;
      background: var(--text-faint);
    }
    .dot.on::before { background: #fff; box-shadow: 0 0 8px rgba(255,255,255,0.7); }

    /* The roster is a fixed header over one scroll region holding every
       section (channels, friends, groups, online). */
    .roster-scroll { flex: 1; min-height: 0; overflow-y: auto; display: flex; flex-direction: column; }
    .roster-section { display: flex; flex-direction: column; }

    .room-btn {
      display: flex;
      align-items: center;
      width: 100%;
      min-height: 40px;
      margin-top: 12px;
      padding: 0 12px;
      border: 1px solid var(--line);
      border-radius: var(--radius-sm);
      background: var(--surface-raised);
      color: var(--text-dim);
      font: inherit;
      font-weight: 600;
      font-size: 14px;
      text-align: left;
      cursor: pointer;
    }
    .room-btn:hover { background: var(--surface-hover); color: var(--text); }
    .room-btn.active { background: var(--accent); border-color: transparent; color: #000000; }

    .roster-label {
      margin: 16px 0 8px;
      font-size: 11px;
      font-weight: 700;
      letter-spacing: 0.1em;
      text-transform: uppercase;
      color: var(--text-faint);
    }
    .members { display: grid; gap: 6px; align-content: start; }
    .member {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: 8px;
      min-height: 38px;
      padding: 0 6px 0 10px;
      border-radius: var(--radius-sm);
      transition: background 0.14s ease;
    }
    .member:hover { background: var(--surface-raised); }
    .member-name {
      flex: 1;
      min-width: 0;
      display: flex;
      align-items: center;
      gap: 6px;
      font-size: 13.5px;
      color: var(--text-dim);
      background: none;
      border: none;
      font-family: inherit;
      text-align: left;
      cursor: pointer;
    }
    /* Only the name itself ellipsizes; the dot and badge keep their size. */
    .member-name > span:not(.dm-dot):not(.badge) {
      min-width: 0;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    .member.is-blocked .member-name { color: var(--text-faint); text-decoration: line-through; }
    .member-actions { display: flex; gap: 4px; opacity: 0; flex-shrink: 0; }
    .member:hover .member-actions, .member:focus-within .member-actions { opacity: 1; }

    /* Unread-DM indicator: a small teal dot before the sender's name. */
    .dm-dot {
      flex-shrink: 0;
      width: 8px;
      height: 8px;
      border-radius: 50%;
      background: var(--teal);
      box-shadow: 0 0 8px var(--teal);
    }

    /* Rank badges. The server grants these from account membership. */
    .badge {
      flex-shrink: 0;
      padding: 1px 6px;
      border-radius: var(--radius-pill);
      border: 1px solid transparent;
      font-size: 9.5px;
      font-weight: 700;
      letter-spacing: 0.04em;
      text-transform: uppercase;
      line-height: 1.5;
    }
    /* One colour per tier, so a subscription is legible at a glance and the
       staff badges stay distinct from the paid ones. These are deliberately
       fixed hues rather than the theme accent: the badge has to mean the same
       thing to everyone in the room, and it would collide with the accent on
       whatever colour that person happened to pick. */
    .badge-owner {
      color: #1a1206;
      background: linear-gradient(135deg, #ffd66b, #f0a326);
      border-color: transparent;
      box-shadow: 0 2px 10px rgba(240, 163, 38, 0.35);
    }
    .badge-developer {
      color: #f2e6ff;
      background: rgba(168, 85, 247, 0.22);
      border-color: rgba(168, 85, 247, 0.6);
    }
    .badge-premium {
      color: #0a1020;
      background: linear-gradient(135deg, #8fd0ff, #4d7cff);
      border-color: transparent;
      box-shadow: 0 2px 10px rgba(77, 124, 255, 0.32);
    }
    .badge-basic {
      color: #ccf7e0;
      background: rgba(34, 197, 94, 0.2);
      border-color: rgba(34, 197, 94, 0.58);
    }
    .badge-ad-free {
      color: #d8dee9;
      background: rgba(255, 255, 255, 0.12);
      border-color: rgba(255, 255, 255, 0.3);
    }
    .msg-meta .badge { align-self: center; }

    .thread { display: flex; flex-direction: column; min-width: 0; min-height: 0; }
    .thread-head {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: 14px;
      padding: 15px 18px;
      border-bottom: 1px solid var(--line);
    }
    .thread-head h2 { font-size: 16px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    .thread-head p { margin-top: 2px; font-size: 12px; color: var(--text-faint); }

    .messages {
      flex: 1;
      min-height: 0;
      overflow-y: auto;
      display: flex;
      flex-direction: column;
      gap: 10px;
      padding: 18px;
    }
    .msg {
      position: relative;
      width: fit-content;
      max-width: min(660px, 84%);
      padding: 9px 12px;
      border: 1px solid var(--line);
      border-radius: var(--radius-sm);
      background: var(--surface-raised);
      line-height: 1.45;
      font-size: 14px;
    }
    .msg.mine {
      align-self: flex-end;
      background: var(--accent-soft);
      border-color: var(--accent-line);
    }

    /* Briefly ring a message when you click the quote that points at it. */
    .msg.flash { animation: msg-flash 1.4s ease-out; }
    @keyframes msg-flash {
      0%   { box-shadow: 0 0 0 3px var(--accent-line); }
      100% { box-shadow: 0 0 0 3px transparent; }
    }

    /* ── Replies ───────────────────────────────────────────── */
    /* The quoted parent, above the message that answers it. It is a button so
       it is keyboard-reachable: clicking scrolls to the original. */
    .msg-quote {
      display: flex;
      align-items: baseline;
      gap: 7px;
      width: 100%;
      margin-bottom: 6px;
      padding: 4px 8px 4px 9px;
      border: 0;
      border-left: 2px solid var(--accent-line);
      border-radius: 0;
      background: rgba(255, 255, 255, 0.05);
      color: inherit;
      font: inherit;
      font-size: 12px;
      text-align: left;
      cursor: pointer;
    }
    .msg-quote:hover { background: rgba(255, 255, 255, 0.09); }
    .msg-quote-who { flex-shrink: 0; font-weight: 600; color: var(--accent-color); }
    /* One line only — a quote should hint at the parent, not restate it. */
    .msg-quote-text {
      min-width: 0;
      overflow: hidden;
      white-space: nowrap;
      text-overflow: ellipsis;
      color: var(--text-faint);
    }

    /* Hover actions, pinned to the bubble's top edge. Hidden until the message
       is hovered or something inside it has focus, so the list stays quiet —
       but always shown on touch, where there is no hover to reveal them. */
    .msg-actions {
      position: absolute;
      top: -13px;
      right: 8px;
      display: flex;
      gap: 2px;
      padding: 2px;
      border: 1px solid var(--line);
      border-radius: 0;
      background: rgba(10, 12, 18, 0.96);
      box-shadow: 0 4px 14px rgba(0, 0, 0, 0.5);
      opacity: 0;
      pointer-events: none;
      transition: opacity 0.12s ease;
    }
    .msg:hover .msg-actions,
    .msg:focus-within .msg-actions { opacity: 1; pointer-events: auto; }
    @media (hover: none) {
      .msg-actions { opacity: 1; pointer-events: auto; }
    }
    .msg-action {
      display: grid;
      place-items: center;
      width: 26px;
      height: 24px;
      padding: 0;
      border: 0;
      border-radius: 0;
      background: none;
      color: var(--text-faint);
      cursor: pointer;
      transition: background 0.12s ease, color 0.12s ease;
    }
    .msg-action:hover { background: var(--surface-hover); color: var(--text); }
    .msg-action svg { width: 14px; height: 14px; }
    .msg-meta { display: flex; gap: 8px; margin-bottom: 3px; font-size: 11.5px; color: var(--text-faint); }
    .msg-meta strong { color: var(--text-dim); font-weight: 600; }

    .empty { margin: auto; text-align: center; color: var(--text-faint); font-size: 13.5px; }
    .notice {
      align-self: center;
      padding: 6px 12px;
      border-radius: var(--radius-pill);
      background: rgba(255, 107, 107, 0.12);
      border: 1px solid rgba(255, 107, 107, 0.34);
      color: #ff9f9f;
      font-size: 12.5px;
    }

    /* Reply bar. Sits between the message list and the composer while a reply
       is armed, so what you are answering stays visible as you type. */
    .reply-bar {
      display: flex;
      align-items: center;
      gap: 10px;
      padding: 9px 14px;
      border-top: 1px solid var(--line);
      background: var(--accent-soft);
    }
    .reply-bar .reply-icon { width: 16px; height: 16px; flex-shrink: 0; color: var(--accent-color); }
    .reply-bar-text { display: flex; gap: 8px; min-width: 0; align-items: baseline; font-size: 12.5px; }
    .reply-bar-to { flex-shrink: 0; font-weight: 600; color: var(--accent-color); }
    .reply-bar-quote {
      min-width: 0;
      overflow: hidden;
      white-space: nowrap;
      text-overflow: ellipsis;
      color: var(--text-dim);
    }
    .reply-cancel {
      margin-left: auto;
      width: 24px;
      height: 24px;
      flex-shrink: 0;
      border: 0;
      border-radius: 0;
      background: none;
      color: var(--text-faint);
      font-size: 18px;
      line-height: 1;
      cursor: pointer;
    }
    .reply-cancel:hover { background: var(--surface-hover); color: var(--text); }

    .composer { display: flex; gap: 8px; padding: 14px; border-top: 1px solid var(--line); }

    .join-card { width: min(400px, 100%); margin: 14vh auto 0; padding: 24px; }
    .join-card h1 { font-size: 20px; margin-bottom: 6px; }
    .join-card p { margin-bottom: 18px; }
    .join-grid { display: grid; gap: 9px; }
    .hidden { display: none !important; }

    /* ── Channels ─────────────────────────────────────────────── */
    .channel-list { display: grid; gap: 4px; }
    .channel-btn {
      display: flex; align-items: center; gap: 8px;
      width: 100%; min-height: 34px; padding: 0 10px;
      border: 1px solid transparent; border-radius: var(--radius-sm);
      background: none; color: var(--text-dim);
      font: inherit; font-size: 14px; font-weight: 500; text-align: left; cursor: pointer;
    }
    .channel-btn:hover { background: var(--surface-raised); color: var(--text); }
    .channel-btn.active { background: var(--surface-hover); color: var(--text); border-color: var(--line); font-weight: 600; }
    .channel-hash { color: var(--text-faint); font-weight: 700; }
    .channel-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

    /* Unread indicator, shared by channels/friends/groups/members. */
    .unread-dot {
      flex-shrink: 0; width: 8px; height: 8px; border-radius: 50%;
      background: #fff; box-shadow: 0 0 8px rgba(255,255,255,0.7); margin-left: auto;
    }
    .member-name .unread-dot, .friend-open .unread-dot { margin-left: 0; }

    /* ── Roster section headers ───────────────────────────────── */
    .roster-label { display: flex; align-items: center; gap: 6px; }
    .label-hint { margin-left: 4px; color: var(--text-faint); font-weight: 700; letter-spacing: 0; }
    .roster-add {
      margin-left: auto; width: 22px; height: 22px; line-height: 1;
      border: 1px solid var(--line); border-radius: 0;
      background: var(--surface-raised); color: var(--text-dim);
      font-size: 15px; cursor: pointer; letter-spacing: 0;
    }
    .roster-add:hover { background: var(--surface-hover); color: var(--text); }
    .roster-empty { padding: 4px 2px 8px; font-size: 12.5px; color: var(--text-faint); }

    /* ── Friends ──────────────────────────────────────────────── */
    .friend-requests { display: grid; gap: 4px; margin-bottom: 4px; }
    .friend-request {
      display: flex; align-items: center; justify-content: space-between; gap: 6px;
      padding: 6px 8px; border: 1px solid var(--line-strong); border-radius: var(--radius-sm);
      background: var(--surface-raised);
    }
    .fr-name { font-size: 13px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    .fr-actions { display: flex; gap: 4px; flex-shrink: 0; }
    .friend-list { display: grid; gap: 2px; }
    .friend-row { display: flex; align-items: center; gap: 4px; border-radius: var(--radius-sm); }
    .friend-row:hover { background: var(--surface-raised); }
    .friend-open {
      flex: 1; min-width: 0; display: flex; align-items: center; gap: 8px;
      min-height: 34px; padding: 0 8px; background: none; border: 0;
      color: var(--text-dim); font: inherit; font-size: 13.5px; text-align: left; cursor: pointer;
    }
    .friend-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    .presence { flex-shrink: 0; width: 8px; height: 8px; border-radius: 50%; background: var(--text-faint); }
    .presence.on { background: #fff; box-shadow: 0 0 7px rgba(255,255,255,0.7); }
    .friend-remove {
      flex-shrink: 0; width: 24px; height: 24px; margin-right: 4px;
      background: none; border: 0; border-radius: 0; color: var(--text-faint);
      font-size: 16px; cursor: pointer; opacity: 0;
    }
    .friend-row:hover .friend-remove { opacity: 1; }
    .friend-remove:hover { background: rgba(255,255,255,0.1); color: var(--text); }
    .member-pending { font-size: 11px; color: var(--text-faint); align-self: center; padding: 0 4px; }

    /* ── Groups ───────────────────────────────────────────────── */
    .group-list { display: grid; gap: 2px; }
    .group-btn {
      display: flex; align-items: center; gap: 8px; width: 100%;
      min-height: 34px; padding: 0 10px; border: 1px solid transparent; border-radius: var(--radius-sm);
      background: none; color: var(--text-dim); font: inherit; font-size: 13.5px; text-align: left; cursor: pointer;
    }
    .group-btn:hover { background: var(--surface-raised); color: var(--text); }
    .group-btn.active { background: var(--surface-hover); color: var(--text); border-color: var(--line); }
    .group-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 600; }
    .group-meta { flex-shrink: 0; font-size: 11px; color: var(--text-faint); font-variant-numeric: tabular-nums; }

    /* ── Thread actions ───────────────────────────────────────── */
    .thread-actions { display: flex; align-items: center; gap: 6px; flex-shrink: 0; }

    /* ── In-chat game panel (Hangman) ─────────────────────────── */
    .game-panel {
      margin: 12px 18px 0; padding: 14px 16px;
      border: 1px solid var(--line-strong); border-radius: var(--radius);
      background: var(--surface-raised);
    }
    .game-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px; }
    .game-title { font-size: 13px; font-weight: 700; letter-spacing: 0.02em; text-transform: uppercase; color: var(--text); }
    .hangman-word {
      font-size: clamp(22px, 4vw, 30px); font-weight: 700; letter-spacing: 0.14em;
      text-align: center; margin: 6px 0 10px; font-family: "Inter", monospace;
      word-break: break-all;
    }
    .hangman-info { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 12px; }
    .hangman-lives { font-size: 16px; letter-spacing: 0.24em; color: var(--text); }
    .hangman-starter { font-size: 11.5px; color: var(--text-faint); }
    .hangman-keys { display: grid; grid-template-columns: repeat(auto-fill, minmax(30px, 1fr)); gap: 5px; }
    .hkey {
      min-height: 32px; border: 1px solid var(--line); border-radius: 0;
      background: var(--surface); color: var(--text); font: inherit; font-size: 14px;
      text-transform: uppercase; cursor: pointer; transition: background 0.12s ease;
    }
    .hkey:hover:not(:disabled) { background: #fff; color: #000; }
    .hkey.used { opacity: 0.3; cursor: default; }
    .hangman-result { margin: 4px 0 12px; font-size: 14px; text-align: center; }
    .hangman-result.won { color: #fff; font-weight: 600; }
    .hangman-result.lost { color: var(--text-dim); }
    .game-panel .ol-btn-primary { display: block; margin: 0 auto; }
    .game-prompt { font-size: 13.5px; color: var(--text-dim); text-align: center; margin: 4px 0 10px; }
    .game-wordform { display: flex; gap: 8px; }
    .game-wordform .ol-input { flex: 1; }
    .game-wordform .ol-btn-primary { margin: 0; }

    /* ── Modals ───────────────────────────────────────────────── */
    .modal-overlay {
      position: fixed; inset: 0; z-index: 200; display: none;
      align-items: center; justify-content: center; padding: 20px;
      background: rgba(0,0,0,0.68); backdrop-filter: blur(4px);
    }
    .modal-overlay.open { display: flex; }
    .modal { width: min(420px, 100%); padding: 22px; display: flex; flex-direction: column; gap: 12px; }
    .modal-actions { display: flex; gap: 8px; justify-content: flex-end; margin-top: 4px; }
    .group-pick { display: flex; flex-direction: column; gap: 4px; max-height: 46vh; overflow-y: auto; }
    .pick-row {
      display: flex; align-items: center; gap: 10px; justify-content: space-between;
      padding: 9px 11px; border: 1px solid var(--line); border-radius: var(--radius-sm);
      font-size: 14px; cursor: pointer;
    }
    .pick-row input { accent-color: #fff; width: 16px; height: 16px; }
    .pick-row span { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

    /* ── Overlay mode (?overlay=1) — embedded in the in-game button ── */
    body.overlay { background: #000; }
    body.overlay .ol-sidebar { display: none !important; }
    body.overlay #particles { display: none !important; }
    body.overlay .ol-stage { margin-left: 0 !important; padding: 10px !important; }
    body.overlay .chat-shell { height: calc(100vh - 20px); }
    body.overlay .join-card { margin-top: 8vh; }

    @media (max-width: 820px) {
      .chat-shell { grid-template-columns: 1fr; height: auto; }
      .roster { max-height: 300px; }
      .thread { height: 68vh; }
    }

    /* ── Message text wrapping ─────────────────────────────────────────────
       A pasted wall of one unbroken "word" was blowing past the bubble's
       max-width and dragging a horizontal scrollbar across the whole
       thread. Break anywhere, but keep the sender's own line breaks. */
    .msg { overflow-wrap: anywhere; }
    .msg-body {
      overflow-wrap: anywhere;
      word-break: break-word;
      white-space: pre-wrap;
    }
    .messages { overflow-x: hidden; }
    .roster-scroll { overflow-x: hidden; }

    /* Scrollbar theming lives in css/ui.css now — site-wide. */

