/* QChat mobile polish v1
 * Fixes dynamic mobile viewport/auth scrolling, chat composer spacing,
 * single-photo message lane overflow, and profile-blog composer layout.
 */

/* Dynamic browser toolbars (Yandex/Chrome/Android): keep auth scroll area inside
   the visible viewport instead of the legacy 100vh layout viewport. */
@media (max-width: 767.98px) {
    #authSection {
        height: 100vh;
        min-height: 100vh;
        max-height: 100vh;
        overflow-y: auto !important;
        overflow-x: hidden !important;
        overscroll-behavior-y: contain;
        -webkit-overflow-scrolling: touch;
        padding-bottom: calc(28px + env(safe-area-inset-bottom, 0px)) !important;
        scroll-padding-bottom: calc(92px + env(safe-area-inset-bottom, 0px));
        box-sizing: border-box;
    }

    @supports (height: 100dvh) {
        #authSection {
            height: 100dvh;
            min-height: 100dvh;
            max-height: 100dvh;
        }
    }

    #authSection .row.justify-content-center {
        margin-left: 0;
        margin-right: 0;
    }

    #authSection .row.justify-content-center > [class*="col-"] {
        width: 100%;
        max-width: 620px;
        padding-left: 10px;
        padding-right: 10px;
    }

    #registerSubmitBtn {
        min-height: 42px;
        scroll-margin-bottom: calc(96px + env(safe-area-inset-bottom, 0px));
    }

    /* Give the chat input a little breathing room above Android navigation/browser UI. */
    #messagingTab .qchat-chat-column .card-body > .p-2.border-top {
        flex: 0 0 auto !important;
        padding: 8px 10px calc(10px + env(safe-area-inset-bottom, 0px)) !important;
        background: var(--bs-body-bg, #fff);
        position: relative;
        z-index: 4;
    }

    /* The voice button is appended dynamically after Send. A grid keeps all five
       controls aligned and prevents the mic from hanging below/right of the row. */
    #message_div.qchat-composer {
        display: grid !important;
        grid-template-columns: 38px 38px minmax(0, 1fr) auto 38px;
        gap: 6px !important;
        align-items: end !important;
        width: 100% !important;
        min-width: 0 !important;
        margin: 0 !important;
    }

    #message_div.qchat-composer > #uploadFileBtn,
    #message_div.qchat-composer > #emojiToggleBtn,
    #message_div.qchat-composer > #voiceRecordBtn {
        width: 38px !important;
        min-width: 38px !important;
        max-width: 38px !important;
        height: 40px !important;
        min-height: 40px !important;
        max-height: 40px !important;
        padding: 0 !important;
        margin: 0 !important;
        display: inline-flex !important;
        align-items: center !important;
        justify-content: center !important;
        align-self: end !important;
        border-radius: 9px !important;
        box-sizing: border-box !important;
    }

    #message_div.qchat-composer > #voiceRecordBtn {
        border: 1px solid transparent !important;
    }

    #message_div.qchat-composer > #messageInput {
        width: 100% !important;
        min-width: 0 !important;
        max-width: 100% !important;
        min-height: 40px !important;
        margin: 0 !important;
        border-radius: 9px !important;
        box-sizing: border-box !important;
    }

    #message_div.qchat-composer > #sendMessageBtn,
    #message_div.qchat-composer > button#sendMessageBtn.btn,
    .input-group.qchat-composer#message_div > #sendMessageBtn {
        width: auto !important;
        min-width: 82px !important;
        max-width: 104px !important;
        height: 40px !important;
        min-height: 40px !important;
        max-height: 40px !important;
        flex: none !important;
        margin: 0 !important;
        padding: 0.375rem 0.65rem !important;
        border-radius: 9px !important;
        align-self: end !important;
    }

    /* Bootstrap input-group normally merges borders using negative margins.
       The grid layout intentionally uses separated touch targets. */
    #message_div.qchat-composer > .btn,
    #message_div.qchat-composer > .form-control {
        margin-left: 0 !important;
    }

    /* Single-photo messages: reserve avatar width inside the lane instead of
       asking a 100%-wide bubble and the avatar to coexist in the same row. */
    #messagesContainer .message:has([data-qchat-single-image="1"]) > .d-flex,
    #messagesContainer .message:has(.qchat-file-bundle-grid-images[data-file-group-count="1"]) > .d-flex {
        width: 100% !important;
        max-width: 100% !important;
        min-width: 0 !important;
        padding-left: 4px !important;
        padding-right: 4px !important;
        box-sizing: border-box !important;
        overflow: visible !important;
    }

    #messagesContainer .message:has([data-qchat-single-image="1"]) .message-bubble,
    #messagesContainer .message:has(.qchat-file-bundle-grid-images[data-file-group-count="1"]) .message-bubble {
        flex: 1 1 0 !important;
        width: auto !important;
        max-width: calc(100% - 36px) !important;
        min-width: 0 !important;
        box-sizing: border-box !important;
    }

    #messagesContainer .message:has([data-qchat-single-image="1"]) .message-avatar,
    #messagesContainer .message:has(.qchat-file-bundle-grid-images[data-file-group-count="1"]) .message-avatar,
    #messagesContainer .message:has([data-qchat-single-image="1"]) .avatar-placeholder.encrypted-message-avatar,
    #messagesContainer .message:has(.qchat-file-bundle-grid-images[data-file-group-count="1"]) .avatar-placeholder.encrypted-message-avatar {
        flex: 0 0 30px !important;
        width: 30px !important;
        min-width: 30px !important;
        max-width: 30px !important;
        height: 30px !important;
        min-height: 30px !important;
        max-height: 30px !important;
        margin-left: 0 !important;
        margin-right: 0 !important;
        box-sizing: border-box !important;
    }

    /* Public profile/blog composer: on phones, text gets its own full row and
       actions get a second row. This avoids the narrow textarea/overlapping Publish button. */
    #profileBlogComposerInputGroup.qchat-profile-blog-composer-input,
    #profileBlogComposer .qchat-profile-blog-composer-input {
        display: grid !important;
        grid-template-columns: 40px 40px minmax(0, 1fr) auto 40px;
        grid-template-areas:
            "input input input input input"
            "attach emoji spacer send voice";
        gap: 8px !important;
        align-items: center !important;
        width: 100% !important;
        min-width: 0 !important;
    }

    #profileBlogAttachFileBtn {
        grid-area: attach;
    }

    #profileBlogEmojiToggleBtn {
        grid-area: emoji;
    }

    #profileBlogInput {
        grid-area: input;
        width: 100% !important;
        min-width: 0 !important;
        max-width: 100% !important;
        min-height: 42px !important;
        margin: 0 !important;
        border-radius: 9px !important;
        box-sizing: border-box !important;
    }

    #createProfileBlogPostBtn {
        grid-area: send;
        width: auto !important;
        min-width: 104px !important;
        max-width: 124px !important;
        min-height: 40px !important;
        margin: 0 !important;
        padding: 0.375rem 0.65rem !important;
        border-radius: 9px !important;
        white-space: nowrap !important;
    }

    #profileBlogVoiceRecordBtn {
        grid-area: voice;
    }

    #profileBlogAttachFileBtn,
    #profileBlogEmojiToggleBtn,
    #profileBlogVoiceRecordBtn {
        width: 40px !important;
        min-width: 40px !important;
        max-width: 40px !important;
        height: 40px !important;
        min-height: 40px !important;
        max-height: 40px !important;
        padding: 0 !important;
        margin: 0 !important;
        display: inline-flex !important;
        align-items: center !important;
        justify-content: center !important;
        border-radius: 9px !important;
        box-sizing: border-box !important;
    }

    #profileBlogComposerInputGroup > .btn,
    #profileBlogComposerInputGroup > .form-control {
        margin-left: 0 !important;
    }

    #profileBlogComposer .profile-blog-composer-meta {
        gap: 6px 10px !important;
        flex-wrap: wrap !important;
        align-items: flex-start !important;
    }

    #profileBlogComposer .profile-blog-attachments-hint {
        margin-left: auto;
        max-width: min(78%, 330px);
        text-align: right;
        line-height: 1.25;
    }
}

@media (max-width: 380px) {
    #message_div.qchat-composer {
        grid-template-columns: 36px 36px minmax(0, 1fr) auto 36px;
        gap: 4px !important;
    }

    #message_div.qchat-composer > #uploadFileBtn,
    #message_div.qchat-composer > #emojiToggleBtn,
    #message_div.qchat-composer > #voiceRecordBtn {
        width: 36px !important;
        min-width: 36px !important;
        max-width: 36px !important;
    }

    #message_div.qchat-composer > #sendMessageBtn,
    #message_div.qchat-composer > button#sendMessageBtn.btn {
        min-width: 76px !important;
        max-width: 92px !important;
        padding-left: 0.45rem !important;
        padding-right: 0.45rem !important;
    }

    #profileBlogComposerInputGroup.qchat-profile-blog-composer-input,
    #profileBlogComposer .qchat-profile-blog-composer-input {
        grid-template-columns: 38px 38px minmax(0, 1fr) auto 38px;
        gap: 6px !important;
    }

    #profileBlogAttachFileBtn,
    #profileBlogEmojiToggleBtn,
    #profileBlogVoiceRecordBtn {
        width: 38px !important;
        min-width: 38px !important;
        max-width: 38px !important;
    }

    #createProfileBlogPostBtn {
        min-width: 96px !important;
        max-width: 108px !important;
        padding-left: 0.5rem !important;
        padding-right: 0.5rem !important;
    }
}

/* QChat mobile polish v2
 * Dynamic app viewport, stable media/avatar rows, and touch gallery affordances.
 */
@media (max-width: 767.98px) {
    /* The original mobile layout used calc(100vh - 150px). On Android browsers
       with movable top/bottom chrome that can place the composer below the
       actually visible viewport. Make the authenticated app a real flex column
       bound to the dynamic viewport instead. */
    #appSection:not(.hidden) {
        display: flex !important;
        flex-direction: column !important;
        height: 100vh !important;
        max-height: 100vh !important;
        min-height: 0 !important;
        overflow: hidden !important;
    }

    @supports (height: 100dvh) {
        #appSection:not(.hidden) {
            height: 100dvh !important;
            max-height: 100dvh !important;
        }
    }

    #appSection > .app-header,
    #appSection > #keyStatus,
    #appSection > #appMessage,
    #appSection > #appTabs {
        flex: 0 0 auto !important;
    }

    #appSection > .tab-content {
        flex: 1 1 0 !important;
        height: auto !important;
        min-height: 0 !important;
        overflow: hidden !important;
    }

    #messagingTab,
    #messagingTab > .row,
    #messagingTab .qchat-chat-column.active,
    #messagingTab .qchat-chat-column.active > .card,
    #messagingTab .qchat-chat-column.active > .card > .card-body {
        height: 100% !important;
        min-height: 0 !important;
        max-height: 100% !important;
    }

    #messagingTab > .row {
        margin-left: 0 !important;
        margin-right: 0 !important;
    }

    #messagingTab .qchat-chat-column.active {
        padding-left: 0 !important;
        padding-right: 0 !important;
        overflow: hidden !important;
    }

    #messagesContainer {
        flex: 1 1 0 !important;
        min-height: 0 !important;
        margin-bottom: 0 !important;
        overscroll-behavior-y: contain;
        -webkit-overflow-scrolling: touch;
    }

    #messagingTab .qchat-chat-column .card-body > .p-2.border-top {
        padding-bottom: calc(12px + env(safe-area-inset-bottom, 0px)) !important;
    }

    /* Direct image rows should size to their media instead of occupying the full
       86% mobile lane. That keeps the avatar attached to the bubble and prevents
       it from looking detached/off-lane for different album geometries. */
    #messagesContainer .message:has(.qchat-chat-image-tile):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex,
    #messagesContainer .message:has(.qchat-file-bundle-grid-images):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex {
        display: flex !important;
        flex-wrap: nowrap !important;
        width: fit-content !important;
        max-width: min(94%, calc(100% - 4px)) !important;
        min-width: 0 !important;
        align-items: flex-end !important;
        gap: 6px !important;
        box-sizing: border-box !important;
    }

    #messagesContainer .message.sent:has(.qchat-chat-image-tile):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex,
    #messagesContainer .message.sent:has(.qchat-file-bundle-grid-images):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex {
        margin-left: auto !important;
        margin-right: 0 !important;
        justify-content: flex-end !important;
    }

    #messagesContainer .message.received:has(.qchat-chat-image-tile):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex,
    #messagesContainer .message.received:has(.qchat-file-bundle-grid-images):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex {
        margin-left: 0 !important;
        margin-right: auto !important;
        justify-content: flex-start !important;
    }

    #messagesContainer .message:has(.qchat-chat-image-tile):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) .message-bubble,
    #messagesContainer .message:has(.qchat-file-bundle-grid-images):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) .message-bubble {
        flex: 0 1 auto !important;
        width: auto !important;
        max-width: calc(100% - 36px) !important;
        min-width: 0 !important;
        box-sizing: border-box !important;
    }

    #messagesContainer .message:has(.qchat-chat-image-tile):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) :is(.message-avatar, .avatar-placeholder.encrypted-message-avatar),
    #messagesContainer .message:has(.qchat-file-bundle-grid-images):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) :is(.message-avatar, .avatar-placeholder.encrypted-message-avatar) {
        flex: 0 0 30px !important;
        width: 30px !important;
        min-width: 30px !important;
        max-width: 30px !important;
        height: 30px !important;
        min-height: 30px !important;
        max-height: 30px !important;
        margin-left: 0 !important;
        margin-right: 0 !important;
    }

    /* The swipe helper uses pointer events. Keep vertical/pinch gestures available
       while reserving horizontal movement for previous/next navigation. */
    #chatImagePreviewModal :is(.chat-image-preview-body, .chat-image-preview-modal-img),
    #profileBlogImagePreviewModal :is(.profile-blog-image-preview-body, .profile-blog-image-preview-img) {
        touch-action: pan-y pinch-zoom;
        -webkit-user-select: none;
        user-select: none;
    }
}


/* QChat mobile polish v3
 * Clickable brand, canonical avatar side for sent messages, and compact
 * paper-plane actions on phones.
 */

/* Both the login brand and authenticated-app brand lead to the QChat root. */
.qchat-home-logo,
.qchat-home-logo:hover,
.qchat-home-logo:focus,
.qchat-home-logo:active {
    color: inherit;
    text-decoration: none !important;
}

.qchat-home-logo:focus-visible {
    outline: 2px solid var(--bs-primary, #0d6efd);
    outline-offset: 3px;
    border-radius: 6px;
}

/* The renderer already emits sent-message avatars AFTER the bubble and received
   avatars BEFORE it. Legacy CSS also reversed sent flex rows, which moved sent
   avatars to the left of photo/media bubbles. Keep the DOM order canonical on
   desktop and mobile. */
html body #messagesContainer .message.sent > .d-flex,
html body #messagesContainer .message.received > .d-flex {
    flex-direction: row !important;
    flex-wrap: nowrap !important;
    align-items: flex-end !important;
    gap: var(--qchat-message-row-gap, 6px) !important;
    overflow: visible !important;
}

html body #messagesContainer .message > .d-flex > :is(.message-avatar, .avatar-placeholder.encrypted-message-avatar, .avatar-placeholder.message-avatar) {
    flex-shrink: 0 !important;
    box-sizing: border-box !important;
}

/* Font Awesome replaces the <i> with an SVG but keeps qchat-send-icon. */
.qchat-send-action .qchat-send-icon {
    display: none;
}

@media (max-width: 767.98px) {
    .qchat-send-action .qchat-send-label {
        display: none !important;
    }

    .qchat-send-action .qchat-send-icon {
        display: inline-block !important;
        width: 1em;
        height: 1em;
    }

    /* Five compact controls leave the textarea the remaining width. */
    #message_div.qchat-composer {
        grid-template-columns: 38px 38px minmax(0, 1fr) 38px 38px !important;
    }

    #message_div.qchat-composer > #sendMessageBtn,
    #message_div.qchat-composer > button#sendMessageBtn.btn,
    .input-group.qchat-composer#message_div > #sendMessageBtn {
        width: 38px !important;
        min-width: 38px !important;
        max-width: 38px !important;
        padding: 0 !important;
        display: inline-flex !important;
        align-items: center !important;
        justify-content: center !important;
    }

    #profileBlogComposerInputGroup.qchat-profile-blog-composer-input,
    #profileBlogComposer .qchat-profile-blog-composer-input {
        grid-template-columns: 40px 40px minmax(0, 1fr) 40px 40px !important;
    }

    #createProfileBlogPostBtn {
        width: 40px !important;
        min-width: 40px !important;
        max-width: 40px !important;
        height: 40px !important;
        min-height: 40px !important;
        max-height: 40px !important;
        padding: 0 !important;
        display: inline-flex !important;
        align-items: center !important;
        justify-content: center !important;
    }

    /* Image/media rows must include the full avatar inside their available lane. */
    html body #messagesContainer .message:has(.qchat-chat-image-tile):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex,
    html body #messagesContainer .message:has(.qchat-file-bundle-grid-images):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex {
        overflow: visible !important;
        padding-left: 2px !important;
        padding-right: 2px !important;
    }

    html body #messagesContainer .message.sent:has(.qchat-chat-image-tile):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex,
    html body #messagesContainer .message.sent:has(.qchat-file-bundle-grid-images):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex {
        flex-direction: row !important;
    }

    html body #messagesContainer .message.received:has(.qchat-chat-image-tile):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex,
    html body #messagesContainer .message.received:has(.qchat-file-bundle-grid-images):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex {
        flex-direction: row !important;
    }

    html body #messagesContainer .message:has(.qchat-chat-image-tile):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) :is(.message-avatar, .avatar-placeholder.encrypted-message-avatar, .avatar-placeholder.message-avatar),
    html body #messagesContainer .message:has(.qchat-file-bundle-grid-images):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) :is(.message-avatar, .avatar-placeholder.encrypted-message-avatar, .avatar-placeholder.message-avatar) {
        flex: 0 0 30px !important;
        width: 30px !important;
        min-width: 30px !important;
        max-width: 30px !important;
        height: 30px !important;
        min-height: 30px !important;
        max-height: 30px !important;
        margin-left: 0 !important;
        margin-right: 0 !important;
    }
}

@media (max-width: 380px) {
    #message_div.qchat-composer {
        grid-template-columns: 36px 36px minmax(0, 1fr) 36px 36px !important;
    }

    #message_div.qchat-composer > #sendMessageBtn,
    #message_div.qchat-composer > button#sendMessageBtn.btn {
        width: 36px !important;
        min-width: 36px !important;
        max-width: 36px !important;
        padding: 0 !important;
    }

    #profileBlogComposerInputGroup.qchat-profile-blog-composer-input,
    #profileBlogComposer .qchat-profile-blog-composer-input {
        grid-template-columns: 38px 38px minmax(0, 1fr) 38px 38px !important;
    }

    #createProfileBlogPostBtn {
        width: 38px !important;
        min-width: 38px !important;
        max-width: 38px !important;
        padding: 0 !important;
    }
}


/* QChat mobile polish v4
 * Canonical sent-message geometry for every content type and stable metadata
 * alignment. Renderer DOM order is authoritative: sent = bubble, avatar;
 * received = avatar, bubble.
 */
html body #messagesContainer .message.sent:not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex,
html body #messagesContainer .message.sent:not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)):has(.qchat-audio-mini-player) > .d-flex,
html body #messagesContainer .message.sent:not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)):has(.qchat-audio-mini-group) > .d-flex,
html body #messagesContainer .message.sent:not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)):has(.qchat-file-bundle-group-audio) > .d-flex,
html body #messagesContainer .message.sent:not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)):has(.qchat-file-bundle-list-audio) > .d-flex {
    flex-direction: row !important;
    flex-wrap: nowrap !important;
    justify-content: flex-end !important;
    align-items: flex-end !important;
    margin-left: auto !important;
    margin-right: 0 !important;
    overflow: visible !important;
}

html body #messagesContainer .message.received:not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex {
    flex-direction: row !important;
    flex-wrap: nowrap !important;
    justify-content: flex-start !important;
    align-items: flex-end !important;
    margin-left: 0 !important;
    margin-right: auto !important;
    overflow: visible !important;
}

/* Sender metadata should stay visually attached to the outgoing bubble instead
   of stretching to the left edge of a wide file/media lane. */
html body #messagesContainer .message.sent:not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) .message-header {
    width: fit-content !important;
    max-width: 100% !important;
    margin-left: auto !important;
    margin-right: 0 !important;
    align-self: flex-end !important;
    text-align: right !important;
}

html body #messagesContainer .message.sent:not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) .message-footer {
    max-width: 100% !important;
}

/* Keep the right-side avatar completely inside the lane on narrow Android
   viewports, even when an image/file renderer uses width:100% internally. */
@media (max-width: 767.98px) {
    html body #messagesContainer .message.sent:not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) {
        padding-right: 3px !important;
        overflow: visible !important;
    }

    html body #messagesContainer .message.sent:not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex {
        width: 100% !important;
        max-width: 100% !important;
        min-width: 0 !important;
        padding-left: 2px !important;
        padding-right: 2px !important;
        box-sizing: border-box !important;
    }

    html body #messagesContainer .message.sent:not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex > .message-bubble {
        min-width: 0 !important;
        max-width: calc(100% - 36px) !important;
        box-sizing: border-box !important;
    }

    html body #messagesContainer .message.sent:not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex > :is(.message-avatar, .avatar-placeholder.encrypted-message-avatar, .avatar-placeholder.message-avatar) {
        flex: 0 0 30px !important;
        width: 30px !important;
        min-width: 30px !important;
        max-width: 30px !important;
        height: 30px !important;
        min-height: 30px !important;
        max-height: 30px !important;
        margin-left: 0 !important;
        margin-right: 0 !important;
    }
}


/* QChat mobile polish v6
 * Restore stable profile social actions, keep outgoing avatars on the right while
 * sender names use their original left alignment inside the bubble, and make
 * mobile tab labels visually symmetric.
 */

/* Outgoing avatar remains after the bubble (renderer DOM order), but metadata is
   aligned like the original message design: from the left edge of its own bubble.
   This prevents the sender name from drifting toward the chat lane edge. */
html body #messagesContainer .message.sent:not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) .message-header {
    width: 100% !important;
    max-width: 100% !important;
    margin-left: 0 !important;
    margin-right: 0 !important;
    align-self: stretch !important;
    text-align: left !important;
    overflow: hidden !important;
    box-sizing: border-box !important;
}

/* File/photo bubbles should shrink to their actual content on both desktop and
   mobile. The row itself remains right-aligned and still reserves the avatar. */
html body #messagesContainer .message.sent:has(.qchat-chat-image-tile):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex,
html body #messagesContainer .message.sent:has(.qchat-file-bundle-grid-images):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex,
html body #messagesContainer .message.sent:has(.qchat-file-bundle-preview-list):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex {
    width: fit-content !important;
    max-width: var(--qchat-message-lane-width, 50%) !important;
    min-width: 0 !important;
    margin-left: auto !important;
    margin-right: 0 !important;
    justify-content: flex-end !important;
    flex-direction: row !important;
    flex-wrap: nowrap !important;
    overflow: visible !important;
}

html body #messagesContainer .message.sent:has(.qchat-chat-image-tile):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex > .message-bubble,
html body #messagesContainer .message.sent:has(.qchat-file-bundle-grid-images):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex > .message-bubble,
html body #messagesContainer .message.sent:has(.qchat-file-bundle-preview-list):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex > .message-bubble {
    flex: 0 1 auto !important;
    width: fit-content !important;
    min-width: 0 !important;
    max-width: calc(100% - 38px) !important;
    box-sizing: border-box !important;
}

/* The profile action anchor is permanent in the profile header. Rendering a
   foreign profile only needs to populate it; own profile keeps it hidden. */
#profileSocialActions.qchat-profile-social-actions:not(.d-none),
#modalProfileSocialActions.qchat-profile-social-actions:not(.d-none) {
    display: flex !important;
    align-items: center !important;
    justify-content: center !important;
    gap: .4rem !important;
    flex-wrap: wrap !important;
}

@media (max-width: 767.98px) {
    html body #messagesContainer .message.sent:has(.qchat-chat-image-tile):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex,
    html body #messagesContainer .message.sent:has(.qchat-file-bundle-grid-images):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex,
    html body #messagesContainer .message.sent:has(.qchat-file-bundle-preview-list):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex {
        width: fit-content !important;
        max-width: calc(100% - 2px) !important;
        padding-left: 2px !important;
        padding-right: 2px !important;
    }

    /* Built-in mobile tabs use text labels only. Removing the invisible icon box
       makes the active tab's left/right visual padding truly equal. */
    #appTabs .nav-link:not(.qchat-external-profile-tab) {
        justify-content: center !important;
        gap: 0 !important;
        padding-left: .75rem !important;
        padding-right: .75rem !important;
        margin-left: 0 !important;
        margin-right: 0 !important;
        box-sizing: border-box !important;
    }

    #appTabs .nav-link:not(.qchat-external-profile-tab) > i,
    #appTabs .nav-link:not(.qchat-external-profile-tab) > .fas,
    #appTabs .nav-link:not(.qchat-external-profile-tab) > .far,
    #appTabs .nav-link:not(.qchat-external-profile-tab) > .fab {
        display: none !important;
        width: 0 !important;
        min-width: 0 !important;
        max-width: 0 !important;
        margin: 0 !important;
        padding: 0 !important;
    }

    #profileSocialActions.qchat-profile-social-actions:not(.d-none) {
        margin-top: .6rem !important;
        padding-left: 8px !important;
        padding-right: 8px !important;
    }
}

/* QChat mobile polish v7
 * Keep outgoing sender metadata on the same visual side as the outgoing avatar.
 * The bubble geometry from v6 stays unchanged; only the header alignment changes.
 */
html body #messagesContainer .message.sent:not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) .message-header {
    width: 100% !important;
    max-width: 100% !important;
    margin-left: 0 !important;
    margin-right: 0 !important;
    align-self: stretch !important;
    text-align: right !important;
    overflow: hidden !important;
    box-sizing: border-box !important;
}

/* QChat mobile polish v8
 * Hide only the top-level sender avatars in the chat timeline on phones.
 * Keep desktop/tablet avatars and avatars embedded in saved profile/blog cards.
 * Once the avatar is hidden, release the 30-38px space previously reserved by
 * mobile message/media geometry so bubbles can use the complete chat lane.
 */
@media (max-width: 767.98px) {
    html body #messagesContainer .message:not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment))
        > .d-flex
        > :is(.message-avatar, .avatar-placeholder.encrypted-message-avatar, .avatar-placeholder.message-avatar, .qchat-message-avatar-fallback) {
        display: none !important;
        flex: 0 0 0 !important;
        width: 0 !important;
        min-width: 0 !important;
        max-width: 0 !important;
        height: 0 !important;
        min-height: 0 !important;
        max-height: 0 !important;
        margin: 0 !important;
        padding: 0 !important;
        border: 0 !important;
        overflow: hidden !important;
    }

    html body #messagesContainer .message:not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex {
        gap: 0 !important;
    }

    html body #messagesContainer .message:not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment))
        > .d-flex
        > .message-bubble {
        min-width: 0 !important;
        max-width: 100% !important;
        box-sizing: border-box !important;
    }

    html body #messagesContainer .message.sent:not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) {
        padding-right: 0 !important;
    }

    html body #messagesContainer .message.sent:has(.qchat-chat-image-tile):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex > .message-bubble,
    html body #messagesContainer .message.sent:has(.qchat-file-bundle-grid-images):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex > .message-bubble,
    html body #messagesContainer .message.sent:has(.qchat-file-bundle-preview-list):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex > .message-bubble {
        max-width: 100% !important;
    }
}

/* QChat mobile polish v9
 * On phones, normal chat messages use the complete timeline width for both
 * outgoing and incoming directions. Sender avatars are already hidden by v8;
 * remove the remaining fit-content/95%/desktop lane constraints as well.
 * Saved profile/blog cards keep their own card geometry.
 */
@media (max-width: 767.98px) {
    html body #messagesContainer > .message:not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) {
        width: 100% !important;
        max-width: 100% !important;
        min-width: 0 !important;
        margin-left: 0 !important;
        margin-right: 0 !important;
        padding-left: 4px !important;
        padding-right: 4px !important;
        box-sizing: border-box !important;
    }

    html body #messagesContainer > .message.sent:not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex,
    html body #messagesContainer > .message.received:not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex,
    html body #messagesContainer > .message.qchat-sent-media-fit-row:not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex,
    html body #messagesContainer > .message:has(.qchat-chat-image-tile):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex,
    html body #messagesContainer > .message:has(.qchat-file-bundle-grid-images):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex,
    html body #messagesContainer > .message:has(.qchat-file-bundle-preview-list):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex,
    html body #messagesContainer > .message:has(.qchat-audio-mini-player):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex,
    html body #messagesContainer > .message:has(.qchat-audio-mini-group):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex,
    html body #messagesContainer > .message:has(.qchat-file-bundle-group-audio):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex,
    html body #messagesContainer > .message:has(.qchat-file-bundle-list-audio):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex {
        display: flex !important;
        width: 100% !important;
        max-width: 100% !important;
        min-width: 0 !important;
        flex: 1 1 100% !important;
        margin-left: 0 !important;
        margin-right: 0 !important;
        padding-left: 0 !important;
        padding-right: 0 !important;
        gap: 0 !important;
        box-sizing: border-box !important;
    }

    html body #messagesContainer > .message.sent:not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex,
    html body #messagesContainer > .message.received:not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex {
        justify-content: flex-start !important;
    }

    html body #messagesContainer > .message:not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex > .message-bubble,
    html body #messagesContainer > .message.qchat-sent-media-fit-row:not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex > .message-bubble {
        flex: 1 1 100% !important;
        width: 100% !important;
        max-width: 100% !important;
        min-width: 0 !important;
        margin-left: 0 !important;
        margin-right: 0 !important;
        box-sizing: border-box !important;
    }

    html body #messagesContainer > .message:not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) .message-content-wrapper,
    html body #messagesContainer > .message:not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) .message-content,
    html body #messagesContainer > .message:not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) .decrypted-file-content {
        width: 100% !important;
        max-width: 100% !important;
        min-width: 0 !important;
        box-sizing: border-box !important;
    }
}

/* QChat mobile polish v10
 * True full-width mobile chat lane. v9 widened the common direct-child path,
 * but legacy 75% message limits and compact-audio caps could still win in some
 * Android layouts. Apply the mobile lane to every normal sent/received message
 * regardless of intermediate wrappers and explicitly release media/audio caps.
 */
