/* ── Reset & base ── */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

:root {
    --bg:          #f0f2f5;
    --surface:     #ffffff;
    --surface-r: 255; --surface-g: 255; --surface-b: 255;
    --border-r:  182; --border-g:  186; --border-b:  190;
    --chat-bg-alpha: 1;
    --border:      #b6babe;
    --primary:     #4f6ef7;
    --primary-dk:  #3a57d4;
    --danger:      #c0392b;
    --success-bg:  #eafaf1;
    --success-bd:  #27ae60;
    --error-bg:    #fdecea;
    --error-bd:    #e74c3c;
    --text:        #1a1a2e;
    --muted:       #6c757d;
    --own-bubble:  #6f84f0;
    --own-text:    #ffffff;
    --other-bubble:#dcf2e1;
    --other-text:  #14321d;
    /* Link/YouTube preview card background: a lighter shade of the (other) message
       bubble colour so the card reads as related to the message but stays distinct,
       keeping the dark preview text well contrasted. */
    --preview-bg:       color-mix(in srgb, var(--other-bubble) 45%, #ffffff);
    --preview-bg-hover: color-mix(in srgb, var(--other-bubble) 60%, #ffffff);
    --radius:      12px;
    --shadow:      0 2px 12px rgba(0,0,0,.08);
    /* Shared blur+colour for the edge shadow that side panels (chat-info, user
       profile) and the chat-list sidebar cast onto the adjacent area. Direction
       (±4px 0) is set per-element; this keeps the look identical everywhere. */
    --side-shadow: 16px rgba(0,0,0,.12);
    --btn-neutral-bg: #e4e7ec;
    /* Horizontal inset of the chat "card" — the gradient panel border, the gutter
       blur/anim layers and the message-area padding are all derived from this so
       they stay aligned. Shrunk on mobile (see the max-width:640px block). */
    --gutter-w: max(1.25rem, calc((100% - 780px) / 2));
}

/* ── Dark theme ── */
body.dark {
    --bg:          #0f1117;
    --surface:     #1a1d27;
    --surface-r: 26; --surface-g: 29; --surface-b: 39;
    --border-r:  45; --border-g:  49; --border-b:  66;
    --border:      #2d3142;
    --primary:     #6b8afa;
    --primary-dk:  #5a78f0;
    --danger:      #ff7b72;
    --success-bg:  #1a2f1e;
    --success-bd:  #3fb950;
    --error-bg:    #2d1416;
    --error-bd:    #f85149;
    --text:        #e2e4ef;
    --muted:       #8b90a8;
    --own-bubble:  #5870de;
    --own-text:    #ffffff;
    --other-bubble:#2c3666;
    --other-text:  #d7dcf5;
    /* Dark theme: a slightly darker shade of the bubble (light text stays readable). */
    --preview-bg:       color-mix(in srgb, var(--other-bubble) 55%, #000000);
    --preview-bg-hover: color-mix(in srgb, var(--other-bubble) 40%, #000000);
    --shadow:      0 2px 12px rgba(0,0,0,.5);
    --btn-neutral-bg: rgba(255,255,255,.07);
    color-scheme:  dark;
}
body.dark input[type="email"],
body.dark input[type="text"] { background: var(--surface); color: var(--text); }
body.dark textarea           { background: var(--surface); color: var(--text); }
body.dark dialog {
    background: #2a2d3e;
    color: var(--text);
    border: 1px solid #3d4060;
    box-shadow: 0 8px 32px rgba(0,0,0,.5);
    animation: update-banner-pulse-dark 3s ease-in-out infinite;
}
body.dark .status-bar.connecting   { background: #2a2510; color: #d4a017; }
body.dark .status-bar.connected    { background: var(--success-bg); color: #3fb950; }
body.dark .status-bar.disconnected { background: var(--error-bg);   color: var(--danger); }

body {
    font-family: system-ui, -apple-system, sans-serif;
    background: var(--bg);
    color: var(--text);
    height: 100dvh;
    display: flex;
    align-items: center;
    justify-content: center;
}

/* ── Auth page ── */
.auth-container {
    width: 100%;
    max-width: 420px;
    padding: 1.5rem;
}

.auth-card {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
    padding: 2.5rem 2rem;
    display: flex;
    flex-direction: column;
    gap: 1.25rem;
}

.auth-card h1 { font-size: 1.75rem; text-align: center; }
.auth-card .subtitle { color: var(--muted); text-align: center; font-size: .95rem; }

/* ── "or" divider + Google sign-in ── */
.divider {
    display: flex;
    align-items: center;
    color: var(--muted);
    font-size: .85rem;
}
.divider::before,
.divider::after {
    content: '';
    flex: 1;
    border-bottom: 1px solid var(--border);
}
.divider span { padding: 0 .75rem; }
#google-signin { display: flex; justify-content: center; }

/* ── Banners ── */
.banner {
    border-radius: 8px;
    padding: .75rem 1rem;
    font-size: .9rem;
    line-height: 1.5;
}
.banner.error   { background: var(--error-bg);   border: 1px solid var(--error-bd);   color: var(--danger); }
.banner.success { background: var(--success-bg); border: 1px solid var(--success-bd); }

/* ── Form ── */
#login-form { display: flex; flex-direction: column; gap: .75rem; }
#username-form { display: flex; flex-direction: column; gap: 1.5rem; }
.field { display: flex; flex-direction: column; gap: .4rem; }
.field label { font-size: .875rem; font-weight: 600; color: var(--muted); }

.field-hint {
    display: block;
    min-height: 1.2em;   /* reserve a line so the layout doesn't jump as the status changes */
    line-height: 1.2;
    font-size: .8rem;
    transition: color .15s;
}
.field-hint:empty { min-height: 0; }
.field-hint.success { color: var(--success-bd); }
.field-hint.error   { color: var(--danger); }

.field-note { font-size: .8rem; color: var(--muted); }

input[type="email"],
input[type="text"] {
    width: 100%;
    padding: .65rem .9rem;
    border: 1px solid var(--border);
    border-radius: 8px;
    font-size: 1rem;
    outline: none;
    transition: border-color .15s;
}
input:focus { border-color: var(--primary); }

button {
    width: 100%;
    padding: .7rem 1rem;
    border: none;
    border-radius: 8px;
    font-size: 1rem;
    font-weight: 600;
    cursor: pointer;
    background: var(--primary);
    color: #fff;
    transition: background .15s;
}
button:hover:not(:disabled) { background: var(--primary-dk); }
button:disabled { opacity: .55; cursor: not-allowed; }

button.secondary {
    background: transparent;
    color: var(--muted);
    border: 1px solid var(--border);
}
button.secondary:hover:not(:disabled) { background: var(--bg); }
button.secondary.small { width: auto; font-size: .8rem; padding: .3rem .7rem; }

button.ghost {
    background: transparent;
    color: var(--muted);
    border: 1px dashed var(--border);
    font-weight: 400;
    opacity: .7;
}
button.ghost:hover:not(:disabled) { opacity: 1; background: var(--surface); color: var(--text); border-style: solid; }

/* ── Chat page ── */
body:has(.chat-container) {
    align-items: stretch;
    justify-content: stretch;
    padding: 0;
    flex-direction: row;
}

/* ── Chat sidebar ── */
.chat-sidebar {
    position: relative;
    width: var(--sidebar-w, 260px);
    /* Width-based container so children can react to the (resizable) sidebar
       width — see the @container rule that hides the search box and labels
       once it gets too narrow to be useful. */
    container-type: inline-size;
    container-name: sidebar;
    flex-shrink: 0;
    display: flex;
    flex-direction: column;
    background: var(--surface);
    border-right: 1px solid var(--border);
    /* 2× stronger than the shared --side-shadow (.12 → .24 alpha) */
    box-shadow: 4px 0 16px rgba(0,0,0,.24);
    height: 100dvh;
    overflow: hidden;
    z-index: 10;
}

/* Drag handle on the sidebar's right edge to resize its width. */
.sidebar-resizer {
    position: absolute;
    top: 0;
    right: 0;
    width: 6px;
    height: 100%;
    cursor: col-resize;
    z-index: 30;
    background: transparent;
    transition: background .15s ease;
}
.sidebar-resizer:hover,
.sidebar-resizer.dragging {
    background: var(--primary);
}
/* Disable text selection across the page while dragging the handle. */
body.sidebar-resizing {
    cursor: col-resize;
    user-select: none;
}

.sidebar-search-wrap {
    padding: .6rem .75rem;
    border-bottom: 1px solid var(--border);
    flex-shrink: 0;
}

.sidebar-search {
    width: 100%;
    box-sizing: border-box;
    padding: .4rem .7rem;
    border-radius: 8px;
    border: 1px solid var(--border);
    background: var(--bg);
    color: var(--text);
    font-size: .875rem;
    outline: none;
}
.sidebar-search:focus { border-color: var(--primary); }
.sidebar-search::placeholder { color: var(--muted); }

.sidebar-footer {
    padding: .6rem .75rem;
    border-top: 1px solid var(--border);
    flex-shrink: 0;
    /* Match the message-composer footer on the right: 48px send button
       + .45rem*2 vertical padding + 1px border ≈ 63.4px. */
    min-height: 63.5px;
    display: flex;
    align-items: center;
}

.sidebar-new-btn {
    width: 100%;
    padding: .5rem;
    border-radius: 8px;
    font-size: .875rem;
    font-weight: 600;
    background: var(--btn-neutral-bg);
    color: var(--muted);
    border: 1px solid var(--border);
}
.sidebar-new-btn.small {
    width: auto;
    padding: .25rem .65rem;
    font-size: .78rem;
    font-weight: 400;
}
.sidebar-new-btn:hover:not(:disabled) {
    background: var(--border);
    color: var(--text);
    border-color: var(--primary);
}
/* Slightly darker than the plain .ghost look: give it a subtle fill and full-opacity text. */
.sidebar-new-btn.ghost {
    background: color-mix(in srgb, var(--btn-neutral-bg) 50%, transparent);
    color: color-mix(in srgb, var(--muted) 80%, #000);
    opacity: .85;
}
.sidebar-new-btn.ghost:hover:not(:disabled) {
    background: var(--border);
    color: var(--text);
    border-style: solid;
}

.sidebar-chat-list {
    flex: 1;
    overflow-y: auto;
    overflow-x: hidden;
    padding: .4rem 0;
}

/* When the sidebar is dragged very narrow, drop the chrome that no longer fits
   (search box and section labels) so only the chat avatars remain. */
@container sidebar (max-width: 180px) {
    .sidebar-search-wrap { display: none; }
    .sidebar-section-label { display: none; }
}

.sidebar-section-label {
    padding: .5rem 1rem .25rem;
    font-size: .72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .05em;
    color: var(--muted);
}

.sidebar-chat-item {
    display: flex;
    align-items: center;
    gap: .6rem;
    padding: .55rem 1rem;
    cursor: pointer;
    transition: background .12s;
    position: relative;
}
.sidebar-chat-item:hover { background: var(--bg); }
.sidebar-chat-item.active { background: rgba(79,110,247,.1); }
.dark .sidebar-chat-item.active { background: rgba(107,138,250,.15); }

.sidebar-chat-item.has-update { overflow: hidden; }

/* Gas nebula — three overlapping radial blobs that breathe and drift */
.sidebar-chat-item.has-update::after {
    content: '';
    position: absolute;
    right: -2px; top: -2px; bottom: -2px;
    width: 240px;
    background:
        radial-gradient(ellipse 55% 160% at 103% 50%,
            rgba(139, 92, 246, .85) 0%, transparent 55%),
        radial-gradient(ellipse 45% 90%  at 95%  16%,
            rgba(56, 189, 248, .7)  0%, transparent 50%),
        radial-gradient(ellipse 50% 120% at 97%  84%,
            rgba(34, 211, 238, .6)  0%, transparent 48%);
    filter: blur(0.5px);
    animation: gas-cloud-pulse 2.8s ease-in-out infinite;
    pointer-events: none;
}

@keyframes gas-cloud-pulse {
    0%, 100% { opacity: 1;   filter: blur(0.5px); }
    40%       { opacity: .72; filter: blur(1.5px) brightness(1.25); }
    70%       { opacity: .88; filter: blur(0.8px); }
}

.sidebar-chat-av {
    width: 44px;
    height: 44px;
    border-radius: 50%;
    background: var(--primary);
    color: #fff;
    font-size: .85rem;
    font-weight: 700;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    background-size: cover;
    background-position: center;
}

.sidebar-chat-info {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
}

.sidebar-chat-name {
    font-size: .9rem;
    font-weight: 600;
    /* Wrap long names onto a second line, breaking on whole words only,
       then clamp to 2 lines with an ellipsis. */
    display: -webkit-box;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    overflow-wrap: normal;
    word-break: normal;
}

.sidebar-chat-desc {
    font-size: .75rem;
    color: var(--muted);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.sidebar-public-badge {
    font-size: .68rem;
    font-weight: 600;
    background: var(--primary);
    color: #fff;
    padding: .15rem .4rem;
    border-radius: 6px;
    flex-shrink: 0;
}

.sidebar-chat-time {
    font-size: .7rem;
    color: var(--muted);
    flex-shrink: 0;
    align-self: flex-start;
    margin-top: .15rem;
    white-space: nowrap;
    position: relative;
    z-index: 1;
}

.sidebar-empty {
    padding: 1.5rem 1rem;
    color: var(--muted);
    font-size: .85rem;
    text-align: center;
}

/* ── Chat preview overlay ── */
.chat-preview-overlay[hidden] { display: none; }
.chat-preview-overlay {
    position: absolute;
    inset: 0;
    z-index: 20;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(0,0,0,.35);
    backdrop-filter: blur(4px);
}

.chat-preview-card {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 16px;
    padding: 2rem;
    max-width: 420px;
    width: calc(100% - 2rem);
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: .75rem;
    box-shadow: 0 8px 32px rgba(0,0,0,.2);
}

.preview-avatar {
    width: 72px;
    height: 72px;
    border-radius: 50%;
    background: var(--primary);
    color: #fff;
    font-size: 1.8rem;
    font-weight: 700;
    display: flex;
    align-items: center;
    justify-content: center;
    background-size: cover;
    background-position: center;
}

.chat-preview-card h3 {
    font-size: 1.3rem;
    text-align: center;
}

.preview-desc {
    color: var(--muted);
    font-size: .9rem;
    text-align: center;
}

.preview-meta {
    color: var(--muted);
    font-size: .8rem;
    text-align: center;
}

.preview-messages {
    width: 100%;
    max-height: 200px;
    overflow-y: auto;
    border: 1px solid var(--border);
    border-radius: 8px;
    padding: .5rem;
    display: flex;
    flex-direction: column;
    gap: .35rem;
}

.preview-msg-row {
    display: flex;
    gap: .4rem;
    font-size: .82rem;
    align-items: baseline;
}

.preview-msg-sender {
    font-weight: 600;
    flex-shrink: 0;
    color: var(--primary);
}

.preview-msg-text {
    color: var(--text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.preview-join-btn {
    margin-top: .5rem;
    width: 100%;
    max-width: 200px;
}

.chat-container {
    display: flex;
    flex-direction: column;
    flex: 1;
    min-width: 0;
    height: 100dvh;
    background: var(--gutter-bg, var(--bg));
    position: relative;
    z-index: 0;
}

/* Pattern layer — behind all content, animated for Cycle */
.gutter-pattern-layer {
    position: absolute;
    inset: 0;
    pointer-events: none;
    z-index: -1;
    transition: opacity 2.5s ease;
}
#gutter-blur-left,
#gutter-blur-right {
    position: absolute;
    top: 0;
    bottom: 0;
    backdrop-filter: blur(var(--gutter-blur-px, 0px));
    pointer-events: none;
    z-index: -1;
}
#gutter-blur-left {
    left: 0;
    right: calc(100% - var(--gutter-w));
}
#gutter-blur-right {
    right: 0;
    left: calc(100% - var(--gutter-w));
}
#chat-blur-layer {
    position: absolute;
    top: 0;
    bottom: 0;
    left: var(--gutter-w);
    right: var(--gutter-w);
    backdrop-filter: blur(var(--chat-blur-px, 0px));
    pointer-events: none;
    z-index: -1;
}

/* ── Gutter animation overlay ── */
.gutter-anim-layer {
    position: absolute;
    inset: 0;
    pointer-events: none;
    z-index: 5;
}

/* Breathe: soft white pulse over the gutter areas, strongest in center vertically */
.gutter-anim-layer.breathe {
    background: linear-gradient(to right,
        white var(--gutter-w),
        transparent var(--gutter-w),
        transparent calc(100% - var(--gutter-w)),
        white calc(100% - var(--gutter-w))
    );
    mask-image: linear-gradient(to bottom,
        transparent 0%,
        black 22%,
        black 78%,
        transparent 100%
    );
    -webkit-mask-image: linear-gradient(to bottom,
        transparent 0%,
        black 22%,
        black 78%,
        transparent 100%
    );
    animation: gutter-breathe 8s ease-in-out infinite;
}
@keyframes gutter-breathe {
    0%, 100% { opacity: 0; }
    50%       { opacity: .55; }
}


.chat-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: .7rem 1.25rem;
    border: 1px solid var(--border);
    background: var(--bg);
    flex-shrink: 0;
    overflow: hidden;
    min-width: 0;
    /* Float over the messages (like the bottom composer) so the message area
       runs full height and scrolls up underneath this bar to the very top edge. */
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    z-index: 5;
    /* Mirror the floating message composer: rounded card inset from the edges
       (same horizontal gutter, same radius) so the top bar doesn't touch the
       screen edges. */
    margin: .6rem calc(var(--gutter-w) + 0.75rem) 0;
    border-radius: 20px;
}
.chat-header h2 { font-size: 1.15rem; flex: 1; min-width: 0; overflow: hidden; }
/* Title column: chat name on top, member count beneath (left-aligned) */
.chat-header-titlewrap { display: flex; flex-direction: column; min-width: 0; line-height: 1.15; }
.chat-header-members { font-size: .72rem; font-weight: 400; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.chat-header-members:empty { display: none; }
.header-right { display: flex; align-items: center; gap: .75rem; flex-shrink: 0; }
.user-info { display: flex; align-items: center; gap: .75rem; font-size: .875rem; color: var(--muted); }
.user-email-clickable {
    cursor: pointer;
    text-decoration: underline dotted;
    text-underline-offset: 2px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
}
.user-email-clickable:hover { color: var(--primary); }

/* Header avatar — smaller than message avatars, vertically centred in the header row */
.avatar.header-av {
    width: 32px;
    height: 32px;
    font-size: .65rem;
    flex-shrink: 0;
    align-self: center;
}

/* ── Connection dot ── */
.conn-dot {
    display: inline-block;
    width: 9px;
    height: 9px;
    border-radius: 50%;
    background: var(--border);
    margin-right: .45rem;
    vertical-align: middle;
    flex-shrink: 0;
    transition: background .3s;
}
.conn-dot--connected    { background: #22c55e; animation: none; }
.conn-dot--connecting   { background: #e53e3e; animation: conn-blink .7s ease-in-out infinite; }
.conn-dot--disconnected { background: #e53e3e; animation: none; }
@keyframes conn-blink {
    0%,100% { opacity: 1; }
    50%      { opacity: .2; }
}

/* ── Messages ── */
.no-chat-placeholder {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--text-muted, #999);
    font-size: .95rem;
    pointer-events: none;
}
.no-chat-placeholder[hidden] { display: none; }

.messages[hidden] { display: none; }

.messages {
    flex: 1;
    overflow-y: auto;
    scrollbar-gutter: stable;
    padding: 1rem calc(var(--gutter-w) + 0.75rem);
    /* room for the floating header that sits over the top of the area */
    padding-top: 76px;
    /* room for the floating composer that sits over the bottom of the area */
    padding-bottom: 84px;
    background-color: transparent;
    /* Fade messages out toward the top: as they scroll up past the floating
       header they become gradually more transparent (but never fully gone). */
    --top-fade-min: .15;   /* opacity at the edges — partial, not 0 */
    /* The fade is confined to the panel bands only: full opacity right at the
       inner edge of the header (~76px) and the composer (~84px), then a quick,
       sharp drop toward the screen edges. Mirrored top↔bottom. */
    -webkit-mask-image: linear-gradient(to bottom, rgba(0,0,0,var(--top-fade-min)) 0, #000 76px, #000 calc(100% - 84px), rgba(0,0,0,var(--top-fade-min)) 100%);
            mask-image: linear-gradient(to bottom, rgba(0,0,0,var(--top-fade-min)) 0, #000 76px, #000 calc(100% - 84px), rgba(0,0,0,var(--top-fade-min)) 100%);

    display: flex;
    flex-direction: column;
    gap: .75rem;
}

.message {
    display: flex;
    flex-direction: row;
    align-items: flex-end;   /* avatar stays at the bottom edge of the bubble */
    gap: .45rem;
    max-width: min(72%, 600px);
}
.message.own { align-self: flex-end; }
.message.grouped { margin-top: -0.45rem; }
.message.grouped .msg-header { display: none; }
.message.grouped > .avatar { visibility: hidden; }

/* Wraps header + bubble in a column (sits next to the avatar) */
.msg-body {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    min-width: 0;
}
.message.own .msg-body { align-items: flex-end; }

/* Message header: sender name + timestamp on the same line */
.msg-header {
    display: flex;
    align-items: baseline;
    gap: .4rem;
    padding: 0 .3rem;
    margin-bottom: .2rem;
}

/* Avatar circle (shown for other users' messages) */
.avatar {
    width: 36px;
    height: 36px;
    border-radius: 50%;
    object-fit: cover;
    flex-shrink: 0;
    cursor: pointer;
    transition: opacity .15s;
    border: 2px solid var(--border);
}
.avatar:hover { opacity: .8; }

.avatar.avatar-placeholder {
    background: var(--primary);
    color: #fff;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: .7rem;
    font-weight: 700;
    user-select: none;
    border-color: transparent;
}
.avatar.avatar-deleted {
    background: var(--surface);
    font-size: 1rem;
}

.sender {
    font-size: .75rem;
    font-weight: 600;
    color: var(--muted);
}

.clickable-sender {
    cursor: pointer;
    text-decoration: underline dotted;
    text-underline-offset: 2px;
}
.clickable-sender:hover { color: var(--primary); }


.bg-select {
    font-size: .8rem;
    padding: .3rem .4rem;
    border: 1px solid var(--border);
    border-radius: 6px;
    background: var(--surface);
    color: var(--text);
    cursor: pointer;
    outline: none;
    transition: border-color .15s;
    min-width: 0;
    max-width: 140px;
}
.bg-select:focus { border-color: var(--primary); }

.bg-range-wrap {
    display: flex;
    align-items: center;
    gap: .4rem;
    min-width: 0;
    flex: 1;
}
.bg-range {
    flex: 1;
    min-width: 60px;
    cursor: pointer;
    accent-color: var(--muted);
}
#bg-transparency-val {
    font-size: .78rem;
    color: var(--muted);
    min-width: 2.5rem;
}

.bg-color-input {
    width: 36px;
    height: 28px;
    padding: 1px 2px;
    border: 1px solid var(--border);
    border-radius: 6px;
    cursor: pointer;
    background: none;
}

.ui-settings-label {
    font-size: .8rem;
    font-weight: 700;
    color: var(--muted);
    padding: .25rem 0 .5rem;
}
.ui-subsection {
    width: 100%;
    border: 1px solid var(--border);
    border-radius: 8px;
    padding: .5rem .7rem;
    margin-bottom: .5rem;
    background: var(--input-bg, rgba(0,0,0,.02));
}
.ui-subsection-header {
    font-size: .72rem;
    font-weight: 700;
    letter-spacing: .03em;
    color: var(--muted);
    padding: .4rem 0 .25rem;
}

.avatar-deleted-notice {
    width: 100%;
    text-align: center;
    font-size: .85rem;
    color: var(--muted);
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: 8px;
    padding: .5rem 1rem;
}

.sender-deleted {
    background: var(--border);
    color: var(--muted);
    padding: .05rem .4rem;
    border-radius: 4px;
    text-decoration: none;
    font-style: italic;
}
.sender-deleted:hover { color: var(--muted); background: var(--border); }

.bubble {
    padding: .24rem .85rem .42rem;
    border-radius: 8px;
    font-size: 1.0625rem;
    line-height: 1.5;
    word-break: break-word;
    white-space: pre-wrap;   /* preserve newlines from Shift+Enter */
    background: var(--other-bubble);
    color: var(--other-text);
    overflow: hidden;
    min-width: 0;
}
.message.own .bubble {
    background: var(--own-bubble);
    color: var(--own-text);
    border-bottom-right-radius: 4px;
}
.message:not(.own) .bubble { border-bottom-left-radius: 4px; }

/* History messages appear slightly muted to distinguish them from live messages */

/* Long-message truncation: cap at 10 lines */
.bubble.collapsible {
    /* 10 lines × line-height (1.5em) + top + bottom padding (2 × .55rem) */
    max-height: calc(1.5em * 10 + 1.1rem);
    overflow: hidden !important;
}
/* Fade is only applied once checkCollapsible() confirms content actually overflows.
   This prevents the gradient from affecting bubbles whose content fits in 10 lines. */
.bubble.overflows {
    -webkit-mask-image: linear-gradient(to bottom, black 70%, transparent 100%);
    mask-image:         linear-gradient(to bottom, black 70%, transparent 100%);
}
.show-more-btn {
    background: none;
    border: none;
    padding: .2rem .3rem 0;
    width: auto;
    font-size: .8rem;
    font-weight: 600;
    color: var(--muted);
    opacity: .75;
    cursor: pointer;
    display: block;
    align-self: flex-start;   /* left-align inside msg-body column */
}
.message.own .show-more-btn { align-self: flex-end; }
.show-more-btn:hover:not(:disabled) { text-decoration: underline; background: none; }

/* Pending (optimistic) message — slightly faded while waiting for server ack */
.message.pending .bubble { opacity: .6; }
.message.pending .time::after { content: ' · sending…'; font-style: italic; }

/* System notices (Disconnected / Reconnected) */
.system-notice {
    align-self: center;
    font-size: .75rem;
    font-weight: 600;
    padding: .2rem .85rem;
    border-radius: 20px;
    background: var(--bg);
    border: 1px solid var(--border);
    color: var(--muted);
    user-select: none;
}
.system-notice-time {
    font-weight: 500;
    opacity: .7;
}
.system-notice.disconnected {
    background: var(--error-bg);
    border-color: var(--error-bd);
    color: var(--danger);
}
.system-notice.reconnected {
    background: var(--success-bg);
    border-color: var(--success-bd);
    color: #155724;
}

/* Quote blocks inside message bubbles (<q>…</q> in message text) */
.bubble .quote {
    display: block;
    margin: .2rem 0;
    padding: .2rem .6rem;
    border-left: 3px solid rgba(255,255,255,.55);
    background: rgba(0,0,0,.12);
    border-radius: 0 4px 4px 0;
    font-style: italic;
    font-size: .9em;
    word-break: break-word;
}
/* In "other" (grey) bubbles the accent uses the primary colour */
.message:not(.own) .bubble .quote {
    border-left-color: var(--primary);
    background: rgba(79,110,247,.08);
}

/* Text content wrapper — ensures img is never the CSS :only-child when text is present */
.bubble .msg-text { display: block; }

/* Telegram-style inline formatting inside bubbles */
.bubble strong { font-weight: 700; }
.bubble em     { font-style: italic; }
.bubble s      { opacity: .7; }
.bubble code {
    font-family: 'Courier New', Courier, monospace;
    font-size: .85em;
    background: rgba(0,0,0,.12);
    padding: .1em .35em;
    border-radius: 3px;
    word-break: break-all;
}
.message.own .bubble code { background: rgba(255,255,255,.2); }

/* Links inside message bubbles */
.bubble a {
    color: inherit;           /* white in own bubbles, dark in others */
    text-decoration: underline;
    text-underline-offset: 2px;
    word-break: break-all;
}
.bubble a:hover { opacity: .75; }

/* Meta row (edited label + timestamp) inside bubble */
.msg-meta {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: .35rem;
    margin-top: -.1rem;        /* text→date gap (looser so the date doesn't touch the text/link) */
    margin-right: -.44rem;     /* pull date toward the right edge */
    margin-bottom: -.385rem;   /* pull date toward the bottom edge */
    white-space: nowrap;
}
.msg-time {
    font-size: .68rem;
    color: currentColor;
    opacity: .6;
    white-space: nowrap;
}
/* `.time-inline` only marks short messages as non-collapsible (see chat.js); the date
   always sits on its own line below the text — identical block layout to multi-line
   messages, so single- and multi-line bubbles size and space the same way. No special
   flex layout needed here. */

/* ── Reply-quote block (first child inside .bubble for messages with replyTo) ── */
.reply-quote {
    background: rgba(0, 0, 0, .05);
    border-left: 3px solid rgba(0, 0, 0, .25);
    border-radius: 0 4px 4px 0;
    padding: .3rem .6rem;
    margin-bottom: .45rem;
    cursor: pointer;
    overflow: hidden;
    transition: background .12s;
}
.reply-quote:hover { background: rgba(0, 0, 0, .10); }
.reply-quote-sender {
    display: block;
    font-size: .72rem;
    font-weight: 700;
    color: inherit;
    opacity: .94;
    margin-bottom: .1rem;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.reply-quote-text {
    display: block;
    font-size: .8rem;
    opacity: .75;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.reply-quote-text.reply-quote-deleted {
    font-style: italic;
    opacity: .45;
}
/* Own messages have a blue bubble — lighten the quote border for contrast */
.message.own .reply-quote {
    background: rgba(0, 0, 0, .11);
    border-left-color: rgba(255, 255, 255, .45);
}
.message.own .reply-quote:hover { background: rgba(0, 0, 0, .19); }

/* A bubble holding a link preview always expands to the maximum message width
   (same cap as a long plain-text message: min(72%, 600px)), so the card spans the
   full width and the text wraps to match — no empty side gap, and preview messages
   are never narrower than regular ones. */
.bubble:has(.link-preview) {
    width: 600px;          /* the message max-width cap below trims this to min(72%, 600px) */
    max-width: 100%;
}

/* Compact (stored) preview bubbles must never exceed the message width. Their card
   has a nowrap title whose intrinsic width would otherwise stretch the bubble past
   the screen edge on narrow (mobile) viewports. Unlike the large .link-preview card
   above we don't force a fixed width — the bubble still shrinks to fit its content. */
.bubble:has(.stored-preview) {
    max-width: 100%;
}

/* ── YouTube link preview card (inside .bubble, above the text) ── */
.link-preview {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    /* Match the gap above the card to the bubble's side padding (.85rem) so the
       inset looks even on all sides; bubble's own top padding is only .24rem. */
    margin-top: .61rem;
    margin-bottom: .45rem;
    width: 100%;          /* fill the bubble so the card matches the text width */
    /* A lighter shade of the message bubble colour (see --preview-bg) so the card is
       related to the message but distinct, with well-contrasted dark text. */
    background: var(--preview-bg);
    border: 1px solid rgba(0, 0, 0, .08);
    border-radius: 8px;
    overflow: hidden;
    cursor: pointer;
    text-decoration: none;
    color: inherit;
    transition: background .12s;
}
.link-preview:hover { background: var(--preview-bg-hover); }
/* Own messages have a coloured bubble — adjust overlay for contrast */
.message.own .link-preview { background: rgba(0, 0, 0, .12); border-color: rgba(255, 255, 255, .18); }
.message.own .link-preview:hover { background: rgba(0, 0, 0, .18); }
/* The preview card is itself an anchor — override the generic `.bubble a` underline
   (higher specificity) so neither the card nor any links inside it are underlined.
   Covers both the YouTube card (.link-preview) and the compact card (.stored-preview). */
.bubble a.link-preview,
.bubble a.stored-preview,
.bubble .link-preview a,
.bubble .stored-preview a { text-decoration: none; }
.link-preview-info {
    display: flex;
    flex-direction: column;
    gap: .25rem;
    padding: .55rem .75rem;
    overflow: hidden;
    min-width: 0;
    /* Wrap by words, not letters — undo the break-all inherited from `.bubble a`. */
    word-break: normal;
    overflow-wrap: anywhere;
}
.link-preview-site {
    font-size: .8rem;
    font-weight: 700;
    color: #f00;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.message.own .link-preview-site { color: inherit; opacity: .9; }
.link-preview-title {
    font-size: .95rem;
    font-weight: 600;
    line-height: 1.3;
    color: inherit;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.link-preview-desc {
    font-size: .82rem;
    line-height: 1.4;
    color: inherit;
    opacity: .75;
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.link-preview-thumb {
    width: 100%;
    aspect-ratio: 16 / 9;
    object-fit: cover;
    background: #000;
    display: block;
}

/* ── Settings modal ── */
.settings-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: .5rem;
    padding: .45rem 0;
    font-size: .875rem;
    width: 100%;
    min-width: 0;
}
.settings-row > span:first-child {
    flex-shrink: 0;
    font-size: .72rem;
    font-weight: 700;
    letter-spacing: .03em;
    color: var(--muted);
}
.settings-row + .settings-row { border-top: 1px solid var(--border); }

/* Toggle switch */
.toggle-switch {
    position: relative;
    display: inline-block;
    width: 44px;
    height: 24px;
    flex-shrink: 0;
}
.toggle-switch input { opacity: 0; width: 0; height: 0; position: absolute; }
.toggle-slider {
    position: absolute;
    inset: 0;
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: 24px;
    cursor: pointer;
    transition: background .2s;
}
.toggle-slider::before {
    content: '';
    position: absolute;
    width: 18px;
    height: 18px;
    left: 3px;
    top: 3px;
    background: #fff;
    border-radius: 50%;
    transition: transform .2s;
    box-shadow: 0 1px 3px rgba(0,0,0,.3);
}
.toggle-switch input:checked + .toggle-slider { background: var(--border); }
.toggle-switch input:checked + .toggle-slider::before { transform: translateX(20px); }

/* ── Reply bar (shown in footer when composing a reply) ── */
.reply-bar[hidden] { display: none !important; }
.reply-bar {
    display: flex;
    align-items: center;
    gap: .5rem;
    padding: .4rem .9rem;
    background: var(--surface);
    border-bottom: 1px solid var(--border);
    font-size: .85rem;
    overflow: hidden;
}
.reply-bar-content {
    flex: 1;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    color: var(--muted);
}
.reply-bar-content strong { color: var(--primary); }
#reply-bar-cancel {
    background: none;
    border: none;
    width: auto;
    padding: .1rem .35rem;
    font-size: 1.15rem;
    line-height: 1;
    color: var(--muted);
    cursor: pointer;
    border-radius: 50%;
    flex-shrink: 0;
}
#reply-bar-cancel:hover { color: var(--text); background: var(--bg); }

/* ── Edit bar (inline, above input, replaces old edit modal) ── */
.edit-bar[hidden] { display: none !important; }
.edit-bar {
    display: flex;
    align-items: center;
    gap: .5rem;
    padding: .4rem .9rem;
    background: var(--surface);
    border-bottom: 1px solid var(--border);
    font-size: .85rem;
    overflow: hidden;
}
.edit-bar-content {
    flex: 1;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    color: var(--muted);
}
.edit-bar-label { font-weight: 600; color: var(--primary); }
#edit-bar-cancel {
    background: none;
    border: none;
    width: auto;
    padding: .1rem .35rem;
    font-size: 1.15rem;
    line-height: 1;
    color: var(--muted);
    cursor: pointer;
    border-radius: 50%;
    flex-shrink: 0;
}
#edit-bar-cancel:hover { color: var(--text); background: var(--bg); }

/* ── Send error bar (shown above input when message fails) ── */
.send-error-bar[hidden] { display: none !important; }
.send-error-bar {
    padding: .35rem .9rem;
    background: var(--error-bg);
    border-bottom: 1px solid var(--error-bd);
    color: var(--danger);
    font-size: .82rem;
    font-weight: 500;
}

/* ── Footer / input ── */
.chat-footer {
    position: absolute;          /* float over the messages — the message area is
                                    not bounded by the composer, it runs full height */
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 5;
    border: 1px solid var(--border);
    background: var(--bg);   /* slightly grey to separate from the message area */
    padding: .5rem;          /* equal frame thickness on all sides */
    margin: 0 calc(var(--gutter-w) + 0.75rem) .6rem;
    /* Concentric with .msg-input-wrap: inner radius (12px) + the panel padding,
       so the two curves look parallel / equally rounded. */
    border-radius: 20px;
    flex-shrink: 0;
}
.chat-footer form {
    display: flex;
    gap: .6rem;
    align-items: center;
}
.msg-input-wrap {
    flex: 1;
    min-width: 0;
    display: flex;
    align-items: center;
    border: 1px solid var(--border);
    border-radius: 12px;
    background: var(--surface);
    transition: border-color .15s;
}
.msg-input-wrap:focus-within { border-color: var(--primary); }
.chat-footer textarea {
    flex: 1;
    min-width: 0;
    min-height: 37px;   /* 20% tighter top/bottom space than the previous 46px */
    resize: none;
    overflow-x: hidden;
    overflow-y: visible;
    scrollbar-width: none;
    padding: 9px 8px 9px 8px;   /* 20% tighter top/bottom space */
    border: none;
    font-size: 1rem;
    font-family: inherit;
    line-height: 1.2;   /* 20% tighter than the previous 1.5 */
    outline: none;
    background: transparent;
    color: var(--text);
}
.chat-footer textarea::-webkit-scrollbar { display: none; }
.chat-footer button {
    width: auto;
    padding: .65rem 1.25rem;
    align-self: center;
}
#send-btn {
    height: 39px;            /* same height as the .msg-input-wrap (textarea 37px + 2px border) */
    border-radius: 12px;     /* same corner radius as the input row */
    padding-top: 0;
    padding-bottom: 0;
}

/* ── Emoji-insert button ── */
.chat-footer .msg-emoji-btn {
    flex-shrink: 0;
    align-self: center !important;
    width: 28px;
    height: 28px;
    margin-right: 4px;
    padding: 0;
    border: none;
    border-radius: 6px;
    background: none;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    line-height: 0;
    transition: background .12s, color .12s;
    color: var(--muted);
}
.msg-emoji-btn svg { width: 18px; height: 18px; flex-shrink: 0; display: block; }
.msg-emoji-btn:hover:not(:disabled) { background: var(--bg); color: var(--primary); }
.msg-emoji-btn:disabled { opacity: .3; cursor: not-allowed; }

/* ── Emoji insert picker popup ── */
.msg-emoji-picker {
    position: fixed;
    z-index: 400;
    display: flex;
    flex-wrap: wrap;
    gap: .12rem;
    padding: .45rem .45rem .65rem;
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: .6rem;
    box-shadow: 0 4px 16px rgba(0,0,0,.15);
    max-width: 264px;
    max-height: 210px;
    overflow-y: auto;
}
.msg-emoji-picker[hidden] { display: none !important; }

/* ── Chat title button ── */
.chat-title-btn {
    font-size: 1.15rem;
    cursor: pointer;
    user-select: none;
    padding: .2rem .5rem;
    margin: -.2rem -.5rem;
    border-radius: 6px;
    transition: background .15s;
    min-width: 0;
    overflow: hidden;
    display: flex;
    align-items: center;
    gap: .4rem;
}
/* Match the sidebar user section's hover (var(--bg)) rather than the lighter
   var(--surface) that previously washed out part of the header. */
.chat-title-btn:hover { background: var(--bg); }
#chat-header-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }

/* ── Chat info side panel (right) ── */
.chat-panel {
    position: fixed;
    top: 0;
    right: 0;
    width: 280px;
    height: 100dvh;
    background: var(--bg);
    border-left: 1px solid var(--border);
    box-shadow: -4px 0 var(--side-shadow);
    z-index: 200;
    display: flex;
    flex-direction: column;
    animation: panel-slide-in-right .2s ease;
    overflow-y: auto;
    overflow-x: hidden;
    /* Scrollbar hidden by default, revealed on hover. Keep `thin` (Firefox) /
       a fixed webkit width so the gutter is always reserved — only the thumb's
       colour toggles, so revealing it never shifts the panel content. */
    scrollbar-width: thin;
    scrollbar-color: transparent transparent;
}
.chat-panel:hover { scrollbar-color: var(--border) transparent; }
.chat-panel[hidden] { display: none; }
.chat-panel::-webkit-scrollbar { width: 3px; }
.chat-panel::-webkit-scrollbar-track { background: transparent; }
.chat-panel::-webkit-scrollbar-thumb { background: transparent; border-radius: 2px; }
.chat-panel:hover::-webkit-scrollbar-thumb { background: var(--border); }

/* Chat info block inside panel */
.chat-panel-info {
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: 1rem .28rem .5rem .4375rem;
    flex-shrink: 0;
    gap: .35rem;
    width: 100%;
    box-sizing: border-box;
}
.cp-chat-avatar {
    width: 192px;
    height: 192px;
    border-radius: 50%;
    background: var(--primary);
    color: #fff;
    font-size: 4.5rem;
    font-weight: 700;
    display: flex;
    align-items: center;
    justify-content: center;
    background-size: cover;
    background-position: center;
    margin-bottom: .25rem;
    border: 2px solid var(--border);
}
.cp-chat-desc {
    font-size: .85rem;
    color: var(--muted);
    text-align: center;
    margin: 0;
    line-height: 1.4;
}
.cp-desc-wrap { width: 100%; }
.cp-desc-textarea {
    width: 100%;
    box-sizing: border-box;
    padding: .3rem .4rem;
    border-radius: 6px;
    border: 1px solid var(--border);
    background: var(--bg);
    color: var(--text);
    font-size: .85rem;
    line-height: 1.4;
    resize: none;
    outline: none;
    font-family: inherit;
    text-align: left;
    cursor: pointer;
    transition: border-color .15s;
    display: block;
}
.cp-desc-textarea.editing {
    border-color: var(--primary);
    cursor: text;
    resize: vertical;
}
.cp-desc-save-btn,
.profile-save-btn {
    display: block;
    padding: .25rem .75rem;
    border-radius: 6px;
    border: none;
    background: var(--primary);
    color: #fff;
    font-size: .9rem;
    font-weight: 700;
    cursor: pointer;
    width: auto;
    transition: opacity .15s;
}
.cp-desc-save-btn { margin: .3rem 0 0 auto; }
.profile-save-btn { margin: .25rem 0 0; }
#profile-save-section { width: 100%; display: flex; justify-content: flex-end; }
.cp-desc-save-btn:hover, .profile-save-btn:hover { opacity: .85; }
.cp-desc-save-btn:disabled, .profile-save-btn:disabled { opacity: .5; cursor: default; }
.cp-desc-save-btn[hidden], .profile-save-btn[hidden] { display: none; }
.cp-chat-meta {
    font-size: .78rem;
    color: var(--muted);
    margin: 0;
}
.cp-loading {
    padding: .5rem 1.1rem;
    color: var(--muted);
    font-size: .85rem;
    list-style: none;
}
.cp-role-badge {
    font-size: .65rem;
    font-weight: 600;
    text-transform: uppercase;
    background: none;
    border: 1px solid var(--border);
    color: var(--muted);
    padding: .1rem .35rem;
    border-radius: 4px;
    flex-shrink: 0;
    margin-left: auto;
}
/* Right-click context menu for chat panel members */
#cp-member-ctx {
    position: fixed;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 8px;
    box-shadow: var(--shadow);
    z-index: 9999;
    min-width: 160px;
    padding: .3rem 0;
    display: none;
}
#cp-member-ctx.open { display: block; }
.cp-ctx-item {
    width: 100%;
    padding: .5rem .9rem;
    text-align: left;
    background: none;
    border: none;
    font-size: .875rem;
    color: var(--text);
    cursor: pointer;
    display: block;
    border-radius: 0;
    font-weight: 400;
}
.cp-ctx-item:hover { background: var(--bg); }
.cp-ctx-item.danger { color: var(--danger); }
.cp-ctx-item.danger:hover { background: var(--error-bg); }

.chat-panel-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 1rem .55rem .8rem;
    border-bottom: 1px solid var(--border);
    flex-shrink: 0;
    position: sticky;
    top: 0;
    background: var(--bg);
    z-index: 1;
}
.chat-panel-title {
    font-size: 1.05rem;
    font-weight: 700;
    color: var(--text);
}
.chat-panel-close {
    background: none;
    border: none;
    font-size: 1.3rem;
    line-height: 1;
    color: var(--muted);
    cursor: pointer;
    padding: .2rem .4rem;
    border-radius: 4px;
    width: auto;
}
.chat-panel-close:hover { background: var(--surface); color: var(--text); }
.chat-panel-section-label {
    padding: .75rem .625rem .35rem;
    font-size: .72rem;
    font-weight: 700;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--muted);
    flex-shrink: 0;
}
.chat-panel-users {
    list-style: none;
    margin: 0;
    padding: 0 .6rem;
    overflow-y: auto;
    flex: 1;
}
.chat-panel-user {
    display: flex;
    align-items: center;
    gap: .6rem;
    padding: .45rem .5rem;
    border-radius: 8px;
    font-size: .875rem;
    color: var(--text);
}
.chat-panel-user .cp-avatar {
    width: 32px;
    height: 32px;
    border-radius: 50%;
    background: var(--surface);
    background-size: cover;
    background-position: center;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: .75rem;
    font-weight: 700;
    color: var(--muted);
    flex-shrink: 0;
}
.chat-panel-user .cp-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.online-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    flex-shrink: 0;
}
.online-dot.online  { background: #22c55e; }
.online-dot.offline { background: var(--border); }

/* ── Active sessions list ── */
.sessions-header {
    font-size: .8rem;
    font-weight: 700;
    color: var(--muted);
    margin-bottom: .5rem;
}
.sessions-list {
    list-style: none;
    margin: 0;
    padding: 0;
    width: 100%;
    display: flex;
    flex-direction: column;
    gap: .4rem;
    max-height: 200px;
    overflow-y: auto;
}
.session-item {
    display: flex;
    align-items: flex-start;
    gap: .5rem;
    background: var(--surface);
    border-radius: 8px;
    padding: .5rem .65rem;
    font-size: .78rem;
}
.session-item.current-session { border: 1px solid var(--muted); }
.session-meta { flex: 1; min-width: 0; }
.session-badge {
    font-size: .68rem;
    font-weight: 700;
    color: var(--muted);
    margin-bottom: .15rem;
}
.session-detail { color: var(--muted); line-height: 1.4; }
.session-revoke-btn {
    background: none;
    border: none;
    width: auto;
    padding: 0 .3rem;
    font-size: 1rem;
    line-height: 1;
    color: var(--muted);
    cursor: pointer;
    flex-shrink: 0;
    margin-top: .05rem;
}
.session-revoke-btn:hover { color: #e53e3e; }

/* ── User profile side panel (slides in from the right) ── */
.user-panel {
    position: fixed;
    top: 0;
    right: 0;
    width: 304px;
    height: 100dvh;
    background: var(--bg);
    border-left: 1px solid var(--border);
    box-shadow: -4px 0 var(--side-shadow);
    z-index: 200;
    display: flex;
    flex-direction: column;
    overflow-x: hidden;
    animation: panel-slide-in-right .2s ease;
}
.user-panel[hidden] { display: none; }
@keyframes panel-slide-in-right {
    from { transform: translateX(100%); opacity: 0; }
    to   { transform: translateX(0);   opacity: 1; }
}
.user-panel-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 1rem .55rem .8rem;
    border-bottom: 1px solid var(--border);
    flex-shrink: 0;
}
.user-panel-title {
    font-size: 1.05rem;
    font-weight: 700;
    color: var(--text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.user-panel-body {
    flex: 1;
    overflow-y: auto;
    overflow-x: hidden;
    min-height: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: .25rem;
    padding: 1rem .625rem 1rem;
    width: 100%;
    box-sizing: border-box;
}
.user-panel-body > * { flex-shrink: 0; }
.user-panel-body::-webkit-scrollbar { width: 4px; }
.user-panel-body::-webkit-scrollbar-track { background: transparent; }
.user-panel-body::-webkit-scrollbar-thumb { background: var(--border); border-radius: 2px; }
.user-panel-body { scrollbar-width: thin; scrollbar-color: var(--border) transparent; }

.user-panel-footer {
    flex-shrink: 0;
    padding: .75rem .625rem;
    border-top: 1px solid var(--border);
}

/* ── Shared modal base (all confirmation dialogs) ── */
#logout-modal,
#revoke-session-modal,
#leave-chat-modal,
#invite-delete-modal,
#ban-list-modal,
#ban-confirm-modal,
#remove-member-modal,
#invite-info-modal,
#new-chat-modal {
    border: none;
    border-radius: var(--radius);
    box-shadow: 0 8px 32px rgba(0,0,0,.18);
    padding: 0;
    max-width: 320px;
    width: 100%;
    background: var(--surface);
    position: fixed;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    margin: 0;
}
#logout-modal::backdrop,
#revoke-session-modal::backdrop,
#leave-chat-modal::backdrop,
#invite-delete-modal::backdrop,
#ban-list-modal::backdrop,
#ban-confirm-modal::backdrop,
#remove-member-modal::backdrop,
#invite-info-modal::backdrop,
#new-chat-modal::backdrop {
    background: rgba(0,0,0,.45);
}
#invite-info-modal { width: 780px; max-width: calc(100vw - 2rem); padding: 0; }
.invite-info-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: .85rem 1.1rem .7rem;
    border-bottom: 1px solid var(--border);
}
.invite-info-title {
    font-size: 1rem;
    font-weight: 700;
    color: var(--text);
}
.modal-x-btn {
    width: auto;
    padding: .1rem .45rem;
    font-size: 1.1rem;
    line-height: 1;
    background: none;
    border: none;
    color: var(--muted);
    cursor: pointer;
    border-radius: .35rem;
}
.modal-x-btn:hover:not(:disabled) { background: var(--bg); color: var(--text); }
.invite-info-body {
    padding: .75rem 1.1rem 1.1rem;
    width: 100%;
    box-sizing: border-box;
}
.invite-info-meta {
    display: flex;
    flex-direction: column;
    gap: .25rem;
    margin-bottom: .85rem;
    font-size: .85rem;
}
.invite-info-meta-row {
    display: flex;
    gap: .65rem;
}
.invite-info-meta-label {
    color: var(--muted);
    min-width: 5.5rem;
    flex-shrink: 0;
}
.invite-info-empty {
    color: var(--muted);
    font-size: .875rem;
    margin: 0;
}
.invite-info-table { width: 100%; border-collapse: collapse; font-size: .85rem; }
.invite-info-table th,
.invite-info-table td { padding: .35rem .5rem; text-align: left; border-bottom: 1px solid var(--border); }
.invite-info-table th { color: var(--muted); font-weight: 500; }
.invite-info-table tr:last-child td { border-bottom: none; }
.invite-info-av-cell { width: 32px; padding-right: 0 !important; }
.invite-info-av-cell .avatar,
.invite-info-av-cell .avatar-placeholder {
    width: 26px !important;
    height: 26px !important;
    font-size: .65rem !important;
    min-width: unset !important;
    cursor: pointer;
}
.invite-info-uid {
    word-break: break-all;
    font-size: .78rem;
    color: var(--muted);
}
.avatar-modal-inner {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 1rem;
    padding: 1.75rem 1.5rem 1.25rem;
}
.avatar-modal-inner h3 {
    font-size: 1.1rem;
    font-weight: 700;
    color: var(--text);
    word-break: break-word;
    text-align: center;
}
.avatar-modal-preview {
    width: 128px;
    height: 128px;
    border-radius: 50%;
    overflow: hidden;
    border: 3px solid var(--border);
    background: var(--bg);
    display: flex;
    align-items: center;
    justify-content: center;
}
/* Avatar image in the modal — rendered via background-image so the raw
   data URL is never visible as text content in the DOM. */
.avatar-modal-img {
    width: 100%;
    height: 100%;
    background-size: cover;
    background-position: center;
    background-repeat: no-repeat;
}
.avatar-modal-placeholder {
    width: 100%;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--primary);
    color: #fff;
    font-size: 2.5rem;
    font-weight: 700;
    border-radius: 50%;
    user-select: none;
}
.avatar-modal-placeholder.avatar-modal-deleted {
    background: var(--surface);
    font-size: 3rem;
}
#avatar-upload-section {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: .2rem;
    width: 100%;
}
.avatar-file-label {
    display: inline-block;
    cursor: pointer;
    padding: .5rem 1rem;
    border: 1px dashed var(--border);
    border-radius: 8px;
    font-size: .875rem;
    color: var(--muted);
    transition: border-color .15s, color .15s;
    text-align: center;
    flex: 1;
}
.avatar-file-label:hover { border-color: var(--primary); color: var(--primary); }
.avatar-file-label input[type="file"] { display: none; }
.avatar-file-name {
    font-size: .8rem;
    color: var(--muted);
    text-align: center;
    word-break: break-word;
}
.avatar-bio-text[data-empty="true"] {
    color: var(--muted);
    font-style: italic;
}
.avatar-bio-text[data-empty="true"]::before { content: "No bio yet."; }
.avatar-bio-text {
    font-size: .875rem;
    color: var(--text);
    line-height: 1.45;
    word-break: break-word;
    white-space: pre-wrap;
    width: 100%;
    box-sizing: border-box;
    margin: .5rem 0 0;
    padding: .45rem .6rem;
    border: 1px solid var(--border);
    border-radius: 8px;
    min-height: 60px;
}
#avatar-username-section,
#avatar-bio-section,
#avatar-sessions-section,
#avatar-settings-section,
#avatar-ui-settings-section { width: 100%; }
.avatar-bio-textarea {
    width: 100%;
    box-sizing: border-box;
    resize: vertical;
    min-height: 72px;
    padding: .45rem .6rem;
    border: 1px solid var(--border);
    border-radius: 8px;
    background: var(--input-bg, var(--bg));
    color: var(--text);
    font-size: .875rem;
    font-family: inherit;
    line-height: 1.45;
    transition: border-color .15s;
}
.avatar-bio-textarea:focus { outline: none; border-color: var(--primary); }
.avatar-bio-footer {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-top: .3rem;
}

/* ── Logout confirm modal ── */
.modal-body-text {
    font-size: .95rem;
    color: var(--muted);
    text-align: center;
    line-height: 1.5;
}
.modal-actions {
    display: flex;
    flex-direction: row;
    gap: .6rem;
    width: 100%;
    justify-content: flex-end;
}
#logout-confirm-btn,
.danger-btn {
    background: var(--danger);
}
#logout-confirm-btn:hover:not(:disabled),
.danger-btn:hover:not(:disabled) {
    background: #a93226;
}

/* ── Message context menu (right-click on own messages) ── */
#msg-context-menu {
    display: none;
    position: fixed;
    z-index: 1000;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 8px;
    box-shadow: var(--shadow);
    padding: .3rem 0;
    min-width: 140px;
}
#msg-context-menu button {
    display: block;
    width: 100%;
    padding: .55rem 1rem;
    border: none;
    border-radius: 0;
    background: transparent;
    color: var(--text);
    font-size: .9rem;
    font-weight: 500;
    text-align: left;
    cursor: pointer;
    transition: background .1s;
}
#msg-context-menu button:hover {
    background: var(--bg);
}
#ctx-edit-btn {
    border-top: 1px solid var(--border);
    margin-top: 2px;
    padding-top: .55rem;
}
#ctx-delete-btn {
    color: var(--danger) !important;
}

