/* Shared composer media styles: emoji picker + pending media previews.
   Used by both the legacy 1-on-1 chat popup and the VIP page composer. */

/* ─── Emoji picker popover ─────────────────────────────────── */

.emoji-picker {
    position: absolute;
    bottom: 58px;
    left: 8px;
    width: 320px;
    max-width: calc(100vw - 24px);
    max-height: 300px;
    overflow-y: auto;
    background: var(--bg-secondary);
    border: 1px solid var(--glass-border);
    border-radius: var(--radius-md);
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.25);
    padding: 0.6rem;
    z-index: 50;
}

.emoji-picker.hidden { display: none !important; }

.emoji-group + .emoji-group { margin-top: 0.6rem; }

.emoji-group-title {
    font-size: 0.68rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--text-tertiary);
    padding: 0 0.25rem 0.25rem;
}

.emoji-grid {
    display: grid;
    grid-template-columns: repeat(8, 1fr);
    gap: 2px;
}

.emoji-btn {
    background: none;
    border: none;
    cursor: pointer;
    font-size: 1.3rem;
    line-height: 1;
    padding: 0.3rem;
    border-radius: var(--radius-sm);
    transition: background 0.12s;
    color: inherit;
}

.emoji-btn:hover,
.emoji-btn:focus {
    background: var(--bg-tertiary);
    outline: none;
}

/* ─── Pending media preview strip (above composer row) ─────── */

.composer-previews {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    padding: 6px 10px 0;
}

.composer-previews:empty { display: none; }

.composer-media-preview {
    position: relative;
    width: 64px;
    height: 64px;
    border-radius: 8px;
    overflow: hidden;
    background: var(--bg-tertiary);
    flex-shrink: 0;
}