@media (max-width: 767.98px) {
    html body #messagesContainer {
        padding-left: 4px !important;
        padding-right: 4px !important;
    }

    html body #messagesContainer .message.sent,
    html body #messagesContainer .message.received {
        width: 100% !important;
        max-width: 100% !important;
        min-width: 0 !important;
        margin-left: 0 !important;
        margin-right: 0 !important;
        padding-left: 0 !important;
        padding-right: 0 !important;
        box-sizing: border-box !important;
    }

    html body #messagesContainer .message.sent > .d-flex,
    html body #messagesContainer .message.received > .d-flex,
    html body #messagesContainer .message.sent > .d-flex.w-100,
    html body #messagesContainer .message.received > .d-flex.w-100 {
        width: 100% !important;
        max-width: 100% !important;
        min-width: 0 !important;
        flex: 1 1 100% !important;
        margin: 0 !important;
        gap: 0 !important;
        box-sizing: border-box !important;
    }

    html body #messagesContainer .message.sent > .d-flex > .message-bubble,
    html body #messagesContainer .message.received > .d-flex > .message-bubble {
        width: 100% !important;
        max-width: 100% !important;
        min-width: 0 !important;
        flex: 1 1 100% !important;
        margin-left: 0 !important;
        margin-right: 0 !important;
        box-sizing: border-box !important;
    }

    html body #messagesContainer .message .message-content-wrapper,
    html body #messagesContainer .message .message-content,
    html body #messagesContainer .message .decrypted-file-content,
    html body #messagesContainer .message .qchat-file-bundle-message,
    html body #messagesContainer .message .qchat-file-bundle-groups,
    html body #messagesContainer .message .qchat-file-bundle-group,
    html body #messagesContainer .message .qchat-file-bundle-list,
    html body #messagesContainer .message .qchat-audio-mini-group,
    html body #messagesContainer .message .qchat-file-bundle-group-audio,
    html body #messagesContainer .message .qchat-file-bundle-list-audio {
        width: 100% !important;
        max-width: 100% !important;
        min-width: 0 !important;
        box-sizing: border-box !important;
    }

    html body #messagesContainer .message .qchat-audio-mini-player,
    html body #messagesContainer .message .qchat-audio-mini-player:hover,
    html body #messagesContainer .message .qchat-audio-mini-player:focus-within,
    html body #messagesContainer .message .qchat-audio-mini-player.playing,
    html body #messagesContainer .message .audio_card,
    html body #messagesContainer .message .qchat-audio-classic-player {
        width: 100% !important;
        max-width: none !important;
        min-width: 0 !important;
        box-sizing: border-box !important;
    }
}

/* QChat mobile polish v11 (QChat patch v17)
 * Edge-to-edge mobile message cards. Earlier rules widened the message lane,
 * but the bubble's own horizontal padding kept the visible card and embedded
 * audio player inset from the chat viewport. Make the visible bubble span the
 * entire message container while preserving readable padding for normal text.
 * Audio/file players get the full bubble width; their metadata/footer retain
 * their own padding instead of shrinking the player itself.
 */
@media (max-width: 767.98px) {
    html body #messagesContainer.message-container,
    html body #messagesContainer {
        padding-left: 0 !important;
        padding-right: 0 !important;
    }

    html body #messagesContainer > .message.sent:not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)),
    html body #messagesContainer > .message.received:not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) {
        width: 100% !important;
        max-width: 100% !important;
        min-width: 100% !important;
        margin-left: 0 !important;
        margin-right: 0 !important;
        padding-left: 0 !important;
        padding-right: 0 !important;
        border-radius: 0 !important;
    }

    html body #messagesContainer > .message.sent:not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex,
    html body #messagesContainer > .message.received:not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex,
    html body #messagesContainer > .message.sent:not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex > .message-bubble,
    html body #messagesContainer > .message.received:not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex > .message-bubble {
        width: 100% !important;
        max-width: 100% !important;
        min-width: 100% !important;
        flex: 1 1 100% !important;
        margin-left: 0 !important;
        margin-right: 0 !important;
        box-sizing: border-box !important;
    }

    /* The card itself reaches both sides; regular text keeps comfortable inner padding. */
    html body #messagesContainer > .message.sent:not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex > .message-bubble,
    html body #messagesContainer > .message.received:not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex > .message-bubble {
        padding-left: 0 !important;
        padding-right: 0 !important;
        border-radius: 0 !important;
    }

    html body #messagesContainer > .message.sent:not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) .message-content-wrapper,
    html body #messagesContainer > .message.received:not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) .message-content-wrapper {
        width: 100% !important;
        max-width: 100% !important;
        min-width: 0 !important;
        padding-left: .75rem !important;
        padding-right: .75rem !important;
        box-sizing: border-box !important;
    }

    /* Audio/file media must not inherit the text inset. Let the player itself use
       the complete message width and add padding only to textual metadata/footer. */
    html body #messagesContainer > .message:has(.qchat-audio-mini-player):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) .message-content-wrapper,
    html body #messagesContainer > .message:has(.qchat-audio-mini-group):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) .message-content-wrapper,
    html body #messagesContainer > .message:has(.qchat-file-bundle-group-audio):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) .message-content-wrapper,
    html body #messagesContainer > .message:has(.qchat-file-bundle-list-audio):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) .message-content-wrapper {
        padding-left: 0 !important;
        padding-right: 0 !important;
    }

    html body #messagesContainer > .message:has(.qchat-audio-mini-player):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) .qchat-audio-mini-player,
    html body #messagesContainer > .message:has(.qchat-audio-mini-group):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) .qchat-audio-mini-player,
    html body #messagesContainer > .message:has(.qchat-file-bundle-group-audio):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) .qchat-audio-mini-player,
    html body #messagesContainer > .message:has(.qchat-file-bundle-list-audio):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) .qchat-audio-mini-player,
    html body #messagesContainer > .message:has(.qchat-audio-mini-player):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) .qchat-file-bundle-message,
    html body #messagesContainer > .message:has(.qchat-audio-mini-player):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) .qchat-file-bundle-groups,
    html body #messagesContainer > .message:has(.qchat-audio-mini-player):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) .qchat-audio-mini-group {
        width: 100% !important;
        max-width: 100% !important;
        min-width: 100% !important;
        margin-left: 0 !important;
        margin-right: 0 !important;
        box-sizing: border-box !important;
    }

    html body #messagesContainer > .message:has(.qchat-audio-mini-player):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) .message-header,
    html body #messagesContainer > .message:has(.qchat-audio-mini-player):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) .message-footer,
    html body #messagesContainer > .message:has(.qchat-audio-mini-group):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) .message-header,
    html body #messagesContainer > .message:has(.qchat-audio-mini-group):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) .message-footer {
        padding-left: .75rem !important;
        padding-right: .75rem !important;
        box-sizing: border-box !important;
    }
}


/* QChat mobile polish v12 (QChat patch v18)
 * Keep edge-to-edge message cards, but use one canonical horizontal inset for
 * sender/header, normal text/captions and footer metadata. Audio remains truly
 * full-width by bleeding only the audio bundle through that inner inset.
 * Compact music metadata is forced into distinct vertical rows, and marquee
 * clones use an explicit margin so repeated text never visually concatenates.
 */
@media (max-width: 767.98px) {
    html body #messagesContainer {
        --qchat-mobile-message-inset: 12px;
    }

    /* One inset for every visible textual part of a normal chat message. */
    html body #messagesContainer > .message.sent:not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) .message-content-wrapper,
    html body #messagesContainer > .message.received:not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) .message-content-wrapper,
    html body #messagesContainer > .message:has(.qchat-audio-mini-player):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) .message-content-wrapper,
    html body #messagesContainer > .message:has(.qchat-audio-mini-group):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) .message-content-wrapper,
    html body #messagesContainer > .message:has(.qchat-file-bundle-group-audio):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) .message-content-wrapper,
    html body #messagesContainer > .message:has(.qchat-file-bundle-list-audio):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) .message-content-wrapper {
        padding-left: var(--qchat-mobile-message-inset) !important;
        padding-right: var(--qchat-mobile-message-inset) !important;
        box-sizing: border-box !important;
    }

    html body #messagesContainer > .message:not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) .message-header,
    html body #messagesContainer > .message:not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) .message-content,
    html body #messagesContainer > .message:not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) .message-footer {
        padding-left: 0 !important;
        padding-right: 0 !important;
        margin-left: 0 !important;
        margin-right: 0 !important;
        box-sizing: border-box !important;
    }

    /* The audio card alone reaches the physical message edges. Text before or
       after it (caption/comment/time/sender) keeps the canonical 12px inset. */
    html body #messagesContainer > .message:has(.qchat-audio-mini-player):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) .qchat-audio-mini-group,
    html body #messagesContainer > .message:has(.qchat-audio-mini-group):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) .qchat-audio-mini-group,
    html body #messagesContainer > .message:has(.qchat-file-bundle-group-audio):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) .qchat-file-bundle-group-audio {
        width: calc(100% + (2 * var(--qchat-mobile-message-inset))) !important;
        max-width: calc(100% + (2 * var(--qchat-mobile-message-inset))) !important;
        min-width: 0 !important;
        margin-left: calc(-1 * var(--qchat-mobile-message-inset)) !important;
        margin-right: calc(-1 * var(--qchat-mobile-message-inset)) !important;
        box-sizing: border-box !important;
    }

    html body #messagesContainer > .message:has(.qchat-audio-mini-player):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) .qchat-file-bundle-list-audio,
    html body #messagesContainer > .message:has(.qchat-audio-mini-player):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) .qchat-audio-mini-player,
    html body #messagesContainer > .message:has(.qchat-audio-mini-group):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) .qchat-file-bundle-list-audio,
    html body #messagesContainer > .message:has(.qchat-audio-mini-group):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) .qchat-audio-mini-player {
        width: 100% !important;
        max-width: 100% !important;
        min-width: 0 !important;
        margin-left: 0 !important;
        margin-right: 0 !important;
        box-sizing: border-box !important;
    }

    /* Title, artist/details and album/year are independent rows on phones. */
    html body #messagesContainer .message .qchat-audio-mini-player .qchat-audio-mini-meta,
    html body #messagesContainer .message .qchat-audio-mini-player .qchat-file-bundle-preview-meta {
        display: grid !important;
        grid-template-columns: minmax(0, 1fr) !important;
        grid-auto-flow: row !important;
        align-content: center !important;
        align-items: start !important;
        row-gap: 2px !important;
        min-width: 0 !important;
        overflow: hidden !important;
    }

    html body #messagesContainer .message .qchat-audio-mini-player .song-name,
    html body #messagesContainer .message .qchat-audio-mini-player .song-autor,
    html body #messagesContainer .message .qchat-audio-mini-player .qchat-audio-mini-extra,
    html body #messagesContainer .message .qchat-audio-mini-player .qchat-audio-mini-progress {
        display: block !important;
        grid-column: 1 / -1 !important;
        width: 100% !important;
        max-width: 100% !important;
        min-width: 0 !important;
        margin-left: 0 !important;
        margin-right: 0 !important;
        box-sizing: border-box !important;
    }

    /* Android Chrome can visually collapse flex gap while the marquee is being
       transformed. Put the separation on the clone itself instead. */
    html body #messagesContainer .message .qchat-audio-mini-player .song-name .qchat-audio-title-marquee,
    html body #messagesContainer .message .qchat-audio-mini-player .song-autor .qchat-audio-title-marquee {
        gap: 0 !important;
        column-gap: 0 !important;
    }

    html body #messagesContainer .message .qchat-audio-mini-player .song-name .qchat-audio-title-copy-clone,
    html body #messagesContainer .message .qchat-audio-mini-player .song-autor .qchat-audio-title-copy-clone {
        margin-left: 32px !important;
    }
}

/* QChat mobile polish v13 (QChat patch v19)
 * Fix the v18 audio bleed by removing negative-width compensation entirely.
 * The message shell stays edge-to-edge; normal text owns the 12px inset while
 * audio/media cards stay inside the real content box at width:100%.
 * Mobile image modals rely on swipe gestures, so desktop prev/next arrows are
 * hidden on phones. Profile-blog cards/comments become a flat, full-width feed
 * with spacing instead of nested framed boxes.
 */
@media (max-width: 767.98px) {
    /* --- Chat: stable edge-to-edge sizing without negative margins --- */
    html body #messagesContainer > .message:not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) .message-content-wrapper {
        width: 100% !important;
        max-width: 100% !important;
        min-width: 0 !important;
        padding-left: 0 !important;
        padding-right: 0 !important;
        box-sizing: border-box !important;
        overflow-x: clip !important;
    }

    html body #messagesContainer > .message:not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) .message-header,
    html body #messagesContainer > .message:not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) .message-footer,
    html body #messagesContainer > .message:not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) .message-content {
        padding-left: var(--qchat-mobile-message-inset, 12px) !important;
        padding-right: var(--qchat-mobile-message-inset, 12px) !important;
        box-sizing: border-box !important;
    }

    /* Audio/file content itself is full width. Metadata outside the player and
       file captions get the same readable inset as ordinary text. */
    html body #messagesContainer > .message:has(.qchat-audio-mini-player):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) .message-content,
    html body #messagesContainer > .message:has(.qchat-audio-mini-group):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) .message-content,
    html body #messagesContainer > .message:has(.qchat-file-bundle-group-audio):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) .message-content,
    html body #messagesContainer > .message:has(.qchat-file-bundle-list-audio):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) .message-content {
        padding-left: 0 !important;
        padding-right: 0 !important;
    }

    html body #messagesContainer > .message:has(.qchat-audio-mini-player):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) .qchat-audio-mini-group,
    html body #messagesContainer > .message:has(.qchat-audio-mini-group):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) .qchat-audio-mini-group,
    html body #messagesContainer > .message:has(.qchat-file-bundle-group-audio):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) .qchat-file-bundle-group-audio,
    html body #messagesContainer > .message:has(.qchat-file-bundle-list-audio):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) .qchat-file-bundle-list-audio,
    html body #messagesContainer > .message:has(.qchat-audio-mini-player):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) .qchat-audio-mini-player,
    html body #messagesContainer > .message:has(.qchat-audio-mini-group):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) .qchat-audio-mini-player,
    html body #messagesContainer > .message:has(.qchat-file-bundle-group-audio):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) .qchat-audio-mini-player,
    html body #messagesContainer > .message:has(.qchat-file-bundle-list-audio):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) .qchat-audio-mini-player {
        width: 100% !important;
        max-width: 100% !important;
        min-width: 0 !important;
        margin-left: 0 !important;
        margin-right: 0 !important;
        box-sizing: border-box !important;
        transform: none !important;
    }

    html body #messagesContainer > .message:has(.qchat-audio-mini-player):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) .qchat-file-bundle-message,
    html body #messagesContainer > .message:has(.qchat-audio-mini-group):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) .qchat-file-bundle-message,
    html body #messagesContainer > .message:has(.qchat-file-bundle-group-audio):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) .qchat-file-bundle-message {
        width: 100% !important;
        max-width: 100% !important;
        min-width: 0 !important;
        margin-left: 0 !important;
        margin-right: 0 !important;
        padding-left: 0 !important;
        padding-right: 0 !important;
        box-sizing: border-box !important;
        overflow-x: clip !important;
    }

    html body #messagesContainer > .message:has(.qchat-audio-mini-player):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) .file-caption,
    html body #messagesContainer > .message:has(.qchat-audio-mini-group):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) .file-caption,
    html body #messagesContainer > .message:has(.qchat-file-bundle-group-audio):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) .file-caption,
    html body #messagesContainer > .message:has(.qchat-file-bundle-list-audio):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) .file-caption,
    html body #messagesContainer > .message:has(.qchat-audio-mini-player):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) .qchat-file-bundle-title {
        padding-left: var(--qchat-mobile-message-inset, 12px) !important;
        padding-right: var(--qchat-mobile-message-inset, 12px) !important;
        box-sizing: border-box !important;
    }

    /* --- Mobile gallery: swipe only, no left/right overlay arrows --- */
    .chat-image-nav,
    .profile-blog-image-nav,
    #chatImagePreviewModal .chat-image-nav,
    #profileBlogImagePreviewModal .profile-blog-image-nav {
        display: none !important;
    }

    /* --- Profile blog: flat full-width feed --- */
    #profileTab > .row > [class*="col-"],
    #profileTab .card-body.profile-tab-scroll,
    #profileTab .qchat-profile-right-block,
    #profileTab .profile-blog-posts {
        width: 100% !important;
        max-width: 100% !important;
        min-width: 0 !important;
        margin-left: 0 !important;
        margin-right: 0 !important;
        padding-left: 0 !important;
        padding-right: 0 !important;
        box-sizing: border-box !important;
    }

    #profileTab > .row > [class*="col-"] > .card {
        border-left: 0 !important;
        border-right: 0 !important;
        border-radius: 0 !important;
        box-shadow: none !important;
    }

    #profileTab .profile-blog-posts > .profile-blog-post {
        width: 100% !important;
        max-width: 100% !important;
        min-width: 0 !important;
        margin: 0 0 12px !important;
        padding: 12px !important;
        border: 0 !important;
        border-radius: 0 !important;
        box-shadow: none !important;
        box-sizing: border-box !important;
    }

    #profileTab .profile-blog-post .profile-blog-attachments,
    #profileTab .profile-blog-post .profile-blog-comments {
        width: 100% !important;
        max-width: 100% !important;
        min-width: 0 !important;
        margin-left: 0 !important;
        margin-right: 0 !important;
        box-sizing: border-box !important;
    }

    #profileTab .profile-blog-post .profile-blog-comments {
        border-top: 0 !important;
        padding-top: 8px !important;
    }

    #profileTab .profile-blog-post .profile-blog-comments-body {
        width: 100% !important;
        max-width: 100% !important;
        margin: 0 !important;
        padding: 0 !important;
        border: 0 !important;
        border-radius: 0 !important;
        background: transparent !important;
        box-shadow: none !important;
        box-sizing: border-box !important;
    }

    #profileTab .profile-blog-post .profile-blog-comments-list {
        width: 100% !important;
        margin: 0 !important;
        padding: 0 !important;
    }

    #profileTab .profile-blog-post .profile-blog-comment {
        width: 100% !important;
        max-width: 100% !important;
        min-width: 0 !important;
        margin: 0 !important;
        padding: 12px !important;
        border: 0 !important;
        border-radius: 0 !important;
        background: transparent !important;
        box-shadow: none !important;
        box-sizing: border-box !important;
    }

    #profileTab .profile-blog-post .profile-blog-comment + .profile-blog-comment {
        margin-top: 4px !important;
    }

    #profileTab .profile-blog-post .profile-blog-comment-content,
    #profileTab .profile-blog-post .profile-blog-comment-actions {
        margin-left: 36px !important;
        margin-right: 0 !important;
    }

    #profileTab .profile-blog-post .profile-blog-comment-replies {
        width: auto !important;
        max-width: none !important;
        margin: 8px 0 0 20px !important;
        padding: 0 !important;
        border: 0 !important;
        box-sizing: border-box !important;
    }

    #profileTab .profile-blog-post .profile-blog-comment-reply {
        background: transparent !important;
        border: 0 !important;
        box-shadow: none !important;
    }

    #profileTab .profile-blog-post .profile-blog-comment-form {
        width: 100% !important;
        margin: 8px 0 0 !important;
        padding: 0 12px 12px !important;
        box-sizing: border-box !important;
    }
}

/* QChat mobile polish v14 (QChat patch v20)
 * Keep custom blog emoji entry from reopening Android's IME, fit both image
 * preview modals inside the dynamic visual viewport so the download footer is
 * always reachable, and restore comfortable vertical rhythm to flat comments.
 */
@media (max-width: 767.98px) {
    /* --- Mobile image gallery: the complete modal must fit the *visible* viewport. --- */
    #chatImagePreviewModal .modal-dialog,
    #profileBlogImagePreviewModal .modal-dialog {
        width: calc(100% - 12px) !important;
        max-width: calc(100% - 12px) !important;
        height: calc(100vh - 12px) !important;
        height: calc(100dvh - 12px) !important;
        max-height: calc(100dvh - 12px) !important;
        min-height: 0 !important;
        margin: 6px auto !important;
        align-items: stretch !important;
    }

    #chatImagePreviewModal .modal-content,
    #profileBlogImagePreviewModal .modal-content {
        width: 100% !important;
        height: 100% !important;
        max-height: 100% !important;
        min-height: 0 !important;
        display: flex !important;
        flex-direction: column !important;
        overflow: hidden !important;
        box-sizing: border-box !important;
    }

    #chatImagePreviewModal .modal-header,
    #chatImagePreviewModal .modal-footer,
    #profileBlogImagePreviewModal .modal-header,
    #profileBlogImagePreviewModal .modal-footer {
        flex: 0 0 auto !important;
    }

    #chatImagePreviewModal .chat-image-preview-body,
    #profileBlogImagePreviewModal .profile-blog-image-preview-body {
        flex: 1 1 0 !important;
        min-height: 0 !important;
        width: 100% !important;
        overflow: hidden !important;
        display: flex !important;
        align-items: center !important;
        justify-content: center !important;
        padding: 8px !important;
        box-sizing: border-box !important;
    }

    #chatImagePreviewModal .chat-image-preview-modal-img,
    #profileBlogImagePreviewModal .profile-blog-image-preview-img {
        display: block !important;
        width: auto !important;
        height: auto !important;
        max-width: 100% !important;
        max-height: 100% !important;
        object-fit: contain !important;
        object-position: center center !important;
        margin: auto !important;
    }

    #chatImagePreviewModal .modal-footer,
    #profileBlogImagePreviewModal .modal-footer {
        min-height: 58px !important;
        padding: 8px 12px !important;
        box-sizing: border-box !important;
    }

    /* --- Flat blog comments still need readable vertical separation. --- */
    #profileTab .profile-blog-post .profile-blog-comment {
        padding: 14px 12px !important;
        line-height: 1.4 !important;
    }

    #profileTab .profile-blog-post .profile-blog-comment-date {
        margin-top: 3px !important;
        line-height: 1.25 !important;
    }

    #profileTab .profile-blog-post .profile-blog-comment-content {
        margin-top: 8px !important;
        margin-bottom: 0 !important;
        padding-top: 1px !important;
        padding-bottom: 1px !important;
        line-height: 1.5 !important;
        overflow-wrap: anywhere !important;
    }

    #profileTab .profile-blog-post .profile-blog-comment-actions {
        margin-top: 8px !important;
        line-height: 1.35 !important;
    }

    #profileTab .profile-blog-post .profile-blog-comment-replies {
        margin-top: 12px !important;
    }

    #profileTab .profile-blog-post .profile-blog-comment-reply {
        padding-top: 14px !important;
        padding-bottom: 14px !important;
    }
}

/* QChat mobile polish v15 (QChat patch v21)
 * Mobile galleries are swipe-only. Hide the actual navigation button ids as a
 * hard fallback in addition to the generic nav classes, so later JS class
 * toggles cannot make desktop prev/next controls visible on phones.
 */
@media (max-width: 767.98px) {
    #chatImagePreviewModal #chatImagePreviewPrev,
    #chatImagePreviewModal #chatImagePreviewNext,
    #profileBlogImagePreviewModal #profileBlogImagePreviewPrev,
    #profileBlogImagePreviewModal #profileBlogImagePreviewNext {
        display: none !important;
        visibility: hidden !important;
        pointer-events: none !important;
    }
}


/* QChat mobile polish v16 (QChat patch v22)
 * Restore swipe-only gallery navigation without exposing arrow buttons, keep
 * compact audio marquee rows independent on Android, and add a subtle zebra
 * rhythm to flat profile-blog comments in dark theme.
 */
@media (max-width: 767.98px) {
    /* Hidden arrows must not participate visually; qchat-mobile-gallery-swipe
       invokes their enabled click handlers programmatically. */
    #chatImagePreviewModal #chatImagePreviewPrev,
    #chatImagePreviewModal #chatImagePreviewNext,
    #profileBlogImagePreviewModal #profileBlogImagePreviewPrev,
    #profileBlogImagePreviewModal #profileBlogImagePreviewNext {
        display: none !important;
        visibility: hidden !important;
        pointer-events: none !important;
    }

    /* Android: title/artist/album are real rows and an overflowing marquee is
       animated independently of the occasionally-late .playing state. */
    html body #messagesContainer .message .qchat-audio-mini-player .song-name,
    html body #messagesContainer .message .qchat-audio-mini-player .song-autor,
    html body #messagesContainer .message .qchat-audio-mini-player .qchat-audio-mini-extra {
        clear: both !important;
        float: none !important;
        flex: 0 0 auto !important;
        min-height: 1.35em !important;
        line-height: 1.35 !important;
    }

    html body #messagesContainer .message .qchat-audio-mini-player .song-name.qchat-audio-title-overflow .qchat-audio-title-copy-clone,
    html body #messagesContainer .message .qchat-audio-mini-player .song-autor.qchat-audio-title-overflow .qchat-audio-title-copy-clone {
        display: inline-block !important;
        margin-left: 0 !important;
        padding-left: 32px !important;
        box-sizing: content-box !important;
    }

    html body #messagesContainer .message .qchat-audio-mini-player .song-name.qchat-audio-title-overflow .qchat-audio-title-marquee,
    html body #messagesContainer .message .qchat-audio-mini-player .song-autor.qchat-audio-title-overflow .qchat-audio-title-marquee {
        display: inline-flex !important;
        width: max-content !important;
        min-width: max-content !important;
        animation: qchatAudioTitleMarquee var(--qchat-title-marquee-duration, 12s) linear infinite !important;
    }

    /* Dark-theme comments: flat like the feed, but alternate surfaces so the
       boundaries remain legible without returning nested borders. */
    body.dark-theme #profileTab .profile-blog-post .profile-blog-comments-list > .profile-blog-comment:nth-child(odd),
    [data-bs-theme="dark"] #profileTab .profile-blog-post .profile-blog-comments-list > .profile-blog-comment:nth-child(odd) {
        background: rgba(255, 255, 255, 0.035) !important;
    }

    body.dark-theme #profileTab .profile-blog-post .profile-blog-comments-list > .profile-blog-comment:nth-child(even),
    [data-bs-theme="dark"] #profileTab .profile-blog-post .profile-blog-comments-list > .profile-blog-comment:nth-child(even) {
        background: rgba(255, 255, 255, 0.075) !important;
    }

    body.dark-theme #profileTab .profile-blog-post .profile-blog-comment-replies > .profile-blog-comment:nth-child(odd),
    [data-bs-theme="dark"] #profileTab .profile-blog-post .profile-blog-comment-replies > .profile-blog-comment:nth-child(odd) {
        background: rgba(255, 255, 255, 0.045) !important;
    }

    body.dark-theme #profileTab .profile-blog-post .profile-blog-comment-replies > .profile-blog-comment:nth-child(even),
    [data-bs-theme="dark"] #profileTab .profile-blog-post .profile-blog-comment-replies > .profile-blog-comment:nth-child(even) {
        background: rgba(255, 255, 255, 0.085) !important;
    }

    #profileTab .profile-blog-post .profile-blog-comment {
        padding-top: 14px !important;
        padding-bottom: 14px !important;
    }
}


/* QChat chat palette v27
 * Explicit light mode uses one calm message-card surface for both directions,
 * matching the reference card without sent/received zebra striping. Keep the
 * scope strictly inside the live chat so saved Profile/Blog cards are unchanged.
 */
html body.light-theme #messagesContainer > .message.sent:not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex > .message-bubble,
html body.light-theme #messagesContainer > .message.received:not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex > .message-bubble {
    --message-bg: #f9fafb;
    --message-hover-bg: #f9fafb;
    background: #f9fafb !important;
    color: #374151 !important;
    border: 0 !important;
    border-radius: 14px !important;
    box-shadow: none !important;
}

html body.light-theme #messagesContainer > .message:not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) .message-header,
html body.light-theme #messagesContainer > .message:not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) .message-header .profile-link {
    color: #111827 !important;
}

@media (prefers-color-scheme: light) {
    html body.auto-theme #messagesContainer > .message.sent:not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex > .message-bubble,
    html body.auto-theme #messagesContainer > .message.received:not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex > .message-bubble {
        --message-bg: #f9fafb;
        --message-hover-bg: #f9fafb;
        background: #f9fafb !important;
        color: #374151 !important;
        border: 0 !important;
        border-radius: 14px !important;
        box-shadow: none !important;
    }

    html body.auto-theme #messagesContainer > .message:not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) .message-header,
    html body.auto-theme #messagesContainer > .message:not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) .message-header .profile-link {
        color: #111827 !important;
    }
}

/* QChat saved Profile/Blog forwards v36
 * Saved blog cards are still chat messages. In explicit/auto light mode their
 * outer message bubble must use the same calm #f9fafb surface as ordinary
 * messages instead of falling back to the white base card. Keep the embedded
 * blog card itself transparent so the chat bubble is the single background.
 */
html body.light-theme #messagesContainer > .message:has(.saved-profile-blog-post) > .d-flex > .message-bubble,
html body.light-theme #messagesContainer > .message:has(.saved-profile-blog-comment) > .d-flex > .message-bubble {
    --message-bg: #f9fafb;
    --message-hover-bg: #f9fafb;
    background: #f9fafb !important;
    color: #374151 !important;
    border: 0 !important;
    border-radius: 14px !important;
    box-shadow: none !important;
}

html body.light-theme #messagesContainer > .message:has(.saved-profile-blog-post) .qchat-saved-blog-card-shell,
html body.light-theme #messagesContainer > .message:has(.saved-profile-blog-comment) .qchat-saved-blog-card-shell {
    background: transparent !important;
    color: inherit !important;
}

html body.light-theme #messagesContainer > .message:has(.saved-profile-blog-post) .message-header,
html body.light-theme #messagesContainer > .message:has(.saved-profile-blog-comment) .message-header,
html body.light-theme #messagesContainer > .message:has(.saved-profile-blog-post) .message-header .profile-link,
html body.light-theme #messagesContainer > .message:has(.saved-profile-blog-comment) .message-header .profile-link {
    color: #111827 !important;
}

@media (prefers-color-scheme: light) {
    html body.auto-theme #messagesContainer > .message:has(.saved-profile-blog-post) > .d-flex > .message-bubble,
    html body.auto-theme #messagesContainer > .message:has(.saved-profile-blog-comment) > .d-flex > .message-bubble {
        --message-bg: #f9fafb;
        --message-hover-bg: #f9fafb;
        background: #f9fafb !important;
        color: #374151 !important;
        border: 0 !important;
        border-radius: 14px !important;
        box-shadow: none !important;
    }

    html body.auto-theme #messagesContainer > .message:has(.saved-profile-blog-post) .qchat-saved-blog-card-shell,
    html body.auto-theme #messagesContainer > .message:has(.saved-profile-blog-comment) .qchat-saved-blog-card-shell {
        background: transparent !important;
        color: inherit !important;
    }

    html body.auto-theme #messagesContainer > .message:has(.saved-profile-blog-post) .message-header,
    html body.auto-theme #messagesContainer > .message:has(.saved-profile-blog-comment) .message-header,
    html body.auto-theme #messagesContainer > .message:has(.saved-profile-blog-post) .message-header .profile-link,
    html body.auto-theme #messagesContainer > .message:has(.saved-profile-blog-comment) .message-header .profile-link {
        color: #111827 !important;
    }
}

/* QChat dark chat zebra v28
 * Dark chat uses the exact two flat surfaces from Profile/Blog post zebra.
 * Zebra follows message order (not sender direction), while shared saved-post
 * cards keep their own Profile/Blog presentation. Borders and card shadows are
 * removed so the chat stays as flat as the profile feed.
 */
html body.dark-theme #messagesContainer > .message:nth-child(odd of .message):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex > .message-bubble {
    --message-bg: rgba(255, 255, 255, 0.035);
    --message-hover-bg: rgba(255, 255, 255, 0.035);
    background: rgba(255, 255, 255, 0.035) !important;
    color: var(--qchat-dark-text, #c9d1d9) !important;
    border: 0 !important;
    box-shadow: none !important;
}