#delete-modal {
    border: none;
    border-radius: var(--radius);
    box-shadow: 0 8px 32px rgba(0,0,0,.18);
    padding: 0;
    max-width: 320px;
    width: 100%;
    background: var(--surface);
    position: fixed;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    margin: 0;
}
#delete-modal::backdrop {
    background: rgba(0,0,0,.45);
}
#edit-textarea:focus {
    border-color: var(--primary);
}

/* ── "Edited" label inside bubble, left of timestamp ── */
.edited-label {
    font-size: .68rem;
    font-style: italic;
    opacity: .6;
}

/* ── Stored link preview card ── */
.stored-preview {
    display: flex;
    flex-direction: row;
    align-items: stretch;
    margin-top: -.55rem;
    margin-left: -.85rem;
    margin-right: -.85rem;
    margin-bottom: .5rem;
    border-bottom: 1px solid var(--border);
    border-radius: .45rem .45rem 0 0;
    overflow: hidden;
    text-decoration: none;
    color: inherit;
    background: var(--preview-bg);
    transition: background .12s;
}
.stored-preview:hover { background: var(--preview-bg-hover); }
.sp-body {
    flex: 1;
    min-width: 0;
    padding: .8rem .6rem .45rem;
    display: flex;
    flex-direction: column;
    gap: .18rem;
    /* Wrap by words, not letters — undo the break-all inherited from `.bubble a`. */
    word-break: normal;
    overflow-wrap: anywhere;
}
.sp-site  { font-size: .7rem; color: var(--primary); text-transform: uppercase; letter-spacing: .04em; }
.sp-title { font-size: .85rem; font-weight: 600; color: var(--text); line-height: 1.3;
            white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sp-desc  { font-size: .76rem; color: var(--muted); line-height: 1.35;
            display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.sp-image {
    flex-shrink: 0;
    width: 80px;
    height: 80px;
    object-fit: cover;
    display: block;
    border-left: 1px solid var(--border);
}

/* ── Reaction pills ── */
.reaction-pills {
    display: flex;
    flex-wrap: wrap;
    gap: .25rem;
    padding: 0;
    margin-top: .4rem;
}
.reaction-pill {
    display: inline-flex;
    align-items: center;
    gap: .2rem;
    padding: .15rem .45rem;
    border-radius: 1rem;
    border: 1px solid rgba(0,0,0,0.1);
    background: rgba(255,255,255,0.55);
    font-size: .82rem;
    font-weight: normal;
    color: var(--text);
    width: auto;
    cursor: pointer;
    line-height: 1.3;
    transition: background .15s, border-color .15s;
}
.reaction-pill:hover { background: rgba(255,255,255,0.8); border-color: rgba(0,0,0,0.15); }
.reaction-pill.own   { background: rgba(255,255,255,0.78); border-color: rgba(0,0,0,0.14); }
.message.own .reaction-pill {
    background: rgba(255,255,255,0.18);
    border-color: rgba(255,255,255,0.22);
    color: rgba(255,255,255,0.9);
}
.message.own .reaction-pill:hover {
    background: rgba(255,255,255,0.28);
    border-color: rgba(255,255,255,0.35);
}
.message.own .reaction-pill.own {
    background: rgba(255,255,255,0.32);
    border-color: rgba(255,255,255,0.45);
    color: #fff;
}
body.dark .reaction-pill {
    background: rgba(255,255,255,0.07);
    border-color: rgba(255,255,255,0.1);
    color: var(--text);
}
body.dark .reaction-pill:hover { background: rgba(255,255,255,0.13); }
body.dark .reaction-pill.own   { background: rgba(255,255,255,0.14); border-color: rgba(255,255,255,0.18); }

/* ── Context menu "X reacted" button ── */
#msg-context-menu #ctx-reactions-btn {
    display: flex;
    align-items: center;
    gap: .4rem;
}
.ctx-reaction-avatars {
    display: flex;
    align-items: center;
    flex-shrink: 0;
}
.ctx-reaction-avatar {
    width: 21px;
    height: 21px;
    border-radius: 50%;
    border: 1.5px solid var(--surface);
    object-fit: cover;
    background: var(--primary);
    color: #fff;
    font-size: .6rem;
    line-height: 18px;
    text-align: center;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    margin-left: -5px;
    flex-shrink: 0;
    overflow: hidden;
    vertical-align: middle;
}
.ctx-reaction-avatars .ctx-reaction-avatar:first-child { margin-left: 0; }
.ctx-reaction-label { color: var(--muted); }

/* ── Reactions popover ── */
.reactions-popover {
    position: fixed;
    z-index: 500;
    width: 280px;
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: .75rem;
    box-shadow: 0 6px 24px rgba(0,0,0,.18);
    display: flex;
    flex-direction: column;
    overflow: hidden;
}
.reactions-popover[hidden] { display: none !important; }
body.dark .reactions-popover {
    background: #2a2d3e;
    border-color: #3d4060;
    box-shadow: 0 6px 24px rgba(0,0,0,.5);
    animation: update-banner-pulse-dark 3s ease-in-out infinite;
}
.reactions-modal-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: .75rem 1rem .5rem;
    border-bottom: 1px solid var(--border);
}
.reactions-modal-title { font-weight: 700; font-size: 1rem; color: var(--text); }
#reactions-modal-close {
    width: auto;
    padding: .1rem .45rem;
    font-size: 1.15rem;
    line-height: 1;
    background: none;
    border: none;
    color: var(--muted);
    cursor: pointer;
    border-radius: .35rem;
}
#reactions-modal-close:hover { background: var(--surface); color: var(--text); }
.reactions-tabs {
    display: flex;
    flex-wrap: wrap;
    gap: .3rem;
    padding: .6rem .8rem .4rem;
    border-bottom: 1px solid var(--border);
}
.reactions-tab {
    width: auto;
    padding: .25rem .6rem;
    border-radius: 1rem;
    font-size: .85rem;
    font-weight: normal;
    color: var(--text);
    background: var(--surface);
    border: 1px solid var(--border);
    cursor: pointer;
    transition: background .12s, border-color .12s;
}
.reactions-tab:hover { background: var(--bg); border-color: var(--primary); }
.reactions-tab.active { background: color-mix(in srgb, var(--primary) 12%, transparent); border-color: var(--primary); font-weight: 600; }
.reactions-tab-content {
    display: flex;
    flex-direction: column;
    gap: .1rem;
    padding: .5rem;
    max-height: 260px;
    overflow-y: auto;
}
.reactions-user-row {
    display: flex;
    align-items: center;
    gap: .65rem;
    padding: .35rem .5rem;
    border-radius: .4rem;
}
.reactions-user-row:hover { background: var(--surface); }
.reactions-user-row.own { background: color-mix(in srgb, var(--primary) 8%, transparent); }
.reactions-user-av { width: 32px !important; height: 32px !important; font-size: .8rem; flex-shrink: 0; }
.reactions-user-name { font-size: .9rem; color: var(--text); }