.composer-media-preview img,
.composer-media-preview video {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

.composer-media-preview .media-type-badge {
    position: absolute;
    left: 4px;
    bottom: 4px;
    background: rgba(0, 0, 0, 0.6);
    color: #fff;
    font-size: 0.6rem;
    padding: 1px 5px;
    border-radius: 4px;
    letter-spacing: 0.03em;
    text-transform: uppercase;
    pointer-events: none;
}

.composer-media-preview .remove-media {
    position: absolute;
    top: -4px;
    right: -4px;
    width: 20px;
    height: 20px;
    background: var(--accent-danger);
    color: white;
    border: none;
    border-radius: 50%;
    font-size: 0.7rem;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    line-height: 1;
    padding: 0;
}

/* ─── Rendered media inside messages ───────────────────────── */

/* Videos inside message bubbles — works for both chat and VIP message bubbles */
.msg-video {
    display: block;
    max-width: 100%;
    max-height: 320px;
    border-radius: 8px;
    margin-top: 4px;
    background: #000;
}

/* Position context so the emoji popover and mention picker can anchor
   to the composer bottom-left. */
.chat-input-area,
.vip-composer {
    position: relative;
}

/* ─── Markdown-lite formatting inside message bubbles ─────── */

/* Keep formatting subtle — chat messages should still read as chat.
   These rules apply to both .chat-msg-bubble and .vip-msg-bubble via
   the `.chat-msg-text` and `.vip-msg-text` wrappers. */
.chat-msg-text strong,
.vip-msg-text strong { font-weight: 700; }

.chat-msg-text em,
.vip-msg-text em { font-style: italic; }

.chat-msg-text u,
.vip-msg-text u { text-decoration: underline; text-underline-offset: 2px; }

.chat-msg-text s,
.vip-msg-text s { text-decoration: line-through; opacity: 0.75; }

/* Inline code pill — bumped contrast so the difference from regular
   prose is unmistakable even on colored (gradient) bubbles. */
.chat-msg-text code,
.vip-msg-text code {
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    background: rgba(0, 0, 0, 0.18);
    color: #d63384;
    padding: 2px 6px;
    border-radius: 4px;
    font-size: 0.88em;
    border: 1px solid rgba(0, 0, 0, 0.08);
}
html[data-theme="dark"] .chat-msg-text code,
html[data-theme="dark"] .vip-msg-text code {
    background: rgba(255, 255, 255, 0.12);
    color: #f472b6;
    border-color: rgba(255, 255, 255, 0.15);
}
/* On colored / gradient bubbles (user's own outgoing messages), use a
   brighter fill so the pill pops against the purple background. */
.vip-msg.mine .vip-msg-text code,
.chat-msg.mine .chat-msg-text code {
    background: rgba(255, 255, 255, 0.22);
    color: #fef3c7;
    border-color: rgba(255, 255, 255, 0.3);
}

/* ─── Fenced code block (multi-line ```...```) ────────────── */

/* Rendered as <pre class="chat-code-block"><code>...</code></pre>.
   Distinct from the inline pill: its own block, rounded card with
   left accent stripe, monospace font, and a horizontal scroll so
   long lines never force the message bubble to expand. Newlines
   inside are preserved because <pre> keeps whitespace literal. */
.chat-msg-text .chat-code-block,
.vip-msg-text .chat-code-block {
    display: block;
    margin: 6px 0 2px;
    padding: 10px 12px 10px 14px;
    background: rgba(0, 0, 0, 0.28);
    color: #e2e8f0;
    border-left: 3px solid var(--accent-primary, #8b5cf6);
    border-radius: 6px;
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 0.85em;
    line-height: 1.45;
    overflow-x: auto;
    white-space: pre;
    tab-size: 4;
    -moz-tab-size: 4;
}
.chat-msg-text .chat-code-block code,
.vip-msg-text .chat-code-block code {
    /* Inner <code> inherits pre styling — reset the inline pill look. */
    display: block;
    background: transparent;
    color: inherit;
    padding: 0;
    border: none;
    font-size: inherit;
    border-radius: 0;
}
html[data-theme="light"] .chat-msg-text .chat-code-block,
html[data-theme="light"] .vip-msg-text .chat-code-block {
    background: rgba(15, 23, 42, 0.06);
    color: #1e293b;
    border-left-color: var(--accent-primary, #8b5cf6);
}

/* Own (outgoing) bubble: swap to light-on-dark for the stripe so the
   block reads clearly on the purple-blue gradient. */
.vip-msg.mine .vip-msg-text .chat-code-block,
.chat-msg.mine .chat-msg-text .chat-code-block {
    background: rgba(0, 0, 0, 0.35);
    color: #f8fafc;
    border-left-color: rgba(255, 255, 255, 0.75);
}

.chat-msg-text a,
.vip-msg-text a {
    color: var(--accent-primary);
    text-decoration: underline;
    word-break: break-all;
}

/* ─── @Mention (Slack-style inline link) ──────────────────── */

/* Rendered as <a> so the whole "@Name" is one clickable unit — click
   opens the mentioned user's profile. The soft background makes the
   entire name read as a single token rather than loose text. */
.chat-mention {
    display: inline;
    background: rgba(139, 92, 246, 0.15);
    color: var(--accent-primary);
    border-radius: 4px;
    padding: 0 4px;
    font-weight: 600;
    white-space: nowrap;
    text-decoration: none;
    cursor: pointer;
    transition: background 0.12s, text-decoration-color 0.12s;
}
.chat-mention:hover,
.chat-mention:focus {
    background: rgba(139, 92, 246, 0.28);
    text-decoration: underline;
    text-underline-offset: 2px;
}
.chat-mention-self {
    background: rgba(245, 158, 11, 0.22);
    color: var(--accent-warning, #f59e0b);
}
.chat-mention-self:hover,
.chat-mention-self:focus {
    background: rgba(245, 158, 11, 0.38);
}

/* When a mention appears inside my OWN outgoing bubble, the default
   purple-on-purple-gradient has terrible contrast. Switch to a bright
   white-on-translucent-white treatment that reads like a Slack chip
   regardless of the gradient underneath. Self-mentions (amber) stay
   amber so they're always identifiable. */
.vip-msg.mine .chat-mention:not(.chat-mention-self),
.chat-msg.mine .chat-mention:not(.chat-mention-self) {
    background: rgba(255, 255, 255, 0.28);
    color: #fff;
    text-decoration: none;
}
.vip-msg.mine .chat-mention:not(.chat-mention-self):hover,
.vip-msg.mine .chat-mention:not(.chat-mention-self):focus,
.chat-msg.mine .chat-mention:not(.chat-mention-self):hover,
.chat-msg.mine .chat-mention:not(.chat-mention-self):focus {
    background: rgba(255, 255, 255, 0.45);
    text-decoration: underline;
    text-underline-offset: 2px;
}

/* Whole-bubble highlight when *I* am mentioned. Applied to the bubble
   element so it works for both legacy chat (.chat-msg) and VIP
   (.vip-msg-bubble). Stays inside the existing bubble border-radius
   instead of spanning the whole row, so the layout isn't disrupted. */
.chat-msg.mentioned-me,
.vip-msg .vip-msg-bubble.mentioned-me {
    background: rgba(245, 158, 11, 0.14) !important;
    border-left: 3px solid var(--accent-warning, #f59e0b);
    padding-left: calc(var(--spacing-sm, 8px) + 2px);
}

/* ─── Mention picker drop-up ──────────────────────────────── */
/*
 * Positioned ABOVE the entire composer container so it never covers
 * the textarea — no matter how many preview thumbnails or formatting
 * buttons are present. Compact sizing keeps it out of the way. */

.mention-picker {
    position: absolute;
    bottom: calc(100% + 4px);
    left: 12px;
    max-width: 260px;
    max-height: 180px;
    overflow-y: auto;
    background: var(--bg-secondary);
    border: 1px solid var(--glass-border);
    border-radius: var(--radius-md);
    box-shadow: 0 6px 18px rgba(0, 0, 0, 0.25);
    padding: 3px;
    z-index: 60;
}

.mention-picker.hidden { display: none !important; }

.mention-picker-item {
    display: flex;
    align-items: center;
    gap: 7px;
    padding: 4px 6px;
    border-radius: var(--radius-sm);
    cursor: pointer;
    color: var(--text-primary);
    font-size: 0.82rem;
    line-height: 1.2;
    user-select: none;
}

.mention-picker-item[aria-selected="true"],
.mention-picker-item:hover {
    background: var(--bg-tertiary);
}

.mention-picker-avatar {
    width: 22px;
    height: 22px;
    border-radius: 50%;
    background: var(--bg-tertiary);
    object-fit: cover;
    flex-shrink: 0;
}

.mention-picker-name {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.mention-picker-username {
    color: var(--text-tertiary);
    font-size: 0.72rem;
}

.mention-picker-empty {
    padding: 8px 10px;
    color: var(--text-tertiary);
    font-size: 0.8rem;
    text-align: center;
}

/* ─── Formatting toolbar (shared: VIP + chat popup) ───────── */
/*
 * A tiny toolbar of B / I / U / code buttons that sits next to the
 * emoji/attach buttons. Clicking wraps the current textarea selection
 * with markdown-lite markers so the renderer (text-format.js) produces
 * the expected formatting. Gives users a visible affordance that text
 * can be styled, without pulling in a full WYSIWYG editor. */

.composer-fmt-btn {
    width: 26px;
    height: 26px;
    border-radius: var(--radius-sm, 4px);
    border: none;
    background: transparent;
    color: var(--text-secondary);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    padding: 0;
    line-height: 1;
    font-size: 0.78rem;
    font-family: inherit;
    transition: background var(--transition-fast, 0.12s), color var(--transition-fast, 0.12s);
}
.composer-fmt-btn:hover {
    background: var(--bg-tertiary);
    color: var(--text-primary);
}
.composer-fmt-btn.is-bold { font-weight: 800; }
.composer-fmt-btn.is-italic { font-style: italic; font-weight: 600; }
.composer-fmt-btn.is-underline { text-decoration: underline; font-weight: 600; text-underline-offset: 2px; }
.composer-fmt-btn.is-code {
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 0.72rem;
}

/* Visual separator between format group and emoji/attach */
.composer-fmt-sep {
    width: 1px;
    align-self: stretch;
    margin: 3px 4px;
    background: var(--glass-border, rgba(255,255,255,0.08));
    flex-shrink: 0;
}

/* ─── Mention badge in channel list (VIP sidebar) ─────────── */

.vip-convo-mentions {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 18px;
    height: 18px;
    padding: 0 5px;
    margin-left: 4px;
    border-radius: 9px;
    background: var(--accent-warning, #f59e0b);
    color: #fff;
    font-size: 0.65rem;
    font-weight: 700;
    line-height: 1;
}

/* ─── Reactions + unsend + tombstone (shared VIP + legacy chat) ───
   Scoped to `.vip-msg` and `.chat-msg` rather than using an unscoped
   class prefix because both bubble types already set their own
   background gradients (mine) and surfaces (theirs), and the pill
   colors need to adapt to whichever they're sitting on. */

/* Message container needs to be a positioning context for the hover
   action bar. Both surfaces already have relative positioning on
   their mine/theirs bubbles; this extra anchor is harmless. */
.vip-msg,
.chat-msg { position: relative; }

/* Hover/long-press action toolbar — Slack/Discord-style floating pill.
   Positioning notes (this is the bit that used to overlap the bubble):
     • `bottom: 100%` puts the bar's bottom edge flush with the
       bubble's top edge → ZERO overlap with the message content.
       Compare to the old `top: -14px`, which dropped half the bar
       (~14–18px) onto the first line of text.
     • Bottom touches the bubble's top with no gap, so the cursor
       can move from the bubble straight up into the bar without
       crossing empty space (which would dismiss the bar). The
       visual separation comes from the bar's own surface + shadow,
       not from a margin.
     • `white-space: nowrap` is critical: when the bubble is narrow
       (typical short DM), absolute width sized-to-content was
       wrapping "Unsend" onto a stack of letters. Locking it to a
       single row keeps the layout horizontal at any bubble width. */
.msg-action-bar {
    position: absolute;
    bottom: 100%;
    /* Default anchor for THEIRS bubbles: bar's left edge sits 8px in
       from the bubble's left, so the bar extends RIGHT into the open
       chat space next to a left-aligned bubble. For narrow theirs
       messages ("ok") the bar is wider than the bubble — anchoring
       right would push it leftward, clipping against the chat
       window's left wall (or the avatar column on group chats).
       Mine bubbles override this to anchor right (see chat.css and
       private-channel.css) — same principle, mirrored. */
    left: 8px;
    right: auto;
    display: inline-flex;
    align-items: center;
    gap: 2px;
    padding: 3px;
    background: var(--bg-elevated, var(--bg-secondary, #1e293b));
    border: 1px solid var(--glass-border, rgba(148, 163, 184, 0.18));
    border-radius: 999px;
    box-shadow:
        0 10px 24px rgba(0, 0, 0, 0.32),
        0 2px 6px rgba(0, 0, 0, 0.22),
        0 0 0 0.5px rgba(255, 255, 255, 0.04) inset;
    opacity: 0;
    pointer-events: none;
    transform: translateY(2px);
    transform-origin: 100% 100%;
    transition: opacity 0.14s ease, transform 0.16s cubic-bezier(0.2, 0.8, 0.2, 1);
    z-index: 5;
    white-space: nowrap;
    max-width: calc(100vw - 24px);
    /* Small selectable safety margin so quick mouse jiggle near the
       edge doesn't knock the bar offscreen on tiny chat windows. */
    will-change: opacity, transform;
}

/* Reveal on hover (desktop) AND on keyboard focus anywhere inside
   the bubble (tabbing through the action bar itself). Touch devices
   get the bar revealed via :focus-within when the user taps the
   bubble — same affordance, no extra JS. */
.vip-msg:hover .msg-action-bar,
.vip-msg:focus-within .msg-action-bar,
.chat-msg:hover .msg-action-bar,
.chat-msg:focus-within .msg-action-bar,
/* `pinned` is set by the JS when the reaction picker is open so the
   toolbar stays visible while the user picks an emoji even after
   the cursor has moved away from the bubble. */
.msg-action-bar.msg-action-bar-pinned {
    opacity: 1;
    pointer-events: auto;
    transform: translateY(0);
}

/* Each toolbar slot: pill button with icon (+ optional label). The
   button height is fixed at 28px so the bar's overall height is
   predictable regardless of which combination of buttons renders. */
.msg-action-btn {
    background: transparent;
    border: none;
    color: var(--text-secondary, #94a3b8);
    cursor: pointer;
    font-size: 0.78rem;
    font-weight: 600;
    line-height: 1;
    padding: 0 9px;
    height: 28px;
    border-radius: 999px;
    display: inline-flex;
    align-items: center;
    gap: 5px;
    transition: background 0.12s ease, color 0.12s ease;
    -webkit-tap-highlight-color: transparent;
    flex-shrink: 0;
    /* Block accidental text selection of the label/countdown when
       a user double-clicks the toolbar — the bar is a UI control,
       not content. */
    user-select: none;
    -webkit-user-select: none;
}
.msg-action-btn:hover {
    background: rgba(148, 163, 184, 0.18);
    color: var(--text-primary, #e2e8f0);
}
.msg-action-btn:active {
    background: rgba(148, 163, 184, 0.28);
}
/* Visually pressed state for the "+" button while the reaction
   picker is open. Tinted with the brand color so it reads as
   "this control is currently driving the popover". */
.msg-action-btn.msg-action-btn-active,
.msg-action-btn.msg-action-btn-active:hover {
    background: rgba(var(--accent-primary-rgb, 139, 92, 246), 0.22);
    color: var(--text-primary, #e2e8f0);
}

/* React button is icon-only — square slot so the smiley stays
   centered. Width matches the height for a clean circular hover. */
.msg-action-btn.msg-action-react {
    width: 32px;
    padding: 0;
    justify-content: center;
}

/* Inline icon size + alignment. `display: block` kills the inline
   baseline gap that would otherwise misalign the icon vs the label
   text in flex children. */
.msg-action-icon {
    width: 17px;
    height: 17px;
    display: block;
    flex-shrink: 0;
}

/* Wrapper for the smiley + the small "+" badge anchored to its
   bottom-right corner. Uses absolute positioning relative to the
   wrapper so the badge tracks the icon regardless of the button's
   padding/hover state. */
.msg-action-icon-wrap {
    position: relative;
    display: inline-flex;
    width: 17px;
    height: 17px;
}
.msg-action-icon-wrap .msg-action-plus {
    position: absolute;
    right: -5px;
    bottom: -3px;
    width: 11px;
    height: 11px;
    background: var(--accent-primary, #8b5cf6);
    color: #fff;
    border-radius: 50%;
    font-size: 0.62rem;
    font-weight: 800;
    line-height: 11px;
    text-align: center;
    /* Tiny halo in the bar's bg color so the badge "punches out"
       from the smiley underneath. Matches the toolbar's surface so
       it disappears against the pill instead of reading as a ring. */
    box-shadow: 0 0 0 1.5px var(--bg-elevated, var(--bg-secondary, #1e293b));
}

/* Unsend button has an icon + word + countdown, all on ONE row. The
   countdown is divided from the label by a faint vertical separator
   for readability — the dividing line uses a border on the countdown
   itself so it doesn't add a stray DOM node. */
.msg-action-unsend {
    color: var(--text-secondary, #94a3b8);
}
.msg-action-unsend:hover {
    background: rgba(239, 68, 68, 0.14);
    color: var(--accent-danger, #ef4444);
}
.msg-action-unsend .msg-action-label {
    letter-spacing: 0.01em;
}
.msg-action-countdown {
    font-variant-numeric: tabular-nums;
    font-size: 0.7rem;
    font-weight: 500;
    color: var(--text-tertiary, #64748b);
    padding-left: 6px;
    margin-left: 1px;
    border-left: 1px solid var(--glass-border, rgba(148, 163, 184, 0.22));
}
.msg-action-unsend:hover .msg-action-countdown {
    color: inherit;
    border-left-color: rgba(239, 68, 68, 0.3);
}

/* Reaction pills live below the bubble's text/media, before the
   time row bleeds through. Using flex-wrap lets long reaction lists
   break onto a second row instead of overflowing the bubble. */
.msg-reactions {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
    margin-top: 6px;
}

.msg-reaction-pill {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 1px 8px;
    min-height: 22px;
    border-radius: 11px;
    background: var(--glass-bg, rgba(148, 163, 184, 0.12));
    border: 1px solid var(--glass-border, rgba(148, 163, 184, 0.25));
    color: var(--text-primary, #e2e8f0);
    font-size: 0.78rem;
    line-height: 1;
    cursor: pointer;
    transition: background 0.12s, border-color 0.12s, transform 0.08s;
}
.msg-reaction-pill:hover {
    background: rgba(var(--accent-primary-rgb, 139, 92, 246), 0.14);
    border-color: rgba(var(--accent-primary-rgb, 139, 92, 246), 0.4);
}
.msg-reaction-pill:active { transform: scale(0.96); }
.msg-reaction-pill.mine {
    background: rgba(var(--accent-primary-rgb, 139, 92, 246), 0.22);
    border-color: rgba(var(--accent-primary-rgb, 139, 92, 246), 0.55);
    color: var(--text-primary, #e2e8f0);
}
.msg-reaction-emoji { font-size: 0.95rem; line-height: 1; }
.msg-reaction-count {
    font-variant-numeric: tabular-nums;
    font-weight: 600;
    font-size: 0.72rem;
}

.msg-reaction-add {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 26px;
    height: 22px;
    padding: 0;
    border-radius: 11px;
    background: transparent;
    border: 1px dashed var(--glass-border, rgba(148, 163, 184, 0.25));
    color: var(--text-tertiary, #64748b);
    font-size: 1rem;
    font-weight: 600;
    line-height: 1;
    cursor: pointer;
    transition: background 0.12s, color 0.12s, border-color 0.12s;
}
.msg-reaction-add:hover {
    background: var(--glass-bg, rgba(148, 163, 184, 0.14));
    color: var(--text-primary, #e2e8f0);
    border-color: var(--glass-border, rgba(148, 163, 184, 0.45));
    border-style: solid;
}

/* When the bubble is mine (purple gradient), raise pill contrast so
   counts stay readable against the saturated background. Applies to
   both VIP and legacy chat. */
.vip-msg.mine .msg-reaction-pill,
.chat-msg.mine .msg-reaction-pill {
    background: rgba(255, 255, 255, 0.18);
    border-color: rgba(255, 255, 255, 0.32);
    color: #fff;
}
.vip-msg.mine .msg-reaction-pill.mine,
.chat-msg.mine .msg-reaction-pill.mine {
    background: rgba(255, 255, 255, 0.32);
    border-color: rgba(255, 255, 255, 0.55);
}
.vip-msg.mine .msg-reaction-add,
.chat-msg.mine .msg-reaction-add {
    border-color: rgba(255, 255, 255, 0.35);
    color: rgba(255, 255, 255, 0.85);
}
.vip-msg.mine .msg-reaction-add:hover,
.chat-msg.mine .msg-reaction-add:hover {
    background: rgba(255, 255, 255, 0.18);
    color: #fff;
}

/* Global reaction picker popover — positioned absolutely at a point
   computed in JS. Reuses the emoji grid styles so it looks the same
   as the composer picker, just in a floating card.
   - `overscroll-behavior: contain` stops the trackpad inertial scroll
     from "chaining" into the page once the emoji list hits its top/
     bottom; without this, a flick would trigger the window scroll
     listener and dismiss the picker mid-browse.
   - `overflow-y: auto` with a generous max-height keeps the full
     Hearts & Gestures (contains 👍 / 👎) and Things groups reachable
     on a 13" laptop display without needing to resize the window. */
.msg-reaction-picker {
    position: fixed;
    width: 340px;
    max-width: calc(100vw - 16px);
    max-height: min(440px, 70vh);
    overflow-y: auto;
    overscroll-behavior: contain;
    background: var(--bg-secondary);
    border: 1px solid var(--glass-border);
    border-radius: var(--radius-md);
    box-shadow: 0 12px 32px rgba(0, 0, 0, 0.35);
    padding: 0.6rem;
    z-index: 10000;
}
.msg-reaction-picker[hidden] { display: none !important; }

/* Slack-style reactors hover popover — singleton card appended to
   <body>, positioned fixed above the hovered pill. Layout goal: a
   fixed-width card with names flowing horizontally, comma-separated,
   wrapping to the next line only when the total width is exceeded.

   Break rules (per user spec, matches Slack):
     • A single-token username ("coolotter42") stays intact even if
       it's wider than usual — we use `overflow-wrap: normal` and
       `word-break: normal` so the browser NEVER breaks mid-word.
     • A name with a space ("John Smith") can break at the space.
     • The comma+space between names is a natural break point so
       new lines start cleanly with the next name.

   Width capped at 320px (slightly wider than the compact 280px
   earlier version so 3-4 short names fit per line). */
.msg-reactors-popover {
    position: fixed;
    width: 320px;
    max-width: calc(100vw - 16px);
    background: var(--bg-secondary);
    color: var(--text-primary);
    border: 1px solid var(--glass-border);
    border-radius: var(--radius-md);
    box-shadow: 0 10px 28px rgba(0, 0, 0, 0.38);
    padding: 0.6rem 0.7rem;
    z-index: 10001;
    font-size: 0.85rem;
    animation: msgReactorsFadeIn 120ms ease-out;
}
.msg-reactors-popover[hidden] { display: none !important; }
@keyframes msgReactorsFadeIn {
    from { opacity: 0; transform: translateY(2px); }
    to { opacity: 1; transform: translateY(0); }
}
.msg-reactors-head {
    display: flex;
    align-items: baseline;
    gap: 0.4rem;
    padding-bottom: 0.35rem;
    margin-bottom: 0.4rem;
    border-bottom: 1px solid var(--glass-border);
}
.msg-reactors-emoji { font-size: 1.3rem; line-height: 1; }
.msg-reactors-count {
    font-weight: 700;
    font-size: 0.85rem;
    color: var(--text-primary);
}
.msg-reactors-head-verb {
    font-size: 0.75rem;
    color: var(--text-secondary);
}
.msg-reactors-list {
    max-height: 220px;
    overflow-y: auto;
    overscroll-behavior: contain;
    line-height: 1.45;
    color: var(--text-primary);
    word-break: normal;
    overflow-wrap: normal;
}
.msg-reactors-name {
    color: var(--text-primary);
    font-weight: 500;
}
.msg-reactors-sep {
    color: var(--text-secondary);
}
.msg-reactors-more {
    color: var(--text-secondary);
    font-style: italic;
}
.msg-reactors-hint {
    padding-top: 0.4rem;
    margin-top: 0.4rem;
    border-top: 1px solid var(--glass-border);
    font-size: 0.72rem;
    color: var(--text-secondary);
    text-align: center;
}

/* Tombstone (deleted message placeholder). Muted italic text, subtle
   surface so the bubble is clearly distinct from live content. */
.msg-tombstone {
    font-style: italic;
    color: var(--text-tertiary, #64748b);
    font-size: 0.88rem;
    opacity: 0.9;
}
.msg-tombstone-admin { color: var(--accent-danger, #ef4444); }
.msg-tombstone-reason {
    color: var(--text-tertiary, #64748b);
    font-weight: 400;
    margin-left: 2px;
}

/* Soft-delete bubbles get a reduced saturation surface. VIP renders
   its own `.vip-msg-bubble-tombstone` wrapper, styled in
   private-channel.css — the shared rules below cover the legacy
   chat popup + shared tombstone text. */
.vip-msg-deleted .vip-msg-bubble,
.chat-msg.chat-msg-deleted {
    background: var(--glass-bg, rgba(148, 163, 184, 0.08)) !important;
    border: 1px dashed var(--glass-border, rgba(148, 163, 184, 0.35)) !important;
    box-shadow: none !important;
    color: var(--text-tertiary, #64748b) !important;
}