html body.dark-theme #messagesContainer > .message:nth-child(even of .message):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex > .message-bubble {
    --message-bg: rgba(255, 255, 255, 0.075);
    --message-hover-bg: rgba(255, 255, 255, 0.075);
    background: rgba(255, 255, 255, 0.075) !important;
    color: var(--qchat-dark-text, #c9d1d9) !important;
    border: 0 !important;
    box-shadow: none !important;
}

@media (prefers-color-scheme: dark) {
    html body.auto-theme #messagesContainer > .message:nth-child(odd of .message):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex > .message-bubble {
        --message-bg: rgba(255, 255, 255, 0.035);
        --message-hover-bg: rgba(255, 255, 255, 0.035);
        background: rgba(255, 255, 255, 0.035) !important;
        color: #c9d1d9 !important;
        border: 0 !important;
        box-shadow: none !important;
    }

    html body.auto-theme #messagesContainer > .message:nth-child(even of .message):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex > .message-bubble {
        --message-bg: rgba(255, 255, 255, 0.075);
        --message-hover-bg: rgba(255, 255, 255, 0.075);
        background: rgba(255, 255, 255, 0.075) !important;
        color: #c9d1d9 !important;
        border: 0 !important;
        box-shadow: none !important;
    }
}

/* QChat mobile auth viewport v26
 * Do not nest a 100dvh scrolling #authSection inside the globally locked page.
 * Android visual-viewport panning after Turnstile/checkbox focus can otherwise
 * leave the top of the auth card unreachable. While auth is visible, make the
 * document the single scroll owner; the authenticated app keeps its own fixed
 * dynamic-viewport layout via #appSection rules above. */
@media (max-width: 767.98px) {
    html:has(#authSection:not(.hidden)),
    body:has(#authSection:not(.hidden)) {
        height: auto !important;
        min-height: 100% !important;
        overflow-x: hidden !important;
        overflow-y: auto !important;
        overscroll-behavior-y: auto !important;
    }

    body:has(#authSection:not(.hidden)) .qchat-root-container {
        height: auto !important;
        min-height: 100vh !important;
        max-height: none !important;
        overflow: visible !important;
    }

    @supports (min-height: 100dvh) {
        body:has(#authSection:not(.hidden)) .qchat-root-container {
            min-height: 100dvh !important;
        }
    }

    #authSection:not(.hidden) {
        height: auto !important;
        min-height: 100vh !important;
        max-height: none !important;
        overflow: visible !important;
        overscroll-behavior-y: auto !important;
        scroll-padding-top: 16px !important;
        scroll-padding-bottom: calc(28px + env(safe-area-inset-bottom, 0px)) !important;
    }

    @supports (min-height: 100dvh) {
        #authSection:not(.hidden) {
            min-height: 100dvh !important;
        }
    }
}

/* QChat mobile polish v21 (QChat patch v30)
 * Reassert the flat dark chat zebra with selectors supported by older Chromium,
 * and make single-image previews bounded/contained so portrait media cannot fill
 * the viewport or escape its message bubble.
 */

/* Dark chat: same two flat surfaces as Profile/Blog comments, independent of
   sent/received direction. Use plain nth-child instead of "nth-child(... of ...)"
   for compatibility with older Chromium builds. */
html body.dark-theme #messagesContainer > .message:nth-child(odd):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex > .message-bubble {
    --message-bg: rgba(255, 255, 255, 0.035);
    --message-hover-bg: rgba(255, 255, 255, 0.035);
    background: rgba(255, 255, 255, 0.035) !important;
    color: var(--qchat-dark-text, #c9d1d9) !important;
    border: 0 !important;
    outline: 0 !important;
    box-shadow: none !important;
}

html body.dark-theme #messagesContainer > .message:nth-child(even):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex > .message-bubble {
    --message-bg: rgba(255, 255, 255, 0.075);
    --message-hover-bg: rgba(255, 255, 255, 0.075);
    background: rgba(255, 255, 255, 0.075) !important;
    color: var(--qchat-dark-text, #c9d1d9) !important;
    border: 0 !important;
    outline: 0 !important;
    box-shadow: none !important;
}

html body.dark-theme #messagesContainer > .message:not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex > .message-bubble:hover {
    transform: none !important;
    box-shadow: none !important;
}

html body.dark-theme #messagesContainer > .message:not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)):hover {
    transform: none !important;
}

@media (prefers-color-scheme: dark) {
    html body.auto-theme #messagesContainer > .message:nth-child(odd):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex > .message-bubble {
        --message-bg: rgba(255, 255, 255, 0.035);
        --message-hover-bg: rgba(255, 255, 255, 0.035);
        background: rgba(255, 255, 255, 0.035) !important;
        color: #c9d1d9 !important;
        border: 0 !important;
        outline: 0 !important;
        box-shadow: none !important;
    }

    html body.auto-theme #messagesContainer > .message:nth-child(even):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex > .message-bubble {
        --message-bg: rgba(255, 255, 255, 0.075);
        --message-hover-bg: rgba(255, 255, 255, 0.075);
        background: rgba(255, 255, 255, 0.075) !important;
        color: #c9d1d9 !important;
        border: 0 !important;
        outline: 0 !important;
        box-shadow: none !important;
    }

    html body.auto-theme #messagesContainer > .message:not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex > .message-bubble:hover,
    html body.auto-theme #messagesContainer > .message:not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)):hover {
        transform: none !important;
        box-shadow: none !important;
    }
}

/* Normal chat image messages must stay inside the bubble. Do not touch forwarded
   Profile/Blog cards; they preserve their own gallery layout. */
html body #messagesContainer > .message:has(.qchat-chat-image-tile):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex > .message-bubble,
html body #messagesContainer > .message:has(.qchat-file-bundle-grid-images):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex > .message-bubble {
    max-width: min(360px, calc(100% - 38px)) !important;
    min-width: 0 !important;
    overflow: hidden !important;
    box-sizing: border-box !important;
}

html body #messagesContainer > .message:has(.qchat-chat-image-tile):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) :is(
    .message-content-wrapper,
    .message-content,
    .decrypted-file-content,
    .qchat-file-bundle-message,
    .qchat-file-bundle-groups,
    .qchat-file-bundle-group
),
html body #messagesContainer > .message:has(.qchat-file-bundle-grid-images):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) :is(
    .message-content-wrapper,
    .message-content,
    .decrypted-file-content,
    .qchat-file-bundle-message,
    .qchat-file-bundle-groups,
    .qchat-file-bundle-group
) {
    min-width: 0 !important;
    max-width: 100% !important;
    overflow: hidden !important;
    box-sizing: border-box !important;
}

/* Direct single image: renderer already provides a ratio-aware preview width.
   Respect that width instead of stretching the tile to the chat lane. */
html body #messagesContainer .message:not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment))
    .file-preview.image-preview.qchat-chat-image-tile[data-qchat-single-image="1"]:not(.profile-blog-gallery-tile) {
    width: min(var(--qchat-single-preview-width, 260px), 100%) !important;
    max-width: min(320px, 100%) !important;
    min-width: 0 !important;
    height: auto !important;
    min-height: 0 !important;
    max-height: min(420px, 52vh) !important;
    aspect-ratio: var(--qchat-single-ratio, 1) !important;
    overflow: hidden !important;
    box-sizing: border-box !important;
}

html body #messagesContainer .message:not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment))
    .file-preview.image-preview.qchat-chat-image-tile[data-qchat-single-image="1"]:not(.profile-blog-gallery-tile) > img.chat-image-preview {
    width: 100% !important;
    max-width: 100% !important;
    min-width: 0 !important;
    height: 100% !important;
    max-height: 100% !important;
    min-height: 0 !important;
    object-fit: contain !important;
    object-position: center center !important;
    display: block !important;
}

/* A one-image file bundle uses the same bounded geometry. */
html body #messagesContainer .message:not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment))
    .qchat-file-bundle-grid.qchat-file-bundle-grid-images[data-file-group-count="1"] {
    width: min(var(--qchat-album-width, 300px), 100%) !important;
    max-width: min(320px, 100%) !important;
    min-width: 0 !important;
    height: auto !important;
    min-height: 0 !important;
    max-height: min(420px, 52vh) !important;
    aspect-ratio: var(--qchat-album-ratio, 1) !important;
    overflow: hidden !important;
    box-sizing: border-box !important;
}

html body #messagesContainer .message:not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment))
    .qchat-file-bundle-grid.qchat-file-bundle-grid-images[data-file-group-count="1"] > * {
    min-width: 0 !important;
    max-width: 100% !important;
    min-height: 0 !important;
    max-height: 100% !important;
    overflow: hidden !important;
    box-sizing: border-box !important;
}

html body #messagesContainer .message:not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment))
    .qchat-file-bundle-grid.qchat-file-bundle-grid-images[data-file-group-count="1"] img.chat-image-preview {
    width: 100% !important;
    max-width: 100% !important;
    min-width: 0 !important;
    height: 100% !important;
    max-height: 100% !important;
    min-height: 0 !important;
    object-fit: contain !important;
    object-position: center center !important;
    display: block !important;
}

@media (max-width: 767.98px) {
    html body #messagesContainer > .message:has(.qchat-chat-image-tile):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex > .message-bubble,
    html body #messagesContainer > .message:has(.qchat-file-bundle-grid-images):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex > .message-bubble {
        max-width: calc(100% - 36px) !important;
    }

    html body #messagesContainer .message:not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment))
        .file-preview.image-preview.qchat-chat-image-tile[data-qchat-single-image="1"]:not(.profile-blog-gallery-tile),
    html body #messagesContainer .message:not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment))
        .qchat-file-bundle-grid.qchat-file-bundle-grid-images[data-file-group-count="1"] {
        max-width: min(72vw, 300px) !important;
        max-height: min(340px, 42dvh) !important;
    }
}


/* QChat mobile polish v22 (QChat patch v31)
 * Restore iOS/WebKit tab isolation after later mobile-polish merges, keep saved
 * blog audio geometry stable on hover, compact single portrait media, and make
 * the top-history loader cover the chat edge without exposing old rows above it.
 */
@media (max-width: 767.98px) {
    #appTabs,
    #appTabs.nav,
    #appTabs.nav-tabs {
        position: relative !important;
        z-index: 30 !important;
        isolation: isolate !important;
        contain: layout paint !important;
        background-color: var(--bs-body-bg, #fff) !important;
        background-image: none !important;
        border-bottom: 1px solid var(--bs-nav-tabs-border-color, #dee2e6) !important;
        overflow-x: auto !important;
        overflow-y: hidden !important;
        -webkit-overflow-scrolling: auto !important;
        transform: none !important;
        backface-visibility: visible !important;
        -webkit-backface-visibility: visible !important;
    }

    #appTabs.nav-tabs .nav-link.active::after,
    #appTabs.nav-tabs .nav-item.show .nav-link::after {
        display: none !important;
        content: none !important;
    }

    #appTabs .nav-item,
    #appTabs .nav-link,
    #appTabs .qchat-external-profile-tab {
        transform: none !important;
        filter: none !important;
    }

    /* Font Awesome replaces the original <i> nodes with inline <svg>. Earlier
       mobile rules hid only <i>/.fas, so iOS could still paint those generated
       SVG layers through the horizontal tab scroller as large curved fragments. */
    #appTabs .nav-link:not(.qchat-external-profile-tab) > svg.svg-inline--fa,
    #appTabs .nav-link:not(.qchat-external-profile-tab) > svg[data-icon] {
        display: none !important;
        visibility: hidden !important;
        width: 0 !important;
        min-width: 0 !important;
        max-width: 0 !important;
        height: 0 !important;
        min-height: 0 !important;
        max-height: 0 !important;
        margin: 0 !important;
        padding: 0 !important;
        overflow: hidden !important;
    }

    /* Keep dynamic external-profile avatars physically small even while the tab
       strip is a composited horizontal scroller on iOS Chrome/WebKit. */
    #appTabs .qchat-external-profile-tab-avatar,
    #appTabs .qchat-external-profile-tab-avatar img {
        width: 20px !important;
        min-width: 20px !important;
        max-width: 20px !important;
        height: 20px !important;
        min-height: 20px !important;
        max-height: 20px !important;
        border-radius: 50% !important;
        overflow: hidden !important;
        object-fit: cover !important;
    }

    #appSection > .tab-content {
        position: relative !important;
        z-index: 0 !important;
        contain: paint !important;
        overflow: hidden !important;
        transform: none !important;
    }

    /* A forwarded/saved Profile Blog card already renders the author's avatar
       inside the card. Hide the chat-row avatar even when the card was hydrated
       after the outer message DOM had already been created. */
    #messagesContainer .message:has(.saved-profile-blog-post) > .d-flex > :is(.message-avatar, .avatar-placeholder.message-avatar, .encrypted-message-avatar, .qchat-message-avatar-fallback),
    #messagesContainer .message:has(.saved-profile-blog-comment) > .d-flex > :is(.message-avatar, .avatar-placeholder.message-avatar, .encrypted-message-avatar, .qchat-message-avatar-fallback) {
        display: none !important;
        width: 0 !important;
        min-width: 0 !important;
        max-width: 0 !important;
        height: 0 !important;
        min-height: 0 !important;
        max-height: 0 !important;
        margin: 0 !important;
        padding: 0 !important;
        flex: 0 0 0 !important;
        overflow: hidden !important;
    }

    #messagesContainer .message:has(.saved-profile-blog-post) > .d-flex,
    #messagesContainer .message:has(.saved-profile-blog-comment) > .d-flex {
        gap: 0 !important;
    }

    /* Legacy/direct image preview path (non-bundle). */
    #messagesContainer .message .file-message-preview .image-preview {
        width: fit-content !important;
        max-width: min(72vw, 300px) !important;
        max-height: min(300px, 38dvh) !important;
        overflow: hidden !important;
        margin-left: 0 !important;
        margin-right: auto !important;
    }

    #messagesContainer .message .file-message-preview .image-preview > img.preview-image {
        display: block !important;
        width: auto !important;
        height: auto !important;
        max-width: min(72vw, 300px) !important;
        max-height: min(300px, 38dvh) !important;
        object-fit: contain !important;
    }

    /* Source-level one-image bundle renderer. Its runtime style owns the exact
       dimensions; these rules prevent surrounding profile-blog wrappers from
       stretching to the full message height. */
    #messagesContainer .qchat-chat-blog-single-image-host,
    #messagesContainer .qchat-chat-blog-single-image-host .qchat-chat-blog-file-bundle-message,
    #messagesContainer .qchat-chat-blog-single-image-host .qchat-chat-blog-file-bundle-groups,
    #messagesContainer .qchat-chat-blog-single-image-host .qchat-chat-blog-gallery-group {
        width: fit-content !important;
        max-width: min(72vw, 300px) !important;
        height: auto !important;
        min-height: 0 !important;
        max-height: none !important;
        align-self: flex-start !important;
        flex: 0 0 auto !important;
    }
}

body.dark-theme #appTabs,
body.dark-theme #appTabs.nav,
body.dark-theme #appTabs.nav-tabs {
    background-color: var(--qchat-dark-bg, #0d1117) !important;
    border-bottom-color: var(--qchat-dark-surface-3, #30363d) !important;
}

@media (prefers-color-scheme: dark) {
    body.auto-theme #appTabs,
    body.auto-theme #appTabs.nav,
    body.auto-theme #appTabs.nav-tabs {
        background-color: #0d1117 !important;
        border-bottom-color: #30363d !important;
    }
}

/* Saved/forwarded Profile Blog audio: never let fit-content recompute when the
   player enters :hover/:focus/playing states. The complete card owns one width. */
#messagesContainer .message:has(.saved-profile-blog-post):has(.qchat-audio-mini-player) > .d-flex,
#messagesContainer .message:has(.saved-profile-blog-post):has(.qchat-audio-mini-group) > .d-flex,
#messagesContainer .message:has(.saved-profile-blog-post):has(.qchat-file-bundle-group-audio) > .d-flex,
#messagesContainer .message:has(.saved-profile-blog-post):has(.qchat-file-bundle-list-audio) > .d-flex {
    width: min(574px, 100%) !important;
    max-width: min(574px, 100%) !important;
    min-width: 0 !important;
}

#messagesContainer .message:has(.saved-profile-blog-post):has(.qchat-audio-mini-player) .message-bubble,
#messagesContainer .message:has(.saved-profile-blog-post):has(.qchat-audio-mini-group) .message-bubble,
#messagesContainer .message:has(.saved-profile-blog-post):has(.qchat-file-bundle-group-audio) .message-bubble,
#messagesContainer .message:has(.saved-profile-blog-post):has(.qchat-file-bundle-list-audio) .message-bubble,
#messagesContainer .saved-profile-blog-post:has(.qchat-audio-mini-player),
#messagesContainer .saved-profile-blog-post:has(.qchat-audio-mini-group) {
    width: 100% !important;
    max-width: 100% !important;
    min-width: 0 !important;
    box-sizing: border-box !important;
}

#messagesContainer .saved-profile-blog-post .qchat-audio-mini-player,
#messagesContainer .saved-profile-blog-post .qchat-audio-mini-player:hover,
#messagesContainer .saved-profile-blog-post .qchat-audio-mini-player:focus-within,
#messagesContainer .saved-profile-blog-post .qchat-audio-mini-player.playing {
    width: 100% !important;
    max-width: 500px !important;
    min-width: 0 !important;
    transform: none !important;
}

/* Loader is the first direct child; remove the container's normal top padding
   only while it exists so no old message strip is visible above the loader. */
#messagesContainer:has(> .qchat-history-top-sentinel) {
    padding-top: 0 !important;
}

#messagesContainer > .qchat-history-top-sentinel {
    top: 0 !important;
    margin-top: 0 !important;
    min-height: 34px !important;
    display: flex !important;
    align-items: center !important;
    justify-content: center !important;
    width: 100% !important;
    box-sizing: border-box !important;
    background: var(--bs-body-bg, #fff) !important;
}

body.dark-theme #messagesContainer > .qchat-history-top-sentinel {
    background: var(--qchat-dark-bg, #0d1117) !important;
}

@media (prefers-color-scheme: dark) {
    body.auto-theme #messagesContainer > .qchat-history-top-sentinel {
        background: #0d1117 !important;
    }
}


/* QChat mobile polish v23: contacts pane edge-to-edge + strict lone portrait cap. */
@media (max-width: 768px) {
    /* Contacts are a full tab pane on phones. Bootstrap column gutters and the
       dark-theme card border should not inset the whole contact list. */
    #messagingTab > .row > .col-md-3:not(.hidden) {
        width: 100% !important;
        max-width: 100% !important;
        min-width: 0 !important;
        margin: 0 !important;
        padding-left: 0 !important;
        padding-right: 0 !important;
        box-sizing: border-box !important;
    }

    #messagingTab > .row > .col-md-3:not(.hidden) > .card {
        width: 100% !important;
        max-width: 100% !important;
        min-width: 0 !important;
        margin: 0 !important;
        border: 0 !important;
        border-radius: 0 !important;
        box-shadow: none !important;
        box-sizing: border-box !important;
    }

    /* Safety net for old cached/sourced single-image markup. Source JS now owns
       an explicit compact height, but never allow its wrappers to stretch it. */
    #messagesContainer .qchat-chat-blog-single-image-host .qchat-chat-blog-gallery[data-file-group-count="1"] {
        width: fit-content !important;
        max-width: min(72vw, 300px) !important;
        max-height: min(280px, 38dvh) !important;
        align-self: flex-start !important;
    }

    #messagesContainer .qchat-chat-blog-single-image-host .qchat-chat-blog-gallery[data-file-group-count="1"] .qchat-chat-blog-gallery-item,
    #messagesContainer .qchat-chat-blog-single-image-host .qchat-chat-blog-gallery[data-file-group-count="1"] .qchat-chat-blog-gallery-tile,
    #messagesContainer .qchat-chat-blog-single-image-host .qchat-chat-blog-gallery[data-file-group-count="1"] .qchat-chat-blog-attachment-preview,
    #messagesContainer .qchat-chat-blog-single-image-host .qchat-chat-blog-gallery[data-file-group-count="1"] .qchat-chat-blog-image {
        max-height: min(280px, 38dvh) !important;
    }

    #messagesContainer .qchat-chat-blog-single-image-host .qchat-chat-blog-gallery[data-file-group-count="1"] .qchat-chat-blog-image {
        object-fit: contain !important;
    }
}

/* QChat mobile polish v24: forwarded Profile Blog card cleanup + immutable mini-audio width.
 * Saved Blog HTML carries Bootstrap `border rounded` utilities and nests each
 * mini player through several auto-sized attachment wrappers.  The latter can
 * recalculate their intrinsic width when hover/focus changes player controls.
 * Own both concerns here at the final stylesheet layer. */
#messagesContainer .message .saved-profile-blog-post.qchat-saved-blog-card-shell,
#messagesContainer .message .saved-profile-blog-post {
    border: 0 !important;
    outline: 0 !important;
    box-shadow: none !important;
}

/* The forwarded card itself has one deterministic width.  Avoid shrink-to-fit
   feedback loops between the card and its audio descendants. */
#messagesContainer .message:has(.saved-profile-blog-post):has(.qchat-audio-mini-player) > .d-flex,
#messagesContainer .message:has(.saved-profile-blog-post):has(.qchat-audio-mini-group) > .d-flex,
#messagesContainer .message:has(.saved-profile-blog-post):has(.qchat-file-bundle-group-audio) > .d-flex,
#messagesContainer .message:has(.saved-profile-blog-post):has(.qchat-file-bundle-list-audio) > .d-flex {
    width: min(574px, 100%) !important;
    max-width: min(574px, 100%) !important;
    min-width: 0 !important;
    flex: 0 1 574px !important;
    box-sizing: border-box !important;
}

#messagesContainer .message:has(.saved-profile-blog-post):has(.qchat-audio-mini-player) .message-bubble,
#messagesContainer .message:has(.saved-profile-blog-post):has(.qchat-audio-mini-group) .message-bubble,
#messagesContainer .message:has(.saved-profile-blog-post):has(.qchat-file-bundle-group-audio) .message-bubble,
#messagesContainer .message:has(.saved-profile-blog-post):has(.qchat-file-bundle-list-audio) .message-bubble,
#messagesContainer .message:has(.saved-profile-blog-post):has(.qchat-audio-mini-player) .message-content-wrapper,
#messagesContainer .message:has(.saved-profile-blog-post):has(.qchat-audio-mini-player) .message-content,
#messagesContainer .message:has(.saved-profile-blog-post):has(.qchat-audio-mini-player) .saved-profile-blog-post {
    width: 100% !important;
    max-width: 100% !important;
    min-width: 0 !important;
    box-sizing: border-box !important;
}

/* Lock every auto-sized wrapper around a forwarded Blog mini player to the
   same 464px lane.  Hover/focus/playing must only change paint, never geometry. */
#messagesContainer .saved-profile-blog-post .profile-blog-attachments:has(.qchat-audio-mini-player),
#messagesContainer .saved-profile-blog-post .profile-blog-file-bundle-message:has(.qchat-audio-mini-player),
#messagesContainer .saved-profile-blog-post .profile-blog-file-bundle-groups:has(.qchat-audio-mini-player),
#messagesContainer .saved-profile-blog-post .profile-blog-audio-group,
#messagesContainer .saved-profile-blog-post .profile-blog-audio-list,
#messagesContainer .saved-profile-blog-post .profile-blog-audio-attachment,
#messagesContainer .saved-profile-blog-post .profile-blog-audio-attachment > .profile-blog-attachment-preview,
#messagesContainer .saved-profile-blog-post .qchat-audio-mini-group,
#messagesContainer .saved-profile-blog-post .qchat-file-bundle-list-audio,
#messagesContainer .saved-profile-blog-post .qchat-audio-mini-player,
#messagesContainer .saved-profile-blog-post .qchat-audio-mini-player:hover,
#messagesContainer .saved-profile-blog-post .qchat-audio-mini-player:focus-within,
#messagesContainer .saved-profile-blog-post .qchat-audio-mini-player.qchat-audio-controls-open,
#messagesContainer .saved-profile-blog-post .qchat-audio-mini-player.playing {
    width: 464px !important;
    max-width: 100% !important;
    min-width: 0 !important;
    inline-size: 464px !important;
    max-inline-size: 100% !important;
    flex-grow: 0 !important;
    flex-shrink: 1 !important;
    box-sizing: border-box !important;
    transform: none !important;
    transition-property: background-color, border-color, box-shadow !important;
}

/* Controls already occupy 82px; repeat that contract at the final cascade
   layer so revealing/focusing controls cannot alter the player's width. */
#messagesContainer .saved-profile-blog-post .qchat-audio-mini-player .qchat-audio-mini-controls,
#messagesContainer .saved-profile-blog-post .qchat-audio-mini-player:hover .qchat-audio-mini-controls,
#messagesContainer .saved-profile-blog-post .qchat-audio-mini-player:focus-within .qchat-audio-mini-controls,
#messagesContainer .saved-profile-blog-post .qchat-audio-mini-player.qchat-audio-controls-open .qchat-audio-mini-controls,
#messagesContainer .saved-profile-blog-post .qchat-audio-mini-player.playing .qchat-audio-mini-controls {
    flex: 0 0 82px !important;
    flex-basis: 82px !important;
    width: 82px !important;
    min-width: 82px !important;
    max-width: 82px !important;
    transform: none !important;
    transition: none !important;
}


/* QChat mobile polish v21 (2026-09-03)
 * Forward-dialog parity, Android search autofill suppression companion styles,
 * and readable Notification Center text in dark mode.
 */
#forwardMessageModal .modal-body > .mb-3,
#forwardMessageModal #forwardContactsList,
#forwardMessageModal .forward-contacts-scrollable {
    width: 100% !important;
    max-width: 100% !important;
    min-width: 0 !important;
    box-sizing: border-box !important;
}

#forwardMessageModal .modal-body > .mb-3 {
    margin-left: 0 !important;
    margin-right: 0 !important;
}

#forwardMessageModal .forward-contacts-scrollable {
    border: 0 !important;
    border-radius: 0 !important;
    box-shadow: none !important;
    padding-left: 0 !important;
    padding-right: 0 !important;
    background: transparent !important;
}

#forwardMessageModal .forward-contact-item {
    width: 100% !important;
    max-width: 100% !important;
    box-sizing: border-box !important;
}

/* Forward placeholders use the same simple blue initial as the main chat list. */
#forwardMessageModal .forward-contact-avatar .avatar-placeholder,
#forwardMessageModal .forward-contact-avatar.avatar-placeholder,
#forwardMessageModal .qchat-forward-avatar-32.avatar-placeholder {
    width: 32px !important;
    height: 32px !important;
    min-width: 32px !important;
    min-height: 32px !important;
    background: var(--bs-primary, #0d6efd) !important;
    color: #fff !important;
    border: 0 !important;
    border-radius: 50% !important;
    box-shadow: none !important;
    font-size: 14px !important;
}

body.dark-theme #notificationsTab .notification-center-item,
body.dark-theme #notificationsTab .notification-center-item-title,
body.dark-theme #notificationsTab .notification-center-preview,
body.dark-theme #notificationsTab .notification-center-preview.text-body {
    color: var(--qchat-dark-text, #c9d1d9) !important;
}

body.dark-theme #notificationsTab .notification-center-post-preview,
body.dark-theme #notificationsTab .notification-center-item .text-muted,
body.dark-theme #notificationsTab .notification-center-toolbar small {
    color: var(--qchat-dark-muted, #8b949e) !important;
    opacity: 1 !important;
}

body.dark-theme #notificationsTab .notification-center-item {
    background: transparent !important;
    border-color: var(--qchat-dark-surface-3, #30363d) !important;
}

body.dark-theme #notificationsTab .notification-center-item:hover,
body.dark-theme #notificationsTab .notification-center-item:focus-within {
    background: var(--qchat-dark-surface-2, #21262d) !important;
}

@media (prefers-color-scheme: dark) {
    body.auto-theme #notificationsTab .notification-center-item,
    body.auto-theme #notificationsTab .notification-center-item-title,
    body.auto-theme #notificationsTab .notification-center-preview,
    body.auto-theme #notificationsTab .notification-center-preview.text-body {
        color: #c9d1d9 !important;
    }

    body.auto-theme #notificationsTab .notification-center-post-preview,
    body.auto-theme #notificationsTab .notification-center-item .text-muted,
    body.auto-theme #notificationsTab .notification-center-toolbar small {
        color: #8b949e !important;
        opacity: 1 !important;
    }

    body.auto-theme #notificationsTab .notification-center-item {
        background: transparent !important;
        border-color: #30363d !important;
    }

    body.auto-theme #notificationsTab .notification-center-item:hover,
    body.auto-theme #notificationsTab .notification-center-item:focus-within {
        background: #21262d !important;
    }
}


/* QChat mobile polish v25: merged forward-dialog + forwarded-blog geometry fixes.
 * Keep the v24 forwarded Blog card/audio lock while adding the newer forward
 * dialog/contact-search changes. The prior delta accidentally shipped an older
 * mobile-polish.css and therefore removed v24 from the cascade. */
@media (max-width: 767.98px) {
    #forwardMessageModal .modal-dialog {
        width: calc(100vw - 16px) !important;
        max-width: calc(100vw - 16px) !important;
        min-width: 0 !important;
        margin: 8px auto !important;
    }

    #forwardMessageModal .modal-content {
        width: 100% !important;
        max-width: none !important;
        min-width: 0 !important;
        box-sizing: border-box !important;
    }

    #forwardMessageModal .modal-body {
        width: 100% !important;
        min-width: 0 !important;
        box-sizing: border-box !important;
    }
}

/* Initial-letter placeholders must be optically centered like the regular
   chat-list placeholders. Raw text inherited the modal line-height and looked
   several pixels too high on Android. */
#forwardMessageModal .forward-contact-avatar.avatar-placeholder,
#forwardMessageModal .forward-contact-avatar .avatar-placeholder,
#forwardMessageModal .qchat-forward-avatar-32.avatar-placeholder,
#forwardMessageModal .qchat-forward-avatar-32-clip.avatar-placeholder {
    display: grid !important;
    place-items: center !important;
    padding: 0 !important;
    text-align: center !important;
    line-height: 1 !important;
}

#forwardMessageModal .qchat-forward-avatar-initial {
    display: block !important;
    line-height: 1 !important;
    margin: 0 !important;
    padding: 0 !important;
    transform: translateY(1px) !important;
    pointer-events: none !important;
}


/* QChat profile seam fix v1
 * The Profile pane's first Bootstrap card sits directly below #appTabs. Its top
 * border becomes a duplicate horizontal rule (always visible in dark theme and
 * on compact light layouts). Keep the rest of the card geometry unchanged.
 */
#profileTab,
#profileTab > .row,
#profileTab > .row > [class*="col-"] {
    border-top: 0 !important;
}

#profileTab > .row > [class*="col-"] > .card {
    border-top-width: 0 !important;
    border-top-color: transparent !important;
}