/* ── Image lightbox ── */
.lightbox {
    position: fixed;
    inset: 0;
    z-index: 900;
    background: rgba(0,0,0,.75);
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: zoom-out;
}
.lightbox[hidden] { display: none !important; }
.lightbox-img {
    max-width: 80vw;
    max-height: 80vh;
    object-fit: contain;
    border-radius: .5rem;
    box-shadow: 0 8px 40px rgba(0,0,0,.6);
    cursor: default;
}

/* ── Emoji picker popover ── */
.emoji-picker {
    position: fixed;
    z-index: 300;
    display: flex;
    flex-wrap: wrap;
    gap: .2rem;
    padding: .45rem;
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: .6rem;
    box-shadow: 0 4px 16px rgba(0,0,0,.15);
    max-width: 240px;
}
.emoji-picker[hidden] { display: none !important; }
.emoji-pick-btn {
    display: block;
    text-align: center;
    background: none;
    border: none;
    width: 2rem;
    height: 34px;
    line-height: 34px;
    padding: 0;
    font-size: 1.15rem;
    overflow: visible;
    cursor: pointer;
    border-radius: .35rem;
    transition: background .1s;
}
.emoji-pick-btn:hover { background: var(--surface); }
body.dark .emoji-pick-btn:hover { background: #2a2a2a; }

/* ── Image attach button (label wrapping a hidden file input) ── */
.attach-btn {
    flex-shrink: 0;
    align-self: center;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    margin-left: 6px;
    padding: 0;
    border: none;
    border-radius: 6px;
    cursor: pointer;
    font-size: 1.1rem;
    line-height: 1;
    color: var(--muted);
    background: none;
    transition: background .12s, color .12s;
    user-select: none;
}
.attach-btn:hover { background: var(--bg); color: var(--primary); }
.attach-btn input[type="file"] { display: none; }

/* ── Image preview area above the send form ── */
.image-preview-area[hidden] { display: none !important; }
.image-preview-area {
    display: flex;
    flex-wrap: wrap;
    gap: .5rem;
    padding: .5rem 0 .4rem;
}

.image-preview-item {
    position: relative;
    width: 72px;
    height: 72px;
    border-radius: 8px;
    overflow: hidden;
    border: 1px solid var(--border);
    flex-shrink: 0;
}

.image-preview-thumb {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

.image-remove-btn {
    position: absolute;
    top: 2px;
    right: 2px;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    border: none;
    background: rgba(0, 0, 0, .55);
    color: #fff;
    font-size: .85rem;
    line-height: 1;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    transition: background .15s;
}
.image-remove-btn:hover { background: rgba(0,0,0,.8); }

/* ── Videos attached to a message ── */
.msg-videos {
    display: flex;
    flex-direction: column;
    gap: .4rem;
}
.bubble .msg-videos {
    margin: -.55rem -.85rem 0;
    padding-bottom: .75rem;
    overflow: hidden;
    border-radius: 10px 10px 0 0;
}
.bubble .msg-videos:only-child { border-radius: 10px; margin-bottom: -.55rem; padding-bottom: 0; }
.msg-video {
    width: 100%;
    max-width: 480px;
    max-height: 360px;
    display: block;
    background: #000;
    border-radius: 0;
    outline: none;
}

/* Video preview thumbnails in the footer attachment area */
.video-preview-item {
    position: relative;
    width: 80px;
    height: 60px;
    border-radius: 6px;
    overflow: hidden;
    border: 1px solid var(--border);
    background: #111;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}
.video-preview-icon { font-size: 1.5rem; line-height: 1; user-select: none; }
.video-preview-name {
    position: absolute;
    bottom: 0; left: 0; right: 0;
    background: rgba(0,0,0,.6);
    color: #fff;
    font-size: .6rem;
    padding: 1px 3px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.video-preview-item .image-remove-btn { z-index: 2; }
.video-preview-item .image-upload-overlay { border-radius: 6px; }

/* ── Images attached to a message (rendered above the text bubble) ── */
.msg-images {
    display: flex;
    flex-wrap: wrap;
    gap: .4rem;
    margin-bottom: .35rem;
}

/* Images inside a bubble — break out of horizontal padding for full-bleed look */
.bubble .msg-images {
    margin: -.55rem -.85rem 0;
    padding-bottom: .75rem;
    gap: 2px;
    overflow: hidden;
    border-radius: 10px 10px 0 0;
}
.bubble .msg-images:only-child { border-radius: 10px; margin-bottom: -.55rem; padding-bottom: 0; }
.bubble .msg-images .msg-image {
    flex: 1 1 45%;
    min-width: 80px;
    max-width: 100%;
    max-height: 400px;
    height: auto;
    object-fit: contain;
    align-self: flex-start;
    background: var(--surface);
    border-radius: 0;
    border: none;
}

/* 2+ images: even, gap-free grid (Telegram-style). Cells are square and the
   image is cropped to fill (cover), so differing aspect ratios never leave an
   empty area in the bubble. */
.bubble .msg-images-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 2px;
}
.bubble .msg-images-grid .msg-image {
    flex: none;
    min-width: 0;
    width: 100%;
    height: 100%;
    max-width: none;
    max-height: none;
    aspect-ratio: 1 / 1;
    object-fit: cover;
    align-self: stretch;
    border-radius: 0;
}
/* Odd counts: the last image spans the full width as a wide tile */
.bubble .msg-images-grid.count-3 .msg-image:nth-child(3),
.bubble .msg-images-grid.count-5 .msg-image:nth-child(5) {
    grid-column: 1 / -1;
    aspect-ratio: 2 / 1;
}

.msg-image {
    max-width: 220px;
    max-height: 220px;
    border-radius: 8px;
    object-fit: cover;
    display: block;
    cursor: pointer;
    border: 1px solid rgba(0,0,0,.1);
    transition: opacity .15s;
}
.msg-image:hover { opacity: .88; }

/* ── Avatar modal — username-change section ── */
.avatar-section-divider {
    width: 100%;
    border: none;
    border-top: 1px solid var(--border);
    margin: .1rem 0 .25rem;
}
.avatar-username-field {
    width: 100%;
    display: flex;
    flex-direction: column;
    gap: .35rem;
}
.avatar-username-row {
    display: flex;
    gap: .4rem;
    align-items: center;
}

.avatar-username-confirm-btn {
    width: 36px;
    height: 36px;
    padding: 0;
    flex-shrink: 0;
    border-radius: 8px;
    font-size: 1.1rem;
    font-weight: 700;
    background: var(--primary);
    color: #fff;
    border: none;
    cursor: pointer;
    transition: background .15s;
}
.avatar-username-confirm-btn:disabled {
    background: var(--border);
    color: var(--muted);
    cursor: not-allowed;
    opacity: 1;
}
.avatar-username-confirm-btn:hover:not(:disabled) { background: var(--primary-dk); }

.avatar-username-field input[type="text"] {
    width: 100%;
    padding: .55rem .8rem;
    border: 1px solid var(--border);
    border-radius: 8px;
    font-size: .95rem;
    font-family: inherit;
    outline: none;
    background: var(--surface);
    color: var(--text);
    transition: border-color .15s;
}
.avatar-username-field input[type="text"]:focus { border-color: var(--primary); }

/* ── Image upload overlay (spinner while uploading, warning on failure) ── */
.image-upload-overlay {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 8px;
    pointer-events: none;   /* let the remove button stay clickable */
}
.image-upload-overlay.uploading {
    background: rgba(0, 0, 0, .45);
}
.image-upload-overlay.failed {
    background: rgba(160, 0, 0, .6);
}

.image-upload-spinner {
    width: 22px;
    height: 22px;
    border: 3px solid rgba(255, 255, 255, .35);
    border-top-color: #fff;
    border-radius: 50%;
    animation: img-spin .7s linear infinite;
}
@keyframes img-spin {
    to { transform: rotate(360deg); }
}

.image-upload-error-icon {
    color: #fff;
    font-size: 1.15rem;
    font-weight: 700;
    line-height: 1;
    text-shadow: 0 1px 3px rgba(0,0,0,.5);
}

/* ── Chat header avatar ── */
.chat-header-av-wrap {
    display: inline-flex;
    align-items: center;
    margin-right: .4rem;
    flex-shrink: 0;
}
.chat-header-av {
    width: 41px;
    height: 41px;
    border-radius: 50%;
    background: var(--primary);
    color: #fff;
    font-size: .8rem;
    font-weight: 700;
    display: flex;
    align-items: center;
    justify-content: center;
    background-size: cover;
    background-position: center;
    transition: opacity .15s;
}
.chat-header-av-wrap:hover .chat-header-av { opacity: .75; }

/* ── Crop modal ── */
.crop-canvas-wrap {
    display: flex;
    justify-content: center;
    user-select: none;
    touch-action: none;
    cursor: grab;
}
.crop-canvas-wrap:active { cursor: grabbing; }
#crop-canvas { display: block; border-radius: 8px; max-width: 100%; }
.crop-controls {
    display: flex;
    align-items: center;
    gap: .5rem;
    width: 100%;
}
.crop-zoom-slider {
    flex: 1;
    accent-color: var(--muted);
    cursor: pointer;
}

/* ── New-chat avatar picker ── */
.new-chat-av-picker {
    width: 128px;
    height: 128px;
    border-radius: 50%;
    background: var(--bg);
    border: 3px solid var(--border);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 2.25rem;
    transition: opacity .15s;
    background-size: cover;
    background-position: center;
    overflow: hidden;
}
.new-chat-av-picker:hover { opacity: .8; }
.new-chat-av-icon { pointer-events: none; }
/* Fields span the full modal width so Name and Access line up at equal width */
#new-chat-modal .field { width: 100%; }
#new-chat-access { max-width: none; width: 100%; }

/* ── Chat panel header actions (... menu) ── */
.chat-panel-header-actions {
    display: flex;
    align-items: center;
    gap: .25rem;
    position: relative;
}
.chat-panel-menu-btn {
    background: none;
    border: none;
    font-size: 1.1rem;
    line-height: 1;
    color: var(--muted);
    cursor: pointer;
    padding: .2rem .5rem;
    border-radius: 4px;
    letter-spacing: .1em;
    width: auto;
}
.chat-panel-menu-btn:hover { background: var(--surface); color: var(--text); }
.chat-panel-dropdown {
    position: absolute;
    top: calc(100% + 4px);
    right: 28px;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 8px;
    box-shadow: var(--shadow);
    z-index: 9999;
    min-width: 160px;
    padding: .3rem 0;
}
.chat-panel-dropdown[hidden] { display: none; }
.cp-dropdown-item {
    width: 100%;
    padding: .5rem .9rem;
    text-align: left;
    background: none;
    border: none;
    font-size: .875rem;
    color: var(--text);
    cursor: pointer;
    display: block;
    border-radius: 0;
    font-weight: 400;
}
.cp-dropdown-item:hover { background: var(--bg); }
.cp-dropdown-item.danger { color: var(--danger); }
.cp-dropdown-item.danger:hover { background: var(--error-bg); }
.cp-dropdown-item[hidden] { display: none; }

/* ── Admin settings row in chat panel ── */
.cp-settings-section { margin: .5rem 0; }
.cp-settings-section-label {
    padding: .25rem .625rem;
    font-size: .72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .05em;
    color: var(--muted);
}
.cp-settings-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: .45rem .625rem;
    font-size: .85rem;
    color: var(--text);
    gap: 1rem;
}
.cp-settings-row > span { flex: 1; }
.cp-ban-btn-wrap {
    padding: .5rem .625rem;
    border-top: 1px solid var(--border);
    flex-shrink: 0;
}
.cp-ban-btn-wrap[hidden] { display: none; }
.cp-ban-btn {
    width: 100%;
    padding: .45rem .9rem;
    background: none;
    border: 1px solid var(--border);
    border-radius: 8px;
    font-size: .825rem;
    color: var(--text);
    cursor: pointer;
    text-align: left;
}
.cp-ban-btn:hover { background: var(--bg); }

/* ── Unread messages divider ── */
.update-banner {
    position: fixed;
    bottom: .75rem;
    left: .75rem;
    width: 228px;
    background: var(--surface);
    color: var(--text);
    border: 1px solid var(--border);
    border-radius: .5rem;
    padding: 1.1rem .9rem 1.25rem;
    font-size: .84rem;
    display: flex;
    flex-direction: column;
    gap: .9rem;
    box-shadow: 0 4px 20px rgba(0,0,0,.22);
    z-index: 9999;
}
.update-banner span:first-child {
    font-weight: 500;
    padding-right: 1.2rem;
}
.update-banner button {
    background: var(--primary);
    border: none;
    color: #fff;
    padding: .352rem .85rem;
    border-radius: .35rem;
    cursor: pointer;
    font-size: .81rem;
    font-weight: 600;
    align-self: flex-start;
}
.update-banner button:hover { background: var(--primary-dk); }
.update-banner-dismiss {
    position: absolute;
    top: .38rem;
    right: .5rem;
    cursor: pointer;
    font-size: .85rem;
    line-height: 1;
    color: var(--muted);
}
.update-banner-dismiss:hover { color: var(--text); }
body.dark .update-banner {
    background: #2a2d3e;
    border-color: #3d4060;
    box-shadow: 0 4px 24px rgba(0,0,0,.5);
}

@keyframes update-banner-pulse {
    0%, 100% { background: var(--surface); }
    50%       { background: color-mix(in srgb, var(--primary) 12%, var(--surface)); }
}
@keyframes update-banner-pulse-dark {
    0%, 100% { background: #2a2d3e; }
    50%       { background: #373b54; }
}
.update-banner {
    animation: update-banner-pulse 3s ease-in-out infinite;
}
body.dark .update-banner {
    animation: update-banner-pulse-dark 3s ease-in-out infinite;
}

/* ── Blocked-account overlay ── */
.blocked-overlay {
    position: fixed;
    inset: 0;
    z-index: 9999;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(0, 0, 0, 0.92);
    backdrop-filter: blur(4px);
}
.blocked-overlay[hidden] { display: none !important; }
.blocked-card {
    text-align: center;
    padding: 2.5rem 2rem;
    max-width: 380px;
    color: #fff;
}
.blocked-icon {
    font-size: 3rem;
    margin-bottom: 1rem;
    line-height: 1;
}
.blocked-card h2 {
    font-size: 1.4rem;
    font-weight: 700;
    margin-bottom: .75rem;
}
.blocked-card p {
    font-size: .95rem;
    line-height: 1.6;
    color: rgba(255,255,255,.75);
}

.unread-divider {
    display: flex;
    align-items: center;
    gap: .6rem;
    margin: .6rem 0;
    padding: 0 var(--gutter-w);
    color: var(--danger);
    font-size: .75rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .05em;
}
.unread-divider::before,
.unread-divider::after {
    content: '';
    flex: 1;
    height: 1px;
    background: var(--danger);
    opacity: .4;
}

/* ── Older-history loading indicator ── */
.history-older-loading {
    text-align: center;
    padding: .5rem;
    font-size: .8rem;
    color: var(--muted);
    letter-spacing: .03em;
}

/* ── Ban list modal ── */
.ban-list-users {
    list-style: none;
    padding: 0;
    margin: .5rem 0 0;
    max-height: 280px;
    overflow-y: auto;
}
.ban-list-user {
    display: flex;
    align-items: center;
    gap: .6rem;
    padding: .4rem .2rem;
    font-size: .875rem;
    color: var(--text);
}
.ban-list-av {
    width: 32px;
    height: 32px;
    border-radius: 50%;
    background: var(--surface);
    background-size: cover;
    background-position: center;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: .75rem;
    font-weight: 700;
    color: var(--muted);
    flex-shrink: 0;
}
.ban-list-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ban-list-unban-btn {
    width: auto;
    background: none;
    border: 1px solid var(--border);
    border-radius: 6px;
    font-size: .75rem;
    padding: .2rem .5rem;
    color: var(--muted);
    cursor: pointer;
    flex-shrink: 0;
}
.ban-list-unban-btn:hover { background: var(--bg); color: var(--text); }

/* ── Join button — bottom bar, sits where the message composer would be ───── */
.join-footer {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 5;
    margin: 0 calc(var(--gutter-w) + 0.75rem) .6rem;
    display: flex;
    justify-content: center;
    pointer-events: none;   /* empty bar must not block the messages underneath */
}
.join-footer-btn {
    pointer-events: auto;
    width: fit-content;
    padding: .7rem 2.5em;   /* ~2× the text width */
    border-radius: 20px;
    border: none;
    background: var(--danger);
    color: #fff;
    font-size: .9rem;
    font-weight: 600;
    cursor: pointer;
    transition: opacity .15s;
    white-space: nowrap;
}
.join-footer-btn:hover { opacity: .85; }
.join-footer-btn:disabled { opacity: .5; cursor: default; }
.join-footer-btn[hidden] { display: none; }

/* ── Floating "scroll to latest" button ───────────────────────────────────── */
.scroll-bottom-btn {
    position: absolute;
    right: calc(var(--gutter-w) + 1rem);
    bottom: 92px;   /* sits just above the floating composer */
    z-index: 6;
    width: 42px;
    height: 42px;
    border-radius: 50%;
    border: 1px solid var(--border);
    background: var(--surface);
    color: var(--text);
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    box-shadow: 0 2px 10px rgba(0, 0, 0, .22);
    opacity: 0;
    transform: translateY(8px) scale(.9);
    transition: opacity .15s ease, transform .15s ease;
    pointer-events: none;
}
.scroll-bottom-btn.visible {
    opacity: 1;
    transform: translateY(0) scale(1);
    pointer-events: auto;
}
.scroll-bottom-btn:hover { background: var(--bg); }
.scroll-bottom-btn {
    font-size: 24px;
    line-height: 1;
    font-weight: 700;
    /* Thicken the arrow glyph (font-weight alone rarely affects symbol glyphs). */
    -webkit-text-stroke: 1.1px currentColor;
    /* Optically centre the glyph inside the round button. */
    text-align: center;
    padding: 0;
}
.scroll-bottom-btn[hidden] { display: none; }

.cp-avatar-hint {
    display: block;
    text-align: center;
    font-size: .75rem;
    color: var(--muted);
    margin-top: -.25rem;
    margin-bottom: .5rem;
}

/* ── Profile single save button ─────────────────────────────────────────── */

.cp-av-wrap { display: flex; flex-direction: column; align-items: center; gap: .3rem; }
.cp-name-input,
.cp-name-input:focus,
p.cp-name-input,
body.dark .cp-name-input,
body.dark .cp-name-input:focus,
body.dark p.cp-name-input {
    width: 100%;
    box-sizing: border-box;
    padding: .3rem .5rem;
    border: none !important;
    background: transparent !important;
    box-shadow: none !important;
    color: var(--text);
    font-size: .95rem;
    font-weight: 700;
    text-align: center;
    outline: none;
    font-family: inherit;
    cursor: text;
}

/* ── Sidebar user section ───────────────────────────────────────────────── */
.sidebar-user-section {
    display: flex;
    align-items: center;
    gap: .65rem;
    padding: .7rem .9rem;
    border-bottom: 1px solid var(--border);
    cursor: pointer;
    flex-shrink: 0;
    transition: background .12s;
}
.sidebar-user-section:hover { background: var(--bg); }
.sidebar-user-av {
    width: 39px;
    height: 39px;
    border-radius: 50%;
    background: var(--primary);
    color: #fff;
    font-size: .8rem;
    font-weight: 700;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    background-size: cover;
    background-position: center;
}
.sidebar-user-name {
    font-size: .875rem;
    font-weight: 600;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* ── User panel opened from the left (sidebar) ──────────────────────────── */
.user-panel.left-side {
    right: auto;
    left: 0;
    border-left: none;
    border-right: 1px solid var(--border);
    box-shadow: 4px 0 var(--side-shadow);
    animation: panel-slide-in-left .2s ease;
    width: 260px;
}
@keyframes panel-slide-in-left {
    from { transform: translateX(-100%); opacity: 0; }
    to   { transform: translateX(0);     opacity: 1; }
}

/* Active/Banned tab toggle — a compact segmented control sitting in the
   "Users" section header (mirrors the "+ New" button in the Invite links header). */
.cp-tabs { display: flex; gap: .2rem; flex-shrink: 0; }
.cp-tabs[hidden] { display: none; }
.cp-tab {
    width: auto;
    padding: .2rem .55rem;
    font-size: .78rem;
    font-weight: 500;
    background: transparent;
    color: var(--muted);
    border: 1px solid var(--border);
    border-radius: 6px;
    cursor: pointer;
    transition: background .15s, color .15s, border-color .15s;
}
.cp-tab[hidden] { display: none; }
.cp-tab:hover:not(:disabled) { background: var(--surface); color: var(--text); }
.cp-tab.active { background: var(--surface); color: var(--primary); font-weight: 600; border-color: var(--primary); }

/* ── Invite links section ── */
/* Framed like the "Settings" section: a label + button header above a
   rounded .ui-subsection card (no full-bleed top-border breakout). */
.cp-invite-section { width: 100%; }
.cp-invite-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: .5rem; }
.cp-invite-list { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: .4rem; max-height: 210px; overflow-y: auto; }
.cp-invite-item {
    padding: .4rem .6rem;
    border: 1px solid var(--border);
    border-radius: 7px;
    cursor: context-menu;
    transition: background .12s;
}
.cp-invite-item:hover { background: var(--surface); }
.cp-invite-revoked { opacity: .5; }
.cp-invite-top { display: flex; align-items: center; gap: .4rem; flex-wrap: wrap; }
.cp-invite-token { font-size: .75rem; font-family: monospace; color: var(--text); word-break: break-all; }
.cp-invite-badge {
    font-size: .68rem; font-weight: 600; padding: .1rem .35rem;
    border-radius: 4px; background: var(--danger, #e53e3e); color: #fff;
}
.cp-invite-meta { font-size: .72rem; color: var(--muted); margin-top: .2rem; }
.cp-invite-ctx {
    position: fixed; z-index: 9999;
    background: var(--surface); border: 1px solid var(--border);
    border-radius: 8px; box-shadow: 0 4px 16px rgba(0,0,0,.15);
    padding: .3rem; display: flex; flex-direction: column; min-width: 160px;
}
.cp-invite-ctx button {
    width: 100%; text-align: left; background: transparent; color: var(--text);
    border: none; border-radius: 6px; padding: .45rem .75rem; font-size: .88rem;
    font-weight: 400; cursor: pointer;
}
.cp-invite-ctx button:hover { background: var(--bg); }
.cp-invite-ctx button.danger-item { color: var(--danger, #e53e3e); }

/* ── Users section (Active / Banned) — framed like the Invite links section ── */
.cp-users-section { width: 100%; padding: .7rem .28rem .75rem .4375rem; flex-shrink: 0; }
.cp-users-section[hidden] { display: none; }
.cp-users-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: .5rem;
    margin-bottom: .5rem;
}
.cp-users-subsection { padding: .25rem .35rem; max-height: 260px; overflow-y: auto; }
.cp-users-subsection .chat-panel-users { padding: 0; overflow-y: visible; flex: unset; }
.cp-members-section[hidden] { display: none; }

/* ── Hamburger sidebar toggle (hidden on desktop) ── */
.sidebar-toggle {
    display: none;
    background: none;
    border: none;
    font-size: 1.3rem;
    line-height: 1;
    padding: .3rem .45rem;
    margin-right: .25rem;
    color: var(--text);
    cursor: pointer;
    border-radius: 6px;
    flex-shrink: 0;
}
.sidebar-toggle:hover { background: var(--surface); }

/* ── Sidebar backdrop (mobile only) ── */
.sidebar-backdrop {
    display: none;
}

/* ── Mobile layout ── */
@media (max-width: 640px) {
    /* Edge-to-edge on mobile: collapse the decorative side gutters entirely so the
       message area spans the full screen width. Every side layer (blur/anim layers,
       gradient border, system-row padding) derives from --gutter-w, so zeroing it
       removes all of them at once. */
    :root, body.dark { --gutter-w: 0px; }

    /* Hamburger sits flush to the left edge; trim vertical padding ~10% to shorten the bar.
       Mirror the mobile floating composer: small inset + 18px radius. */
    .chat-header { padding-left: .35rem; padding-right: .6rem; padding-top: .5rem; padding-bottom: .5rem; margin: .4rem .4rem 0; border-radius: 18px; }
    .sidebar-toggle { display: flex; align-items: center; justify-content: center; flex: 0 0 40px; margin-right: 0; }

    /* Avatar + chat name left-aligned right after the hamburger (no centering spacer) */
    .chat-header h2 { margin: 0; justify-content: flex-start; }
    .chat-header::after { content: none; }

    /* Sidebar: hidden off-screen by default, slides in as overlay */
    .chat-sidebar {
        position: fixed;
        left: 0;
        top: 0;
        bottom: 0;
        z-index: 200;
        transform: translateX(-100%);
        transition: transform .25s ease;
        box-shadow: 4px 0 20px rgba(0,0,0,.18);
    }
    .chat-sidebar.open { transform: none; }

    /* Dim backdrop behind the open sidebar */
    .sidebar-backdrop {
        display: block;
        position: fixed;
        inset: 0;
        z-index: 199;
        background: rgba(0,0,0,.4);
        opacity: 0;
        pointer-events: none;
        transition: opacity .25s ease;
    }
    .sidebar-backdrop.visible {
        opacity: 1;
        pointer-events: auto;
    }

    /* Chat panel (right info panel): full screen */
    .chat-panel { width: 100vw; }

    /* User profile panel: full screen */
    .user-panel { width: 100vw; }

    /* Message bubbles: allow wider */
    .message { max-width: min(88%, 600px); }

    /* Messages area: use the full screen width (drop the wide desktop gutters).
       Mobile scrollbars are overlay (zero-width), so don't reserve a stable
       gutter — it only adds a lopsided strip on the right that makes the
       right-aligned own messages look like they spill past the edge. */
    .messages {
        padding-left: .5rem;
        padding-right: .5rem;
        padding-top: 60px;      /* room for the floating header */
        padding-bottom: 64px;   /* room for the floating composer */
        scrollbar-gutter: auto;
        -webkit-mask-image: linear-gradient(to bottom, rgba(0,0,0,var(--top-fade-min)) 0, #000 60px, #000 calc(100% - 64px), rgba(0,0,0,var(--top-fade-min)) 100%);
                mask-image: linear-gradient(to bottom, rgba(0,0,0,var(--top-fade-min)) 0, #000 60px, #000 calc(100% - 64px), rgba(0,0,0,var(--top-fade-min)) 100%);
    }

    /* Footer: rounded floating card, compact height, minimal empty space around the input */
    .chat-footer {
        padding: .4rem;        /* equal frame thickness on all sides */
        margin: 0 .4rem .4rem;
        border-radius: 18px;   /* concentric with the 12px input on mobile padding */
    }
    .chat-footer textarea {
        min-height: 30px;
        padding-top: 6px;
        padding-bottom: 6px;
    }
    #send-btn { height: 38px; }   /* match the input row (36px touch targets + 2px border) */

    /* Footer: larger touch targets */
    .attach-btn  { width: 36px; height: 36px; font-size: 1.15rem; margin-left: 2px; }
    .chat-footer .msg-emoji-btn { width: 36px; height: 36px; margin-right: 2px; }
    .msg-emoji-btn svg { width: 22px; height: 22px; }
    #send-btn { padding-left: 1rem; padding-right: 1rem; }

    /* Single image: go full bubble width on mobile */
    .msg-image { max-width: 100%; max-height: 60vw; }

    /* All confirmation dialogs: fit the screen */
    #logout-modal,
    #revoke-session-modal,
    #leave-chat-modal,
    #invite-delete-modal,
    #ban-list-modal,
    #ban-confirm-modal,
    #remove-member-modal,
    #delete-modal { max-width: calc(100vw - 2rem); }

    /* Crop modal canvas: don't overflow */
    #crop-canvas { max-width: calc(100vw - 3rem); }

    /* Invite info modal already has max-width: calc(100vw - 2rem) */
}

/* ── Image-only message: timestamp overlaid on image ── */
.msg-images.msg-images-only {
    position: relative;
}
.msg-time-overlay {
    position: absolute;
    bottom: 6px;
    right: 8px;
    background: rgba(0,0,0,.45);
    color: #fff;
    font-size: .65rem;
    padding: .15rem .45rem;
    border-radius: 999px;
    white-space: nowrap;
    pointer-events: none;
    backdrop-filter: blur(2px);
}