/* QChat mobile polish v28: forwarded Profile Blog audio uses one stable inner lane.
 * Do not force a 464px child inside an indented .profile-blog-attachments block:
 * that combination pushes the controls beyond the card and makes the browser
 * re-evaluate intrinsic widths on hover. Flatten the forwarded Blog attachment
 * indent, let every wrapper use the card content width, and make the mini player
 * a three-column grid (cover / metadata / fixed controls). Hover/focus/play can
 * then change paint only and cannot change geometry. */
#messagesContainer .message .saved-profile-blog-post.qchat-saved-blog-card-shell,
#messagesContainer .message .saved-profile-blog-post {
    border: 0 !important;
    outline: 0 !important;
    box-shadow: none !important;
}

@media (min-width: 521px) {
    html body #messagesContainer .message:has(.saved-profile-blog-post):has(.qchat-audio-mini-player) > .d-flex,
    html body #messagesContainer .message:has(.saved-profile-blog-post):has(.qchat-audio-mini-group) > .d-flex,
    html body #messagesContainer .message:has(.saved-profile-blog-post):has(.qchat-file-bundle-group-audio) > .d-flex,
    html body #messagesContainer .message:has(.saved-profile-blog-post):has(.qchat-file-bundle-list-audio) > .d-flex {
        width: 498px !important;
        min-width: 498px !important;
        max-width: 498px !important;
        flex: 0 0 498px !important;
        box-sizing: border-box !important;
    }

    html body #messagesContainer .message:has(.saved-profile-blog-post):has(.qchat-audio-mini-player) .message-bubble,
    html body #messagesContainer .message:has(.saved-profile-blog-post):has(.qchat-audio-mini-group) .message-bubble,
    html body #messagesContainer .message:has(.saved-profile-blog-post):has(.qchat-file-bundle-group-audio) .message-bubble,
    html body #messagesContainer .message:has(.saved-profile-blog-post):has(.qchat-file-bundle-list-audio) .message-bubble {
        width: 498px !important;
        min-width: 498px !important;
        max-width: 498px !important;
        flex: 0 0 498px !important;
        box-sizing: border-box !important;
    }

    html body #messagesContainer .message:has(.saved-profile-blog-post):has(.qchat-audio-mini-player) .message-content-wrapper,
    html body #messagesContainer .message:has(.saved-profile-blog-post):has(.qchat-audio-mini-player) .message-content,
    html body #messagesContainer .message:has(.saved-profile-blog-post):has(.qchat-audio-mini-player) .saved-profile-blog-post {
        width: 100% !important;
        min-width: 0 !important;
        max-width: 100% !important;
        box-sizing: border-box !important;
    }
}

/* The normal Blog feed indents attachments by 46px. That is useful in the
   profile feed, but not inside a forwarded Blog card: it consumes the exact
   space needed by the fixed audio controls. */
html body #messagesContainer .saved-profile-blog-post .profile-blog-attachments,
html body #messagesContainer .saved-profile-blog-post .profile-blog-attachments:has(.qchat-audio-mini-player) {
    width: 100% !important;
    max-width: 100% !important;
    min-width: 0 !important;
    margin-left: 0 !important;
    margin-right: 0 !important;
    box-sizing: border-box !important;
}

html body #messagesContainer .saved-profile-blog-post .profile-blog-file-bundle-message,
html body #messagesContainer .saved-profile-blog-post .profile-blog-file-bundle-groups,
html body #messagesContainer .saved-profile-blog-post .profile-blog-audio-group,
html body #messagesContainer .saved-profile-blog-post .profile-blog-audio-list,
html body #messagesContainer .saved-profile-blog-post .profile-blog-audio-attachment,
html body #messagesContainer .saved-profile-blog-post .profile-blog-audio-attachment > .profile-blog-attachment-preview,
html body #messagesContainer .saved-profile-blog-post .qchat-audio-mini-group,
html body #messagesContainer .saved-profile-blog-post .qchat-audio-mini-group > .qchat-file-bundle-list,
html body #messagesContainer .saved-profile-blog-post .qchat-file-bundle-group-audio,
html body #messagesContainer .saved-profile-blog-post .qchat-file-bundle-list-audio {
    width: 100% !important;
    min-width: 0 !important;
    max-width: 100% !important;
    inline-size: auto !important;
    min-inline-size: 0 !important;
    max-inline-size: 100% !important;
    margin-left: 0 !important;
    margin-right: 0 !important;
    box-sizing: border-box !important;
}

html body #messagesContainer .saved-profile-blog-post .qchat-audio-mini-player,
html body #messagesContainer .saved-profile-blog-post .qchat-audio-mini-player:hover,
html body #messagesContainer .saved-profile-blog-post .qchat-audio-mini-player:focus-within,
html body #messagesContainer .saved-profile-blog-post .qchat-audio-mini-player.qchat-audio-controls-open,
html body #messagesContainer .saved-profile-blog-post .qchat-audio-mini-player.playing {
    display: grid !important;
    grid-template-columns: 48px minmax(0, 1fr) 82px !important;
    align-items: center !important;
    column-gap: 9px !important;
    width: 100% !important;
    min-width: 0 !important;
    max-width: 100% !important;
    inline-size: 100% !important;
    min-inline-size: 0 !important;
    max-inline-size: 100% !important;
    flex: none !important;
    box-sizing: border-box !important;
    overflow: hidden !important;
    transform: none !important;
    transition-property: background-color, border-color, box-shadow !important;
}

html body #messagesContainer .saved-profile-blog-post .qchat-audio-mini-player .qchat-audio-mini-art,
html body #messagesContainer .saved-profile-blog-post .qchat-audio-mini-player .qchat-file-bundle-preview-icon {
    grid-column: 1 !important;
    margin: 0 !important;
}

html body #messagesContainer .saved-profile-blog-post .qchat-audio-mini-player .qchat-audio-mini-meta,
html body #messagesContainer .saved-profile-blog-post .qchat-audio-mini-player .qchat-file-bundle-preview-meta {
    grid-column: 2 !important;
    width: auto !important;
    min-width: 0 !important;
    max-width: none !important;
    margin: 0 !important;
    overflow: hidden !important;
}

html body #messagesContainer .saved-profile-blog-post .qchat-audio-mini-player .qchat-audio-mini-controls,
html body #messagesContainer .saved-profile-blog-post .qchat-audio-mini-player:hover .qchat-audio-mini-controls,
html body #messagesContainer .saved-profile-blog-post .qchat-audio-mini-player:focus-within .qchat-audio-mini-controls,
html body #messagesContainer .saved-profile-blog-post .qchat-audio-mini-player.qchat-audio-controls-open .qchat-audio-mini-controls,
html body #messagesContainer .saved-profile-blog-post .qchat-audio-mini-player.playing .qchat-audio-mini-controls {
    grid-column: 3 !important;
    display: grid !important;
    grid-template-columns: 24px 28px 24px !important;
    grid-template-areas: "prev play next" "range range range" !important;
    column-gap: 3px !important;
    row-gap: 3px !important;
    width: 82px !important;
    min-width: 82px !important;
    max-width: 82px !important;
    flex: none !important;
    margin-left: 0 !important;
    margin-right: 0 !important;
    align-self: center !important;
    justify-self: end !important;
    overflow: visible !important;
    opacity: 1 !important;
    visibility: visible !important;
    transform: none !important;
    pointer-events: auto !important;
    transition: none !important;
    box-sizing: border-box !important;
}

@media (max-width: 520px) {
    html body #messagesContainer .message:has(.saved-profile-blog-post):has(.qchat-audio-mini-player) > .d-flex,
    html body #messagesContainer .message:has(.saved-profile-blog-post):has(.qchat-audio-mini-group) > .d-flex,
    html body #messagesContainer .message:has(.saved-profile-blog-post):has(.qchat-file-bundle-group-audio) > .d-flex,
    html body #messagesContainer .message:has(.saved-profile-blog-post):has(.qchat-file-bundle-list-audio) > .d-flex,
    html body #messagesContainer .message:has(.saved-profile-blog-post):has(.qchat-audio-mini-player) .message-bubble,
    html body #messagesContainer .message:has(.saved-profile-blog-post):has(.qchat-audio-mini-player) .message-content-wrapper,
    html body #messagesContainer .message:has(.saved-profile-blog-post):has(.qchat-audio-mini-player) .message-content,
    html body #messagesContainer .message:has(.saved-profile-blog-post):has(.qchat-audio-mini-player) .saved-profile-blog-post {
        width: 100% !important;
        min-width: 0 !important;
        max-width: 100% !important;
        flex: 0 0 100% !important;
        box-sizing: border-box !important;
    }

    html body #messagesContainer .saved-profile-blog-post .qchat-audio-mini-player,
    html body #messagesContainer .saved-profile-blog-post .qchat-audio-mini-player:hover,
    html body #messagesContainer .saved-profile-blog-post .qchat-audio-mini-player:focus-within,
    html body #messagesContainer .saved-profile-blog-post .qchat-audio-mini-player.playing {
        grid-template-columns: 48px minmax(0, 1fr) 82px !important;
        column-gap: 6px !important;
    }
}


/* QChat mobile polish v29
 * Mobile tab panes are edge-to-edge surfaces. Bootstrap's outer card border is
 * redundant under the tab strip and made every mobile pane look framed. Remove
 * only the root pane/card frame; nested notification/settings/message cards keep
 * their own semantic borders.
 */
@media (max-width: 767.98px) {
    #appSection > .tab-content,
    #appSection > .tab-content > .tab-pane,
    #messagingTab > .row > [class*="col-"] > .card,
    #profileTab > .row > [class*="col-"] > .card,
    #settingsTab > .row > [class*="col-"] > .card,
    #friendsTab > .row > [class*="col-"] > .card,
    #notificationsTab > .row > [class*="col-"] > .card,
    #friendsTab .qchat-friends-panel {
        border: 0 !important;
        outline: 0 !important;
        box-shadow: none !important;
        border-radius: 0 !important;
    }

    #messagingTab > .row > [class*="col-"] {
        padding-left: 0 !important;
        padding-right: 0 !important;
    }
}

/* Stable E2EE file hydration surface. On slow links the user now sees one
 * explicit loading state until decryption and (for audio) ID3/cover extraction
 * finish, rather than Signal card -> default player -> final-cover player. */
.qchat-file-hydration-placeholder {
    width: min(100%, 520px);
    min-width: 0;
    min-height: 78px;
    display: grid;
    grid-template-columns: 42px minmax(0, 1fr);
    align-items: center;
    gap: 12px;
    padding: 12px;
    box-sizing: border-box;
    border-radius: 10px;
    background: rgba(127, 127, 127, 0.07);
    overflow: hidden;
}

.qchat-file-hydration-icon {
    width: 42px;
    height: 42px;
    display: grid;
    place-items: center;
    border-radius: 50%;
    font-size: 20px;
    color: var(--bs-primary, #0d6efd);
    background: rgba(13, 110, 253, 0.10);
}

.qchat-file-hydration-body,
.qchat-file-hydration-name,
.qchat-file-hydration-stage {
    min-width: 0;
}

.qchat-file-hydration-name {
    display: block;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.qchat-file-hydration-stage {
    margin-top: 2px;
    font-size: .82rem;
    color: var(--bs-secondary-color, #6c757d);
}

.qchat-file-hydration-progress {
    position: relative;
    width: 100%;
    height: 3px;
    margin-top: 8px;
    overflow: hidden;
    border-radius: 999px;
    background: rgba(127, 127, 127, 0.20);
}

.qchat-file-hydration-progress > span {
    position: absolute;
    inset: 0 auto 0 0;
    width: 38%;
    border-radius: inherit;
    background: currentColor;
    color: var(--bs-primary, #0d6efd);
    animation: qchat-file-hydration-slide 1.05s ease-in-out infinite;
}

@keyframes qchat-file-hydration-slide {
    0% { transform: translateX(-110%); }
    50% { transform: translateX(95%); }
    100% { transform: translateX(265%); }
}

body.dark-theme .qchat-file-hydration-placeholder {
    background: rgba(255, 255, 255, 0.045);
    color: var(--qchat-dark-text, #c9d1d9);
}

body.dark-theme .qchat-file-hydration-stage {
    color: var(--qchat-dark-muted, #8b949e);
}

@media (prefers-reduced-motion: reduce) {
    .qchat-file-hydration-progress > span {
        animation-duration: 2.2s;
    }
}

/* QChat mobile polish v30 (QChat patch v38)
 * Final mobile tab-frame cleanup and stable audio control hydration.
 */
@media (max-width: 767.98px) {
    html body #appSection > #appTabs,
    html body #appSection > #appTabs.nav,
    html body #appSection > #appTabs.nav-tabs {
        border-top: 0 !important;
        border-bottom: 0 !important;
        outline: 0 !important;
        box-shadow: none !important;
        background-image: none !important;
    }

    html body #appSection > .tab-content,
    html body #appSection > .tab-content > .tab-pane,
    html body #appSection > .tab-content > .tab-pane > .row,
    html body #messagingTab .card,
    html body #profileTab .card,
    html body #settingsTab .card,
    html body #friendsTab .card,
    html body #notificationsTab .card {
        border-top: 0 !important;
        outline: 0 !important;
        box-shadow: none !important;
    }
}

/* The static audio HTML exists for a few milliseconds before AudioPlayer replaces
 * its volume input with the user's saved value. Hiding only that uninitialized
 * control prevents the visible 20% -> 100% -> 20% jump without hiding the player. */
.qchat-audio-mini-player:not([data-qchat-volume-ready="1"]) .qchat-audio-volume-wrap,
.qchat-audio-mini-player:not([data-qchat-volume-ready="1"]) .qchat-audio-volume-range {
    visibility: hidden !important;
    opacity: 0 !important;
}


/* QChat mobile polish v31 (QChat patch v39)
 * Player/file reconciliation stability after slow-network video repro.
 * The final player is restored from the in-memory decrypted HTML cache by JS;
 * keep only the finalized volume control paintable so the range never flashes
 * at its static-template 100% value between DOM replacement and AudioPlayer init.
 */
.qchat-audio-mini-player[data-qchat-volume-ready="1"] .qchat-audio-volume-wrap,
.qchat-audio-mini-player[data-qchat-volume-ready="1"] .qchat-audio-volume-range {
    visibility: visible !important;
    opacity: 1 !important;
}

/* QChat mobile polish v32 (QChat patch v43)
 * One loading surface for every encrypted attachment in chat, profile/blog and
 * forwarded blog snapshots. Supports determinate network progress without
 * replacing the placeholder while local decryption/metadata work continues.
 */
.qchat-file-hydration-stage-row {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 10px;
    min-width: 0;
}

.qchat-file-hydration-stage-row .qchat-file-hydration-stage {
    flex: 1 1 auto;
    min-width: 0;
}

.qchat-file-hydration-percent,
.qchat-file-hydration-bytes {
    flex: 0 0 auto;
    font-size: .76rem;
    color: var(--bs-secondary-color, #6c757d);
    white-space: nowrap;
}

.qchat-file-hydration-bytes {
    margin-top: 4px;
    overflow: hidden;
    text-overflow: ellipsis;
}

.qchat-file-hydration-progress.qchat-file-hydration-progress-determinate > span {
    width: var(--qchat-file-hydration-progress, 0%);
    animation: none !important;
    transform: none !important;
    transition: width .16s linear;
}

.profile-blog-attachment-preview > .qchat-file-hydration-placeholder,
.profile-blog-downloadable-attachment > .qchat-file-hydration-placeholder,
.qchat-file-bundle-preview-list .qchat-file-hydration-placeholder {
    width: 100%;
    max-width: 100%;
}

.qchat-file-hydration-compact {
    min-height: 64px;
    grid-template-columns: 34px minmax(0, 1fr);
    gap: 9px;
    padding: 9px 10px;
    border-radius: 8px;
}

.qchat-file-hydration-compact .qchat-file-hydration-icon {
    width: 34px;
    height: 34px;
    font-size: 16px;
}

.qchat-file-hydration-media-tile {
    width: 100%;
    max-width: none;
    height: 100%;
    min-height: 100%;
    border-radius: 0;
}

.qchat-file-hydration-media-tile .qchat-file-hydration-name,
.qchat-file-hydration-media-tile .qchat-file-hydration-bytes {
    display: none !important;
}

.qchat-file-hydration-media-tile .qchat-file-hydration-stage-row {
    font-size: .72rem;
}

body.dark-theme .qchat-file-hydration-percent,
body.dark-theme .qchat-file-hydration-bytes,
body.dark-theme .qchat-file-hydration-stage-row .qchat-file-hydration-stage {
    color: var(--qchat-dark-muted, #8b949e);
}

@media (prefers-color-scheme: dark) {
    body.auto-theme .qchat-file-hydration-percent,
    body.auto-theme .qchat-file-hydration-bytes,
    body.auto-theme .qchat-file-hydration-stage-row .qchat-file-hydration-stage {
        color: var(--qchat-dark-muted, #8b949e);
    }
}

.qchat-file-bundle-preview-item.qchat-file-bundle-hydration-item {
    display: block !important;
    padding: 0 !important;
    background: transparent !important;
    border: 0 !important;
}


/* QChat mobile polish v33 (QChat patch v44)
 * UI "Modern" audio player size parity between chat and Profile Blog.
 * The renderer is internally named classic; keep one exact visual lane everywhere
 * and round the actual player surface in both locations.
 */
:root {
    --qchat-modern-audio-width: 240px;
    --qchat-modern-audio-radius: 14px;
}

html body #messagesContainer .audio_card.qchat-audio-classic-card,
html body #messagesContainer .audio_card.qchat-audio-classic-card > .qchat-audio-classic-player,
html body #messagesContainer .qchat-audio-classic-player,
html body .profile-blog-post .audio_card.qchat-audio-classic-card,
html body .profile-blog-post .audio_card.qchat-audio-classic-card > .qchat-audio-classic-player,
html body .profile-blog-post .qchat-audio-classic-player,
html body .profile-blog-audio-section .audio_card.qchat-audio-classic-card,
html body .profile-blog-audio-section .qchat-audio-classic-player,
html body .profile-blog-attachment-preview .audio_card.qchat-audio-classic-card,
html body .profile-blog-attachment-preview .qchat-audio-classic-player {
    width: min(var(--qchat-modern-audio-width), 100%) !important;
    min-width: min(var(--qchat-modern-audio-width), 100%) !important;
    max-width: var(--qchat-modern-audio-width) !important;
    inline-size: min(var(--qchat-modern-audio-width), 100%) !important;
    min-inline-size: min(var(--qchat-modern-audio-width), 100%) !important;
    max-inline-size: var(--qchat-modern-audio-width) !important;
    flex: 0 1 var(--qchat-modern-audio-width) !important;
    flex-basis: var(--qchat-modern-audio-width) !important;
    box-sizing: border-box !important;
}

/* Profile wrappers used to reserve a wider lane than the same player in chat. */
html body .profile-blog-post .profile-blog-attachments:has(.audio_card.qchat-audio-classic-card),
html body .profile-blog-post .profile-blog-file-bundle-message:has(.audio_card.qchat-audio-classic-card),
html body .profile-blog-post .profile-blog-file-bundle-groups:has(.audio_card.qchat-audio-classic-card),
html body .profile-blog-post .profile-blog-audio-group:has(.audio_card.qchat-audio-classic-card),
html body .profile-blog-post .profile-blog-audio-list:has(.audio_card.qchat-audio-classic-card),
html body .profile-blog-post .profile-blog-audio-attachment:has(.audio_card.qchat-audio-classic-card),
html body .profile-blog-post .profile-blog-attachment-preview:has(.audio_card.qchat-audio-classic-card),
html body .profile-blog-post .qchat-file-bundle-group-audio:has(.audio_card.qchat-audio-classic-card),
html body .profile-blog-post .qchat-file-bundle-list-audio:has(.audio_card.qchat-audio-classic-card),
html body .profile-blog-post .qchat-file-bundle-item-audio:has(.audio_card.qchat-audio-classic-card) {
    width: min(var(--qchat-modern-audio-width), 100%) !important;
    min-width: 0 !important;
    max-width: var(--qchat-modern-audio-width) !important;
    inline-size: min(var(--qchat-modern-audio-width), 100%) !important;
    max-inline-size: var(--qchat-modern-audio-width) !important;
    flex: 0 1 var(--qchat-modern-audio-width) !important;
    flex-basis: var(--qchat-modern-audio-width) !important;
    box-sizing: border-box !important;
}

html body #messagesContainer .audio_card.qchat-audio-classic-card,
html body #messagesContainer .audio_card.qchat-audio-classic-card .current-song,
html body #messagesContainer .qchat-audio-classic-player,
html body .profile-blog-post .audio_card.qchat-audio-classic-card,
html body .profile-blog-post .audio_card.qchat-audio-classic-card .current-song,
html body .profile-blog-post .qchat-audio-classic-player,
html body .profile-blog-audio-section .audio_card.qchat-audio-classic-card,
html body .profile-blog-audio-section .qchat-audio-classic-player {
    border-radius: var(--qchat-modern-audio-radius) !important;
    overflow: hidden !important;
}

@media (max-width: 260px) {
    html body #messagesContainer .audio_card.qchat-audio-classic-card,
    html body #messagesContainer .qchat-audio-classic-player,
    html body .profile-blog-post .audio_card.qchat-audio-classic-card,
    html body .profile-blog-post .qchat-audio-classic-player,
    html body .profile-blog-audio-section .audio_card.qchat-audio-classic-card,
    html body .profile-blog-audio-section .qchat-audio-classic-player {
        width: 100% !important;
        min-width: 0 !important;
        max-width: 100% !important;
        inline-size: 100% !important;
        min-inline-size: 0 !important;
        max-inline-size: 100% !important;
        flex-basis: 100% !important;
    }
}


/* QChat mobile polish v35 (QChat patch v46)
 * Modern player: Profile Blog is the reference rendering.
 * IMPORTANT: this renderer is a column flexbox. A numeric flex-basis on
 * .qchat-audio-classic-player is therefore a HEIGHT, not a width; the old
 * 240px basis clipped the controls row in chat. Keep the 240px width via
 * width/max-width only and let the player use its natural content height.
 */
:root {
    --qchat-modern-audio-width: 240px;
}

html body #messagesContainer .message:not(:has(.saved-profile-blog-post)):has(.audio_card.qchat-audio-classic-card) .message-content-wrapper,
html body #messagesContainer .message:not(:has(.saved-profile-blog-post)):has(.audio_card.qchat-audio-classic-card) .message-content,
html body #messagesContainer .message:not(:has(.saved-profile-blog-post)):has(.audio_card.qchat-audio-classic-card) .decrypted-file-content,
html body #messagesContainer .message:not(:has(.saved-profile-blog-post)):has(.qchat-audio-classic-player) .message-content-wrapper,
html body #messagesContainer .message:not(:has(.saved-profile-blog-post)):has(.qchat-audio-classic-player) .message-content,
html body #messagesContainer .message:not(:has(.saved-profile-blog-post)):has(.qchat-audio-classic-player) .decrypted-file-content {
    width: var(--qchat-modern-audio-width) !important;
    min-width: 0 !important;
    max-width: var(--qchat-modern-audio-width) !important;
    inline-size: var(--qchat-modern-audio-width) !important;
    min-inline-size: 0 !important;
    max-inline-size: var(--qchat-modern-audio-width) !important;
    flex: 0 1 auto !important;
    flex-basis: auto !important;
    height: auto !important;
    min-height: 0 !important;
    max-height: none !important;
    box-sizing: border-box !important;
    overflow: visible !important;
}

html body #messagesContainer .message:not(:has(.saved-profile-blog-post)):has(.audio_card.qchat-audio-classic-card) .message-bubble,
html body #messagesContainer .message:not(:has(.saved-profile-blog-post)):has(.qchat-audio-classic-player) .message-bubble {
    width: fit-content !important;
    min-width: 0 !important;
    max-width: calc(var(--qchat-modern-audio-width) + 28px) !important;
    flex: 0 1 auto !important;
    flex-basis: auto !important;
    height: auto !important;
    min-height: 0 !important;
    max-height: none !important;
    overflow: visible !important;
    box-sizing: border-box !important;
}

/* Card keeps the same 240px footprint as Profile Blog. */
html body #messagesContainer .audio_card.qchat-audio-classic-card {
    width: min(var(--qchat-modern-audio-width), 100%) !important;
    min-width: 0 !important;
    max-width: var(--qchat-modern-audio-width) !important;
    inline-size: min(var(--qchat-modern-audio-width), 100%) !important;
    min-inline-size: 0 !important;
    max-inline-size: var(--qchat-modern-audio-width) !important;
    flex: 0 1 auto !important;
    flex-basis: auto !important;
    height: auto !important;
    min-height: 0 !important;
    max-height: none !important;
    overflow: hidden !important;
    box-sizing: border-box !important;
}

/* The actual Modern player must size by content height, just like in Profile Blog. */
html body #messagesContainer .audio_card.qchat-audio-classic-card > .current-song.qchat-audio-classic-player,
html body #messagesContainer .qchat-audio-classic-player {
    width: 100% !important;
    min-width: 0 !important;
    max-width: 100% !important;
    inline-size: 100% !important;
    min-inline-size: 0 !important;
    max-inline-size: 100% !important;
    flex: 0 1 auto !important;
    flex-basis: auto !important;
    height: auto !important;
    min-height: 0 !important;
    max-height: none !important;
    overflow: visible !important;
    box-sizing: border-box !important;
    line-height: 1.5 !important;
}

html body #messagesContainer .audio_card.qchat-audio-classic-card > .current-song > .controls,
html body #messagesContainer .qchat-audio-classic-player > .controls {
    position: static !important;
    display: flex !important;
    width: 100% !important;
    min-width: 0 !important;
    max-width: 100% !important;
    min-height: 80px !important;
    height: auto !important;
    margin: 8px 0 0 !important;
    padding: 0 !important;
    align-items: center !important;
    justify-content: center !important;
    gap: 0 !important;
    flex: 0 0 auto !important;
    flex-basis: auto !important;
    flex-shrink: 0 !important;
    visibility: visible !important;
    opacity: 1 !important;
    overflow: visible !important;
    transform: none !important;
    box-sizing: border-box !important;
}

html body #messagesContainer .audio_card.qchat-audio-classic-card > .current-song > .controls > button,
html body #messagesContainer .qchat-audio-classic-player > .controls > button {
    position: static !important;
    display: inline-flex !important;
    align-items: center !important;
    justify-content: center !important;
    flex: 0 0 auto !important;
    visibility: visible !important;
    opacity: 1 !important;
    pointer-events: auto !important;
    transform: none !important;
}

@media (max-width: 300px) {
    html body #messagesContainer .message:not(:has(.saved-profile-blog-post)):has(.audio_card.qchat-audio-classic-card) .message-content-wrapper,
    html body #messagesContainer .message:not(:has(.saved-profile-blog-post)):has(.audio_card.qchat-audio-classic-card) .message-content,
    html body #messagesContainer .message:not(:has(.saved-profile-blog-post)):has(.audio_card.qchat-audio-classic-card) .decrypted-file-content,
    html body #messagesContainer .audio_card.qchat-audio-classic-card {
        width: 100% !important;
        min-width: 0 !important;
        max-width: 100% !important;
        inline-size: 100% !important;
        min-inline-size: 0 !important;
        max-inline-size: 100% !important;
        flex-basis: auto !important;
    }
}


/* QChat mobile polish v32 (QChat patch v40)
 * 1) The home brand is a navigation control, not an input: never leave a
 *    persistent browser focus ring around the logo after returning from it.
 * 2) Profile/settings already live inside the dynamic-viewport flex shell.
 *    Override the old calc(100vh - 180px) inner scroller height so installed
 *    Android PWAs do not reserve an extra blank strip below those tabs.
 */
.qchat-home-logo,
.qchat-home-logo:hover,
.qchat-home-logo:focus,
.qchat-home-logo:focus-visible,
.qchat-home-logo:active {
    outline: 0 !important;
    box-shadow: none !important;
    border-color: transparent !important;
}

@media (max-width: 767.98px) {
    #profileTab,
    #settingsTab,
    #profileTab > .row,
    #settingsTab > .row,
    #profileTab > .row > [class*="col-"],
    #settingsTab > .row > [class*="col-"],
    #profileTab > .row > [class*="col-"] > .card,
    #settingsTab > .row > [class*="col-"] > .card {
        height: 100% !important;
        min-height: 0 !important;
        max-height: 100% !important;
    }

    #profileTab > .row > [class*="col-"],
    #settingsTab > .row > [class*="col-"] {
        display: flex !important;
        flex-direction: column !important;
    }

    #profileTab .profile-tab-scroll,
    #settingsTab .settings-tab-scroll {
        flex: 1 1 0 !important;
        height: 100% !important;
        min-height: 0 !important;
        max-height: 100% !important;
        overflow-y: auto !important;
        overflow-x: hidden !important;
        -webkit-overflow-scrolling: touch;
        overscroll-behavior-y: contain;
        box-sizing: border-box !important;
    }
}

/* QChat mobile polish v38
 * Normalize the outer bubble width for ordinary one-image chat messages.
 * Several image render paths coexist (direct single preview, legacy one-image
 * bundle, and the source-level qchat-chat-blog single-image renderer). Their
 * thumbnails are already compact, but the outer message could still inherit a
 * much wider generic message lane. Keep the thumbnail/original behavior intact
 * and only normalize the desktop/tablet message shell around one image. */
@media (min-width: 768px) {
    html body #messagesContainer > .message:has(.qchat-chat-blog-single-image-host):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex,
    html body #messagesContainer > .message:has(.file-preview.image-preview.qchat-chat-image-tile[data-qchat-single-image="1"]):not(:has(.qchat-file-bundle-grid-images)):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex,
    html body #messagesContainer > .message:has(.qchat-file-bundle-grid.qchat-file-bundle-grid-images[data-file-group-count="1"]):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex {
        width: fit-content !important;
        max-width: min(380px, calc(100vw - 24px)) !important;
        min-width: 0 !important;
        flex: 0 1 auto !important;
        box-sizing: border-box !important;
        align-items: flex-end !important;
        gap: var(--qchat-message-row-gap, 8px) !important;
    }

    html body #messagesContainer > .message.sent:has(.qchat-chat-blog-single-image-host):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex,
    html body #messagesContainer > .message.sent:has(.file-preview.image-preview.qchat-chat-image-tile[data-qchat-single-image="1"]):not(:has(.qchat-file-bundle-grid-images)):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex,
    html body #messagesContainer > .message.sent:has(.qchat-file-bundle-grid.qchat-file-bundle-grid-images[data-file-group-count="1"]):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex {
        margin-left: auto !important;
        margin-right: 0 !important;
        justify-content: flex-end !important;
    }

    html body #messagesContainer > .message.received:has(.qchat-chat-blog-single-image-host):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex,
    html body #messagesContainer > .message.received:has(.file-preview.image-preview.qchat-chat-image-tile[data-qchat-single-image="1"]):not(:has(.qchat-file-bundle-grid-images)):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex,
    html body #messagesContainer > .message.received:has(.qchat-file-bundle-grid.qchat-file-bundle-grid-images[data-file-group-count="1"]):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex {
        margin-left: 0 !important;
        margin-right: auto !important;
        justify-content: flex-start !important;
    }

    html body #messagesContainer > .message:has(.qchat-chat-blog-single-image-host):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex > .message-bubble,
    html body #messagesContainer > .message:has(.file-preview.image-preview.qchat-chat-image-tile[data-qchat-single-image="1"]):not(:has(.qchat-file-bundle-grid-images)):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex > .message-bubble,
    html body #messagesContainer > .message:has(.qchat-file-bundle-grid.qchat-file-bundle-grid-images[data-file-group-count="1"]):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex > .message-bubble {
        flex: 0 0 auto !important;
        width: 324px !important;
        max-width: min(324px, calc(100vw - 96px)) !important;
        min-width: 0 !important;
        margin-left: 0 !important;
        margin-right: 0 !important;
        overflow: hidden !important;
        box-sizing: border-box !important;
    }

    html body #messagesContainer > .message:has(.qchat-chat-blog-single-image-host):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex > .message-bubble :is(.message-content-wrapper, .message-header, .message-content, .decrypted-file-content, .message-footer),
    html body #messagesContainer > .message:has(.file-preview.image-preview.qchat-chat-image-tile[data-qchat-single-image="1"]):not(:has(.qchat-file-bundle-grid-images)):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex > .message-bubble :is(.message-content-wrapper, .message-header, .message-content, .decrypted-file-content, .message-footer),
    html body #messagesContainer > .message:has(.qchat-file-bundle-grid.qchat-file-bundle-grid-images[data-file-group-count="1"]):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex > .message-bubble :is(.message-content-wrapper, .message-header, .message-content, .decrypted-file-content, .message-footer) {
        width: 100% !important;
        max-width: 100% !important;
        min-width: 0 !important;
        box-sizing: border-box !important;
    }
}

/* QChat mobile polish v39
 * Ordinary chat image cards reuse Profile Blog attachment classes. The Blog
 * feed intentionally indents attachments by 46px, but in a received chat row
 * that margin consumes the bubble's content lane and pushes/shrinks the preview
 * against the right edge. Direct chat source media must not inherit that indent. */
html body #messagesContainer > .message:has(.qchat-chat-blog-image-host):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment))
    .qchat-chat-blog-image-host.profile-blog-attachments.qchat-profile-blog-bundle-host {
    margin-left: 0 !important;
    margin-right: 0 !important;
}

/* QChat mobile polish v42
 * Desktop lone-image previews now mirror the phone geometry: keep a bounded
 * preview width, but let the lane height follow the real media aspect ratio.
 * This removes the desktop-only 300x300 square stage, so wide screenshots are
 * rendered as wide previews and portrait photos remain proportional. Multi-image
 * albums are not touched. */
@media (min-width: 769px) {
    html body #messagesContainer > .message:has(.qchat-chat-blog-single-image-host):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment))
        .qchat-chat-blog-single-image-host,
    html body #messagesContainer > .message:has(.qchat-chat-blog-single-image-host):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment))
        .qchat-chat-blog-single-image-host .qchat-chat-blog-file-bundle-message,
    html body #messagesContainer > .message:has(.qchat-chat-blog-single-image-host):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment))
        .qchat-chat-blog-single-image-host .qchat-chat-blog-file-bundle-groups,
    html body #messagesContainer > .message:has(.qchat-chat-blog-single-image-host):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment))
        .qchat-chat-blog-single-image-host .qchat-chat-blog-gallery-group {
        width: 300px !important;
        max-width: min(300px, calc(100vw - 96px)) !important;
        min-width: 0 !important;
        height: auto !important;
        min-height: 0 !important;
        max-height: none !important;
        box-sizing: border-box !important;
    }

    html body #messagesContainer > .message:has(.qchat-chat-blog-single-image-host):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment))
        .qchat-chat-blog-single-image-host .qchat-chat-blog-gallery[data-file-group-count="1"] {
        width: 300px !important;
        max-width: min(300px, calc(100vw - 96px)) !important;
        height: auto !important;
        min-height: 0 !important;
        max-height: none !important;
        aspect-ratio: var(--qchat-album-ratio, 1) !important;
        grid-template-columns: minmax(0, 1fr) !important;
        grid-template-rows: minmax(0, 1fr) !important;
        overflow: hidden !important;
        place-items: stretch !important;
        box-sizing: border-box !important;
    }

    html body #messagesContainer > .message:has(.qchat-chat-blog-single-image-host):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment))
        .qchat-chat-blog-single-image-host .qchat-chat-blog-gallery[data-file-group-count="1"] :is(
            .qchat-chat-blog-gallery-item,
            .qchat-chat-blog-gallery-tile,
            .qchat-chat-blog-attachment-preview
        ) {
        width: 100% !important;
        max-width: none !important;
        min-width: 0 !important;
        height: 100% !important;
        min-height: 0 !important;
        max-height: none !important;
        aspect-ratio: auto !important;
        box-sizing: border-box !important;
    }

    html body #messagesContainer > .message:has(.qchat-chat-blog-single-image-host):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment))
        .qchat-chat-blog-single-image-host .qchat-chat-blog-gallery[data-file-group-count="1"] img.qchat-chat-blog-image {
        width: 100% !important;
        max-width: none !important;
        min-width: 0 !important;
        height: 100% !important;
        min-height: 0 !important;
        max-height: none !important;
        object-fit: contain !important;
        object-position: center center !important;
        transform: none !important;
        box-sizing: border-box !important;
    }
}


/* QChat mobile polish v41
 * Restore the phone lone-image geometry after the desktop square-stage fix.
 * Mobile must not shrink-wrap the source gallery: `fit-content` can collapse
 * against the reused Profile Blog 170px intrinsic lane after chat restore.
 * Give the one-image lane the same bounded phone width as before and derive
 * its height from the real album ratio. Desktop v40 remains untouched. */
@media (max-width: 768px) {
    html body #messagesContainer > .message:has(.qchat-chat-blog-single-image-host):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment))
        .qchat-chat-blog-single-image-host,
    html body #messagesContainer > .message:has(.qchat-chat-blog-single-image-host):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment))
        .qchat-chat-blog-single-image-host .qchat-chat-blog-file-bundle-message,
    html body #messagesContainer > .message:has(.qchat-chat-blog-single-image-host):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment))
        .qchat-chat-blog-single-image-host .qchat-chat-blog-file-bundle-groups,
    html body #messagesContainer > .message:has(.qchat-chat-blog-single-image-host):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment))
        .qchat-chat-blog-single-image-host .qchat-chat-blog-gallery-group {
        width: min(72vw, 300px) !important;
        max-width: min(72vw, 300px) !important;
        min-width: 0 !important;
        height: auto !important;
        min-height: 0 !important;
        max-height: none !important;
        align-self: flex-start !important;
        flex: 0 0 auto !important;
        box-sizing: border-box !important;
    }

    html body #messagesContainer > .message:has(.qchat-chat-blog-single-image-host):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment))
        .qchat-chat-blog-single-image-host .qchat-chat-blog-gallery[data-file-group-count="1"] {
        width: min(72vw, 300px) !important;
        max-width: min(72vw, 300px) !important;
        min-width: 0 !important;
        height: auto !important;
        min-height: 0 !important;
        max-height: min(280px, 38dvh) !important;
        aspect-ratio: var(--qchat-album-ratio, 1) !important;
        grid-template-columns: minmax(0, 1fr) !important;
        grid-template-rows: minmax(0, 1fr) !important;
        overflow: hidden !important;
        place-items: stretch !important;
        box-sizing: border-box !important;
    }

    html body #messagesContainer > .message:has(.qchat-chat-blog-single-image-host):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment))
        .qchat-chat-blog-single-image-host .qchat-chat-blog-gallery[data-file-group-count="1"] :is(
            .qchat-chat-blog-gallery-item,
            .qchat-chat-blog-gallery-tile,
            .qchat-chat-blog-attachment-preview
        ) {
        width: 100% !important;
        max-width: none !important;
        min-width: 0 !important;
        height: 100% !important;
        min-height: 0 !important;
        max-height: none !important;
        aspect-ratio: auto !important;
        box-sizing: border-box !important;
    }

    html body #messagesContainer > .message:has(.qchat-chat-blog-single-image-host):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment))
        .qchat-chat-blog-single-image-host .qchat-chat-blog-gallery[data-file-group-count="1"] img.qchat-chat-blog-image {
        width: 100% !important;
        max-width: none !important;
        min-width: 0 !important;
        height: 100% !important;
        min-height: 0 !important;
        max-height: none !important;
        object-fit: contain !important;
        object-position: center center !important;
        transform: none !important;
        box-sizing: border-box !important;
    }
}

/* QChat mobile polish v43
 * Two-image chat bundles were still inheriting the generic full-width phone
 * message lane from v9/v10. Desktop keeps these albums shrink-wrapped around
 * the media, which is much easier to scan. Mirror that behavior on phones,
 * while keeping the already-approved compact 72vw media lane used by lone
 * images. Only ordinary two-image chat bundles are affected; saved Blog cards,
 * one-image previews, and albums with 3+ items keep their existing geometry. */
@media (max-width: 767.98px) {
    html body #messagesContainer > .message:has(.qchat-chat-blog-multi-image-host .qchat-chat-blog-gallery[data-file-group-count="2"]):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex,
    html body #messagesContainer > .message:has(.qchat-file-bundle-grid.qchat-file-bundle-grid-images[data-file-group-count="2"]):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex {
        width: fit-content !important;
        max-width: calc(100% - 8px) !important;
        min-width: 0 !important;
        flex: 0 1 auto !important;
        gap: 0 !important;
        box-sizing: border-box !important;
    }

    html body #messagesContainer > .message.sent:has(.qchat-chat-blog-multi-image-host .qchat-chat-blog-gallery[data-file-group-count="2"]):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex,
    html body #messagesContainer > .message.sent:has(.qchat-file-bundle-grid.qchat-file-bundle-grid-images[data-file-group-count="2"]):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex {
        margin-left: auto !important;
        margin-right: 0 !important;
        justify-content: flex-end !important;
    }

    html body #messagesContainer > .message.received:has(.qchat-chat-blog-multi-image-host .qchat-chat-blog-gallery[data-file-group-count="2"]):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex,
    html body #messagesContainer > .message.received:has(.qchat-file-bundle-grid.qchat-file-bundle-grid-images[data-file-group-count="2"]):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex {
        margin-left: 0 !important;
        margin-right: auto !important;
        justify-content: flex-start !important;
    }

    html body #messagesContainer > .message:has(.qchat-chat-blog-multi-image-host .qchat-chat-blog-gallery[data-file-group-count="2"]):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex > .message-bubble,
    html body #messagesContainer > .message:has(.qchat-file-bundle-grid.qchat-file-bundle-grid-images[data-file-group-count="2"]):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex > .message-bubble {
        flex: 0 0 auto !important;
        width: min(calc(72vw + 24px), 324px) !important;
        max-width: calc(100vw - 8px) !important;
        min-width: 0 !important;
        margin-left: 0 !important;
        margin-right: 0 !important;
        overflow: hidden !important;
        box-sizing: border-box !important;
    }

    html body #messagesContainer > .message:has(.qchat-chat-blog-multi-image-host .qchat-chat-blog-gallery[data-file-group-count="2"]):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment))
        .qchat-chat-blog-multi-image-host,
    html body #messagesContainer > .message:has(.qchat-chat-blog-multi-image-host .qchat-chat-blog-gallery[data-file-group-count="2"]):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment))
        .qchat-chat-blog-multi-image-host .qchat-chat-blog-file-bundle-message,
    html body #messagesContainer > .message:has(.qchat-chat-blog-multi-image-host .qchat-chat-blog-gallery[data-file-group-count="2"]):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment))
        .qchat-chat-blog-multi-image-host .qchat-chat-blog-file-bundle-groups,
    html body #messagesContainer > .message:has(.qchat-chat-blog-multi-image-host .qchat-chat-blog-gallery[data-file-group-count="2"]):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment))
        .qchat-chat-blog-multi-image-host .qchat-chat-blog-gallery-group,
    html body #messagesContainer > .message:has(.qchat-chat-blog-multi-image-host .qchat-chat-blog-gallery[data-file-group-count="2"]):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment))
        .qchat-chat-blog-multi-image-host .qchat-chat-blog-gallery[data-file-group-count="2"] {
        width: min(72vw, 300px) !important;
        max-width: min(72vw, 300px) !important;
        min-width: 0 !important;
        box-sizing: border-box !important;
    }

    html body #messagesContainer > .message:has(.qchat-chat-blog-multi-image-host .qchat-chat-blog-gallery[data-file-group-count="2"]):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment))
        .qchat-chat-blog-gallery[data-file-group-count="2"] {
        height: auto !important;
        max-height: none !important;
        aspect-ratio: var(--qchat-album-ratio, 2) !important;
        overflow: hidden !important;
        place-items: stretch !important;
    }

    html body #messagesContainer > .message:has(.qchat-chat-blog-multi-image-host .qchat-chat-blog-gallery[data-file-group-count="2"]):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment))
        .qchat-chat-blog-gallery[data-file-group-count="2"] :is(.qchat-chat-blog-gallery-item, .qchat-chat-blog-gallery-tile, .qchat-chat-blog-attachment-preview, img.qchat-chat-blog-image) {
        min-width: 0 !important;
        min-height: 0 !important;
        max-width: none !important;
        max-height: none !important;
        box-sizing: border-box !important;
    }
}


/* QChat mobile polish v44
 * Follow-up for the two-image phone album. v43 shrink-wrapped the whole
 * message row/bubble around the desktop-sized media lane; on phones that made
 * outgoing cards look shifted to the right. Keep the normal full-width mobile
 * message lane, but center only the compact two-image media bundle inside it.
 * Also own the outer album corners explicitly because source-rendered tiles
 * carry runtime border-radius:0 styles. */
@media (max-width: 767.98px) {
    html body #messagesContainer > .message:has(.qchat-chat-blog-multi-image-host .qchat-chat-blog-gallery[data-file-group-count="2"]):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex,
    html body #messagesContainer > .message:has(.qchat-file-bundle-grid.qchat-file-bundle-grid-images[data-file-group-count="2"]):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex {
        width: 100% !important;
        max-width: 100% !important;
        min-width: 0 !important;
        flex: 1 1 100% !important;
        margin-left: 0 !important;
        margin-right: 0 !important;
        justify-content: flex-start !important;
        gap: 0 !important;
        box-sizing: border-box !important;
    }

    html body #messagesContainer > .message:has(.qchat-chat-blog-multi-image-host .qchat-chat-blog-gallery[data-file-group-count="2"]):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex > .message-bubble,
    html body #messagesContainer > .message:has(.qchat-file-bundle-grid.qchat-file-bundle-grid-images[data-file-group-count="2"]):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex > .message-bubble {
        flex: 1 1 100% !important;
        width: 100% !important;
        max-width: 100% !important;
        min-width: 0 !important;
        margin-left: 0 !important;
        margin-right: 0 !important;
        overflow: visible !important;
        box-sizing: border-box !important;
    }

    /* Keep the compact two-image lane, but place it predictably in the middle
       of the phone bubble instead of letting sent/received row alignment move
       the whole card sideways. */
    html body #messagesContainer > .message:has(.qchat-chat-blog-multi-image-host .qchat-chat-blog-gallery[data-file-group-count="2"]):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment))
        .qchat-chat-blog-multi-image-host {
        margin-left: auto !important;
        margin-right: auto !important;
    }

    html body #messagesContainer > .message:has(.qchat-chat-blog-multi-image-host .qchat-chat-blog-gallery[data-file-group-count="2"]):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment))
        .qchat-chat-blog-gallery[data-file-group-count="2"] {
        border-radius: 12px !important;
        overflow: hidden !important;
        isolation: isolate !important;
    }

    /* Source tiles intentionally have border-radius:0 in their runtime style.
       Clip the two edge items themselves so the desktop-style outer corners
       remain visible on Android/WebView as well. */
    html body #messagesContainer > .message:has(.qchat-chat-blog-multi-image-host .qchat-chat-blog-gallery[data-file-group-count="2"][data-qchat-album-layout="tg-2-side"]):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment))
        .qchat-chat-blog-gallery[data-file-group-count="2"][data-qchat-album-layout="tg-2-side"] > .qchat-chat-blog-gallery-item[data-qchat-chat-blog-gallery-index="0"] {
        border-radius: 12px 0 0 12px !important;
        overflow: hidden !important;
    }

    html body #messagesContainer > .message:has(.qchat-chat-blog-multi-image-host .qchat-chat-blog-gallery[data-file-group-count="2"][data-qchat-album-layout="tg-2-side"]):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment))
        .qchat-chat-blog-gallery[data-file-group-count="2"][data-qchat-album-layout="tg-2-side"] > .qchat-chat-blog-gallery-item[data-qchat-chat-blog-gallery-index="1"] {
        border-radius: 0 12px 12px 0 !important;
        overflow: hidden !important;
    }

    html body #messagesContainer > .message:has(.qchat-chat-blog-multi-image-host .qchat-chat-blog-gallery[data-file-group-count="2"][data-qchat-album-layout="tg-2-stack"]):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment))
        .qchat-chat-blog-gallery[data-file-group-count="2"][data-qchat-album-layout="tg-2-stack"] > .qchat-chat-blog-gallery-item[data-qchat-chat-blog-gallery-index="0"] {
        border-radius: 12px 12px 0 0 !important;
        overflow: hidden !important;
    }

    html body #messagesContainer > .message:has(.qchat-chat-blog-multi-image-host .qchat-chat-blog-gallery[data-file-group-count="2"][data-qchat-album-layout="tg-2-stack"]):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment))
        .qchat-chat-blog-gallery[data-file-group-count="2"][data-qchat-album-layout="tg-2-stack"] > .qchat-chat-blog-gallery-item[data-qchat-chat-blog-gallery-index="1"] {
        border-radius: 0 0 12px 12px !important;
        overflow: hidden !important;
    }
}

/* QChat mobile polish v45
 * Two-image albums already round the outer gallery/item shells, but the
 * source-rendered tile/preview/image layers carry their own radius:0 runtime
 * rules. Round the visible media layers too, so the actual photos have the
 * same outer corners as the desktop album rather than only the dark wrapper. */
@media (max-width: 767.98px) {
    html body #messagesContainer > .message:has(.qchat-chat-blog-multi-image-host .qchat-chat-blog-gallery[data-file-group-count="2"][data-qchat-album-layout="tg-2-side"]):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment))
        .qchat-chat-blog-gallery[data-file-group-count="2"][data-qchat-album-layout="tg-2-side"] > .qchat-chat-blog-gallery-item[data-qchat-chat-blog-gallery-index="0"] :is(.qchat-chat-blog-gallery-tile, .qchat-chat-blog-attachment-preview, img.qchat-chat-blog-image) {
        border-radius: 12px 0 0 12px !important;
        overflow: hidden !important;
    }

    html body #messagesContainer > .message:has(.qchat-chat-blog-multi-image-host .qchat-chat-blog-gallery[data-file-group-count="2"][data-qchat-album-layout="tg-2-side"]):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment))
        .qchat-chat-blog-gallery[data-file-group-count="2"][data-qchat-album-layout="tg-2-side"] > .qchat-chat-blog-gallery-item[data-qchat-chat-blog-gallery-index="1"] :is(.qchat-chat-blog-gallery-tile, .qchat-chat-blog-attachment-preview, img.qchat-chat-blog-image) {
        border-radius: 0 12px 12px 0 !important;
        overflow: hidden !important;
    }

    html body #messagesContainer > .message:has(.qchat-chat-blog-multi-image-host .qchat-chat-blog-gallery[data-file-group-count="2"][data-qchat-album-layout="tg-2-stack"]):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment))
        .qchat-chat-blog-gallery[data-file-group-count="2"][data-qchat-album-layout="tg-2-stack"] > .qchat-chat-blog-gallery-item[data-qchat-chat-blog-gallery-index="0"] :is(.qchat-chat-blog-gallery-tile, .qchat-chat-blog-attachment-preview, img.qchat-chat-blog-image) {
        border-radius: 12px 12px 0 0 !important;
        overflow: hidden !important;
    }

    html body #messagesContainer > .message:has(.qchat-chat-blog-multi-image-host .qchat-chat-blog-gallery[data-file-group-count="2"][data-qchat-album-layout="tg-2-stack"]):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment))
        .qchat-chat-blog-gallery[data-file-group-count="2"][data-qchat-album-layout="tg-2-stack"] > .qchat-chat-blog-gallery-item[data-qchat-chat-blog-gallery-index="1"] :is(.qchat-chat-blog-gallery-tile, .qchat-chat-blog-attachment-preview, img.qchat-chat-blog-image) {
        border-radius: 0 0 12px 12px !important;
        overflow: hidden !important;
    }
}

/* QChat mobile polish v46
 * Desktop source-rendered multi-image chat albums must own a stable 360px
 * content lane. The chat bubble itself shrink-wraps with width:fit-content;
 * using width:min(360px,100%) on every nested Profile Blog-compatible wrapper
 * creates an intrinsic-size feedback loop. Symmetric/even layouts (2/4/6/8/10)
 * can then collapse toward their min-content width while odd hero layouts stay
 * visibly wider. Mobile does not have this problem because its message lane is
 * explicitly constrained, so keep the fix desktop-only.
 *
 * Pin only ordinary source chat albums (2+ images) to the renderer's intended
 * 360px lane. Saved Profile/Blog cards and single-image previews keep their
 * existing geometry. */
@media (min-width: 769px) {
    html body #messagesContainer > .message:has(.qchat-chat-blog-multi-image-host):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment))
        .qchat-chat-blog-multi-image-host,
    html body #messagesContainer > .message:has(.qchat-chat-blog-multi-image-host):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment))
        .qchat-chat-blog-multi-image-host .qchat-chat-blog-file-bundle-message,
    html body #messagesContainer > .message:has(.qchat-chat-blog-multi-image-host):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment))
        .qchat-chat-blog-multi-image-host .qchat-chat-blog-file-bundle-groups,
    html body #messagesContainer > .message:has(.qchat-chat-blog-multi-image-host):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment))
        .qchat-chat-blog-multi-image-host .qchat-chat-blog-gallery-group,
    html body #messagesContainer > .message:has(.qchat-chat-blog-multi-image-host):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment))
        .qchat-chat-blog-multi-image-host .qchat-chat-blog-gallery {
        width: 360px !important;
        max-width: 360px !important;
        min-width: 360px !important;
        box-sizing: border-box !important;
    }

    /* Let the bubble shrink-wrap around that fixed media lane instead of using
       the album's row/column min-content width as the bubble width. */
    html body #messagesContainer > .message:has(.qchat-chat-blog-multi-image-host):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment))
        > .d-flex > .message-bubble,
    html body #messagesContainer > .message:has(.qchat-chat-blog-multi-image-host):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment))
        > .d-flex > .message-bubble > .message-content-wrapper,
    html body #messagesContainer > .message:has(.qchat-chat-blog-multi-image-host):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment))
        > .d-flex > .message-bubble > .message-content-wrapper > .message-content,
    html body #messagesContainer > .message:has(.qchat-chat-blog-multi-image-host):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment))
        .decrypted-file-content {
        width: auto !important;
        min-width: 360px !important;
        max-width: none !important;
        box-sizing: border-box !important;
    }
}

/* QChat mobile polish v47
 * Source-rendered chat albums reuse Profile Blog tile classes. The generic
 * Profile Blog card skin gives each tile its own square aspect-ratio, border
 * and translucent background. Inside a chat CSS-grid album that creates an
 * extra inner frame and, for a two-portrait desktop pair, lets the square tile
 * sit inside the taller grid row instead of filling it. Strip that card skin
 * from ordinary chat album tiles and let the album grid own all geometry.
 *
 * Also make forwarded/saved Blog audio messages truly use the full mobile
 * message lane. The card/player already scale to 100%; the final override here
 * locks the outer message row and bubble to the same lane so sent alignment or
 * legacy fit-content rules cannot leave a large left inset. */
html body #messagesContainer > .message:has(.qchat-chat-blog-multi-image-host .qchat-chat-blog-gallery[data-file-group-count="2"]):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment))
    .qchat-chat-blog-gallery > .qchat-chat-blog-gallery-item {
    border: 0 !important;
    outline: 0 !important;
    box-shadow: none !important;
    background: transparent !important;
    padding: 0 !important;
    min-height: 0 !important;
}

html body #messagesContainer > .message:has(.qchat-chat-blog-multi-image-host .qchat-chat-blog-gallery[data-file-group-count="2"]):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment))
    .qchat-chat-blog-gallery :is(.qchat-chat-blog-gallery-tile, .qchat-chat-blog-attachment-preview, img.qchat-chat-blog-image) {
    width: 100% !important;
    height: 100% !important;
    min-width: 0 !important;
    min-height: 0 !important;
    max-width: none !important;
    max-height: none !important;
    aspect-ratio: auto !important;
    border: 0 !important;
    outline: 0 !important;
    box-shadow: none !important;
    background: transparent !important;
    box-sizing: border-box !important;
}

html body #messagesContainer > .message:has(.qchat-chat-blog-multi-image-host .qchat-chat-blog-gallery[data-file-group-count="2"]):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment))
    .qchat-chat-blog-gallery .qchat-chat-blog-gallery-tile {
    display: block !important;
    padding: 0 !important;
    margin: 0 !important;
}

html body #messagesContainer > .message:has(.qchat-chat-blog-multi-image-host .qchat-chat-blog-gallery[data-file-group-count="2"]):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment))
    .qchat-chat-blog-gallery .qchat-chat-blog-attachment-preview {
    display: block !important;
    overflow: hidden !important;
}

html body #messagesContainer > .message:has(.qchat-chat-blog-multi-image-host .qchat-chat-blog-gallery[data-file-group-count="2"]):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment))
    .qchat-chat-blog-gallery img.qchat-chat-blog-image {
    display: block !important;
    object-fit: cover !important;
    object-position: center center !important;
}

/* QChat mobile polish v48
 * v47's Profile Blog tile-skin reset is intentionally limited to the two-image
 * layout. Counts 3+ have their own hero/row geometry and must keep the existing
 * gallery-item cascade; applying the pair reset to every count flattened those
 * layouts. Mobile saved-Blog audio width is additionally enforced by the runtime
 * normalizer because its inline !important lane contract wins over stylesheet
 * overrides. */

/* Removing only the visual card chrome is safe for every multi-image count.
   Keep sizing/aspect/display contracts count-specific so 3+/hero layouts retain
   their established grid geometry. */
html body #messagesContainer > .message:has(.qchat-chat-blog-multi-image-host):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment))
    .qchat-chat-blog-gallery > .qchat-chat-blog-gallery-item,
html body #messagesContainer > .message:has(.qchat-chat-blog-multi-image-host):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment))
    .qchat-chat-blog-gallery :is(.qchat-chat-blog-gallery-tile, .qchat-chat-blog-attachment-preview, img.qchat-chat-blog-image) {
    border: 0 !important;
    outline: 0 !important;
    box-shadow: none !important;
    background: transparent !important;
}

html body #messagesContainer > .message:has(.qchat-chat-blog-multi-image-host):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment))
    .qchat-chat-blog-gallery > .qchat-chat-blog-gallery-item,
html body #messagesContainer > .message:has(.qchat-chat-blog-multi-image-host):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment))
    .qchat-chat-blog-gallery .qchat-chat-blog-gallery-tile {
    padding: 0 !important;
    margin: 0 !important;
}

@media (max-width: 767.98px) {
    html body #messagesContainer > .message:has(.saved-profile-blog-post):has(.qchat-audio-mini-player),
    html body #messagesContainer > .message:has(.saved-profile-blog-post):has(.qchat-audio-mini-group),
    html body #messagesContainer > .message:has(.saved-profile-blog-post):has(.qchat-file-bundle-group-audio),
    html body #messagesContainer > .message:has(.saved-profile-blog-post):has(.qchat-file-bundle-list-audio) {
        width: 100% !important;
        max-width: 100% !important;
        min-width: 0 !important;
        margin-left: 0 !important;
        margin-right: 0 !important;
        box-sizing: border-box !important;
    }

    html body #messagesContainer > .message:has(.saved-profile-blog-post):has(.qchat-audio-mini-player) > .d-flex,
    html body #messagesContainer > .message:has(.saved-profile-blog-post):has(.qchat-audio-mini-group) > .d-flex,
    html body #messagesContainer > .message:has(.saved-profile-blog-post):has(.qchat-file-bundle-group-audio) > .d-flex,
    html body #messagesContainer > .message:has(.saved-profile-blog-post):has(.qchat-file-bundle-list-audio) > .d-flex {
        width: 100% !important;
        max-width: 100% !important;
        min-width: 0 !important;
        flex: 1 1 100% !important;
        margin-left: 0 !important;
        margin-right: 0 !important;
        justify-content: flex-start !important;
        gap: 0 !important;
        box-sizing: border-box !important;
    }

    html body #messagesContainer > .message:has(.saved-profile-blog-post):has(.qchat-audio-mini-player) > .d-flex > .message-bubble,
    html body #messagesContainer > .message:has(.saved-profile-blog-post):has(.qchat-audio-mini-group) > .d-flex > .message-bubble,
    html body #messagesContainer > .message:has(.saved-profile-blog-post):has(.qchat-file-bundle-group-audio) > .d-flex > .message-bubble,
    html body #messagesContainer > .message:has(.saved-profile-blog-post):has(.qchat-file-bundle-list-audio) > .d-flex > .message-bubble {
        width: 100% !important;
        max-width: 100% !important;
        min-width: 0 !important;
        flex: 1 1 100% !important;
        margin-left: 0 !important;
        margin-right: 0 !important;
        box-sizing: border-box !important;
    }

    html body #messagesContainer > .message:has(.saved-profile-blog-post):has(.qchat-audio-mini-player)
        :is(.message-content-wrapper, .message-content, .saved-profile-blog-post),
    html body #messagesContainer > .message:has(.saved-profile-blog-post):has(.qchat-audio-mini-group)
        :is(.message-content-wrapper, .message-content, .saved-profile-blog-post),
    html body #messagesContainer > .message:has(.saved-profile-blog-post):has(.qchat-file-bundle-group-audio)
        :is(.message-content-wrapper, .message-content, .saved-profile-blog-post),
    html body #messagesContainer > .message:has(.saved-profile-blog-post):has(.qchat-file-bundle-list-audio)
        :is(.message-content-wrapper, .message-content, .saved-profile-blog-post) {
        width: 100% !important;
        max-width: 100% !important;
        min-width: 0 !important;
        box-sizing: border-box !important;
    }
}

/* QChat mobile polish v49
 * Saved Blog snapshots use their own message lane.  On phones the entire card,
 * including the final hydrated audio host, is fluid.  On desktop image posts keep
 * the compact 500px card and the same 360px media lane used by Profile Blog. */
@media (max-width: 767.98px) {
    html body #messagesContainer > .message:has(.saved-profile-blog-post),
    html body #messagesContainer > .message:has(.saved-profile-blog-comment),
    html body #messagesContainer > .message:has(.saved-profile-blog-post) > .d-flex,
    html body #messagesContainer > .message:has(.saved-profile-blog-comment) > .d-flex,
    html body #messagesContainer > .message:has(.saved-profile-blog-post) > .d-flex > .message-bubble,
    html body #messagesContainer > .message:has(.saved-profile-blog-comment) > .d-flex > .message-bubble,
    html body #messagesContainer > .message:has(.saved-profile-blog-post) :is(.message-content-wrapper, .message-content, .saved-profile-blog-post),
    html body #messagesContainer > .message:has(.saved-profile-blog-comment) :is(.message-content-wrapper, .message-content, .saved-profile-blog-comment) {
        width: 100% !important;
        max-width: 100% !important;
        min-width: 0 !important;
        box-sizing: border-box !important;
    }

    html body #messagesContainer > .message:has(.saved-profile-blog-post),
    html body #messagesContainer > .message:has(.saved-profile-blog-comment),
    html body #messagesContainer > .message:has(.saved-profile-blog-post) > .d-flex,
    html body #messagesContainer > .message:has(.saved-profile-blog-comment) > .d-flex,
    html body #messagesContainer > .message:has(.saved-profile-blog-post) > .d-flex > .message-bubble,
    html body #messagesContainer > .message:has(.saved-profile-blog-comment) > .d-flex > .message-bubble {
        margin-left: 0 !important;
        margin-right: 0 !important;
    }

    html body #messagesContainer .saved-profile-blog-post .profile-blog-attachments.qchat-profile-blog-bundle-host,
    html body #messagesContainer .saved-profile-blog-post .profile-blog-attachments:has(.qchat-audio-mini-player),
    html body #messagesContainer .saved-profile-blog-post .profile-blog-file-bundle-message:has(.qchat-audio-mini-player),
    html body #messagesContainer .saved-profile-blog-post .profile-blog-file-bundle-groups:has(.qchat-audio-mini-player),
    html body #messagesContainer .saved-profile-blog-post .profile-blog-audio-group,
    html body #messagesContainer .saved-profile-blog-post .profile-blog-audio-list,
    html body #messagesContainer .saved-profile-blog-post .profile-blog-audio-attachment,
    html body #messagesContainer .saved-profile-blog-post .profile-blog-audio-attachment > .profile-blog-attachment-preview,
    html body #messagesContainer .saved-profile-blog-post .qchat-audio-mini-group,
    html body #messagesContainer .saved-profile-blog-post .qchat-file-bundle-group-audio,
    html body #messagesContainer .saved-profile-blog-post .qchat-file-bundle-list-audio,
    html body #messagesContainer .saved-profile-blog-post .qchat-audio-mini-player,
    html body #messagesContainer .saved-profile-blog-post .qchat-audio-mini-player:hover,
    html body #messagesContainer .saved-profile-blog-post .qchat-audio-mini-player:focus-within,
    html body #messagesContainer .saved-profile-blog-post .qchat-audio-mini-player.playing {
        width: 100% !important;
        max-width: 100% !important;
        min-width: 0 !important;
        inline-size: 100% !important;
        max-inline-size: 100% !important;
        box-sizing: border-box !important;
    }
}

@media (min-width: 768px) {
    html body #messagesContainer > .message:has(.saved-profile-blog-post) > .d-flex,
    html body #messagesContainer > .message:has(.saved-profile-blog-comment) > .d-flex,
    html body #messagesContainer > .message:has(.saved-profile-blog-post) > .d-flex > .message-bubble,
    html body #messagesContainer > .message:has(.saved-profile-blog-comment) > .d-flex > .message-bubble,
    html body #messagesContainer > .message:has(.saved-profile-blog-post) :is(.message-content-wrapper, .message-content, .saved-profile-blog-post),
    html body #messagesContainer > .message:has(.saved-profile-blog-comment) :is(.message-content-wrapper, .message-content, .saved-profile-blog-comment) {
        width: min(500px, 100%) !important;
        max-width: min(500px, 100%) !important;
        min-width: 0 !important;
        box-sizing: border-box !important;
    }

    html body #messagesContainer .saved-profile-blog-post .profile-blog-attachments:not(:has(.qchat-audio-mini-player)):not(:has(.qchat-audio-classic-player)),
    html body #messagesContainer .saved-profile-blog-post .profile-blog-file-bundle-message:not(:has(.qchat-audio-mini-player)):not(:has(.qchat-audio-classic-player)),
    html body #messagesContainer .saved-profile-blog-post .profile-blog-file-bundle-groups:not(:has(.qchat-audio-mini-player)):not(:has(.qchat-audio-classic-player)),
    html body #messagesContainer .saved-profile-blog-post .profile-blog-gallery-group,
    html body #messagesContainer .saved-profile-blog-post .profile-blog-gallery,
    html body #messagesContainer .saved-profile-blog-post .qchat-file-bundle-grid-images {
        width: min(360px, 100%) !important;
        max-width: min(360px, 100%) !important;
        min-width: 0 !important;
        box-sizing: border-box !important;
    }
}

/* QChat mobile polish v50
 * Saved Blog cards use an explicit message class instead of depending on :has()
 * timing. This keeps the desktop card compact and the mobile card truly full-lane
 * before, during and after async attachment/audio hydration. */
@media (max-width: 767.98px) {
    html body #messagesContainer .message.qchat-saved-blog-message,
    html body #messagesContainer .message.qchat-saved-blog-message > .d-flex,
    html body #messagesContainer .message.qchat-saved-blog-message > .d-flex > .message-bubble,
    html body #messagesContainer .message.qchat-saved-blog-message .message-content-wrapper,
    html body #messagesContainer .message.qchat-saved-blog-message .message-content,
    html body #messagesContainer .message.qchat-saved-blog-message .saved-profile-blog-post,
    html body #messagesContainer .message.qchat-saved-blog-message .saved-profile-blog-comment {
        width: 100% !important;
        max-width: 100% !important;
        min-width: 0 !important;
        box-sizing: border-box !important;
    }

    html body #messagesContainer .message.qchat-saved-blog-message > .d-flex,
    html body #messagesContainer .message.qchat-saved-blog-message > .d-flex > .message-bubble {
        flex: 1 1 100% !important;
        margin-left: 0 !important;
        margin-right: 0 !important;
    }

    html body #messagesContainer .message.qchat-saved-blog-message > .d-flex {
        justify-content: flex-start !important;
        gap: 0 !important;
    }

    html body #messagesContainer .message.qchat-saved-blog-audio-message .profile-blog-attachments,
    html body #messagesContainer .message.qchat-saved-blog-audio-message .qchat-profile-blog-bundle-host,
    html body #messagesContainer .message.qchat-saved-blog-audio-message .profile-blog-file-bundle-message,
    html body #messagesContainer .message.qchat-saved-blog-audio-message .profile-blog-file-bundle-groups,
    html body #messagesContainer .message.qchat-saved-blog-audio-message .profile-blog-audio-group,
    html body #messagesContainer .message.qchat-saved-blog-audio-message .profile-blog-audio-list,
    html body #messagesContainer .message.qchat-saved-blog-audio-message .profile-blog-audio-attachment,
    html body #messagesContainer .message.qchat-saved-blog-audio-message .profile-blog-attachment-preview,
    html body #messagesContainer .message.qchat-saved-blog-audio-message .qchat-file-bundle-group-audio,
    html body #messagesContainer .message.qchat-saved-blog-audio-message .qchat-file-bundle-list-audio,
    html body #messagesContainer .message.qchat-saved-blog-audio-message .qchat-audio-mini-group,
    html body #messagesContainer .message.qchat-saved-blog-audio-message .qchat-audio-mini-player {
        width: 100% !important;
        max-width: 100% !important;
        min-width: 0 !important;
        inline-size: 100% !important;
        max-inline-size: 100% !important;
        box-sizing: border-box !important;
    }
}

@media (min-width: 768px) {
    html body #messagesContainer .message.qchat-saved-blog-message > .d-flex,
    html body #messagesContainer .message.qchat-saved-blog-message > .d-flex > .message-bubble,
    html body #messagesContainer .message.qchat-saved-blog-message .message-content-wrapper,
    html body #messagesContainer .message.qchat-saved-blog-message .message-content,
    html body #messagesContainer .message.qchat-saved-blog-message .saved-profile-blog-post,
    html body #messagesContainer .message.qchat-saved-blog-message .saved-profile-blog-comment {
        width: min(500px, 100%) !important;
        max-width: min(500px, 100%) !important;
        min-width: 0 !important;
        box-sizing: border-box !important;
    }

    html body #messagesContainer .message.sent.qchat-saved-blog-message > .d-flex {
        margin-left: auto !important;
        margin-right: 0 !important;
    }

    html body #messagesContainer .message.received.qchat-saved-blog-message > .d-flex {
        margin-left: 0 !important;
        margin-right: auto !important;
    }
}


/* QChat mobile polish v51
 * Final Saved Blog message-lane contract.
 * - Mobile snapshots must remain visible and occupy the same full chat lane as
 *   ordinary audio/file messages after ACK, history replacement and hydration.
 * - Desktop image snapshots shrink to the 360px media lane + card padding,
 *   instead of reserving the old generic 500px text-card width. */
@media (max-width: 767.98px) {
    html body #messagesContainer > .message.qchat-saved-blog-message,
    html body #messagesContainer > .message.qchat-saved-blog-message > .d-flex,
    html body #messagesContainer > .message.qchat-saved-blog-message > .d-flex > .message-bubble,
    html body #messagesContainer > .message.qchat-saved-blog-message .message-content-wrapper,
    html body #messagesContainer > .message.qchat-saved-blog-message .message-content,
    html body #messagesContainer > .message.qchat-saved-blog-message .saved-profile-blog-post,
    html body #messagesContainer > .message.qchat-saved-blog-message .saved-profile-blog-comment,
    html body #messagesContainer > .message:has(.message-content > .saved-profile-blog-post),
    html body #messagesContainer > .message:has(.message-content > .saved-profile-blog-comment),
    html body #messagesContainer > .message:has(.message-content > .saved-profile-blog-post) > .d-flex,
    html body #messagesContainer > .message:has(.message-content > .saved-profile-blog-comment) > .d-flex,
    html body #messagesContainer > .message:has(.message-content > .saved-profile-blog-post) > .d-flex > .message-bubble,
    html body #messagesContainer > .message:has(.message-content > .saved-profile-blog-comment) > .d-flex > .message-bubble {
        width: 100% !important;
        max-width: 100% !important;
        min-width: 0 !important;
        box-sizing: border-box !important;
        margin-left: 0 !important;
        margin-right: 0 !important;
    }

    html body #messagesContainer > .message.qchat-saved-blog-message > .d-flex,
    html body #messagesContainer > .message:has(.message-content > .saved-profile-blog-post) > .d-flex,
    html body #messagesContainer > .message:has(.message-content > .saved-profile-blog-comment) > .d-flex {
        flex: 1 1 100% !important;
        justify-content: flex-start !important;
        gap: 0 !important;
    }

    html body #messagesContainer > .message.qchat-saved-blog-message > .d-flex > .message-bubble,
    html body #messagesContainer > .message:has(.message-content > .saved-profile-blog-post) > .d-flex > .message-bubble,
    html body #messagesContainer > .message:has(.message-content > .saved-profile-blog-comment) > .d-flex > .message-bubble {
        flex: 1 1 100% !important;
        overflow: visible !important;
        height: auto !important;
        max-height: none !important;
    }

    html body #messagesContainer > .message.qchat-saved-blog-message :is(.message-content-wrapper, .message-content),
    html body #messagesContainer > .message:has(.message-content > .saved-profile-blog-post) :is(.message-content-wrapper, .message-content),
    html body #messagesContainer > .message:has(.message-content > .saved-profile-blog-comment) :is(.message-content-wrapper, .message-content) {
        width: 100% !important;
        max-width: 100% !important;
        min-width: 0 !important;
        height: auto !important;
        max-height: none !important;
        overflow: visible !important;
        box-sizing: border-box !important;
    }

    html body #messagesContainer > .message.qchat-saved-blog-message .saved-profile-blog-post,
    html body #messagesContainer > .message.qchat-saved-blog-message .saved-profile-blog-comment,
    html body #messagesContainer > .message:has(.message-content > .saved-profile-blog-post) .saved-profile-blog-post,
    html body #messagesContainer > .message:has(.message-content > .saved-profile-blog-comment) .saved-profile-blog-comment {
        display: block !important;
        visibility: visible !important;
        opacity: 1 !important;
        position: relative !important;
        width: 100% !important;
        max-width: 100% !important;
        min-width: 0 !important;
        height: auto !important;
        min-height: 0 !important;
        max-height: none !important;
        overflow: visible !important;
        box-sizing: border-box !important;
    }

    html body #messagesContainer > .message.qchat-saved-blog-audio-message .saved-profile-blog-post :is(
        .profile-blog-attachments,
        .qchat-profile-blog-bundle-host,
        .profile-blog-file-bundle-message,
        .qchat-file-bundle-message,
        .profile-blog-file-bundle-groups,
        .qchat-file-bundle-groups,
        .profile-blog-audio-group,
        .profile-blog-audio-list,
        .profile-blog-audio-attachment,
        .profile-blog-attachment-preview,
        .qchat-file-bundle-group-audio,
        .qchat-file-bundle-list-audio,
        .qchat-audio-mini-group,
        .qchat-audio-mini-player
    ) {
        width: 100% !important;
        max-width: 100% !important;
        min-width: 0 !important;
        inline-size: 100% !important;
        max-inline-size: 100% !important;
        box-sizing: border-box !important;
    }
}

@media (min-width: 768px) {
    html body #messagesContainer > .message.qchat-saved-blog-image-message:not(.qchat-saved-blog-audio-message):has(.message-content > .saved-profile-blog-post) > .d-flex,
    html body #messagesContainer > .message.qchat-saved-blog-image-message:not(.qchat-saved-blog-audio-message):has(.message-content > .saved-profile-blog-post) > .d-flex > .message-bubble,
    html body #messagesContainer > .message.qchat-saved-blog-image-message:not(.qchat-saved-blog-audio-message):has(.message-content > .saved-profile-blog-post) :is(.message-content-wrapper, .message-content, .saved-profile-blog-post) {
        width: min(calc(340px + 2rem + 2px), 100%) !important;
        max-width: min(calc(340px + 2rem + 2px), 100%) !important;
        min-width: 0 !important;
        box-sizing: border-box !important;
    }

    html body #messagesContainer > .message.qchat-saved-blog-image-message:not(.qchat-saved-blog-audio-message):has(.message-content > .saved-profile-blog-post)
        .saved-profile-blog-post :is(
            .profile-blog-attachments,
            .profile-blog-file-bundle-message,
            .profile-blog-file-bundle-groups,
            .profile-blog-gallery-group,
            .profile-blog-gallery,
            .qchat-file-bundle-group-image,
            .qchat-file-bundle-grid-images
        ) {
        width: min(340px, 100%) !important;
        max-width: min(340px, 100%) !important;
        min-width: 0 !important;
        box-sizing: border-box !important;
    }

    html body #messagesContainer > .message.sent.qchat-saved-blog-image-message > .d-flex {
        margin-left: auto !important;
        margin-right: 0 !important;
    }

    html body #messagesContainer > .message.received.qchat-saved-blog-image-message > .d-flex {
        margin-left: 0 !important;
        margin-right: auto !important;
    }
}

/* QChat mobile polish v52
 * Saved Blog snapshots in Saved Messages use the native Profile Blog mobile lane.
 * Old saved-audio/image rules still reserve fixed/desktop-sized rows (498px/50%/fit-content)
 * with very specific :has() selectors.  Override those contracts at the final layer,
 * remove the redundant outer chat avatar/header, and let the embedded Blog card own
 * the full message width exactly like the Profile Blog feed on phones. */
@media (max-width: 767.98px) {
    html body #messagesContainer > .message.qchat-saved-blog-message:has(.message-content > .saved-profile-blog-post),
    html body #messagesContainer > .message.qchat-saved-blog-message:has(.message-content > .saved-profile-blog-comment) {
        display: block !important;
        width: 100% !important;
        inline-size: 100% !important;
        max-width: none !important;
        max-inline-size: none !important;
        min-width: 0 !important;
        margin-left: 0 !important;
        margin-right: 0 !important;
        box-sizing: border-box !important;
    }

    /* Beat the old fixed 498px audio lane and the old 50% Blog-image lane. */
    html body #messagesContainer > .message.qchat-saved-blog-message:has(.message-content > .saved-profile-blog-post) > .d-flex,
    html body #messagesContainer > .message.qchat-saved-blog-message:has(.message-content > .saved-profile-blog-comment) > .d-flex,
    html body #messagesContainer > .message.qchat-saved-blog-audio-message:has(.message-content > .saved-profile-blog-post):has(.qchat-audio-mini-player, .qchat-audio-mini-group, .qchat-file-bundle-group-audio, .qchat-file-bundle-list-audio) > .d-flex,
    html body #messagesContainer > .message.qchat-saved-blog-image-message:has(.message-content > .saved-profile-blog-post):has(.qchat-file-bundle-grid-images, .profile-blog-gallery) > .d-flex {
        display: block !important;
        width: 100% !important;
        inline-size: 100% !important;
        max-width: none !important;
        max-inline-size: none !important;
        min-width: 0 !important;
        flex: none !important;
        margin-left: 0 !important;
        margin-right: 0 !important;
        gap: 0 !important;
        box-sizing: border-box !important;
    }

    /* The Blog card already contains its own author avatar/name.  The outer chat
       avatar/header only steals horizontal space and duplicates the same author. */
    html body #messagesContainer > .message.qchat-saved-blog-message:has(.message-content > .saved-profile-blog-post) > .d-flex > .message-avatar,
    html body #messagesContainer > .message.qchat-saved-blog-message:has(.message-content > .saved-profile-blog-comment) > .d-flex > .message-avatar,
    html body #messagesContainer > .message.qchat-saved-blog-message:has(.message-content > .saved-profile-blog-post) .message-content-wrapper > .message-header,
    html body #messagesContainer > .message.qchat-saved-blog-message:has(.message-content > .saved-profile-blog-comment) .message-content-wrapper > .message-header {
        display: none !important;
    }

    html body #messagesContainer > .message.qchat-saved-blog-message:has(.message-content > .saved-profile-blog-post) > .d-flex > .message-bubble,
    html body #messagesContainer > .message.qchat-saved-blog-message:has(.message-content > .saved-profile-blog-comment) > .d-flex > .message-bubble,
    html body #messagesContainer > .message.qchat-saved-blog-audio-message:has(.message-content > .saved-profile-blog-post):has(.qchat-audio-mini-player, .qchat-audio-mini-group, .qchat-file-bundle-group-audio, .qchat-file-bundle-list-audio) > .d-flex > .message-bubble,
    html body #messagesContainer > .message.qchat-saved-blog-image-message:has(.message-content > .saved-profile-blog-post):has(.qchat-file-bundle-grid-images, .profile-blog-gallery) > .d-flex > .message-bubble {
        display: block !important;
        width: 100% !important;
        inline-size: 100% !important;
        max-width: none !important;
        max-inline-size: none !important;
        min-width: 0 !important;
        flex: none !important;
        margin: 0 !important;
        box-sizing: border-box !important;
        overflow: visible !important;
    }

    html body #messagesContainer > .message.qchat-saved-blog-message:has(.message-content > .saved-profile-blog-post)
        :is(.message-content-wrapper, .message-content, .saved-profile-blog-post),
    html body #messagesContainer > .message.qchat-saved-blog-message:has(.message-content > .saved-profile-blog-comment)
        :is(.message-content-wrapper, .message-content, .saved-profile-blog-comment) {
        display: block !important;
        width: 100% !important;
        inline-size: 100% !important;
        max-width: none !important;
        max-inline-size: none !important;
        min-width: 0 !important;
        margin-left: 0 !important;
        margin-right: 0 !important;
        box-sizing: border-box !important;
        overflow: visible !important;
    }

    /* Profile Blog itself is fluid on mobile.  Do the same for its snapshot in
       Saved Messages instead of retaining the 360px desktop media lane. */
    html body #messagesContainer > .message.qchat-saved-blog-message:has(.message-content > .saved-profile-blog-post)
        .saved-profile-blog-post :is(
            .profile-blog-attachments,
            .qchat-profile-blog-bundle-host,
            .profile-blog-file-bundle-message,
            .qchat-file-bundle-message,
            .profile-blog-file-bundle-groups,
            .qchat-file-bundle-groups,
            .profile-blog-gallery-group,
            .qchat-file-bundle-group-image,
            .profile-blog-gallery,
            .qchat-file-bundle-grid-images,
            .profile-blog-audio-group,
            .profile-blog-audio-list,
            .profile-blog-audio-attachment,
            .profile-blog-attachment-preview,
            .qchat-file-bundle-group-audio,
            .qchat-file-bundle-list-audio,
            .qchat-audio-mini-group,
            .qchat-audio-mini-player
        ) {
        width: 100% !important;
        inline-size: 100% !important;
        max-width: 100% !important;
        max-inline-size: 100% !important;
        min-width: 0 !important;
        margin-left: 0 !important;
        margin-right: 0 !important;
        box-sizing: border-box !important;
    }
}

/* QChat mobile polish v53
 * Saved Profile Blog cards are already marked with qchat-saved-blog-message by
 * the renderer.  Use that stable class directly instead of depending on :has()
 * so Android/WebView versions and late hydration cannot fall back to the old
 * 170/348/360/498px saved-blog lanes from responsive.css/profile.css. */
@media (max-width: 767.98px) {
    html body #messagesContainer > .message.qchat-saved-blog-message {
        --qchat-saved-blog-lane-width: 100% !important;
        --qchat-audio-saved-blog-card-width: 100% !important;
        --qchat-saved-blog-classic-audio-card-width: 100% !important;
        --qchat-audio-mini-saved-card-width: 100% !important;
        display: block !important;
        width: 100% !important;
        inline-size: 100% !important;
        max-width: 100% !important;
        max-inline-size: 100% !important;
        min-width: 0 !important;
        margin-left: 0 !important;
        margin-right: 0 !important;
        padding-left: 0 !important;
        padding-right: 0 !important;
        box-sizing: border-box !important;
    }

    html body #messagesContainer > .message.qchat-saved-blog-message > .d-flex,
    html body #messagesContainer > .message.qchat-saved-blog-message > .d-flex.w-100 {
        display: flex !important;
        flex: 1 1 100% !important;
        width: 100% !important;
        inline-size: 100% !important;
        max-width: 100% !important;
        max-inline-size: 100% !important;
        min-width: 0 !important;
        margin-left: 0 !important;
        margin-right: 0 !important;
        justify-content: flex-start !important;
        gap: 0 !important;
        box-sizing: border-box !important;
    }

    html body #messagesContainer > .message.qchat-saved-blog-message > .d-flex > :is(
        .message-avatar,
        .avatar-placeholder.message-avatar,
        .encrypted-message-avatar,
        .qchat-message-avatar-fallback
    ),
    html body #messagesContainer > .message.qchat-saved-blog-message .message-content-wrapper > .message-header {
        display: none !important;
        width: 0 !important;
        min-width: 0 !important;
        max-width: 0 !important;
        margin: 0 !important;
        padding: 0 !important;
        flex: 0 0 0 !important;
        overflow: hidden !important;
    }

    html body #messagesContainer > .message.qchat-saved-blog-message > .d-flex > .message-bubble,
    html body #messagesContainer > .message.qchat-saved-blog-message .message-content-wrapper,
    html body #messagesContainer > .message.qchat-saved-blog-message .message-content,
    html body #messagesContainer > .message.qchat-saved-blog-message .saved-profile-blog-post,
    html body #messagesContainer > .message.qchat-saved-blog-message .saved-profile-blog-comment {
        display: block !important;
        flex: 1 1 100% !important;
        width: 100% !important;
        inline-size: 100% !important;
        max-width: 100% !important;
        max-inline-size: 100% !important;
        min-width: 0 !important;
        margin-left: 0 !important;
        margin-right: 0 !important;
        box-sizing: border-box !important;
        overflow: visible !important;
    }

    /* Inside the full-width Blog card, media/audio uses the card's content box.
       This intentionally beats the old count-specific 1/2-photo compact lanes. */
    html body #messagesContainer > .message.qchat-saved-blog-message .saved-profile-blog-post :is(
        .profile-blog-attachments,
        .qchat-profile-blog-bundle-host,
        .profile-blog-file-bundle-message,
        .qchat-file-bundle-message,
        .profile-blog-file-bundle-groups,
        .qchat-file-bundle-groups,
        .qchat-file-bundle-group,
        .profile-blog-gallery-group,
        .qchat-file-bundle-group-image,
        .profile-blog-gallery,
        .qchat-file-bundle-grid-images,
        .profile-blog-audio-group,
        .profile-blog-audio-list,
        .profile-blog-audio-attachment,
        .profile-blog-attachment-preview,
        .qchat-file-bundle-group-audio,
        .qchat-file-bundle-list-audio,
        .qchat-audio-mini-group,
        .qchat-audio-mini-player,
        .audio_card.qchat-audio-classic-card,
        .qchat-audio-classic-player,
        .current-song
    ) {
        width: 100% !important;
        inline-size: 100% !important;
        max-width: 100% !important;
        max-inline-size: 100% !important;
        min-width: 0 !important;
        margin-left: 0 !important;
        margin-right: 0 !important;
        box-sizing: border-box !important;
    }

    html body #messagesContainer > .message.qchat-saved-blog-message .profile-blog-content {
        white-space: normal !important;
        overflow-wrap: anywhere !important;
    }
}


/* QChat mobile polish v54
 * Saved Profile Blog snapshots must use the same wide message lane as normal
 * mobile messages.  Do not rely on :has() here: some Android/Huawei browser
 * builds either skip those selectors or end up in the 576..1200px media band,
 * where responsive.css gives 1/2-image bundles fixed 170/348px widths.
 * The explicit qchat-saved-blog-* classes are attached by the renderer, so this
 * contract remains stable before/after async image/audio hydration. */
@media (max-width: 1200px) {
    html body #messagesContainer > .message.qchat-saved-blog-message {
        width: 100% !important;
        max-width: 100% !important;
        min-width: 0 !important;
        margin-left: 0 !important;
        margin-right: 0 !important;
        box-sizing: border-box !important;
    }

    html body #messagesContainer > .message.qchat-saved-blog-message > .d-flex {
        display: flex !important;
        width: 100% !important;
        max-width: 100% !important;
        min-width: 0 !important;
        flex: 1 1 100% !important;
        gap: 0 !important;
        margin-left: 0 !important;
        margin-right: 0 !important;
        justify-content: stretch !important;
        align-items: stretch !important;
        box-sizing: border-box !important;
    }

    /* A saved Blog card already has the author avatar/name inside it.  The
       ordinary chat-shell avatar only steals 30-48px from the row. */
    html body #messagesContainer > .message.qchat-saved-blog-message > .d-flex > .message-avatar {
        display: none !important;
        width: 0 !important;
        min-width: 0 !important;
        max-width: 0 !important;
        flex: 0 0 0 !important;
        margin: 0 !important;
    }

    html body #messagesContainer > .message.qchat-saved-blog-message .message-content-wrapper > .message-header {
        display: none !important;
    }

    html body #messagesContainer > .message.qchat-saved-blog-message > .d-flex > .message-bubble,
    html body #messagesContainer > .message.qchat-saved-blog-message .message-content-wrapper,
    html body #messagesContainer > .message.qchat-saved-blog-message .message-content,
    html body #messagesContainer > .message.qchat-saved-blog-message .saved-profile-blog-post,
    html body #messagesContainer > .message.qchat-saved-blog-message .saved-profile-blog-comment {
        display: block !important;
        width: 100% !important;
        inline-size: 100% !important;
        max-width: 100% !important;
        max-inline-size: 100% !important;
        min-width: 0 !important;
        flex: 1 1 100% !important;
        margin-left: 0 !important;
        margin-right: 0 !important;
        box-sizing: border-box !important;
    }

    /* Beat responsive.css v74's fixed 170px / 348px widths for one/two photos.
       Explicit saved-message classes intentionally give these rules more
       specificity than the generic file-bundle rules. */
    html body #messagesContainer > .message.qchat-saved-blog-image-message .saved-profile-blog-post .profile-blog-attachments,
    html body #messagesContainer > .message.qchat-saved-blog-image-message .saved-profile-blog-post .qchat-profile-blog-bundle-host,
    html body #messagesContainer > .message.qchat-saved-blog-image-message .saved-profile-blog-post .profile-blog-file-bundle-message,
    html body #messagesContainer > .message.qchat-saved-blog-image-message .saved-profile-blog-post .qchat-file-bundle-message,
    html body #messagesContainer > .message.qchat-saved-blog-image-message .saved-profile-blog-post .profile-blog-file-bundle-groups,
    html body #messagesContainer > .message.qchat-saved-blog-image-message .saved-profile-blog-post .qchat-file-bundle-groups,
    html body #messagesContainer > .message.qchat-saved-blog-image-message .saved-profile-blog-post .profile-blog-gallery-group,
    html body #messagesContainer > .message.qchat-saved-blog-image-message .saved-profile-blog-post .qchat-file-bundle-group-image,
    html body #messagesContainer > .message.qchat-saved-blog-image-message .saved-profile-blog-post .profile-blog-gallery,
    html body #messagesContainer > .message.qchat-saved-blog-image-message .saved-profile-blog-post .qchat-file-bundle-grid.qchat-file-bundle-grid-images,
    html body #messagesContainer > .message.qchat-saved-blog-image-message .saved-profile-blog-post .qchat-file-bundle-grid.qchat-file-bundle-grid-one,
    html body #messagesContainer > .message.qchat-saved-blog-image-message .saved-profile-blog-post .qchat-file-bundle-grid.qchat-file-bundle-grid-two,
    html body #messagesContainer > .message.qchat-saved-blog-image-message .saved-profile-blog-post .qchat-file-bundle-grid.qchat-file-bundle-grid-many,
    html body #messagesContainer > .message.qchat-saved-blog-image-message .saved-profile-blog-post .qchat-file-bundle-grid[data-file-group-count="1"],
    html body #messagesContainer > .message.qchat-saved-blog-image-message .saved-profile-blog-post .qchat-file-bundle-grid[data-file-group-count="2"] {
        width: 100% !important;
        inline-size: 100% !important;
        max-width: 100% !important;
        max-inline-size: 100% !important;
        min-width: 0 !important;
        margin-left: 0 !important;
        margin-right: 0 !important;
        box-sizing: border-box !important;
    }

    html body #messagesContainer > .message.qchat-saved-blog-image-message .saved-profile-blog-post .qchat-file-bundle-grid.qchat-file-bundle-grid-one,
    html body #messagesContainer > .message.qchat-saved-blog-image-message .saved-profile-blog-post .qchat-file-bundle-grid[data-file-group-count="1"] {
        grid-template-columns: minmax(0, 1fr) !important;
    }

    html body #messagesContainer > .message.qchat-saved-blog-image-message .saved-profile-blog-post .qchat-file-bundle-grid.qchat-file-bundle-grid-two,
    html body #messagesContainer > .message.qchat-saved-blog-image-message .saved-profile-blog-post .qchat-file-bundle-grid[data-file-group-count="2"] {
        grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
    }

    /* Saved Blog audio: the whole card and the mini-player use the card's fluid
       content lane instead of the generic 464px desktop cap. */
    html body #messagesContainer > .message.qchat-saved-blog-audio-message .saved-profile-blog-post .profile-blog-attachments,
    html body #messagesContainer > .message.qchat-saved-blog-audio-message .saved-profile-blog-post .qchat-profile-blog-bundle-host,
    html body #messagesContainer > .message.qchat-saved-blog-audio-message .saved-profile-blog-post .profile-blog-file-bundle-message,
    html body #messagesContainer > .message.qchat-saved-blog-audio-message .saved-profile-blog-post .qchat-file-bundle-message,
    html body #messagesContainer > .message.qchat-saved-blog-audio-message .saved-profile-blog-post .profile-blog-file-bundle-groups,
    html body #messagesContainer > .message.qchat-saved-blog-audio-message .saved-profile-blog-post .qchat-file-bundle-groups,
    html body #messagesContainer > .message.qchat-saved-blog-audio-message .saved-profile-blog-post .profile-blog-audio-group,
    html body #messagesContainer > .message.qchat-saved-blog-audio-message .saved-profile-blog-post .profile-blog-audio-list,
    html body #messagesContainer > .message.qchat-saved-blog-audio-message .saved-profile-blog-post .profile-blog-audio-attachment,
    html body #messagesContainer > .message.qchat-saved-blog-audio-message .saved-profile-blog-post .profile-blog-attachment-preview,
    html body #messagesContainer > .message.qchat-saved-blog-audio-message .saved-profile-blog-post .qchat-file-bundle-group-audio,
    html body #messagesContainer > .message.qchat-saved-blog-audio-message .saved-profile-blog-post .qchat-file-bundle-list-audio,
    html body #messagesContainer > .message.qchat-saved-blog-audio-message .saved-profile-blog-post .qchat-audio-mini-group,
    html body #messagesContainer > .message.qchat-saved-blog-audio-message .saved-profile-blog-post .qchat-audio-mini-player {
        width: 100% !important;
        inline-size: 100% !important;
        max-width: 100% !important;
        max-inline-size: 100% !important;
        min-width: 0 !important;
        box-sizing: border-box !important;
    }
}

/* QChat v55: Favorites/Profile-Blog messages use the normal mobile message lane.
   This deliberately matches the old compact-lane selectors with at least equal
   specificity so 170/348/calc(100vw - 92px) rules cannot win the cascade. */
@media (max-width: 767.98px) {
    html body #messagesContainer .message.qchat-saved-blog-message:has(.saved-profile-blog-post) {
        width: 100% !important;
        max-width: 100% !important;
        min-width: 0 !important;
        margin-left: 0 !important;
        margin-right: 0 !important;
    }

    html body #messagesContainer .message.qchat-saved-blog-message:has(.saved-profile-blog-post) > .d-flex,
    html body #messagesContainer .message.qchat-saved-blog-message:has(.saved-profile-blog-post) > .d-flex.w-100,
    html body #messagesContainer .message.qchat-saved-blog-message:has(.saved-profile-blog-post):has(.profile-blog-gallery.qchat-file-bundle-grid-images):not(:has(.qchat-audio-mini-player)):not(:has(.qchat-file-bundle-group-audio)):not(:has(.qchat-file-bundle-list-audio)) > .d-flex,
    html body #messagesContainer .message.qchat-saved-blog-message:has(.saved-profile-blog-post):has(.profile-blog-gallery.qchat-file-bundle-grid-images):not(:has(.qchat-audio-mini-player)):not(:has(.qchat-file-bundle-group-audio)):not(:has(.qchat-file-bundle-list-audio)) > .d-flex.w-100 {
        width: 100% !important;
        max-width: 100% !important;
        min-width: 0 !important;
        flex: 1 1 100% !important;
        margin-left: 0 !important;
        margin-right: 0 !important;
        box-sizing: border-box !important;
    }

    html body #messagesContainer .message.qchat-saved-blog-message:has(.saved-profile-blog-post) > .d-flex > .message-bubble {
        width: 100% !important;
        max-width: 100% !important;
        min-width: 0 !important;
        flex: 1 1 100% !important;
        margin: 0 !important;
        padding-left: 0 !important;
        padding-right: 0 !important;
        box-sizing: border-box !important;
    }

    html body #messagesContainer .message.qchat-saved-blog-message:has(.saved-profile-blog-post) .message-content-wrapper,
    html body #messagesContainer .message.qchat-saved-blog-message:has(.saved-profile-blog-post) .message-content,
    html body #messagesContainer .message.qchat-saved-blog-message:has(.saved-profile-blog-post) .saved-profile-blog-post,
    html body #messagesContainer .message.qchat-saved-blog-message:has(.saved-profile-blog-post) .qchat-saved-blog-card-shell,
    html body #messagesContainer .message.qchat-saved-blog-message:has(.saved-profile-blog-post) .profile-blog-attachments,
    html body #messagesContainer .message.qchat-saved-blog-message:has(.saved-profile-blog-post) .profile-blog-file-bundle-message,
    html body #messagesContainer .message.qchat-saved-blog-message:has(.saved-profile-blog-post) .profile-blog-file-bundle-groups,
    html body #messagesContainer .message.qchat-saved-blog-message:has(.saved-profile-blog-post) .profile-blog-gallery-group,
    html body #messagesContainer .message.qchat-saved-blog-message:has(.saved-profile-blog-post) .profile-blog-gallery {
        width: 100% !important;
        max-width: 100% !important;
        min-width: 0 !important;
        box-sizing: border-box !important;
    }

    html body #messagesContainer .message.qchat-saved-blog-audio-message:has(.saved-profile-blog-post) .qchat-profile-blog-bundle-host,
    html body #messagesContainer .message.qchat-saved-blog-audio-message:has(.saved-profile-blog-post) .qchat-profile-blog-bundle-has-audio,
    html body #messagesContainer .message.qchat-saved-blog-audio-message:has(.saved-profile-blog-post) .qchat-file-bundle-group-audio,
    html body #messagesContainer .message.qchat-saved-blog-audio-message:has(.saved-profile-blog-post) .qchat-file-bundle-list-audio,
    html body #messagesContainer .message.qchat-saved-blog-audio-message:has(.saved-profile-blog-post) .qchat-audio-mini-group,
    html body #messagesContainer .message.qchat-saved-blog-audio-message:has(.saved-profile-blog-post) .qchat-audio-mini-player {
        width: 100% !important;
        max-width: 100% !important;
        min-width: 0 !important;
        box-sizing: border-box !important;
    }

    html body #messagesContainer .message.qchat-saved-blog-message:has(.saved-profile-blog-post) > .d-flex > .message-avatar {
        display: none !important;
        width: 0 !important;
        min-width: 0 !important;
        margin: 0 !important;
    }
}

/* QChat v55 audio lane: match the legacy mini-audio selector exactly and add
   the saved-blog class, so its fit-content/min(574px,100%) rule cannot win. */
@media (max-width: 767.98px) {
    html body #messagesContainer .message.qchat-saved-blog-message:has(.saved-profile-blog-post):has(.qchat-audio-mini-player):not(:has(.audio_card.qchat-audio-classic-card)):not(:has(.qchat-audio-classic-player)) > .d-flex,
    html body #messagesContainer .message.qchat-saved-blog-message:has(.saved-profile-blog-post):has(.qchat-audio-mini-group):not(:has(.audio_card.qchat-audio-classic-card)):not(:has(.qchat-audio-classic-player)) > .d-flex,
    html body #messagesContainer .message.qchat-saved-blog-message:has(.saved-profile-blog-post):has(.qchat-file-bundle-group-audio):not(:has(.audio_card.qchat-audio-classic-card)):not(:has(.qchat-audio-classic-player)) > .d-flex,
    html body #messagesContainer .message.qchat-saved-blog-message:has(.saved-profile-blog-post):has(.qchat-file-bundle-list-audio):not(:has(.audio_card.qchat-audio-classic-card)):not(:has(.qchat-audio-classic-player)) > .d-flex,
    html body #messagesContainer .message.qchat-saved-blog-message:has(.saved-profile-blog-post):has(.qchat-audio-mini-player):not(:has(.audio_card.qchat-audio-classic-card)):not(:has(.qchat-audio-classic-player)) > .d-flex.w-100,
    html body #messagesContainer .message.qchat-saved-blog-message:has(.saved-profile-blog-post):has(.qchat-audio-mini-group):not(:has(.audio_card.qchat-audio-classic-card)):not(:has(.qchat-audio-classic-player)) > .d-flex.w-100,
    html body #messagesContainer .message.qchat-saved-blog-message:has(.saved-profile-blog-post):has(.qchat-file-bundle-group-audio):not(:has(.audio_card.qchat-audio-classic-card)):not(:has(.qchat-audio-classic-player)) > .d-flex.w-100,
    html body #messagesContainer .message.qchat-saved-blog-message:has(.saved-profile-blog-post):has(.qchat-file-bundle-list-audio):not(:has(.audio_card.qchat-audio-classic-card)):not(:has(.qchat-audio-classic-player)) > .d-flex.w-100 {
        width: 100% !important;
        max-width: 100% !important;
        min-width: 0 !important;
        flex: 1 1 100% !important;
        margin-left: 0 !important;
        margin-right: 0 !important;
        align-items: stretch !important;
        box-sizing: border-box !important;
    }

    html body #messagesContainer .message.qchat-saved-blog-message:has(.saved-profile-blog-post):has(.qchat-audio-mini-player):not(:has(.audio_card.qchat-audio-classic-card)):not(:has(.qchat-audio-classic-player)) .message-bubble,
    html body #messagesContainer .message.qchat-saved-blog-message:has(.saved-profile-blog-post):has(.qchat-audio-mini-group):not(:has(.audio_card.qchat-audio-classic-card)):not(:has(.qchat-audio-classic-player)) .message-bubble,
    html body #messagesContainer .message.qchat-saved-blog-message:has(.saved-profile-blog-post):has(.qchat-file-bundle-group-audio):not(:has(.audio_card.qchat-audio-classic-card)):not(:has(.qchat-audio-classic-player)) .message-bubble,
    html body #messagesContainer .message.qchat-saved-blog-message:has(.saved-profile-blog-post):has(.qchat-file-bundle-list-audio):not(:has(.audio_card.qchat-audio-classic-card)):not(:has(.qchat-audio-classic-player)) .message-bubble,
    html body #messagesContainer .message.qchat-saved-blog-message:has(.saved-profile-blog-post):has(.qchat-audio-mini-player):not(:has(.audio_card.qchat-audio-classic-card)):not(:has(.qchat-audio-classic-player)) .message-content-wrapper,
    html body #messagesContainer .message.qchat-saved-blog-message:has(.saved-profile-blog-post):has(.qchat-audio-mini-player):not(:has(.audio_card.qchat-audio-classic-card)):not(:has(.qchat-audio-classic-player)) .message-content,
    html body #messagesContainer .message.qchat-saved-blog-message:has(.saved-profile-blog-post):has(.qchat-audio-mini-player):not(:has(.audio_card.qchat-audio-classic-card)):not(:has(.qchat-audio-classic-player)) .saved-profile-blog-post {
        width: 100% !important;
        max-width: 100% !important;
        min-width: 0 !important;
        flex: 1 1 100% !important;
        box-sizing: border-box !important;
    }
}

/* QChat mobile polish v56 (QChat patch v61)
 * Desktop mixed image/video albums use the same 360px media content lane as
 * ordinary source-rendered photo albums.  The legacy direct-album rules set
 * both the bubble border-box and its inner content to 360px; because the
 * bubble also has 12px horizontal padding, the inner album overflowed by 24px
 * and the right edge was clipped.  Give the bubble/row room for that padding
 * without changing the album geometry or mobile full-width behavior. */
@media (min-width: 768px) {
    html body #messagesContainer#messagesContainer > .message:has(.qchat-file-bundle-grid-visual-mixed):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex {
        width: fit-content !important;
        max-width: min(440px, calc(100vw - 24px)) !important;
        min-width: 0 !important;
        flex: 0 1 auto !important;
        box-sizing: border-box !important;
    }

    html body #messagesContainer#messagesContainer > .message:has(.qchat-file-bundle-grid-visual-mixed):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex > .message-bubble {
        width: 384px !important;
        max-width: min(384px, calc(100vw - 80px)) !important;
        min-width: 0 !important;
        flex: 0 1 auto !important;
        box-sizing: border-box !important;
    }
}


/* Audio-bearing chat messages need one full-width mobile lane, including mixed
   photo/audio bundles. Override the photo rule reserving 36px for an avatar.
   Keep the lane while the live player is temporarily in the floating dock. */
@media (max-width: 767.98px) {
    html body #messagesContainer#messagesContainer > .message:has(:is(.qchat-audio-mini-player, .qchat-file-bundle-group-audio, .qchat-audio-return-slot)):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex {
        width: 100% !important;
        max-width: 100% !important;
        min-width: 0 !important;
        flex: 1 1 100% !important;
        margin-left: 0 !important;
        margin-right: 0 !important;
        padding-left: 0 !important;
        padding-right: 0 !important;
        gap: 0 !important;
        box-sizing: border-box !important;
    }

    html body #messagesContainer#messagesContainer > .message:has(:is(.qchat-audio-mini-player, .qchat-file-bundle-group-audio, .qchat-audio-return-slot)):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex > .message-bubble {
        width: 100% !important;
        max-width: 100% !important;
        min-width: 0 !important;
        flex: 1 1 100% !important;
        margin-left: 0 !important;
        margin-right: 0 !important;
        box-sizing: border-box !important;
    }

    html body #messagesContainer#messagesContainer > .message:has(:is(.qchat-audio-mini-player, .qchat-file-bundle-group-audio, .qchat-audio-return-slot)):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex > .message-avatar {
        display: none !important;
    }
}


/* A dock must not inherit grid areas/30px row caps from chat and blog layouts.
   Explicit positions keep the volume lane inside the same 82px control box. */
html body #qchatPersistentAudioDock .qchat-audio-mini-controls {
    display: block !important;
    position: relative !important;
    inset: auto !important;
    width: 82px !important;
    min-width: 82px !important;
    max-width: 82px !important;
    height: 48px !important;
    min-height: 48px !important;
    max-height: 48px !important;
    padding: 0 !important;
    margin: 0 0 0 auto !important;
    transform: none !important;
    box-sizing: border-box !important;
    overflow: visible !important;
}
html body #qchatPersistentAudioDock .qchat-audio-mini-controls > button {
    position: absolute !important;
    top: 0 !important;
    bottom: auto !important;
    margin: 0 !important;
    transform: none !important;
}
html body #qchatPersistentAudioDock .qchat-audio-mini-controls > .prev { left: 0 !important; right: auto !important; }
html body #qchatPersistentAudioDock .qchat-audio-mini-controls > .play { left: 27px !important; right: auto !important; }
html body #qchatPersistentAudioDock .qchat-audio-mini-controls > .next { left: auto !important; right: 0 !important; }

/* Keep the floating volume control visible independently of chat/blog styles. */
html body #qchatPersistentAudioDock .qchat-audio-mini-controls .qchat-audio-volume-wrap {
    display: block !important;
    visibility: visible !important;
    opacity: 1 !important;
    position: absolute !important;
    grid-area: auto !important;
    inset: auto auto 0 0 !important;
    transform: none !important;
    min-width: 82px !important;
    max-width: 82px !important;
    max-height: 16px !important;
    width: 82px !important;
    height: 16px !important;
    min-height: 16px !important;
    overflow: visible !important;
    pointer-events: auto !important;
}
html body #qchatPersistentAudioDock .qchat-audio-mini-controls .qchat-audio-volume-range {
    display: block !important;
    visibility: visible !important;
    opacity: 1 !important;
    position: absolute !important;
    grid-area: auto !important;
    transform: none !important;
    min-width: 74px !important;
    max-width: 74px !important;
    inset: 0 auto auto 4px !important;
    width: 74px !important;
    height: 16px !important;
    min-height: 16px !important;
    max-height: 16px !important;
    margin: 0 !important;
    padding: 0 !important;
    appearance: none !important;
    -webkit-appearance: none !important;
    background: transparent !important;
    pointer-events: auto !important;
}

/* Match the 440px compact chat player; mobile continues to fit the viewport. */
@media (min-width: 768px) {
    html body #qchatPersistentAudioDock {
        width: min(440px, calc(100vw - 16px)) !important;
        max-width: min(440px, calc(100vw - 16px)) !important;
    }
}


/* Dock surfaces are opaque and depend only on playback, never hover/current. */
html body #qchatPersistentAudioDock {
    --qchat-dock-idle-bg: #fff;
    --qchat-dock-playing-bg: #eef4ff;
    opacity: 1 !important;
    mix-blend-mode: normal !important;
}
html body.dark-theme #qchatPersistentAudioDock {
    --qchat-dock-idle-bg: #21262d;
    --qchat-dock-playing-bg: #1d3154;
}
@media (prefers-color-scheme: dark) {
    html body.auto-theme #qchatPersistentAudioDock {
        --qchat-dock-idle-bg: #21262d;
        --qchat-dock-playing-bg: #1d3154;
    }
}
html body #qchatPersistentAudioDock > .qchat-persistent-audio-dock-surface {
    background: var(--qchat-dock-idle-bg) !important;
    border-radius: 10px !important;
    opacity: 1 !important;
    mix-blend-mode: normal !important;
    backdrop-filter: none !important;
    -webkit-backdrop-filter: none !important;
}
html body #qchatPersistentAudioDock > .qchat-persistent-audio-dock-surface:has(.qchat-audio-mini-player.playing) {
    background: var(--qchat-dock-playing-bg) !important;
}
html body #qchatPersistentAudioDock .qchat-audio-mini-player:not(.playing) {
    background: var(--qchat-dock-idle-bg) !important;
    opacity: 1 !important;
    mix-blend-mode: normal !important;
}
html body #qchatPersistentAudioDock .qchat-audio-mini-player.playing {
    background: var(--qchat-dock-playing-bg) !important;
    opacity: 1 !important;
    mix-blend-mode: normal !important;
}

/* The dock itself is an opaque backing, including after drag position changes. */
html body #qchatPersistentAudioDock {
    background: var(--qchat-dock-idle-bg) !important;
    border-radius: 10px !important;
    isolation: isolate !important;
}
html body #qchatPersistentAudioDock:has(.qchat-audio-mini-player.playing) {
    background: var(--qchat-dock-playing-bg) !important;
}
.qchat-chat-info .modal-content { background: #fff; color: #212529; border-radius: 14px; }
.qchat-chat-info-row { display: block; width: 100%; border: 0; border-radius: 8px; padding: 12px; text-align: left; background: transparent; color: inherit; overflow-wrap: anywhere; }
.qchat-chat-info-row small { display: block; margin-top: 4px; }
.qchat-chat-info-row:hover:not(:disabled), .qchat-chat-info-row:focus-visible { background: #0d6efd20; }
.qchat-chat-info-row:disabled { opacity: .55; }
body.dark-theme .qchat-chat-info .modal-content { background: #21262d; color: #ced4da; }
@media (prefers-color-scheme: dark) { body.auto-theme .qchat-chat-info .modal-content { background: #21262d; color: #ced4da; } }

/* Chat media browser: chronological photo contact sheet. */
.qchat-photo-month { margin: 18px 0 8px; text-transform: capitalize; }
.qchat-photo-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 3px; }
.qchat-photo-tile { aspect-ratio: 1; min-width: 0; padding: 0; border: 0; overflow: hidden; background: #80808025; color: inherit; font-size: 11px; }
.qchat-photo-tile img { width: 100%; height: 100%; object-fit: cover; display: block; }
.qchat-photo-tile:focus-visible { outline: 3px solid #0d6efd; outline-offset: -3px; }
.qchat-photo-full { display: block; width: 100%; max-height: 65vh; object-fit: contain; }
.qchat-photo-view p { overflow-wrap: anywhere; }
@media (max-width: 380px) { .qchat-photo-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }

.qchat-photo-tile { position: relative; }
.qchat-video-badge { position: absolute; right: 6px; bottom: 6px; color: white; background: #0009; padding: 2px 6px; border-radius: 4px; }
.qchat-media-result { padding: 12px 0; border-bottom: 1px solid #80808035; overflow-wrap: anywhere; }
.qchat-media-result strong { display: block; margin-bottom: 8px; }
.qchat-media-result audio { width: 100%; margin-top: 8px; }
.qchat-media-link .qchat-link-preview { max-width: 100%; margin: 0; }

/* Reuse the QChat player inside the media browser. */
.qchat-gallery-audio { width: 100%; min-width: 0; margin-top: 8px; }
.qchat-gallery-audio .qchat-audio-mini-player,
.qchat-gallery-audio .qchat-audio-classic-card { width: 100%; max-width: 100%; box-sizing: border-box; }

/* Keep compact controls in their slots in the media modal, including hover. */
html body #qchatChatInfoModal .qchat-gallery-audio .qchat-audio-mini-controls { position: relative !important; display: block !important; width: 82px !important; min-width: 82px !important; height: 48px !important; min-height: 48px !important; transform: none !important; }
html body #qchatChatInfoModal .qchat-gallery-audio .qchat-audio-mini-controls > button { position: absolute !important; top: 0 !important; bottom: auto !important; margin: 0 !important; transform: none !important; opacity: 1 !important; visibility: visible !important; display: flex !important; }
html body #qchatChatInfoModal .qchat-gallery-audio .qchat-audio-prev-btn { left: 0 !important; right: auto !important; }
html body #qchatChatInfoModal .qchat-gallery-audio .qchat-audio-play-btn { left: 27px !important; right: auto !important; }
html body #qchatChatInfoModal .qchat-gallery-audio .qchat-audio-next-btn { right: 0 !important; left: auto !important; }
html body #qchatChatInfoModal .qchat-gallery-audio .qchat-audio-volume-wrap { position: absolute !important; inset: auto auto 0 0 !important; width: 82px !important; height: 16px !important; transform: none !important; opacity: 1 !important; visibility: visible !important; }

.qchat-chat-info-back { margin-bottom: 12px; font: inherit; text-decoration: none; }
#qchatChatInfoModal.qchat-under-image-viewer { visibility: hidden !important; pointer-events: none !important; }
#chatImagePreviewModal.qchat-media-browser-viewer { background: #0b0f14 !important; }

/* Legacy/hydrated forward markup has the same compact presentation as files. */
html body #messagesContainer .forwarded-message-container,
html body #messagesContainer .forwarded-message {
    border: 0 !important; background: transparent !important;
    border-radius: 0 !important; padding: 0 !important; margin: 0 !important;
}
html body #messagesContainer .forwarded-header {
    margin: 0 0 6px !important; padding: 0 !important;
    font-size: .85em !important; font-style: normal !important;
}
html body #messagesContainer .forwarded-header .forwarded-label {
    font-size: inherit !important; font-style: normal !important;
}
html body #messagesContainer .forwarded-header a,
html body #messagesContainer .forwarded-header strong { font-weight: 400 !important; }

/* Forward provenance names are interactive, but visually they are sender names,
   not generic blue links. Match the ordinary message-header weight/color without
   adding synthetic spacing around the sender text. */
html body #messagesContainer .forwarded-header .qchat-forwarded-sender-name {
    color: #111827 !important;
    font-weight: 600 !important;
    text-decoration: none !important;
}
html body #messagesContainer .forwarded-header .qchat-forwarded-sender-name:hover {
    color: #111827 !important;
    text-decoration: none !important;
}
html body.dark-theme #messagesContainer .forwarded-header .qchat-forwarded-sender-name,
html body.dark-theme #messagesContainer .forwarded-header .qchat-forwarded-sender-name:hover {
    color: var(--qchat-dark-text, #c9d1d9) !important;
}
@media (prefers-color-scheme: dark) {
    html body.auto-theme #messagesContainer .forwarded-header .qchat-forwarded-sender-name,
    html body.auto-theme #messagesContainer .forwarded-header .qchat-forwarded-sender-name:hover {
        color: #c9d1d9 !important;
    }
}
html body #messagesContainer .forwarded-content {
    padding: 0 !important; margin: 0 !important; background: transparent !important;
    border: 0 !important; white-space: normal;
}

html body #chatImagePreviewModal .qchat-original-fullscreen { position: fixed; inset: 0; z-index: 2147483647; background: #080b10; color: white; display: flex; flex-direction: column; width: 100vw; height: 100dvh; }
.qchat-original-toolbar { display: flex; justify-content: flex-end; gap: 8px; padding: 10px; flex: 0 0 auto; }
.qchat-original-scroll { flex: 1 1 auto; min-height: 0; overflow: auto; display: grid; place-items: center; }
.qchat-original-scroll img { display: block; max-width: 100%; max-height: calc(100dvh - 64px); width: auto; height: auto; object-fit: contain; }
.qchat-original-natural .qchat-original-scroll { display: block; }
.qchat-original-natural .qchat-original-scroll img { max-width: none; max-height: none; margin: auto; }

/* Media windows: visible close control and compact transfer status. */
#qchatChatInfoModal .modal-header { position: relative; padding-right: 64px; }
#qchatChatInfoModal .qchat-chat-info-close {
    position: absolute !important; top: 12px; right: 12px; display: inline-flex !important;
    align-items: center; justify-content: center; width: 44px; height: 44px;
    padding: 0; border: 0; background: transparent; color: inherit !important;
    font-size: 30px; line-height: 1; opacity: 1 !important; visibility: visible !important;
}
#qchatChatInfoModal .qchat-chat-info-close:hover { background: rgba(128,128,128,.18); }
#qchatChatInfoModal .qchat-chat-info-close:focus-visible { outline: 2px solid #579fff; }
#chatImagePreviewModal .qchat-original-scroll { position: relative; display: block; overflow: hidden; touch-action: none; user-select: none; }
#chatImagePreviewModal .qchat-original-scroll img {
    position: absolute; left: 50%; top: 50%; max-width: none; max-height: none;
    margin: 0; transform-origin: center; pointer-events: none;
}
.qchat-file-hydration-image.qchat-file-hydration-media-tile,
.qchat-file-bundle-hydration-item .qchat-file-hydration-image,
.qchat-photo-tile .qchat-file-hydration-placeholder {
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    gap: 12px; padding: 12px; min-width: 0;
}
.qchat-file-hydration-image.qchat-file-hydration-media-tile .qchat-file-hydration-stage,
.qchat-file-bundle-hydration-item .qchat-file-hydration-image .qchat-file-hydration-stage,
.qchat-photo-tile .qchat-file-hydration-stage,
.qchat-photo-tile .qchat-file-hydration-name { display: none !important; }
.qchat-file-hydration-media-tile .qchat-file-hydration-body,
.qchat-file-bundle-hydration-item .qchat-file-hydration-image .qchat-file-hydration-body { width: 100%; min-width: 0; }
.qchat-file-hydration-media-tile .qchat-file-hydration-stage-row { justify-content: center; }
.qchat-file-hydration-media-tile .qchat-file-hydration-bytes:not([hidden]) {
    display: block !important; white-space: normal; overflow-wrap: normal;
    text-align: center; font-size: 10px; line-height: 1.4; margin-top: 6px;
}
.qchat-photo-tile .qchat-file-hydration-placeholder { box-sizing: border-box; height: 100%; }
.qchat-photo-tile .qchat-file-hydration-icon { display: none; }

/* Optional source diagnostics, controlled by AppConfig.debug.mediaGallerySources. */
#qchatChatInfoModal .qchat-photo-tile { position: relative; }
#qchatChatInfoModal .qchat-media-source-debug {
    position: absolute; bottom: 0; left: 0; right: 0; z-index: 2;
    padding: 5px; background: rgba(0,0,0,.85); color: #fff;
    font: 10px/1.35 system-ui, sans-serif; text-align: left;
    white-space: normal; overflow-wrap: anywhere; pointer-events: none;
}

.profile-blog-attachment-preview, .qchat-chat-image-tile { position: relative; }
.qchat-preview-source-debug { position:absolute; bottom:0; left:0; right:0; z-index:3; padding:5px; background:rgba(0,0,0,.85); color:white; font:10px/1.35 system-ui,sans-serif; white-space:normal; pointer-events:none; }

.current-song[aria-busy="true"] { cursor: progress; }
.current-song[aria-busy="true"]::after {
    content: ""; position:absolute; top:6px; right:6px; width:14px; height:14px;
    border:2px solid #65758b; border-top-color:#fff; border-radius:50%;
    animation:qchat-audio-deferred-spin .8s linear infinite; pointer-events:none;
}
@keyframes qchat-audio-deferred-spin { to { transform:rotate(360deg); } }


/* 2026-09-09: keep the active Updates tab visible and make edit composer tall enough on phones. */
@media (max-width: 600px) {
    #appSection > #appTabs,
    #appSection > #appTabs.nav,
    #appSection > #appTabs.nav-tabs {
        scroll-padding-inline: 10px !important;
    }

    #updatesTabItem {
        scroll-margin-inline: 10px !important;
    }

    #qchatPostEditorModal #profileBlogComposer.qchat-post-editor-shared-composer #profileBlogInput,
    #qchatPostEditorModal .qchat-post-editor-shared-composer #profileBlogInput {
        min-height: 190px !important;
        height: 30vh !important;
        max-height: 38vh !important;
        overflow-y: auto !important;
        resize: none !important;
    }

    #qchatPostEditorModal .qchat-post-editor-modal-body {
        padding: 16px !important;
        overflow-y: auto !important;
        -webkit-overflow-scrolling: touch !important;
    }
}

@media (min-width: 601px) {
    #qchatPostEditorModal #profileBlogComposer.qchat-post-editor-shared-composer #profileBlogInput,
    #qchatPostEditorModal .qchat-post-editor-shared-composer #profileBlogInput {
        min-height: 220px !important;
        height: 220px !important;
        max-height: 45vh !important;
        overflow-y: auto !important;
    }
}

/* QChat mobile polish v40
 * Give Updates the same single-scroll-owner layout as Profile/Settings.
 * The app shell itself is overflow:hidden on phones, so every pane that needs
 * vertical scrolling must explicitly fill the remaining tab-content height and
 * give its inner body min-height:0 + overflow-y:auto.
 */
@media (max-width: 767.98px) {
    #updatesTab,
    #updatesTab > .row,
    #updatesTab > .row > [class*="col-"],
    #updatesTab > .row > [class*="col-"] > .qchat-updates-card {
        height: 100% !important;
        min-height: 0 !important;
        max-height: 100% !important;
    }

    #updatesTab > .row > [class*="col-"] {
        display: flex !important;
        flex-direction: column !important;
    }

    #updatesTab .qchat-updates-card {
        flex: 1 1 0 !important;
        min-height: 0 !important;
        overflow: hidden !important;
    }

    #updatesTab .qchat-updates-scroll {
        flex: 1 1 0 !important;
        height: auto !important;
        min-height: 0 !important;
        max-height: 100% !important;
        overflow-y: auto !important;
        overflow-x: hidden !important;
        -webkit-overflow-scrolling: touch !important;
        overscroll-behavior-y: contain !important;
        touch-action: pan-y !important;
        box-sizing: border-box !important;
    }
}

/* QChat mobile polish v56 — reply visibility + stable media geometry. */
.reply-preview-close,
#cancelReplyBtn.reply-preview-close {
    display: inline-flex !important;
    align-items: center !important;
    justify-content: center !important;
    width: 34px !important;
    height: 34px !important;
    flex: 0 0 34px !important;
    padding: 0 !important;
    border: 0 !important;
    border-radius: 8px !important;
    background: transparent !important;
    color: var(--text-color, #c9d1d9) !important;
    opacity: .95 !important;
}
.reply-preview-close svg,
#cancelReplyBtn.reply-preview-close svg {
    width: 18px !important;
    height: 18px !important;
    color: inherit !important;
    fill: currentColor !important;
    opacity: 1 !important;
}
.reply-preview-close:hover,
.reply-preview-close:focus-visible {
    background: rgba(128, 128, 128, .18) !important;
    color: var(--text-color, #c9d1d9) !important;
    opacity: 1 !important;
}

@media (max-width: 767.98px) {
    /* A deferred video inside an album is a grid tile, not a standalone video.
       Standalone portrait sizing (72vw) used to overflow the right-hand album
       cell on Android and got clipped by the gallery's overflow:hidden. */
    html body #messagesContainer .qchat-file-bundle-grid .qchat-file-bundle-item-video > .qchat-deferred-video.qchat-video-preview-tile,
    html body #messagesContainer .qchat-file-bundle-grid .qchat-deferred-video.qchat-video-preview-tile,
    html body #messagesContainer .qchat-chat-blog-gallery .qchat-file-bundle-item-video > .qchat-deferred-video.qchat-video-preview-tile,
    html body #messagesContainer .qchat-chat-blog-gallery .qchat-deferred-video.qchat-video-preview-tile {
        width: 100% !important;
        max-width: 100% !important;
        min-width: 0 !important;
        height: 100% !important;
        max-height: 100% !important;
        min-height: 0 !important;
        aspect-ratio: auto !important;
        margin: 0 !important;
        box-sizing: border-box !important;
    }

    /* Keep every mobile smart album inside the actual message content lane,
       including forwarded/source-rendered galleries that reuse Blog wrappers. */
    html body #messagesContainer .qchat-chat-blog-multi-image-host,
    html body #messagesContainer .qchat-chat-blog-multi-image-host :is(
        .qchat-chat-blog-file-bundle-message,
        .qchat-chat-blog-file-bundle-groups,
        .qchat-chat-blog-gallery-group,
        .qchat-file-bundle-group-image
    ) {
        width: 100% !important;
        max-width: 100% !important;
        min-width: 0 !important;
        margin-left: 0 !important;
        margin-right: 0 !important;
        box-sizing: border-box !important;
    }

    html body #messagesContainer .qchat-chat-blog-multi-image-host .qchat-chat-blog-gallery[data-qchat-album-layout^="tg-"],
    html body #messagesContainer .qchat-file-bundle-grid.qchat-file-bundle-grid-images[data-qchat-album-layout^="tg-"] {
        width: min(360px, 100%) !important;
        max-width: 100% !important;
        min-width: 0 !important;
        margin-left: 0 !important;
        margin-right: 0 !important;
        box-sizing: border-box !important;
    }

    /* Single-image cards always round the actual media surface. Before this,
       landscape images happened to expose the gallery radius while portrait
       images could show square image corners inside a rounded message block. */
    html body #messagesContainer .file-preview.image-preview.qchat-chat-image-tile[data-qchat-single-image="1"],
    html body #messagesContainer .file-preview.image-preview.qchat-chat-image-tile[data-qchat-single-image="1"] > img.chat-image-preview,
    html body #messagesContainer .qchat-chat-blog-single-image-host .qchat-chat-blog-gallery[data-file-group-count="1"],
    html body #messagesContainer .qchat-chat-blog-single-image-host .qchat-chat-blog-gallery[data-file-group-count="1"] :is(
        .qchat-chat-blog-gallery-item,
        .qchat-chat-blog-gallery-tile,
        .qchat-chat-blog-attachment-preview,
        img.qchat-chat-blog-image
    ) {
        border-radius: 12px !important;
        overflow: hidden !important;
    }
}

/* QChat mobile polish v57 — mobile album lane, media corner ownership and dark reply close. */
body.dark-theme .reply-preview-close,
body.dark-theme #cancelReplyBtn.reply-preview-close {
    color: #f0f6fc !important;
    background: rgba(255,255,255,.08) !important;
}
body.dark-theme .reply-preview-close:hover,
body.dark-theme .reply-preview-close:focus-visible,
body.dark-theme #cancelReplyBtn.reply-preview-close:hover,
body.dark-theme #cancelReplyBtn.reply-preview-close:focus-visible {
    color: #ffffff !important;
    background: rgba(255,255,255,.16) !important;
}
@media (prefers-color-scheme: dark) {
    body.auto-theme .reply-preview-close,
    body.auto-theme #cancelReplyBtn.reply-preview-close {
        color: #f0f6fc !important;
        background: rgba(255,255,255,.08) !important;
    }
}

@media (max-width: 767.98px) {
    /* Source/blog-compatible chat galleries used a literal 360px inline lane.
       The bubble has its own padding/metadata, so a 360px viewport could clip the
       final grid column. Keep desktop at 360px but reserve phone-side breathing room. */
    html body #messagesContainer .qchat-chat-blog-multi-image-host,
    html body #messagesContainer .qchat-chat-blog-multi-image-host .qchat-chat-blog-file-bundle-message,
    html body #messagesContainer .qchat-chat-blog-multi-image-host .qchat-chat-blog-file-bundle-groups,
    html body #messagesContainer .qchat-chat-blog-multi-image-host .qchat-chat-blog-gallery-group,
    html body #messagesContainer .qchat-chat-blog-multi-image-host .qchat-chat-blog-gallery {
        width: min(360px, calc(100vw - 64px)) !important;
        max-width: min(360px, calc(100vw - 64px)) !important;
        min-width: 0 !important;
        box-sizing: border-box !important;
    }

    html body #messagesContainer .qchat-chat-blog-multi-image-host .qchat-chat-blog-gallery,
    html body #messagesContainer .qchat-file-bundle-grid.qchat-file-bundle-grid-images:not([data-file-group-count="1"]) {
        overflow: hidden !important;
        border-radius: 12px !important;
        isolation: isolate !important;
    }

    /* Direct mixed image/video bundles use a different DOM tree from the
       source renderer. Give them the same mobile lane so their right-most tile
       cannot be clipped either. */
    html body #messagesContainer .qchat-file-bundle-grid.qchat-file-bundle-grid-images:not([data-file-group-count="1"]),
    html body #messagesContainer .qchat-file-bundle-group:has(.qchat-file-bundle-grid.qchat-file-bundle-grid-images:not([data-file-group-count="1"])),
    html body #messagesContainer .qchat-file-bundle-message:has(.qchat-file-bundle-grid.qchat-file-bundle-grid-images:not([data-file-group-count="1"])) {
        width: min(360px, calc(100vw - 64px)) !important;
        max-width: min(360px, calc(100vw - 64px)) !important;
        min-width: 0 !important;
        box-sizing: border-box !important;
    }

    html body #messagesContainer .qchat-file-bundle-grid.qchat-file-bundle-grid-images > .qchat-file-bundle-item,
    html body #messagesContainer .qchat-chat-blog-gallery > .qchat-chat-blog-gallery-item {
        min-width: 0 !important;
        max-width: 100% !important;
        overflow: hidden !important;
        box-sizing: border-box !important;
    }

    /* One-image messages must clip the image itself, not rely on the outer
       message bubble. Inline source styles are fixed in JS as well; clip-path is
       an extra safety net for restored/cached markup. */
    html body #messagesContainer .qchat-chat-blog-single-image-host .qchat-chat-blog-gallery[data-file-group-count="1"],
    html body #messagesContainer .qchat-chat-blog-single-image-host .qchat-chat-blog-gallery[data-file-group-count="1"] .qchat-chat-blog-gallery-item,
    html body #messagesContainer .qchat-chat-blog-single-image-host .qchat-chat-blog-gallery[data-file-group-count="1"] .qchat-chat-blog-gallery-tile,
    html body #messagesContainer .qchat-chat-blog-single-image-host .qchat-chat-blog-gallery[data-file-group-count="1"] .qchat-chat-blog-attachment-preview,
    html body #messagesContainer .qchat-chat-blog-single-image-host .qchat-chat-blog-gallery[data-file-group-count="1"] img.qchat-chat-blog-image,
    html body #messagesContainer .file-preview.image-preview.qchat-chat-image-tile[data-qchat-single-image="1"],
    html body #messagesContainer .file-preview.image-preview.qchat-chat-image-tile[data-qchat-single-image="1"] > img.chat-image-preview {
        border-radius: 12px !important;
        overflow: hidden !important;
        clip-path: inset(0 round 12px) !important;
    }
}


/* QChat mobile polish v58 — parent-relative gallery sizing + compact selection actions.
 * The previous viewport formula could still be wider than the *actual* content box
 * after message padding/forward metadata. On phones, size albums strictly from the
 * containing message lane. */
@media (max-width: 767.98px) {
    html body #messagesContainer .qchat-chat-blog-multi-image-host,
    html body #messagesContainer .qchat-chat-blog-multi-image-host .qchat-chat-blog-file-bundle-message,
    html body #messagesContainer .qchat-chat-blog-multi-image-host .qchat-chat-blog-file-bundle-groups,
    html body #messagesContainer .qchat-chat-blog-multi-image-host .qchat-chat-blog-gallery-group,
    html body #messagesContainer .qchat-chat-blog-multi-image-host .qchat-chat-blog-gallery,
    html body #messagesContainer .qchat-file-bundle-message:has(.qchat-file-bundle-grid.qchat-file-bundle-grid-images:not([data-file-group-count="1"])),
    html body #messagesContainer .qchat-file-bundle-group:has(.qchat-file-bundle-grid.qchat-file-bundle-grid-images:not([data-file-group-count="1"])),
    html body #messagesContainer .qchat-file-bundle-grid.qchat-file-bundle-grid-images:not([data-file-group-count="1"]) {
        width: 100% !important;
        max-width: 100% !important;
        min-width: 0 !important;
        margin-left: 0 !important;
        margin-right: 0 !important;
        box-sizing: border-box !important;
    }

    html body #messagesContainer .qchat-chat-blog-gallery > .qchat-chat-blog-gallery-item,
    html body #messagesContainer .qchat-file-bundle-grid.qchat-file-bundle-grid-images > .qchat-file-bundle-item {
        width: 100% !important;
        min-width: 0 !important;
        max-width: none !important;
        box-sizing: border-box !important;
    }

    html body #messagesContainer .qchat-chat-blog-gallery .qchat-deferred-video.qchat-video-preview-tile,
    html body #messagesContainer .qchat-file-bundle-grid.qchat-file-bundle-grid-images .qchat-deferred-video.qchat-video-preview-tile,
    html body #messagesContainer .qchat-chat-blog-gallery .qchat-deferred-video-surface,
    html body #messagesContainer .qchat-file-bundle-grid.qchat-file-bundle-grid-images .qchat-deferred-video-surface {
        width: 100% !important;
        max-width: 100% !important;
        min-width: 0 !important;
        height: 100% !important;
        max-height: 100% !important;
        min-height: 0 !important;
        aspect-ratio: auto !important;
        box-sizing: border-box !important;
    }

    html body #messagesContainer .qchat-chat-blog-gallery .qchat-video-poster,
    html body #messagesContainer .qchat-file-bundle-grid.qchat-file-bundle-grid-images .qchat-video-poster {
        width: 100% !important;
        max-width: 100% !important;
        height: 100% !important;
        max-height: none !important;
        object-fit: cover !important;
        display: block !important;
    }

    /* Selection mode should never create horizontal page overflow on a phone. */
    #selectionModePanel {
        width: 100% !important;
        max-width: 100% !important;
        min-width: 0 !important;
        overflow-x: hidden !important;
        box-sizing: border-box !important;
    }
    #selectionModePanel > .d-flex {
        width: 100% !important;
        min-width: 0 !important;
        align-items: stretch !important;
    }
    #selectionModePanel .qchat-selection-actions {
        width: 100% !important;
        min-width: 0 !important;
        display: grid !important;
        grid-template-columns: repeat(3, minmax(0, 1fr)) !important;
        gap: .35rem !important;
    }
    #selectionModePanel .qchat-selection-actions .btn {
        width: 100% !important;
        min-width: 0 !important;
        margin: 0 !important;
        padding-left: .4rem !important;
        padding-right: .4rem !important;
        white-space: normal !important;
        line-height: 1.15 !important;
        overflow: hidden !important;
    }
}

@media (max-width: 420px) {
    #selectionModePanel .qchat-selection-actions .btn :is(.forward-selected-label, .delete-selected-label, .cancel-selection-label) {
        display: none !important;
    }
    #selectionModePanel .qchat-selection-actions .btn svg {
        margin-right: 0 !important;
    }
}


/* QChat P97 — chat-info row parity + exact single-photo Profile Blog/chat geometry. */
/* The chat title is itself the entry into the attachments browser. Do not show a
 * floating tooltip here: use the same blue row hover/focus surface as the category
 * buttons inside the attachments modal. */
html body #chatWithUser[role="button"] {
    cursor: pointer;
    display: flex !important;
    align-items: center !important;
    flex: 1 1 auto !important;
    flex-grow: 1 !important;
    width: auto !important;
    max-width: none !important;
    min-width: 0 !important;
    margin-right: 0 !important;
    padding: .35rem .75rem !important;
    border-radius: 8px !important;
    transform: none !important;
    box-shadow: none !important;
}
html body #chatWithUser[role="button"]:hover,
html body #chatWithUser[role="button"]:focus-visible {
    background: #0d6efd20 !important;
    color: inherit !important;
    transform: none !important;
    box-shadow: none !important;
}
body.dark-theme #chatWithUser[role="button"]:hover,
body.dark-theme #chatWithUser[role="button"]:focus-visible {
    background: #0d6efd20 !important;
    color: inherit !important;
}
@media (prefers-color-scheme: dark) {
    body.auto-theme #chatWithUser[role="button"]:hover,
    body.auto-theme #chatWithUser[role="button"]:focus-visible {
        background: #0d6efd20 !important;
        color: inherit !important;
    }
}

/* A one-photo Profile Blog post keeps its dedicated 360px media lane.
 * Saved Messages use the later v310 compact 340px snapshot contract. Keep the full source ratio visible
 * and let narrow viewports shrink from the parent instead of using a separate
 * 72vw/300px Blog-only geometry. */
/* P103: mixed Blog cards use independent media lanes. The single photo keeps
 * the 360px image lane, while mini audio follows the same 560px content width as
 * .qchat-link-preview-blog. */
html body #profileTab .profile-blog-post .profile-blog-attachments.qchat-profile-blog-bundle-host:has(.profile-blog-gallery[data-file-group-count="1"]),
html body #profileTab .profile-blog-post .profile-blog-attachments.qchat-profile-blog-bundle-host:has(.profile-blog-gallery[data-file-group-count="1"]) .profile-blog-file-bundle-message,
html body #profileTab .profile-blog-post .profile-blog-attachments.qchat-profile-blog-bundle-host:has(.profile-blog-gallery[data-file-group-count="1"]) .profile-blog-file-bundle-groups,
html body #profileTab .profile-blog-post .profile-blog-attachments.qchat-profile-blog-bundle-host:has(.profile-blog-gallery[data-file-group-count="1"]) .profile-blog-audio-group,
html body #profileTab .profile-blog-post .profile-blog-attachments.qchat-profile-blog-bundle-host:has(.profile-blog-gallery[data-file-group-count="1"]) .profile-blog-audio-list,
html body #profileTab .profile-blog-post .profile-blog-attachments.qchat-profile-blog-bundle-host:has(.profile-blog-gallery[data-file-group-count="1"]) .profile-blog-audio-attachment,
html body #profileTab .profile-blog-post .profile-blog-attachments.qchat-profile-blog-bundle-host:has(.profile-blog-gallery[data-file-group-count="1"]) .profile-blog-audio-attachment > .profile-blog-attachment-preview,
html body #profileTab .profile-blog-post .profile-blog-attachments.qchat-profile-blog-bundle-host:has(.profile-blog-gallery[data-file-group-count="1"]) .qchat-audio-mini-group,
html body #profileTab .profile-blog-post .profile-blog-attachments.qchat-profile-blog-bundle-host:has(.profile-blog-gallery[data-file-group-count="1"]) .qchat-audio-mini-player {
    width: min(560px, 100%) !important;
    max-width: min(560px, 100%) !important;
    inline-size: min(560px, 100%) !important;
    max-inline-size: min(560px, 100%) !important;
    min-width: 0 !important;
    min-inline-size: 0 !important;
    flex-basis: auto !important;
    height: auto !important;
    min-height: 0 !important;
    box-sizing: border-box !important;
}

html body #profileTab .profile-blog-post .profile-blog-attachments.qchat-profile-blog-bundle-host:has(.profile-blog-gallery[data-file-group-count="1"]) .profile-blog-gallery-group {
    width: min(360px, 100%) !important;
    max-width: min(360px, 100%) !important;
    min-width: 0 !important;
    height: auto !important;
    min-height: 0 !important;
    box-sizing: border-box !important;
}

html body #profileTab .profile-blog-post .profile-blog-gallery[data-file-group-count="1"] {
    width: min(360px, 100%) !important;
    max-width: min(360px, 100%) !important;
    min-width: 0 !important;
    height: auto !important;
    min-height: 0 !important;
    max-height: none !important;
    aspect-ratio: var(--qchat-album-ratio, 1) !important;
    grid-template-columns: minmax(0, 1fr) !important;
    grid-template-rows: minmax(0, 1fr) !important;
    overflow: hidden !important;
    place-items: stretch !important;
    border-radius: 12px !important;
    box-sizing: border-box !important;
}

html body #profileTab .profile-blog-post .profile-blog-gallery[data-file-group-count="1"] > .profile-blog-gallery-item,
html body #profileTab .profile-blog-post .profile-blog-gallery[data-file-group-count="1"] .profile-blog-gallery-tile,
html body #profileTab .profile-blog-post .profile-blog-gallery[data-file-group-count="1"] .profile-blog-attachment-preview {
    width: 100% !important;
    max-width: none !important;
    min-width: 0 !important;
    height: 100% !important;
    max-height: none !important;
    min-height: 0 !important;
    aspect-ratio: auto !important;
    overflow: hidden !important;
    border-radius: 12px !important;
    box-sizing: border-box !important;
}

html body #profileTab .profile-blog-post .profile-blog-gallery[data-file-group-count="1"] .profile-blog-attachment-preview > img {
    display: block !important;
    width: 100% !important;
    max-width: none !important;
    min-width: 0 !important;
    height: 100% !important;
    max-height: none !important;
    min-height: 0 !important;
    object-fit: contain !important;
    object-position: center center !important;
    transform: none !important;
    border-radius: 12px !important;
    box-sizing: border-box !important;
}


/* QChat P99 — full-width attachments affordance + IMG-owned Blog photo corners.
 * Keep the title as the full flex lane between the back button and right-side
 * call/search controls.  The visible image itself owns rounding; intermediate
 * Blog wrappers stay transparent so square pixels can never leak through a
 * rounded outer shell. */
html body #chatWithUser[role="button"] {
    display: flex !important;
    flex: 1 1 auto !important;
    flex-grow: 1 !important;
    width: auto !important;
    max-width: none !important;
    min-width: 0 !important;
    margin-right: 0 !important;
}

html body #profileTab .profile-blog-post .profile-blog-gallery[data-file-group-count="1"],
html body #profileTab .profile-blog-post .profile-blog-gallery[data-file-group-count="1"] > .profile-blog-gallery-item,
html body #profileTab .profile-blog-post .profile-blog-gallery[data-file-group-count="1"] .profile-blog-gallery-tile,
html body #profileTab .profile-blog-post .profile-blog-gallery[data-file-group-count="1"] .profile-blog-attachment-preview {
    border-radius: 12px !important;
    overflow: hidden !important;
    background: transparent !important;
    background-color: transparent !important;
    box-shadow: none !important;
}

html body #profileTab .profile-blog-post .profile-blog-gallery[data-file-group-count="1"] .profile-blog-attachment-preview > img {
    border-radius: 12px !important;
    overflow: hidden !important;
    clip-path: inset(0 round 12px) !important;
    -webkit-clip-path: inset(0 round 12px) !important;
    background-clip: padding-box !important;
}

/* QChat compact inline message metadata v20.
 * Ordinary text/call/emoji rows keep timestamp + delivery status on the same
 * visual row as the message body. This intentionally overrides the older
 * mobile rule that made .message-footer a full-width block below content. */
@media (max-width: 767.98px) {
    html body #messagesContainer > .message.qchat-message-inline-meta:not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) .message-content-wrapper {
        display: grid !important;
        grid-template-columns: minmax(0, 1fr) max-content !important;
        grid-template-areas:
            "header header"
            "reply reply"
            "content meta" !important;
        align-items: end !important;
        column-gap: 0.38rem !important;
        row-gap: 0 !important;
        width: 100% !important;
        max-width: 100% !important;
        min-width: 0 !important;
        padding-left: var(--qchat-mobile-message-inset, 12px) !important;
        padding-right: var(--qchat-mobile-message-inset, 12px) !important;
        box-sizing: border-box !important;
        overflow-x: clip !important;
    }

    html body #messagesContainer > .message.qchat-message-inline-meta:not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) .message-header {
        grid-area: header !important;
        padding-left: 0 !important;
        padding-right: 0 !important;
        margin-left: 0 !important;
        margin-right: 0 !important;
    }

    html body #messagesContainer > .message.qchat-message-inline-meta:not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) .message-reply-preview {
        grid-area: reply !important;
        min-width: 0 !important;
    }

    html body #messagesContainer > .message.qchat-message-inline-meta:not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) .message-content {
        grid-area: content !important;
        width: auto !important;
        max-width: 100% !important;
        min-width: 0 !important;
        padding-left: 0 !important;
        padding-right: 0 !important;
        margin: 0 !important;
        align-self: end !important;
    }

    html body #messagesContainer > .message.qchat-message-inline-meta:not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) .message-footer,
    html body #messagesContainer > .message.qchat-message-inline-meta.sent:not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) .message-footer,
    html body #messagesContainer > .message.qchat-message-inline-meta.received:not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) .message-footer {
        grid-area: meta !important;
        display: inline-flex !important;
        width: auto !important;
        min-width: max-content !important;
        max-width: none !important;
        flex: 0 0 auto !important;
        align-items: center !important;
        justify-content: flex-end !important;
        justify-self: end !important;
        align-self: end !important;
        gap: 0.18rem !important;
        margin: 0 0 0.04rem 0 !important;
        padding: 0 !important;
        line-height: 1.05 !important;
        text-align: right !important;
        overflow: visible !important;
    }

    html body #messagesContainer > .message.qchat-message-inline-meta:not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) .message-footer.justify-content-between {
        justify-content: flex-end !important;
    }

    html body #messagesContainer > .message.qchat-message-inline-meta:not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) :is(.message-time-wrap, .message-checkmark, .message-status) {
        flex: 0 0 auto !important;
        margin: 0 !important;
        line-height: 1.05 !important;
    }
}


/* QChat patch v325: keep temporary file-send status inside the phone viewport
 * and remove the synthetic blank strip below the final chat message. */
@media (max-width: 767.98px) {
    html body #messagesContainer.message-container,
    html body #messagesContainer {
        padding-bottom: 0 !important;
    }

    html body #messagesContainer > .message:not(:has(~ .message)) {
        margin-bottom: 0 !important;
    }

    html body #messagesContainer .temporary-file-message,
    html body #messagesContainer .temporary-file-message .file-preview,
    html body #messagesContainer .temporary-file-message .file-info,
    html body #messagesContainer .temporary-file-message .file-meta,
    html body #messagesContainer .temporary-file-message .encryption-status {
        width: 100% !important;
        max-width: 100% !important;
        min-width: 0 !important;
        box-sizing: border-box !important;
    }

    html body #messagesContainer .temporary-file-message .file-meta {
        display: flex !important;
        flex-wrap: wrap !important;
        align-items: center !important;
        justify-content: center !important;
        gap: 4px 8px !important;
    }

    html body #messagesContainer .temporary-file-message .file-meta .badge {
        margin-left: 0 !important;
        max-width: 100% !important;
        white-space: normal !important;
    }

    html body #messagesContainer .temporary-file-message .file-info > strong,
    html body #messagesContainer .temporary-file-message .encryption-status small {
        display: block !important;
        max-width: 100% !important;
        overflow-wrap: anywhere !important;
        word-break: break-word !important;
        white-space: normal !important;
    }
}

/* QChat patch v326: keep Profile Blog and Updates comments pixel-identical on phones.
 * This block is intentionally last because mobile-polish loads after index-static. */
@media (max-width: 767.98px) {
    :is(#profileTab, #updatesTab) .profile-blog-post .profile-blog-comments {
        width: 100% !important;
        max-width: 100% !important;
        min-width: 0 !important;
        margin-left: 0 !important;
        margin-right: 0 !important;
        padding-top: 8px !important;
        border-top: 0 !important;
        box-sizing: border-box !important;
    }

    :is(#profileTab, #updatesTab) .profile-blog-post .profile-blog-comments-body,
    :is(#profileTab, #updatesTab) .profile-blog-post .profile-blog-comments-list {
        width: 100% !important;
        max-width: 100% !important;
        min-width: 0 !important;
        margin: 0 !important;
        padding: 0 !important;
        border: 0 !important;
        border-radius: 0 !important;
        background: transparent !important;
        box-shadow: none !important;
        box-sizing: border-box !important;
    }

    :is(#profileTab, #updatesTab) .profile-blog-post .profile-blog-comment {
        width: 100% !important;
        max-width: 100% !important;
        min-width: 0 !important;
        margin: 0 !important;
        padding: 14px 12px !important;
        border: 0 !important;
        border-radius: 0 !important;
        box-shadow: none !important;
        box-sizing: border-box !important;
    }

    :is(#profileTab, #updatesTab) .profile-blog-post .profile-blog-comment + .profile-blog-comment {
        margin-top: 4px !important;
    }

    :is(#profileTab, #updatesTab) .profile-blog-post .profile-blog-comment-content,
    :is(#profileTab, #updatesTab) .profile-blog-post .profile-blog-comment-actions {
        margin-left: 36px !important;
        margin-right: 0 !important;
    }

    :is(#profileTab, #updatesTab) .profile-blog-post .profile-blog-comment-replies {
        width: auto !important;
        max-width: none !important;
        margin: 8px 0 0 20px !important;
        padding: 0 !important;
        border: 0 !important;
        box-shadow: none !important;
        box-sizing: border-box !important;
    }

    :is(#profileTab, #updatesTab) .profile-blog-post .profile-blog-comment-form {
        width: 100% !important;
        max-width: 100% !important;
        margin: 8px 0 0 !important;
        padding: 0 12px 12px !important;
        box-sizing: border-box !important;
    }

    .profile-blog-comment-form .input-group {
        align-items: stretch !important;
        min-height: 38px !important;
    }

    .profile-blog-comment-form .profile-blog-comment-input {
        min-height: 38px !important;
        box-sizing: border-box !important;
        margin: 0 !important;
    }

    .profile-blog-comment-form .input-group > .btn[type="submit"] {
        height: auto !important;
        min-height: 38px !important;
        max-height: none !important;
        align-self: stretch !important;
    }
}


/* QChat patch v327: restore subtle chat zebra surfaces in light mode.
 * v27 intentionally flattened both directions to #f9fafb; on a bright page
 * that removes row separation. Alternate only real chat bubbles and leave
 * saved Profile/Blog cards on their dedicated surface. */
html body.light-theme #messagesContainer > .message:nth-child(odd of .message):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex > .message-bubble {
    --message-bg: #f7f7f7;
    --message-hover-bg: #f7f7f7;
    background: #f7f7f7 !important;
}

html body.light-theme #messagesContainer > .message:nth-child(even of .message):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex > .message-bubble {
    --message-bg: #edf2f7;
    --message-hover-bg: #edf2f7;
    background: #edf2f7 !important;
}

@media (prefers-color-scheme: light) {
    html body.auto-theme #messagesContainer > .message:nth-child(odd of .message):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex > .message-bubble {
        --message-bg: #f7f7f7;
        --message-hover-bg: #f7f7f7;
        background: #f7f7f7 !important;
    }

    html body.auto-theme #messagesContainer > .message:nth-child(even of .message):not(:has(.saved-profile-blog-post)):not(:has(.saved-profile-blog-comment)) > .d-flex > .message-bubble {
        --message-bg: #edf2f7;
        --message-hover-bg: #edf2f7;
        background: #edf2f7 !important;
    }
}

/* QChat patch v327: keep the new upload card compact on narrow chat lanes.
 * This intentionally follows the v325 emergency wrapping rules so the modern
 * progress card wins without reintroducing off-screen status text. */
@media (max-width: 575.98px) {
    html body #messagesContainer .temporary-file-message.qchat-file-upload-card .qchat-file-upload-name {
        display: block !important;
        max-width: 100% !important;
        overflow: hidden !important;
        text-overflow: ellipsis !important;
        white-space: nowrap !important;
        word-break: normal !important;
        overflow-wrap: normal !important;
    }

    html body #messagesContainer .temporary-file-message.qchat-file-upload-card .qchat-file-upload-status,
    html body #messagesContainer .qchat-file-bundle-upload-state .qchat-file-upload-status {
        max-width: 100% !important;
        overflow: hidden !important;
        text-overflow: ellipsis !important;
        white-space: nowrap !important;
    }
}

/* QChat patch v330: light-theme active inline audio parity.
 * v328 accidentally shipped this block with literal "\n" escape text, so the
 * browser never parsed the selectors. The live DOM already marks the playing
 * inline track with playing + chat-audio-current; target that exact state and
 * mirror the floating dock playing surface. */
html body.light-theme #messagesContainer .message .qchat-audio-mini-player.playing.chat-audio-current,
html body.light-theme #messagesContainer .message .qchat-audio-mini-player.current-song.playing.chat-audio-current,
html body.light-theme #messagesContainer .message .qchat-audio-mini-player.playing.blog-audio-current,
html body.light-theme .profile-blog-post .qchat-audio-mini-player.playing.blog-audio-current {
    background: #eef4ff !important;
    background-color: #eef4ff !important;
    border-color: #c7d8f5 !important;
    opacity: 1 !important;
    mix-blend-mode: normal !important;
}

@media (prefers-color-scheme: light) {
    html body.auto-theme #messagesContainer .message .qchat-audio-mini-player.playing.chat-audio-current,
    html body.auto-theme #messagesContainer .message .qchat-audio-mini-player.current-song.playing.chat-audio-current,
    html body.auto-theme #messagesContainer .message .qchat-audio-mini-player.playing.blog-audio-current,
    html body.auto-theme .profile-blog-post .qchat-audio-mini-player.playing.blog-audio-current {
        background: #eef4ff !important;
        background-color: #eef4ff !important;
        border-color: #c7d8f5 !important;
        opacity: 1 !important;
        mix-blend-mode: normal !important;
    }
}

/* QChat v393: iOS/WebKit auto-zooms focused controls whose computed font size
   is below 16px. The app's "small" font setting intentionally lowers the root
   to 14px, so keep composer text controls at the iOS-safe minimum while leaving
   message/UI typography unchanged. */
@media (max-width: 767.98px) {
    @supports (-webkit-touch-callout: none) {
        #messageInput.qchat-message-textarea,
        #profileBlogInput.qchat-message-textarea,
        .profile-blog-comment-form .profile-blog-comment-input,
        #editMessageText.form-control {
            font-size: 16px !important;
        }
    }
}
