* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
    touch-action: manipulation;
    -webkit-tap-highlight-color: transparent;
}

:root {
    --bg-body: #000;
    --bg-sidebar: #0a0a0a;
    --bg-primary: #0a0a0a;
    --bg-secondary: #141414;
    --bg-tertiary: #1e1e1e;
    --bg-widget: #1a1a1a;
    --border: #151515;
    --border-hover: #3a3a3a;
    --text: #e5e5e5;
    --text-dim: #777;
    --text-muted: #555;
    --accent: #007aff;
    --accent-light: #409cff;
    --green: #22c55e;
    --red: #ef4444;
    --orange: #f59e0b;
    --radius: 12px;
    --widget-radius: 18px;
    --chat-h: 78px;
    --dashboard-header-h: 144px;
    --hover-overlay: rgba(255, 255, 255, 0.06);
    --hover-overlay-strong: rgba(255, 255, 255, 0.1);
    --floating-panel-bg: rgba(0, 0, 0, 0.86);
    --shadow-color: rgba(0, 0, 0, 0.3);
    --shadow-heavy: rgba(0, 0, 0, 0.5);
    --backdrop-color: rgba(0, 0, 0, 0.55);
    --icon-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
    /* profile + tabs floating zone */
}

[data-theme="light"] {
    --bg-body: #f7f7fa;
    --bg-sidebar: #ffffff;
    --bg-primary: #ffffff;
    --bg-secondary: #ffffff;
    --bg-tertiary: #f0f0f0;
    --bg-widget: #ffffff;
    --border: #eae4e4;
    --border-hover: #c0c0c0;
    --text: #1c1c1e;
    --text-dim: #8e8e93;
    --text-muted: #aeaeb2;
    --accent: #007aff;
    --accent-light: #409cff;
    --green: #34c759;
    --red: #ff3b30;
    --orange: #ff9500;
    --hover-overlay: rgba(0, 0, 0, 0.04);
    --hover-overlay-strong: rgba(0, 0, 0, 0.08);
    --floating-panel-bg: rgba(255, 255, 255, 0.86);
    --shadow-color: rgba(0, 0, 0, 0.08);
    --shadow-heavy: rgba(0, 0, 0, 0.15);
    --backdrop-color: rgba(0, 0, 0, 0.3);
    --icon-shadow: 0 1px 4px rgba(0, 0, 0, 0.1);
}

body {
    font-family:
        -apple-system, BlinkMacSystemFont, "SF Pro Display", "Segoe UI", Roboto,
        sans-serif;
    background: var(--bg-body);
    color: var(--text);
    height: 100vh;
    overflow: hidden;
}

/* ── Loading Screen ── */
.loading-screen {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 100vh;
}

/* ── Typing Logo ── */
.typing-logo {
    display: flex;
    flex-direction: column;
    min-width: 280px;
    font-family: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, 'Liberation Mono', monospace;
    padding-left: 42px;
    color: var(--text);
    user-select: none;
    position: relative;
}

#loadingLogo {
    flex-direction: row;
    align-items: center;
    justify-content: center;
    padding-left: 0;
}

.typing-text {
    font-size: 70px;
    font-weight: 700;
    letter-spacing: 4px;
}

.typing-line1 {
    display: flex;
    align-items: center;
    font-size: 70px;
    font-weight: 700;
    letter-spacing: 4px;
}

.typing-cursor {
    display: inline-block;
    width: 32px;
    height: 58px;
    background: #007aff;
    margin-left: 4px;
    vertical-align: middle;
    animation: cursor-blink 0.7s step-end infinite;
}

@keyframes cursor-blink {

    0%,
    100% {
        opacity: 1;
    }

    50% {
        opacity: 0;
    }
}

/* ── Auth Screen ── */
.auth-screen {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    height: 100vh;
    gap: 24px;
}

.auth-logo {
    display: flex;
    flex-direction: column;
    align-items: center;
}

/* ── Pixel Logo ── */
.px-row {
    display: flex;
    justify-content: center;
}

.px {
    flex-shrink: 0;
    border-radius: 1px;
}

.px.on {
    animation: px-shimmer 6s ease-in-out infinite;
}

.px-gap {
    flex-shrink: 0;
}

@keyframes px-shimmer {

    0%,
    100% {
        background: #e06070;
    }

    16% {
        background: #e0a050;
    }

    33% {
        background: #60c060;
    }

    50% {
        background: #40b0b0;
    }

    66% {
        background: #5080d0;
    }

    83% {
        background: #9060c0;
    }
}

.auth-logo .px {
    margin: 1px;
    border-radius: 2px;
    width: 8px;
    height: 8px;
}

.auth-logo .px-gap {
    width: 5px;
}

.chat-logo .px {
    margin: 1px;
    border-radius: 2px;
    width: 3px;
    height: 3px;
}

.chat-logo .px-gap {
    width: 2px;
}

/* Base: hidden everywhere; wide-screen @media rules show it when
   sidebar-appchat is open. Without this default, mobile (no matching @media)
   would show it since the only display rules live inside min-width: 900px. */
.sidebar-back-btn {
    display: none;
}

/* Logo panel — positioned outside chat-header so backdrop-filter works */
.logo-panel {
    position: absolute;
    top: 16px;
    left: 20px;
    z-index: 2100;
    display: none;
}

.logo-panel-header {
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
}

.logo-panel-header:active .key-logo {
    transform: scale(0.88);
    box-shadow:
        0 1px 0 #1a1a1c,
        0 1px 2px rgba(0, 0, 0, 0.3);
}

.logo-panel-body {
    position: absolute;
    top: -5px;
    left: -5px;
    width: 48px;
    max-height: 48px;
    overflow: hidden;
    border-radius: 10px;
    background: transparent;
    border: 1px solid transparent;
    transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
    pointer-events: none;
    z-index: -1;
}

.logo-panel.open .logo-panel-body {
    width: 190px;
    max-height: 220px;
    background: rgba(30, 30, 34, 0.97);
    border-color: rgba(255, 255, 255, 0.1);
    box-shadow: 0 8px 32px rgba(0, 0, 0, 0.45);
    pointer-events: auto;
}

.logo-panel-items {
    opacity: 0;
    transition: opacity 0.15s ease 0s;
    padding: 44px 4px 4px;
}

.logo-panel.open .logo-panel-items {
    opacity: 1;
    transition: opacity 0.15s ease 0.1s;
}

.logo-panel-item {
    width: 100%;
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 10px;
    border: none;
    background: none;
    border-radius: 8px;
    font-size: 15px;
    font-family: inherit;
    cursor: pointer;
    color: var(--text);
    transition: background 0.1s;
    text-align: left;
    white-space: nowrap;
}

.logo-panel-item:hover {
    background: rgba(255, 255, 255, 0.07);
}

.logo-panel-item.danger {
    color: #f87171;
}

.logo-panel-item.danger:hover {
    background: rgba(248, 113, 113, 0.1);
}

/* Logo menu backdrop */
.logo-menu-backdrop {
    display: none;
    position: fixed;
    inset: 0;
    z-index: 2099;
}

.logo-menu-backdrop.open {
    display: block;
}

/* Keyboard key logo */
.key-logo {
    width: 36px;
    height: 35px;
    background: #2a2a2e;
    border-radius: 6px;
    display: flex;
    align-items: center;
    justify-content: center;
    position: relative;
    box-shadow:
        0 2px 0 #1a1a1c,
        0 3px 4px rgba(0, 0, 0, 0.3);
    transition:
        transform 0.1s ease,
        box-shadow 0.1s ease;
}

.key-logo-f {
    font-family: Georgia, "Times New Roman", serif;
    font-size: 20px;
    font-weight: 700;
    color: #f0f0f0;
    line-height: 1;
}

.key-logo-cursor {
    width: 9px;
    height: 15px;
    background: var(--accent);
    margin-left: 2px;
}

[data-theme="light"] .key-logo {
    background: #e8e8e8;
    box-shadow:
        0 2px 0 #c0c0c0,
        0 3px 4px rgba(0, 0, 0, 0.15);
}

[data-theme="light"] .key-logo-f {
    color: #1a1a1a;
}

.auth-sub {
    color: var(--text-dim);
    font-size: 15px;
    margin: 0;
    width: 300px;
}

#g_id_onload,
.g_id_signin {
    margin-top: 8px;
}

/* ── Auth Divider ── */
.auth-divider {
    display: flex;
    align-items: center;
    gap: 12px;
    width: 260px;
    color: var(--text-muted);
    font-size: 13px;
}

.auth-divider::before,
.auth-divider::after {
    content: "";
    flex: 1;
    height: 1px;
    background: var(--border);
}

.email-code-active > #googleBtn,
.email-code-active > #appleBtn,
.email-code-active > #telegramLoginWrap,
.email-code-active > .auth-divider {
    display: none !important;
}

/* ── Email Auth ── */
.email-auth {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 10px;
    width: 240px;
}

.email-auth-step {
    display: flex;
    flex-direction: column;
    gap: 10px;
    width: 100%;
}

.email-input-wrap {
    position: relative;
    width: 100%;
}

.email-send-icon {
    position: absolute;
    right: -48px;
    top: 50%;
    transform: translateY(-50%) scale(0);
    width: 38px;
    height: 38px;
    border-radius: 50%;
    background: var(--accent);
    color: #fff;
    border: none;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition:
        transform 0.2s cubic-bezier(0.4, 0, 0.2, 1),
        background 0.15s;
    opacity: 0;
}

.email-send-icon.visible {
    transform: translateY(-50%) scale(1);
    opacity: 1;
}

.email-send-icon:hover {
    background: var(--accent-light);
}

.email-send-icon:disabled {
    opacity: 0.5;
    cursor: not-allowed;
}

.email-auth-input {
    width: 100%;
    padding: 12px 24px;
    background: var(--bg-tertiary);
    border: 1px solid var(--border);
    border-radius: 24px;
    color: var(--text);
    font-size: 15px;
    font-family: inherit;
    outline: none;
    transition: border-color 0.15s;
}

.email-auth-input:focus {
    border-color: var(--border-hover);
}

.email-auth-input::placeholder {
    color: var(--text-muted);
}

.email-auth-input.code-input {
    text-align: center;
    font-size: 24px;
    letter-spacing: 8px;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    padding: 10px 24px;
}

.email-auth-btn {
    width: 100%;
    padding: 12px;
    background: var(--accent);
    color: #fff;
    border: none;
    border-radius: 24px;
    font-size: 15px;
    font-weight: 500;
    font-family: inherit;
    cursor: pointer;
    transition: background 0.15s;
}

.email-auth-btn:hover {
    background: var(--accent-light);
}

.email-auth-btn:disabled {
    opacity: 0.5;
    cursor: not-allowed;
}

.email-auth-sent {
    font-size: 13px;
    color: var(--text-dim);
    text-align: center;
}

.email-auth-back {
    background: none;
    border: none;
    color: var(--text-muted);
    font-size: 13px;
    font-family: inherit;
    cursor: pointer;
    padding: 4px;
    transition: color 0.15s;
}

.email-auth-back:hover {
    color: var(--text);
}

.email-auth-error {
    font-size: 13px;
    color: var(--red);
    text-align: center;
    min-height: 0;
}

.auth-footer {
    position: absolute;
    bottom: 24px;
    text-align: center;
    color: #555;
    font-size: 11px;
    line-height: 1.5;
}

.auth-footer-company {
    font-weight: 600;
    color: #666;
}

/* ── Main Layout ── */
.app {
    display: none;
}

.app.visible {
    display: block;
}

/* A direct /{user} boot hydrates the dashboard with normal layout behind the
   loading screen. The surface becomes visible only after URL routing has mounted
   the profile (or another user section) above it, preventing a dashboard flash. */
body.user-route-boot-pending #mainApp {
    visibility: hidden;
    pointer-events: none;
}

/* ── Desktop Surface ── */
.desktop {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    overflow: hidden;
    background: transparent;
    display: flex;
    flex-direction: column;
}

/* Gradient that icons scroll under — top (covers floating header zone) */
.desktop::before {
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: calc(var(--dashboard-header-h) + 28px);
    background: linear-gradient(to bottom,
            rgba(0, 0, 0, 0.35) 40%,
            transparent 100%);
    z-index: 5;
    pointer-events: none;
}

/* Gradient that icons scroll under — bottom (covers chat input zone) */
.desktop::after {
    content: "";
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    height: calc(var(--chat-h) + 24px);
    background: linear-gradient(to top, rgba(0, 0, 0, 0.4) 40%, transparent 100%);
    z-index: 5;
    pointer-events: none;
}

.desktop.app-fullscreen::before,
.desktop.app-fullscreen::after {
    display: none;
}

/* Background canvas. A WebGL shader (background.js) paints the dark-theme
   aurora, one frame per second. Light theme keeps the plain body background. */
#bgDots {
    position: fixed;
    inset: 0;
    width: 100%;
    height: 100%;
    z-index: -1;
    display: none;
    background: #fff;
    pointer-events: none;
    contain: strict;
}

/* Dark theme with working (hardware) WebGL: show the aurora canvas. */
html.bg-aurora-gl:not([data-theme="light"]) #bgDots {
    display: block;
    background: var(--bg-body);
}

/* No usable WebGL (SwiftShader, lost context): no background at all — the
   canvas hides and the plain body color shows. */
html.bg-static #bgDots {
    display: none;
}

/* Tab switcher — centered glass pill */
.desktop-tabs {
    display: flex;
    gap: 0;
    flex-shrink: 0;
    background: rgba(30, 30, 30, 0.55);
    backdrop-filter: blur(20px);
    -webkit-backdrop-filter: blur(20px);
    border: 1px solid rgba(255, 255, 255, 0.12);
    border-radius: 20px;
    margin: 12px auto 0;
    padding: 3px;
    position: relative;
    z-index: 10;
    overflow-x: auto;
    scrollbar-width: none;
    box-shadow: 0 2px 12px rgba(0, 0, 0, 0.3);
    width: fit-content;
}

.desktop-tabs::-webkit-scrollbar {
    display: none;
}

.desktop-tab {
    flex: 0 0 auto;
    padding: 7px 16px;
    border: none;
    background: transparent;
    color: rgba(255, 255, 255, 0.55);
    font:
        13px/1 -apple-system,
        system-ui,
        sans-serif;
    font-weight: 500;
    border-radius: 17px;
    cursor: pointer;
    transition:
        color 0.2s,
        background 0.2s;
    position: relative;
    z-index: 1;
    -webkit-tap-highlight-color: transparent;
    white-space: nowrap;
}

/* Sliding indicator behind active tab */
.desktop-tabs-indicator {
    position: absolute;
    top: 3px;
    bottom: 3px;
    left: 0;
    background: rgba(255, 255, 255, 0.15);
    border-radius: 17px;
    transition:
        transform 0.3s cubic-bezier(0.4, 0, 0.2, 1),
        width 0.3s cubic-bezier(0.4, 0, 0.2, 1);
    z-index: 0;
    pointer-events: none;
}

.desktop-tab.active {
    color: #fff;
}

/* App tabs */
.desktop-tab.app-tab {
    display: flex;
    align-items: center;
    gap: 6px;
    max-width: 160px;
    padding: 5px 6px 5px 12px;
}

.app-tab-name {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.app-tab-close {
    width: 18px;
    height: 18px;
    border-radius: 50%;
    border: none;
    background: transparent;
    color: var(--text-muted);
    font-size: 13px;
    line-height: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    flex-shrink: 0;
    transition:
        background 0.15s,
        color 0.15s;
    padding: 0;
}

.app-tab-close:hover {
    background: rgba(255, 255, 255, 0.15);
    color: var(--text);
}

/* Panels container — fills full desktop area, panels scroll independently */
.desktop-panels {
    position: absolute;
    inset: 0;
    overflow: hidden;
    z-index: 1;
}

/* On the mobile dashboard, let the sticky profile card participate in the
   desktop stacking context so its z-index can place it above the top fade.
   Keep the apps grid in its own lower layer: icons still scroll under the
   fade, while profile text and photos remain undimmed. */
@media (max-width: 899px) {
    .desktop-panels {
        z-index: auto;
    }

    .desktop-icons {
        position: relative;
        z-index: 1;
    }
}

.desktop-panel {
    display: none;
}

.desktop-panel-title {
    display: none;
}

.desktop-panel.active {
    display: block;
    position: absolute;
    inset: 0;
    overflow-y: auto;
}

.desktop-panel.app-panel.active {
    display: flex;
    flex-direction: column;
    position: absolute;
    inset: 0;
    overflow: hidden;
    background: var(--bg-primary);
}

/* Icons grid — grid-template-columns is set dynamically by fitIconGridColumns() */
.desktop-icons {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    /* fallback before JS runs */
    gap: 12px;
    padding: 10px 10px 16px;
    padding-bottom: calc(var(--chat-h) + 24px);
    align-content: start;
}

/* When an app tab is active, hide tabs — app fills the whole column. The
   public-profile pill lives inside #panelPrivate, so it disappears with the
   dashboard panel automatically (no per-element hide needed). */
.desktop.app-fullscreen>.desktop-tabs,
.desktop.app-fullscreen>#sectionPanel {
    display: none;
}

/* App takes priority over profile — make panels and profile buttons visible */
.desktop.app-fullscreen .desktop-panels {
    opacity: 1 !important;
    pointer-events: auto !important;
    transform: none !important;
}

.desktop.app-fullscreen .back-btn,
.desktop.app-fullscreen #profileOpenHeader,
.desktop.app-fullscreen~.profile-actions-btn,
.desktop.app-fullscreen~.profile-actions-dropdown {
    display: none !important;
}

/* While an app is on top, hide ALL section/profile chrome regardless of
   .app-fullscreen scoping. Sections (profile / user-apps / notifs) keep
   their DOM mounted and their open classes — only the visual layer is
   suppressed — so closing the app reveals them instantly without any
   re-fetch or re-render. URL is restored from a snapshot in closeAppTab.
   Note: #sectionRightGutter stays clickable / hoverable so the wide
   right-side click-to-close + hover-scales-X behaviour still works (it's
   transparent — no overlay on the app); the gutter's own X is hidden so
   the global #homeCloseHint is the only X shown. */
body.app-active #sectionPanel,
body.app-active .profile-open-header,
body.app-active .profile-actions-btn,
body.app-active .profile-actions-dropdown,
body.app-active #sectionRightGutter>.section-right-gutter-x {
    display: none !important;
}

/* Floating glass toolbar over app — must stay above the loader and native
   modal host so close/title/menu remain reachable while app content is covered. */
.app-tab-toolbar {
    position: absolute;
    top: 10px;
    left: 10px;
    right: 10px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    z-index: 10030;
    pointer-events: none;
}

/* Users who haven't completed the invite flow are in "viewer-only" mode —
   hide the floating toolbar entirely (close, title pill, three-dots menu).
   Toolbar is absolutely positioned, so the iframe keeps its full-bleed layout
   and no top spacing is left behind. */
body.needs-invite .app-tab-toolbar {
    display: none !important;
}

.app-tab-toolbar>* {
    pointer-events: auto;
}

/* Shared close/back circle button — one visual style across the whole app.
   Positional + entrance rules live on the individual selectors below. */
.app-toolbar-back,
.back-btn {
    width: 40px;
    height: 40px;
    border-radius: 50%;
    border: 1px solid rgba(255, 255, 255, 0.12);
    /* Dense tint, no blur — sits over the live app iframe (same treatment
       as .app-toolbar-title). */
    background: rgba(30, 30, 30, 0.78);
    color: #fff;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    padding: 0;
    box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
    transition: background 0.15s, transform 0.15s;
}

@media (hover: hover) {

    .app-toolbar-back:hover,
    .back-btn:hover {
        background: rgba(50, 50, 50, 0.7);
        transform: scale(1.05);
    }
}

.app-toolbar-back:active,
.back-btn:active {
    transform: scale(0.95);
}

/* Desktop: close (X) mode goes to the right; back-arrow stays on the left. */
@media (min-width: 900px) {
    .app-tab-toolbar:has(.app-toolbar-back.close-mode) {
        justify-content: flex-end;
        gap: 8px;
    }

    .app-toolbar-back.close-mode {
        order: 2;
    }
}

/* Center title pill — the overflow-menu trigger on every layout. */
.app-toolbar-title {
    display: none;
    align-items: center;
    justify-content: center;
    gap: 4px;
    max-width: 60%;
    min-width: 0;
    height: 36px;
    --app-toolbar-title-padding-left: 14px;
    --app-toolbar-title-padding-right: 14px;
    padding: 0 var(--app-toolbar-title-padding-right) 0 var(--app-toolbar-title-padding-left);
    border: 1px solid rgba(255, 255, 255, 0.12);
    border-radius: 18px;
    /* Denser tint instead of glass: this pill sits over the live app iframe
       for the whole session, so a blur re-filters at the app's frame rate. */
    background: rgba(30, 30, 30, 0.78);
    color: rgba(255, 255, 255, 0.9);
    font-family: inherit;
    font-size: 14px;
    font-weight: 600;
    cursor: pointer;
    overflow: hidden;
    box-shadow: 0 2px 12px rgba(0, 0, 0, 0.3);
    transition:
        width 0.42s cubic-bezier(0.34, 1.32, 0.64, 1),
        height 0.42s cubic-bezier(0.34, 1.32, 0.64, 1),
        padding-left 0.3s cubic-bezier(0.22, 1, 0.36, 1),
        padding-right 0.3s cubic-bezier(0.22, 1, 0.36, 1),
        border-radius 0.3s cubic-bezier(0.22, 1, 0.36, 1),
        background 0.2s,
        transform 0.15s;
}

.app-toolbar-title:active {
    transform: translateX(-50%) translateY(1px) scale(0.95);
}

.app-toolbar-title.is-press-bouncing {
    animation: app-toolbar-title-press 260ms cubic-bezier(0.22, 1, 0.36, 1);
}

@keyframes app-toolbar-title-press {
    0%   { transform: translateX(-50%) translateY(0) scale(1); }
    42%  { transform: translateX(-50%) translateY(1px) scale(0.95); }
    72%  { transform: translateX(-50%) translateY(-0.5px) scale(1.01); }
    100% { transform: translateX(-50%) translateY(0) scale(1); }
}

.app-toolbar-title-name {
    flex: 0 0 auto;
    overflow: visible;
    text-overflow: clip;
    white-space: nowrap;
    min-width: 0;
}

.app-toolbar-title-chevron {
    display: inline-flex;
    flex: 0 0 14px;
    width: 14px;
    height: 14px;
    margin-left: 2px;
    opacity: 0.72;
}

.app-toolbar-title-chevron svg {
    width: 14px;
    height: 14px;
}

.app-toolbar-title-hint {
    display: none;
}

/* On pointer-driven desktop layouts, reveal what the title pill does without
   competing with its toast/loading surfaces. The pill keeps its top edge in
   place and grows downward. Symmetric 3px padding increases make the pill
   exactly 6px wider on every hover, including while its menu is open. */
@media (min-width: 900px) and (hover: hover) {
    body.app-active .app-toolbar-title-hint {
        position: absolute;
        left: 8px;
        right: 8px;
        bottom: 5px;
        display: flex;
        align-items: center;
        justify-content: center;
        gap: 3px;
        color: rgba(255, 255, 255, 0.48);
        font-size: 9px;
        font-weight: 500;
        line-height: 1;
        white-space: nowrap;
        opacity: 0;
        transform: translateY(-2px);
        pointer-events: none;
        transition:
            opacity 0.16s ease,
            transform 0.26s cubic-bezier(0.22, 1, 0.36, 1);
    }

    body.app-active .app-toolbar-title-hint svg {
        width: 9px;
        height: 9px;
        flex: 0 0 9px;
    }

    body.app-active .app-toolbar-title:not(.is-toast):not(.is-loading):not(.is-pull-active):not(.is-pull-refreshing):not(.is-title-fade-out):not(.is-menu-open):not(.is-menu-measuring-closed):hover {
        height: 50px;
        padding-left: calc(var(--app-toolbar-title-padding-left) + 3px);
        padding-right: calc(var(--app-toolbar-title-padding-right) + 3px);
        border-radius: 17px;
    }

    body.app-active .app-toolbar-title:not(.is-toast):not(.is-loading):not(.is-pull-active):not(.is-pull-refreshing):not(.is-title-fade-out):not(.is-menu-open):not(.is-menu-measuring-closed):hover > .app-toolbar-app-icon,
    body.app-active .app-toolbar-title:not(.is-toast):not(.is-loading):not(.is-pull-active):not(.is-pull-refreshing):not(.is-title-fade-out):not(.is-menu-open):not(.is-menu-measuring-closed):hover > .app-toolbar-avatar,
    body.app-active .app-toolbar-title:not(.is-toast):not(.is-loading):not(.is-pull-active):not(.is-pull-refreshing):not(.is-title-fade-out):not(.is-menu-open):not(.is-menu-measuring-closed):hover > .app-toolbar-title-name {
        transform: translateY(-7px);
    }

    body.app-active .app-toolbar-title:not(.is-toast):not(.is-loading):not(.is-pull-active):not(.is-pull-refreshing):not(.is-title-fade-out):not(.is-menu-open):not(.is-menu-measuring-closed):hover > .app-toolbar-title-hint {
        opacity: 1;
        transform: translateY(0);
    }

    [data-theme="light"] body.app-active .app-toolbar-title-hint {
        color: rgba(20, 20, 20, 0.46);
    }
}

/* Toasts use the title pill itself as their surface. The app icon/name fade
   away while the status content fades in; runtime.js animates the pill's
   measured width so this reads as one object expanding and contracting. */
.app-toolbar-title > .app-toolbar-app-icon,
.app-toolbar-title > .app-toolbar-avatar,
.app-toolbar-title > .app-toolbar-title-name,
.app-toolbar-title > .app-toolbar-title-chevron {
    transition:
        opacity 0.16s ease,
        transform 0.42s cubic-bezier(0.34, 1.32, 0.64, 1);
}

/* Fork.pullToRefresh keeps the app title as the stable surface. During the
   pull it grows downward for a small second line; after release the app icon
   is replaced in-place by a host spinner until the app releases the refresh. */
.app-toolbar-pull-label {
    position: absolute;
    left: 10px;
    right: 10px;
    top: 34px;
    display: flex;
    align-items: center;
    justify-content: center;
    color: rgba(255, 255, 255, 0.52);
    font-size: 10px;
    font-weight: 500;
    line-height: 1;
    white-space: nowrap;
    opacity: 0;
    transform: translateY(-3px) scale(0.76);
    pointer-events: none;
    transform-origin: 50% 50%;
    transition:
        opacity 240ms ease,
        transform 240ms cubic-bezier(0.22, 1, 0.36, 1);
}

body.app-active .app-toolbar-title.is-pull-active {
    /* The existing web pill is 36px tall. Matching iOS's +24pt expansion
       yields 60px here while keeping the absolutely-positioned top edge fixed. */
    height: 60px;
    border-radius: 20px;
    cursor: default;
    transform: translateX(-50%);
}

.app-toolbar-title.is-pull-active > .app-toolbar-app-icon,
.app-toolbar-title.is-pull-active > .app-toolbar-avatar,
.app-toolbar-title.is-pull-active > .app-toolbar-title-name,
.app-toolbar-title.is-pull-active > .app-toolbar-title-chevron,
.app-toolbar-title.is-pull-active > .app-toolbar-pull-spinner {
    /* Flex centering would move the original row down by 12px as height grows.
       Cancel exactly that delta so the icon/title baseline never moves. */
    transform: translateY(-12px);
}

.app-toolbar-title.is-pull-active > .app-toolbar-pull-label {
    opacity: 1;
    transform: translateY(0) scale(1);
    transition-duration: 460ms;
}

.app-toolbar-pull-spinner {
    width: 20px;
    height: 20px;
    flex: 0 0 20px;
    display: none;
    align-items: center;
    justify-content: center;
    color: currentColor;
    transition: transform 0.42s cubic-bezier(0.34, 1.32, 0.64, 1);
}

.app-toolbar-pull-spinner svg {
    width: 20px;
    height: 20px;
    fill: none;
    stroke: currentColor;
    stroke-width: 2;
    stroke-linecap: round;
    transform: rotate(-90deg);
    transform-origin: 50% 50%;
}

.app-toolbar-pull-spinner circle {
    stroke-dasharray: 100;
    stroke-dashoffset: 100;
    transition: stroke-dashoffset 40ms linear;
}

.app-toolbar-pull-spinner circle.is-settling {
    transition-duration: 180ms;
    transition-timing-function: cubic-bezier(0.22, 1, 0.36, 1);
}

.app-toolbar-title.is-pull-refreshing {
    cursor: default;
}

.app-toolbar-title.is-pull-active > .app-toolbar-app-icon,
.app-toolbar-title.is-pull-active > .app-toolbar-avatar,
.app-toolbar-title.is-pull-refreshing > .app-toolbar-app-icon,
.app-toolbar-title.is-pull-refreshing > .app-toolbar-avatar {
    display: none;
}

.app-toolbar-title.is-pull-active > .app-toolbar-pull-spinner,
.app-toolbar-title.is-pull-refreshing > .app-toolbar-pull-spinner {
    display: flex;
}

.app-toolbar-title.is-pull-spinning > .app-toolbar-pull-spinner svg {
    animation: fork-pull-to-refresh-spin 300ms linear infinite;
}

@keyframes fork-pull-to-refresh-spin {
    from { transform: rotate(-90deg); }
    to { transform: rotate(270deg); }
}

/* runtime.js uses this one midpoint state for main-title replacements,
   toast-to-toast replacements and loading-title updates. Surface-to-surface
   changes use the same controller and the regular rules below as a crossfade. */
.app-toolbar-title.is-title-fade-out > .app-toolbar-title-name,
.app-toolbar-title.is-title-fade-out > .app-toolbar-toast,
.app-toolbar-title.is-title-fade-out > .app-toolbar-loading {
    opacity: 0 !important;
    transform: translateY(-5px) scale(0.97) !important;
}

.fork-title-fade {
    transition: opacity 0.16s ease, transform 0.28s cubic-bezier(0.22, 1, 0.36, 1);
}

.fork-title-fade.is-title-fade-out {
    opacity: 0;
    transform: translateY(-4px);
}

.app-toolbar-toast {
    position: absolute;
    inset: 0 14px;
    min-width: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    opacity: 0;
    transform: translateY(6px) scale(0.96);
    pointer-events: none;
    transition:
        opacity 0.18s ease,
        transform 0.34s cubic-bezier(0.22, 1, 0.36, 1);
}

.app-toolbar-toast-dot {
    width: 8px;
    height: 8px;
    flex: 0 0 8px;
    border-radius: 50%;
    background: var(--app-toast-color, #007aff);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--app-toast-color, #007aff) 18%, transparent);
}

.app-toolbar-toast-message {
    min-width: 0;
    flex: 0 0 auto;
    overflow: visible;
    text-overflow: clip;
    white-space: nowrap;
}

.app-toolbar-title.is-toast {
    gap: 0;
    padding-left: 14px;
    max-width: min(calc(100% - 104px), 560px);
    cursor: pointer;
    background: rgba(24, 24, 26, 0.94);
}

.app-toolbar-title.is-toast:active {
    transform: translateX(-50%);
}

.app-toolbar-title.is-toast > .app-toolbar-app-icon,
.app-toolbar-title.is-toast > .app-toolbar-avatar,
.app-toolbar-title.is-toast > .app-toolbar-title-name,
.app-toolbar-title.is-toast > .app-toolbar-title-chevron {
    opacity: 0;
    transform: translateY(-6px) scale(0.96);
}

.app-toolbar-title.is-toast > .app-toolbar-toast {
    opacity: 1;
    transform: translateY(0) scale(1);
}

/* ── Fork.loading — host-owned WebView loading surfaces ── */
.app-toolbar-loading {
    position: absolute;
    inset: 0 12px;
    min-width: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 7px;
    opacity: 0;
    transform: translateY(6px) scale(0.96);
    pointer-events: none;
    transition:
        opacity 0.18s ease,
        transform 0.34s cubic-bezier(0.22, 1, 0.36, 1);
}

.app-toolbar-title.is-loading {
    cursor: pointer;
    max-width: min(calc(100% - 104px), 560px);
    background: rgba(24, 24, 26, 0.94);
}

.app-toolbar-title.is-loading > .app-toolbar-toast {
    opacity: 0;
    transform: translateY(6px) scale(0.96);
}

.app-toolbar-title.is-loading > .app-toolbar-loading {
    opacity: 1;
    transform: translateY(0) scale(1);
}

.app-toolbar-loading .fork-loading-title,
.app-toolbar-loading .fork-loading-percent {
    flex: 0 0 auto;
    min-width: 0;
    overflow: visible;
    overflow-wrap: normal;
    text-overflow: clip;
    white-space: nowrap;
}

.app-toolbar-loading .fork-loading-percent {
    color: rgba(255, 255, 255, 0.62);
    font-variant-numeric: tabular-nums;
}

.app-toolbar-loading .fork-loading-cancel {
    width: 18px;
    height: 18px;
    flex: 0 0 18px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.1);
    color: rgba(255, 255, 255, 0.72);
    font-size: 15px;
    line-height: 1;
}

.fork-loading-overlay {
    position: absolute;
    inset: 0;
    z-index: 10015; /* over the WebView, under platform toolbar/modal chrome */
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 24px;
    background: rgba(0, 0, 0, 0.18);
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.2s ease;
}

.fork-loading-overlay.is-visible {
    opacity: 1;
}

.fork-loading-overlay.is-blocking {
    pointer-events: auto;
}

.fork-loading-hud {
    position: relative;
    box-sizing: border-box;
    min-width: 112px;
    max-width: min(360px, 90%);
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto auto;
    align-items: center;
    gap: 12px;
    padding: 16px 18px;
    border: 1px solid rgba(255, 255, 255, 0.12);
    border-radius: 20px;
    background: rgba(24, 24, 26, 0.94);
    color: rgba(255, 255, 255, 0.94);
    box-shadow: 0 18px 54px rgba(0, 0, 0, 0.34);
    transform: translateY(7px) scale(0.97);
    transition:
        transform 0.3s cubic-bezier(0.16, 1, 0.3, 1),
        width 0.34s cubic-bezier(0.22, 1, 0.36, 1);
}

.fork-loading-overlay.is-visible .fork-loading-hud {
    transform: translateY(0) scale(1);
}

.fork-loading-copy {
    min-width: 0;
}

.fork-loading-title {
    min-width: 0;
    overflow: visible;
    overflow-wrap: anywhere;
    text-overflow: clip;
    white-space: normal;
    font-size: 14px;
    font-weight: 650;
    line-height: 1.25;
}

.fork-loading-message {
    min-width: 0;
    margin-top: 3px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: rgba(255, 255, 255, 0.58);
    font-size: 12px;
    line-height: 1.25;
}

.fork-loading-percent {
    color: rgba(255, 255, 255, 0.68);
    font-size: 12px;
    font-weight: 650;
    font-variant-numeric: tabular-nums;
}

.fork-loading-cancel {
    width: 26px;
    height: 26px;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.09);
    color: rgba(255, 255, 255, 0.74);
    font: 19px/1 -apple-system, BlinkMacSystemFont, sans-serif;
    cursor: pointer;
    pointer-events: auto;
}

.fork-loading-indicator {
    position: relative;
    width: 28px;
    height: 28px;
    flex: 0 0 28px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: #0a84ff;
}

.app-toolbar-loading .fork-loading-indicator {
    width: 18px;
    height: 18px;
    flex-basis: 18px;
}

.fork-loading-spinner-svg,
.fork-loading-progress-svg,
.fork-loading-terminal,
.fork-loading-generative {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    display: none;
}

.is-spinner:not(.is-success):not(.is-error) .fork-loading-spinner-svg,
.is-progress:not(.is-success):not(.is-error) .fork-loading-progress-svg,
.is-generative:not(.is-success):not(.is-error) .fork-loading-generative,
.is-success .fork-loading-terminal-success,
.is-error .fork-loading-terminal-error {
    display: block;
}

.fork-loading-spinner-svg {
    animation: fork-loading-spin 0.82s linear infinite;
}

.fork-loading-spinner-svg circle {
    fill: none;
    stroke: currentColor;
    stroke-width: 2.6;
    stroke-linecap: round;
    stroke-dasharray: 52 20;
}

.fork-loading-progress-svg {
    transform: rotate(-90deg);
}

.fork-loading-progress-track,
.fork-loading-progress-value {
    fill: none;
    stroke-width: 2.5;
}

.fork-loading-progress-track {
    stroke: rgba(128, 128, 128, 0.22);
}

.fork-loading-progress-value {
    stroke: currentColor;
    stroke-linecap: round;
    stroke-dasharray: 100;
    transition: stroke-dashoffset 0.3s cubic-bezier(0.22, 1, 0.36, 1);
}

.fork-loading-generative i {
    position: absolute;
    width: 62%;
    height: 62%;
    border-radius: 50%;
    filter: blur(1px);
    animation: fork-loading-orbit 1.8s ease-in-out infinite alternate;
}

.fork-loading-generative i:nth-child(1) { left: 0; top: 18%; background: #7c3aed; }
.fork-loading-generative i:nth-child(2) { right: 0; top: 2%; background: #0a84ff; animation-delay: -0.6s; }
.fork-loading-generative i:nth-child(3) { left: 24%; bottom: 0; background: #ec4899; animation-delay: -1.1s; }

.fork-loading-terminal {
    fill: none;
    stroke: currentColor;
    stroke-width: 2.3;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.is-success .fork-loading-indicator { color: #34c759; }
.is-error .fork-loading-indicator { color: #ff453a; }

.fork-loading-bar {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    z-index: 10031;
    height: 3px;
    overflow: hidden;
    opacity: 0;
    pointer-events: none;
    background: rgba(128, 128, 128, 0.16);
    transition: opacity 0.16s ease;
}

.fork-loading-bar.is-visible {
    opacity: 1;
}

.fork-loading-bar-value {
    display: block;
    width: 0;
    height: 100%;
    border-radius: 0 3px 3px 0;
    background: #0a84ff;
    transition: width 0.3s cubic-bezier(0.22, 1, 0.36, 1);
}

.fork-loading-bar.is-indeterminate .fork-loading-bar-value {
    animation: fork-loading-bar 1.25s ease-in-out infinite;
}

.fork-loading-bar.is-success .fork-loading-bar-value { background: #34c759; }
.fork-loading-bar.is-error .fork-loading-bar-value { background: #ff453a; }

@keyframes fork-loading-spin {
    to { transform: rotate(360deg); }
}

@keyframes fork-loading-orbit {
    from { transform: translate3d(-2px, 2px, 0) scale(0.82); opacity: 0.58; }
    to { transform: translate3d(3px, -2px, 0) scale(1.05); opacity: 0.94; }
}

@keyframes fork-loading-bar {
    0% { transform: translateX(-110%); }
    55% { transform: translateX(115%); }
    100% { transform: translateX(260%); }
}

.app-toolbar-app-icon {
    position: relative;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    flex-shrink: 0;
    overflow: hidden;
    display: flex;
    align-items: center;
    justify-content: center;
    color: rgba(255, 255, 255, 0.92);
    font-size: 10px;
    font-weight: 700;
    line-height: 1;
}

.app-toolbar-app-icon-img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    border-radius: inherit;
    object-fit: cover;
    opacity: 0;
    transition: opacity 0.15s;
}

.app-toolbar-app-icon-img.is-loaded {
    opacity: 1;
}

@media (max-width: 899px) {
    .app-toolbar-title {
        display: inline-flex;
        position: absolute;
        top: 2px;
        left: 50%;
        max-width: calc(100% - 104px);
        transform: translateX(-50%);
    }

    .app-toolbar-chat-btn {
        position: absolute;
        top: 0;
        right: 0;
    }
}

.app-toolbar-action {
    width: 40px;
    height: 40px;
    border: none;
    border-radius: 50%;
    background: rgba(30, 30, 30, 0.78);
    border: 1px solid rgba(255, 255, 255, 0.12);
    color: rgba(255, 255, 255, 0.75);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition:
        background 0.15s,
        color 0.15s;
    padding: 0;
    box-shadow: 0 2px 12px rgba(0, 0, 0, 0.3);
}

.app-toolbar-action:hover {
    background: rgba(50, 50, 50, 0.7);
    color: #fff;
}

.app-toolbar-action.flash {
    color: var(--green, #34d399);
}

/* The chat bubble is only present while the app itself is visible. Fade and
   shrink it out before making it non-interactive; closing/collapsing chat runs
   the same transition in reverse. */
.app-toolbar-chat-btn {
    opacity: 1;
    visibility: visible;
    transform: scale(1);
    transition:
        background 0.15s,
        color 0.15s,
        opacity 0.2s ease,
        transform 0.2s cubic-bezier(0.4, 0, 0.2, 1),
        visibility 0s linear 0s;
}

body.app-active.chat-open .app-toolbar-chat-btn,
body.app-active.sidebar-appchat-open:not(.chat-collapsed) .app-toolbar-chat-btn {
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transform: scale(0.72);
    transition:
        background 0.15s,
        color 0.15s,
        opacity 0.2s ease,
        transform 0.2s cubic-bezier(0.4, 0, 0.2, 1),
        visibility 0s linear 0.2s;
}

@media (prefers-reduced-motion: reduce) {
    .app-toolbar-chat-btn {
        transition: none;
    }

    .app-toolbar-title,
    .app-tab-iframe.is-pull-settling,
    .app-toolbar-title > .app-toolbar-app-icon,
    .app-toolbar-title > .app-toolbar-avatar,
    .app-toolbar-title > .app-toolbar-title-name,
    .app-toolbar-title-hint,
    .app-toolbar-pull-label,
    .app-toolbar-toast,
    .app-toolbar-loading,
    .fork-loading-overlay,
    .fork-loading-hud,
    .fork-loading-bar,
    .fork-loading-bar-value {
        transition: none;
    }

    .app-toolbar-title.is-press-bouncing {
        animation: none;
    }

    .app-toolbar-toast.is-replacing {
        animation: none;
    }

    .fork-loading-spinner-svg,
    .app-toolbar-pull-spinner svg,
    .fork-loading-generative i,
    .fork-loading-bar.is-indeterminate .fork-loading-bar-value {
        animation: none;
    }

    .app-toolbar-dropdown.open {
        animation: none;
    }
}

.app-toolbar-close-btn {
    display: none;
}

.app-escape-close-hint {
    animation: app-escape-close-bounce 360ms ease-out;
}

@keyframes app-escape-close-bounce {
    0%, 100% { transform: scale(1); }
    35% { transform: scale(1.12); }
    65% { transform: scale(0.97); }
    82% { transform: scale(1.03); }
}

@media (prefers-reduced-motion: reduce) {
    .app-escape-close-hint { animation: none; }
}

@media (min-width: 900px) {
    .app-tab-toolbar:has(.app-toolbar-back:not(.close-mode)) .app-toolbar-close-btn {
        display: flex;
    }
}

/* Counterpart image shown INSIDE the title pill, just left of the title text — a nav
   level's image or a chat window's avatar. Half the size of the toolbar buttons. */
.app-toolbar-avatar {
    width: 20px;
    height: 20px;
    border-radius: 50%;
    flex-shrink: 0;
    overflow: hidden;
    background: rgba(255, 255, 255, 0.14) center / cover no-repeat;
    color: rgba(255, 255, 255, 0.75);
    display: flex;
    align-items: center;
    justify-content: center;
    animation: fork-toolbar-avatar-in 0.24s cubic-bezier(0.32, 0.72, 0, 1) both;
}

.app-toolbar-avatar.is-square {
    border-radius: 5px;
}

.app-toolbar-avatar svg {
    width: 13px;
    height: 13px;
}

@keyframes fork-toolbar-avatar-in {
    from { opacity: 0; transform: scale(0.5); }
    to   { opacity: 1; transform: scale(1); }
}

/* Tighten the pill's left padding so the small app image/avatar sits snugly. */
.app-toolbar-title:has(.app-toolbar-app-icon),
.app-toolbar-title:has(.app-toolbar-avatar) {
    --app-toolbar-title-padding-left: 6px;
    padding-left: var(--app-toolbar-title-padding-left);
}

/* A nav/chat avatar replaces the base app icon instead of appearing beside it. */
.app-toolbar-title:has(.app-toolbar-avatar) .app-toolbar-app-icon {
    display: none;
}

/* The normal icon treatment tightens the left edge to 6px; a toast has no
   visible icon, so restore symmetric padding while it owns the pill. */
.app-toolbar-title.is-toast:has(.app-toolbar-app-icon),
.app-toolbar-title.is-toast:has(.app-toolbar-avatar) {
    --app-toolbar-title-padding-left: 14px;
    padding-left: var(--app-toolbar-title-padding-left);
}

[data-theme="light"] .app-toolbar-avatar {
    background-color: rgba(0, 0, 0, 0.08);
    color: rgba(0, 0, 0, 0.55);
}

/* The app menu is painted inside the title pill's expanded bounds. The menu
   element only owns the actions; the title remains the single visible surface. */
.app-toolbar-title.is-menu-measuring-closed {
    width: auto !important;
    height: 36px !important;
    padding-left: var(--app-toolbar-title-padding-left) !important;
    padding-right: var(--app-toolbar-title-padding-right) !important;
    transition: none !important;
}

.app-toolbar-title.is-menu-open {
    width: var(--app-toolbar-menu-width) !important;
    height: var(--app-toolbar-menu-height) !important;
    gap: 0;
    padding: 0;
    border-radius: 16px;
    background: rgba(24, 24, 28, 0.64);
    backdrop-filter: blur(24px) saturate(1.35);
    -webkit-backdrop-filter: blur(24px) saturate(1.35);
    cursor: default;
}

.app-toolbar-title.is-menu-open > .app-toolbar-app-icon,
.app-toolbar-title.is-menu-open > .app-toolbar-avatar,
.app-toolbar-title.is-menu-open > .app-toolbar-title-name,
.app-toolbar-title.is-menu-open > .app-toolbar-title-chevron,
.app-toolbar-title.is-menu-open > .app-toolbar-title-hint,
.app-toolbar-title.is-menu-open > .app-toolbar-toast,
.app-toolbar-title.is-menu-open > .app-toolbar-loading,
.app-toolbar-title.is-menu-open > .app-toolbar-pull-label,
.app-toolbar-title.is-menu-open > .app-toolbar-pull-spinner {
    opacity: 0 !important;
    transform: translateY(-4px) scale(0.96) !important;
    pointer-events: none;
}

.app-toolbar-dropdown {
    display: none;
    position: absolute;
    top: 2px;
    right: auto;
    left: 50%;
    width: var(--app-toolbar-menu-width, min(220px, calc(100vw - 20px)));
    max-width: calc(100vw - 20px);
    transform: translateX(-50%);
    padding: 4px;
    z-index: 20;
    opacity: 0;
    pointer-events: none;
    background: transparent;
    border: 0;
    border-radius: 0;
    box-shadow: none;
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
}

.app-toolbar-dropdown.is-measuring {
    display: block;
    width: max-content;
    min-width: min(220px, calc(100vw - 20px));
    max-width: calc(100vw - 20px);
    visibility: hidden;
    opacity: 0;
    pointer-events: none;
}

.app-toolbar-dropdown.open {
    display: block;
    pointer-events: auto;
    animation: app-toolbar-menu-content-in 260ms ease 80ms both;
}

@keyframes app-toolbar-menu-content-in {
    from { opacity: 0; }
    to { opacity: 1; }
}

.app-toolbar-drop-item {
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
    padding: 9px 12px;
    border: none;
    background: transparent;
    color: rgba(255, 255, 255, 0.8);
    font-size: 13px;
    font-family: inherit;
    cursor: pointer;
    border-radius: 12px;
    transition: background 0.12s;
    white-space: nowrap;
}

.app-toolbar-drop-item:hover {
    background: rgba(255, 255, 255, 0.1);
    color: #fff;
}

.app-toolbar-drop-item:disabled {
    opacity: 0.42;
    cursor: default;
    pointer-events: none;
}

.app-toolbar-menu-app-section {
    margin-bottom: 4px;
    padding-bottom: 4px;
    border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}

.app-toolbar-menu-app-icon,
.app-toolbar-menu-app-icon svg {
    width: 14px;
    height: 14px;
    flex: 0 0 14px;
}

.app-toolbar-drop-item-danger {
    color: #ef4444;
}
.app-toolbar-drop-item-danger:hover {
    background: rgba(239, 68, 68, 0.12);
    color: #ef4444;
}

/* The whole toolbar family lost its blur (perf — it floats over the live
   app iframe), so the gradient is denser to keep contents readable. */
[data-theme="light"] .app-toolbar-back,
[data-theme="light"] .app-toolbar-title,
[data-theme="light"] .app-toolbar-action {
    background: linear-gradient(100deg, rgba(255, 255, 255, 0.92), rgba(255, 255, 255, 0.78));
    border-color: rgba(0, 0, 0, 0.08);
    color: rgba(20, 20, 20, 0.72);
    box-shadow: rgba(0, 0, 0, 0.1) 0 4px 14px;
}

[data-theme="light"] .app-toolbar-title.is-toast {
    background: linear-gradient(100deg, rgba(255, 255, 255, 0.98), rgba(245, 245, 247, 0.92));
    color: rgba(20, 20, 20, 0.86);
}

[data-theme="light"] .app-toolbar-title.is-menu-open {
    background: rgba(248, 248, 250, 0.68);
}

[data-theme="light"] .app-toolbar-pull-label {
    color: rgba(20, 20, 20, 0.5);
}

[data-theme="light"] .app-toolbar-menu-app-section {
    border-bottom-color: rgba(0, 0, 0, 0.1);
}

[data-theme="light"] .app-toolbar-loading .fork-loading-percent,
[data-theme="light"] .app-toolbar-loading .fork-loading-cancel {
    color: rgba(20, 20, 20, 0.58);
}

[data-theme="light"] .app-toolbar-loading .fork-loading-cancel {
    background: rgba(0, 0, 0, 0.06);
}

[data-theme="light"] .fork-loading-overlay {
    background: rgba(255, 255, 255, 0.12);
}

[data-theme="light"] .fork-loading-hud {
    border-color: rgba(0, 0, 0, 0.08);
    background: rgba(255, 255, 255, 0.96);
    color: rgba(20, 20, 20, 0.9);
    box-shadow: 0 18px 54px rgba(0, 0, 0, 0.16);
}

[data-theme="light"] .fork-loading-message,
[data-theme="light"] .fork-loading-percent {
    color: rgba(20, 20, 20, 0.55);
}

[data-theme="light"] .fork-loading-cancel {
    background: rgba(0, 0, 0, 0.06);
    color: rgba(20, 20, 20, 0.6);
}

[data-theme="light"] .app-toolbar-back:hover,
[data-theme="light"] .app-toolbar-action:hover {
    background: linear-gradient(100deg, rgba(255, 255, 255, 0.82), rgba(255, 255, 255, 0.52));
    color: rgba(20, 20, 20, 0.92);
}

[data-theme="light"] .app-toolbar-drop-item {
    color: rgba(20, 20, 20, 0.76);
}

[data-theme="light"] .app-toolbar-drop-item:hover {
    background: rgba(0, 0, 0, 0.06);
    color: rgba(20, 20, 20, 0.94);
}

/* (Removed: .app-toolbar-cta — the standalone blue Add/Fork button on the
   app toolbar. The Add and Fork actions now live behind a click on the
   .app-toolbar-title pill, which routes through showAddAppModal /
   showForkAppModal so the viewer sees a confirm with consequences first.) */

/* ── Custom tooltip ── */
.custom-tooltip {
    position: fixed;
    z-index: 99999;
    background: rgba(20, 20, 20, 0.92);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    border: 1px solid rgba(255, 255, 255, 0.1);
    color: #fff;
    font-size: 12px;
    font-weight: 500;
    white-space: nowrap;
    padding: 6px 10px;
    border-radius: 8px;
    pointer-events: none;
    opacity: 0;
    transition: opacity 0.15s;
}

.custom-tooltip.visible {
    opacity: 1;
}

.app-tab-iframe {
    position: absolute;
    inset: 0;
    border: none;
    width: 100%;
    height: 100%;
    background: var(--bg-primary);
}

/* The web pull-to-refresh gesture originates inside the cross-origin iframe,
   while its visual stretch belongs to the host. Move the complete app surface
   with the finger, keep it parked while refreshing, then spring it home. */
.app-tab-iframe.is-pull-offset {
    transform: translate3d(0, var(--app-pull-content-offset, 0), 0);
    will-change: transform;
}

.app-tab-iframe.is-pull-offset:not(.is-pull-settling) {
    transition: none;
}

.app-tab-iframe.is-pull-settling {
    transition: transform 0.42s cubic-bezier(0.22, 1, 0.36, 1);
}

.app-tab-loader {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--bg-primary);
    z-index: 10;
}

.app-tab-spinner {
    width: 28px;
    height: 28px;
    border: 3px solid rgba(255, 255, 255, 0.1);
    border-top-color: rgba(255, 255, 255, 0.5);
    border-radius: 50%;
    animation: spin 0.7s linear infinite;
}

[data-theme="light"] .app-tab-spinner {
    border-color: rgba(0, 0, 0, 0.08);
    border-top-color: rgba(0, 0, 0, 0.35);
}

@keyframes spin {
    to {
        transform: rotate(360deg);
    }
}

/* ── Chat area inside chat ── */
.chat-body {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: flex-end;
    overflow: hidden;
    min-height: 0;
    padding-bottom: 0px;
    scrollbar-width: none;
    opacity: 0;
}

.chat-body::-webkit-scrollbar {
    display: none;
}

/* ── Chat panel ── */
.chat {
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    top: 0;
    height: 100vh;
    background: #000;
    display: none;
    flex-direction: column;
    z-index: 999;
    overflow: hidden;
}

/* Wide: sidebar chat (always open) + content panels to the right */
@media (min-width: 900px) {

    /* ── Chat sidebar: always visible on the left ── */
    .chat {
        display: flex;
        left: 0;
        right: auto;
        top: 0;
        bottom: 0;
        width: var(--chat-w, 600px);
        height: 100vh !important;
        border-right: 1px solid var(--border);
        transition: transform 0.25s cubic-bezier(0.4, 0, 0.2, 1);
    }

    /* The opaque chat panel covers the dashboard behind this scroll area. */
    .chat-body {
        overflow-y: auto;
        overflow-x: hidden;
        justify-content: flex-start;
        opacity: 1;
        transition: opacity 0.15s;
        overscroll-behavior: contain;
    }

    /* App-active mode: .chat is the always-on left sidebar (base rule sets it to
       a fixed --chat-w). Extend to viewport right so the panel covers the
       full right area. (Home-wide already gets this from its own rule below.) */
    body.app-active .chat {
        right: 0 !important;
        width: auto !important;
        max-width: none !important;
        margin-left: 0 !important;
        margin-right: 0 !important;
    }

    /* Constrain inner chat content to the same centered column used by the
       desktop icon grid. chat-body itself spans the full desktop area;
       the content column stays centered inside that area. */
    .chat-body {
        box-sizing: border-box;
    }

    .chat-body>* {
        width: 100%;
        max-width: 800px;
        margin-left: auto;
        margin-right: auto;
        align-self: center;
    }

    /* Right-side click gutter for the home-modal chat. Strip on the far right of
       the chat panel; clicking anywhere closes the chat. The global #homeCloseHint
       remains the visible X (top-right) and CSS :has() scales it on gutter hover. */
    .chat-right-gutter {
        display: none;
    }

    body.chat-open .chat-right-gutter {
        display: block;
        position: absolute;
        top: 0;
        right: 0;
        bottom: 0;
        width: var(--sidebar-w);
        cursor: pointer;
        z-index: 1;
    }

    body:has(#chatRightGutter:hover) #homeCloseHint {
        transform: scale(1.2);
        background: rgba(0, 0, 0, 0.1);
        color: rgba(0, 0, 0, 0.6);
    }

    .chat-body::before {
        content: '';
        flex: 1 0 0px;
    }

    .messages {
        overflow: visible;
    }

    /* Neutralise body.chat-open transitions */
    body.chat-open .chat {
        height: 100vh !important;
    }

    /* Frosted glass input */
    .chat-input,
    .chat-input-row,
    body.chat-open .chat-input-row {
        flex: 1 !important;
    }

    .chat-input-row,
    body.chat-open .chat-input-row {
        min-height: 52px !important;
    }

    body.chat-open .chat-send {
        width: 38px !important;
        height: 38px !important;
    }

    /* Desktop occupies the area to the right of the sidebar */
    .desktop {
        left: var(--chat-w, 600px);
        bottom: 0;
        transition: left 0.25s cubic-bezier(0.4, 0, 0.2, 1);
    }

    /* No bottom chat bar in wide mode — remove bottom gradient and padding */
    .desktop::after {
        display: none;
    }

    .desktop-icons {
        grid-template-columns: repeat(4, 1fr);
        padding-bottom: 24px;
    }

    .desktop-empty {
        padding-bottom: 0;
    }

    /* Hide mobile-only overlay elements */
    .chat-close {
        display: none !important;
    }

    /* Chat resize handle */
    .chat-resize-handle {
        position: fixed;
        top: 0;
        bottom: 0;
        width: 6px;
        left: calc(var(--chat-w, 600px) - 3px);
        cursor: col-resize;
        z-index: 1000;
        background: transparent;
        transition:
            background 0.15s,
            left 0.25s cubic-bezier(0.4, 0, 0.2, 1),
            width 0.25s;
    }

    .chat-resize-handle:hover,
    .chat-resize-handle.dragging {
        background: rgba(255, 255, 255, 0.15);
    }

    /* Collapse/expand button centered on handle — hidden until hover */
    .chat-collapse-btn {
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        width: 14px;
        height: 32px;
        display: flex;
        align-items: center;
        justify-content: center;
        background: rgba(255, 255, 255, 0.03);
        border: none;
        border-radius: 5px;
        cursor: pointer;
        color: rgba(255, 255, 255, 0.25);
        backdrop-filter: blur(12px) saturate(1.3);
        -webkit-backdrop-filter: blur(12px) saturate(1.3);
        transition:
            color 0.15s,
            background 0.15s,
            border-color 0.15s,
            opacity 0.15s;
        z-index: 1;
        opacity: 0;
        pointer-events: none;
    }

    .chat-resize-handle:hover .chat-collapse-btn {
        opacity: 1;
        pointer-events: auto;
    }

    .chat-collapse-btn:hover {
        color: rgba(255, 255, 255, 0.55);
        background: rgba(255, 255, 255, 0.08);
    }

    .chat-collapse-btn svg {
        transition: transform 0.2s;
    }

    /* When chat is collapsed */
    body.chat-collapsed .chat {
        transform: translateX(-100%);
    }

    body.chat-collapsed .chat-bar {
        transform: translateX(-100%);
    }

    body.chat-collapsed .desktop {
        left: 0 !important;
    }

    body.chat-collapsed .chat-resize-handle {
        left: 0 !important;
        width: 20px;
        background: none !important;
        cursor: pointer;
        transition: background 0.2s, width 0.2s;
    }

    body.chat-collapsed .chat-resize-handle:hover {
        width: 28px;
        background: rgba(255, 255, 255, 0.06) !important;
    }

    body.chat-collapsed .chat-collapse-btn {
        left: 8px;
        border-radius: 0 6px 6px 0;
        opacity: 1;
        pointer-events: auto;
    }

    body.chat-collapsed .chat-collapse-btn svg {
        transform: rotate(180deg);
    }

    body.chat-collapsed .profile-overlay {
        left: 0;
    }

    /* Disable transitions during drag resize */
    body.chat-resizing .chat,
    body.chat-resizing .chat-bar,
    body.chat-resizing .desktop,
    body.chat-resizing .chat-resize-handle {
        transition: none !important;
    }
}

/* Hide resize handles on mobile — both the chat and sidebar handles are
   desktop-only chrome (their show rules live inside @media min-width:900). */
@media (max-width: 899px) {

    .chat-resize-handle,
    .sidebar-resize-handle {
        display: none !important;
    }
}

/* ── Public apps grid (desktop icon cards, same as dashboard) ── */
/* Public-apps grid — wraps into rows (no horizontal scroll). JS clamps it to
   two rows by hiding overflow icons (see _clampProfileApps), then reveals the
   "show all" button below to expand the rest. */
.profile-apps-strip {
    display: grid;
    grid-template-columns: repeat(auto-fill, 96px);
    justify-content: space-between;
    gap: 10px 6px;
    width: 100%;
    max-width: 434px;
    padding: 2px 16px 4px 16px;
    box-sizing: border-box;
    align-items: start;
}

.profile-apps-block {
    margin-bottom: 8px;
}

/* Hidden by default; _clampProfileApps adds .has-more only when icons spill
   past two rows, and .expanded hides it again once the user expands. */
.profile-apps-showall {
    display: none;
    width: calc(100% - 32px);
    margin: 0 16px;
    padding: 20px 16px;
    border: none;
    background: transparent;
    color: var(--text-dim);
    font-size: 13px;
    font-weight: 600;
    align-items: center;
    justify-content: center;
    gap: 5px;
    cursor: pointer;
    transition: color 0.15s;
}

.profile-apps-block.has-more .profile-apps-showall {
    display: flex;
}

.profile-apps-block.expanded .profile-apps-showall {
    display: none;
}

.profile-apps-showall-chevron {
    opacity: 0.7;
    transition: transform 0.15s, opacity 0.15s;
}

.profile-apps-showall:hover {
    color: var(--text);
}

.profile-apps-showall:hover .profile-apps-showall-chevron {
    opacity: 1;
    transform: translateY(1px);
}

.profile-app-more-box {
    background: rgba(255, 255, 255, 0.08);
    color: var(--text-muted);
    box-shadow: none;
}

.desktop-icon:hover .profile-app-more-box {
    background: rgba(255, 255, 255, 0.14);
    color: var(--text-primary);
    box-shadow: none;
}

.profile-apps-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(96px, 1fr));
    gap: 12px;
    padding: 4px 0 8px 0;
    align-items: start;
    justify-content: center;
}

.apps-overlay-content {
    padding: 56px 16px 16px;
}

.apps-overlay-section-title {
    margin: 12px 0 4px;
}

@media (min-width: 800px) {
    .apps-overlay-content {
        padding-left: 32px;
        padding-right: 32px;
    }
}

/* ─── Unified Page Stack overlay ─── */
.page-stack-root:empty {
    display: none;
}

.page-stack-layer {
    position: fixed;
    inset: 0;
    z-index: 200;
    /* Translucent dark + blur — same frost language as the profile background.
       On dark theme this reads as a frosted overlay
       on top of the animated backdrop / desktop, not a solid black sheet. */
    background: rgba(18, 18, 24, 0.55);
    backdrop-filter: blur(24px) saturate(1.4);
    -webkit-backdrop-filter: blur(24px) saturate(1.4);
    display: flex;
    flex-direction: row;
    justify-content: center;
    overflow: hidden;
}

[data-theme="light"] .page-stack-layer {
    background: rgba(255, 255, 255, 0.7);
}

/* Left spacer + right gutter are wide-screen only — on mobile the content fills
   the full width and there's no gutter to click. */
.page-stack-left-spacer,
.page-stack-right-gutter {
    display: none;
    flex-shrink: 0;
}

.page-stack-right-gutter {
    cursor: pointer;
}

.page-stack-right-gutter-passive {
    pointer-events: none;
    cursor: default;
}

/* On wide screens the layer starts where the sidebar ends. padding-right
   mirrors the sidebar so the centered content column lines up horizontally
   with .chat-bar (same sidebar-w gap on both sides). Left spacer stays out
   of the flex flow (0 width); justify-content:center centers the content.
   The right gutter is lifted out of the flex flow via position:fixed so its
   click/hover zone extends past the padding all the way to the viewport's
   right corner — that's where the global .home-close-hint sits. */
@media (min-width: 900px) {
    .page-stack-layer {
        left: var(--sidebar-w, 320px);
        padding-right: var(--sidebar-w, 320px);
        box-sizing: border-box;
    }

    .page-stack-left-spacer {
        display: none;
    }

    .page-stack-right-gutter {
        display: block;
        position: fixed;
        top: 0;
        right: 0;
        bottom: 0;
        width: max(0px, calc(50vw - 400px));
        cursor: pointer;
        z-index: 201;
    }
}

.page-stack-layer-hidden {
    display: none;
}

.page-stack-content {
    overflow-y: auto;
    flex: 1 1 auto;
    min-width: 0;
    padding: 6px 16px 16px;
    width: 100%;
    box-sizing: border-box;
}

@media (min-width: 900px) {
    .page-stack-content {
        flex: 0 1 800px;
        max-width: 800px;
        padding-left: 32px;
        padding-right: 32px;
    }
}

.page-stack-title {
    font-size: 20px;
    font-weight: 600;
    color: var(--text-primary);
    letter-spacing: -0.2px;
    margin: 4px 0 16px;
}

@media (min-width: 800px) {
    .profile-apps-strip {
        grid-template-columns: repeat(auto-fill, 112px);
        max-width: 506px;
        padding-left: 20px;
        padding-right: 20px;
    }

    .profile-apps-showall {
        width: calc(100% - 64px);
        margin-left: 32px;
        margin-right: 32px;
    }

    .profile-overlay-content {
        padding: 12px 24px 0;
    }
}

@media (min-width: 1200px) {

    .profile-overlay-content {
        padding: 12px 40px 0;
    }
}

.people-search {
    width: 100%;
    min-height: 52px;
    padding: 12px 18px;
    margin-bottom: 14px;
    border-radius: 999px;
    border: 1px solid transparent;
    background: rgb(22 22 22);
    color: var(--text);
    font-family: inherit;
    font-size: 14px;
    outline: none;
    box-sizing: border-box;
    transition: background 0.2s;
}

.people-search:focus {
    background: rgb(14 14 14);
    border-color: var(--accent);
}

[data-theme="light"] .people-search {
    background: rgb(245 245 245);
    color: var(--text);
}

[data-theme="light"] .people-search::placeholder {
    color: rgba(0, 0, 0, 0.48);
}

[data-theme="light"] .people-search:focus {
    background: #fff;
    border-color: var(--accent);
}

.desktop-icon {
    --iconbox-h: 60px;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 6px;
    cursor: pointer;
    padding: 8px;
    border-radius: 12px;
    transition: transform 0.2s ease;
    position: relative;
    -webkit-tap-highlight-color: transparent;
    min-width: 0;
    width: 100%;
    box-sizing: border-box;
}

@media (hover: hover) {
    .desktop-icon:hover {
        transform: scale(1.04);
    }
}

.desktop-icon .icon-box {
    width: 60px;
    height: 60px;
    border-radius: 15px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 24px;
    color: #fff;
    font-weight: 700;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
    transition: box-shadow 0.15s;
}

.desktop-icon:hover .icon-box {
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.4);
}

/* ── Building state (app is being created) ── */
.icon-box.icon-building-box {
    position: relative;
    overflow: hidden;
    background: transparent;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
    border-radius: 15px;
}

.icon-building-inner {
    position: absolute;
    inset: 0;
    border-radius: 15px;
    overflow: hidden;
}

.icon-building-overlay {
    position: absolute;
    inset: 0;
    border-radius: 15px;
    background: rgba(0, 0, 0, 0.45);
    z-index: 1;
    pointer-events: none;
}

.icon-arc-svg {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    pointer-events: none;
    z-index: 2;
}

.icon-arc-track {
    fill: none;
    stroke: rgba(255, 255, 255, 0.2);
    stroke-width: 3;
    stroke-linecap: round;
}

.icon-arc-fill {
    fill: none;
    stroke: #fff;
    stroke-width: 3;
    stroke-linecap: round;
    /* JS-driven animation — no CSS transition */
}

.icon-building-pct {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    font-size: 17px;
    font-weight: 700;
    color: #fff;
    z-index: 3;
    pointer-events: none;
    letter-spacing: -0.5px;
    line-height: 1;
}

.desktop-icon .icon-box.icon-logo {
    object-fit: cover;
    border-radius: 25px;
    font-size: 0;
}

.desktop-icon .icon-label {
    font-size: 14px;
    font-weight: 500;
    color: var(--text-dim);
    background: linear-gradient(180deg, rgba(255, 255, 255, 0.95) 0%, var(--text-dim) 100%);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    text-align: center;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    padding: 3px 2px 0px;
    line-height: 1.2;
}

/* Author handle pill — shown under the icon when the app belongs to a
   different user (i.e. added from someone else's account). Absolutely
   positioned so it overlaps the icon-box bottom edge without affecting
   the layout (icon size + label position stay identical). */
.desktop-icon .icon-author {
    position: absolute;
    left: 50%;
    top: var(--iconbox-h);
    transform: translateX(-50%);
    max-width: calc(100% - 8px);
    font-size: 10px;
    font-weight: 600;
    line-height: 1;
    color: var(--text-dim);
    background: rgba(30, 30, 36, 0.85);
    border: 1px solid rgba(255, 255, 255, 0.1);
    border-radius: 999px;
    padding: 2px 7px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    letter-spacing: 0.1px;
    z-index: 5;
    pointer-events: none;
}
[data-theme="light"] .desktop-icon .icon-author {
    color: var(--text);
    background: rgba(255, 255, 255, 0.9);
    border-color: rgba(0, 0, 0, 0.1);
}

.desktop-icon {
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    user-select: none;
}

.desktop-icon .icon-delete {
    position: absolute;
    top: 2px;
    right: 2px;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    background: rgba(120, 120, 128, 0.85);
    color: #fff;
    border: 2px solid var(--bg-primary);
    font-size: 11px;
    line-height: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    opacity: 0;
    transition: opacity 0.15s;
    z-index: 10;
}

.desktop-icon:hover .icon-delete {
    opacity: 1;
}

.desktop-icon.deleting {
    pointer-events: none;
}

.desktop-icon.deleting .icon-box {
    animation: iconDeletingPulse 0.7s ease-in-out infinite;
}

.desktop-icon.deleting .icon-delete {
    opacity: 1;
}

@keyframes iconDeletingPulse {
    0%, 100% {
        opacity: 0.45;
        transform: scale(0.98);
    }
    50% {
        opacity: 1;
        transform: scale(1);
    }
}

@media (max-width: 799px) {
    /* Three large icons with equal space between them and at both edges:
       each column is the icon plus 2p, the grid adds p at each side, so
       W = 3w + 8p. Labels still get the full column width. */
    .desktop-icons {
        --app-icon: min(25vw, 124px);
        column-gap: 0;
        row-gap: 5px;
        padding-left: calc((100% - 3 * var(--app-icon)) / 8);
        padding-right: calc((100% - 3 * var(--app-icon)) / 8);
    }

    .desktop-icon .icon-delete {
        display: none !important;
    }

    .desktop-icon {
        --iconbox-h: var(--app-icon, clamp(76px, 20vw, 94px));
        padding: 9px 0 8px;
    }

    .desktop-icon .icon-box {
        width: var(--iconbox-h);
        height: var(--iconbox-h);
        border-radius: 22px;
        font-size: 34px;
    }

    .desktop-icon .icon-box.icon-logo {
        border-radius: 22px;
    }

    .icon-box.icon-building-box,
    .icon-building-inner,
    .icon-building-overlay {
        border-radius: 22px;
    }

    .desktop-icon .icon-label {
        font-size: 12px;
    }
}

/* ── Large desktop: bigger icons ── */
@media (min-width: 1200px) {
    .desktop-icon {
        --iconbox-h: 88px;
    }

    .desktop-icon .icon-box {
        width: 88px;
        height: 88px;
        border-radius: 20px;
        font-size: 32px;
    }

    .desktop-icon .icon-box.icon-logo img {
        border-radius: 20px;
    }

    .icon-box.icon-building-box,
    .icon-building-inner,
    .icon-building-overlay {
        border-radius: 20px;
    }

    .icon-building-pct {
        font-size: 22px;
    }

    .desktop-icon .icon-label {
        font-size: 13px;
    }
}

/* ── Icon context menu (mobile long-press) ── */
.icon-context-menu {
    background: rgba(30, 30, 36, 0.95);
    border: 1px solid rgba(255, 255, 255, 0.12);
    border-radius: 12px;
    padding: 4px;
    box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5);
    min-width: 140px;
}

.icon-context-item {
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
    padding: 10px 14px;
    border: none;
    background: none;
    color: var(--text);
    font-size: 14px;
    border-radius: 8px;
    cursor: pointer;
    white-space: nowrap;
}

.icon-context-item.danger {
    color: #ef4444;
}

/* ── Drag & Drop Reordering ── */

.desktop-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    min-height: 50vh;
    color: var(--text-muted);
    user-select: none;
}

.desktop-empty .empty-icon {
    font-size: 56px;
    margin-bottom: 16px;
}

.desktop-empty .empty-text {
    font-size: 18px;
    font-weight: 600;
    color: var(--text-dim);
}

.desktop-empty .empty-sub {
    font-size: 14px;
    margin-top: 6px;
}

body.chat-open .chat {
    display: flex;
}

/* Mobile chat is a pushed screen: it slides in from the right and back out to
   the right. Keep the panel mounted (display:flex) and park it offscreen with
   transform so it can animate smoothly. Opacity only hides the parked panel
   and flips instantly at the end of the exit. Wide screens use their own
   sidebar layout inside the @media (min-width: 900px) block above. */
@media (max-width: 799px) {
    .chat {
        display: flex;
        transform: translateX(100%);
        opacity: 0;
        pointer-events: none;
        transition: transform 0.34s cubic-bezier(0.32, 0.72, 0, 1),
                    opacity 0s linear 0.34s;
        will-change: transform;
    }

    body.chat-open .chat {
        transform: translateX(0);
        opacity: 1;
        pointer-events: auto;
        transition: transform 0.34s cubic-bezier(0.32, 0.72, 0, 1),
                    opacity 0s;
    }

    /* The parked panel keeps the open chat's scroll layout, so its scroll
       position survives closing and the chat reopens exactly where it was
       instead of re-laying out and scrolling. */
    .chat-body {
        overflow-y: auto;
        overflow-x: hidden;
        justify-content: flex-start;
        overscroll-behavior: contain;
        padding-top: 72px;
    }

    .chat-body::before {
        content: '';
        flex: 1 0 0px;
    }

    .messages {
        overflow: visible;
    }
}

body.chat-open .chat-body {
    overflow-y: auto;
    overflow-x: hidden;
    justify-content: flex-start;
    opacity: 1;
    overscroll-behavior: contain;
}

body.chat-open .chat-body::before {
    content: '';
    flex: 1 0 0px;
}

body.chat-open .messages {
    overflow: visible;
    padding-bottom: 4px;
}

/* Short conversations sit at the bottom using a flexible spacer. Hold its
   current height before streamed text grows, so line wraps create scrollable
   room instead of instantly pushing every earlier message upward. */
body .chat-body.chat-tail-space::before { flex: 0 0 var(--chat-tail-space, 0px); }
.chat-body.chat-tail-follow,
.chat-body.chat-tail-follow .messages { overflow-anchor: none; }

.sidebar-chat-item.has-unread .sidebar-chat-name { padding-right: 32px; }
.sidebar-chat-unread { position: absolute; top: 12px; right: 12px; min-width: 19px; padding: 1px 5px; border-radius: 12px; background: var(--accent); color: #fff; font-size: 11px; font-weight: 600; line-height: 17px; text-align: center; }
.sidebar-chat-icon.chat-direct-icon { border-radius: 50%; font-size: 18px; font-weight: 600; }
/* Personal avatars stay circular under desktop and mobile chat icon styles. */
#sidebarChats .sidebar-chat-icon.chat-direct-icon,
#sidebarChats .chat-direct-icon .chat-topic-photo { border-radius: 50%; }
.sidebar-chat-load-error { padding: 12px 18px; color: var(--text-muted); font-size: 12px; }
.sidebar-chat-load-error button { border: 0; background: transparent; color: var(--accent); font: inherit; cursor: pointer; }
#sidebarChats.is-initial-loading { display: flex; align-items: center; justify-content: center; }
.sidebar-chats-more { display: flex; align-items: center; justify-content: center; flex-shrink: 0; gap: 8px; min-height: 56px; padding: 8px 18px; color: var(--text-muted); font-size: 12px; }
.sidebar-chats-more button { border: 0; background: transparent; color: var(--accent); font: inherit; cursor: pointer; }
.sidebar-chats-more .app-tab-spinner { width: 20px; height: 20px; }
.sidebar-chats-more .app-tab-spinner, .sidebar-chats-loading .app-tab-spinner { border-color: var(--border); border-top-color: var(--text-dim); }

/* ── Chat header (logo, wide screens only) ── */
.chat-header {
    display: none;
    position: absolute;
    top: 0;
    left: 0;
    width: var(--chat-w, 600px);
    flex-shrink: 0;
    padding: 16px 20px 16px;
    /* Denser tint over the solid chat background; no per-frame blur. */
    background: rgba(10, 10, 10, 0.9);
    border-bottom: 1px solid var(--border);
}

.chat-header::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    bottom: -20px;
    height: 20px;
    background: linear-gradient(to bottom, rgba(10, 10, 10, 0.3), transparent);
    pointer-events: none;
}

.chat-context {
    position: absolute;
    left: 50%;
    top: 18px;
    transform: translateX(-50%);
    z-index: 101;
    display: none;
}

@media (min-width: 900px) {
    .chat-header {
        display: flex;
        align-items: center;
        width: var(--chat-w, 600px);
        z-index: 100;
    }

    .chat-header .chat-logo {
        display: flex;
        flex-direction: column;
        justify-content: center;
    }

    .logo-panel {
        display: block;
    }

    .chat-context {
        display: block;
    }
}

@media (max-width: 799px) {
    body.chat-open .chat-header {
        display: flex;
        position: fixed;
        top: 20px;
        left: 0;
        right: 0;
        width: 100% !important;
        justify-content: center;
        align-items: center;
        padding: 14px 16px;
        background: transparent;
        backdrop-filter: none;
        -webkit-backdrop-filter: none;
        border-bottom: none;
        z-index: 1002;
    }

    body.chat-open .logo-panel {
        display: none;
    }

    body.chat-open .chat-header::after {
        display: none;
    }

    /* Match the floating app title pill over chat content. */
    body .chat-context-btn {
        background: rgba(30, 30, 30, 0.78);
        border-radius: 18px;
        padding: 0 14px;
        box-shadow: 0 2px 12px rgba(0, 0, 0, 0.3);
        color: rgba(255, 255, 255, 0.9);
    }

    body.chat-open .chat-menu {
        position: absolute;
        right: 16px;
        top: 50%;
        transform: translateY(-50%);
    }

    body.chat-open .chat-menu-btn {
        width: 36px;
        height: 36px;
        border-radius: 50%;
        background: rgba(30, 30, 30, 0.75);
        border: 1px solid rgba(255, 255, 255, 0.18);
        color: #fff;
    }

    body.chat-open .chat-body {
        padding-top: 72px;
    }

    /* Model selection moves to the top chat actions on mobile. */
    .model-selector {
        display: none;
    }

    body:not(.app-active) .chat-input-bottom {
        display: none;
    }

}

/* Mobile chat tweaks — keep slide-up animation on .chat itself (see @media 799px block
   above) but cancel transitions on ancillary elements where they were distracting. */
@media (max-width: 799px) {
    .chat-input-row {
        transition: border-color 0.15s !important;
    }

    .chat-close-inline {
        transition:
            width 0.3s cubic-bezier(0.4, 0, 0.2, 1),
            opacity 0.3s cubic-bezier(0.4, 0, 0.2, 1),
            background 0.15s !important;
    }

    .chat-body {
        transition: none !important;
    }
}

/* ── Chat three-dots menu ── */
.chat-menu {
    margin-left: auto;
    position: relative;
    flex-shrink: 0;
}

.chat-menu-btn {
    width: 30px;
    height: 30px;
    border-radius: 8px;
    border: none;
    background: transparent;
    color: var(--text-dim);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition:
        background 0.15s,
        color 0.15s;
}

.chat-menu-btn:hover {
    background: rgba(255, 255, 255, 0.08);
    color: var(--text);
}

.chat-menu-dropdown {
    display: none;
    position: absolute;
    top: calc(100% + 6px);
    right: 0;
    min-width: 180px;
    background: rgba(18, 18, 22, 0.97);
    border: 1px solid rgba(255, 255, 255, 0.12);
    border-radius: 10px;
    box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5);
    z-index: 2100;
    padding: 4px;
    overflow: hidden;
}

.chat-menu-dropdown.open {
    display: block;
}

.chat-menu-item {
    width: 100%;
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 10px;
    border: none;
    background: none;
    border-radius: 7px;
    font-size: 13px;
    font-family: inherit;
    cursor: pointer;
    color: var(--text);
    transition: background 0.1s;
    text-align: left;
}

.chat-menu-item:hover {
    background: rgba(255, 255, 255, 0.07);
}

.chat-menu-item.danger {
    color: #f87171;
}

.chat-menu-item.danger:hover {
    background: rgba(248, 113, 113, 0.1);
}

/* ── Mobile chat actions + model settings ── */
.mobile-chat-back { display: none; }
.mobile-chat-actions { display: none; }
.mobile-model-sheet-backdrop { display: none; }

@media (max-width: 799px) {
    body.chat-open .mobile-chat-back {
        position: fixed; top: 10px; left: 10px; z-index: 1004;
        display: flex;
    }
    body.chat-open .mobile-chat-actions {
        position: fixed; top: 10px; right: 10px; z-index: 1004; display: block;
    }
    .mobile-chat-actions-menu {
        display: none; position: absolute; top: calc(100% + 8px); right: 0;
        min-width: 248px; padding: 6px; border: 1px solid rgba(255,255,255,.12);
        border-radius: 20px; background: rgba(30,30,30,.96); box-shadow: 0 14px 40px rgba(0,0,0,.32);
    }
    .mobile-chat-actions.open .mobile-chat-actions-menu { display: block; }
    .mobile-chat-actions-item {
        width: 100%; display: flex; align-items: center; gap: 14px; padding: 14px 13px;
        border: 0; border-radius: 15px; background: transparent; color: var(--text);
        font: inherit; font-size: 17px; text-align: left; cursor: pointer;
    }
    .mobile-chat-actions-item:active { background: rgba(255,255,255,.1); }

    .mobile-model-sheet-backdrop {
        position: fixed; inset: 0; z-index: 12000; display: none; align-items: flex-end;
        background: rgba(0,0,0,.36);
    }
    .mobile-model-sheet-backdrop.open { display: flex; }
    .mobile-model-sheet {
        width: 100%; max-height: min(92vh,760px); display: flex; flex-direction: column; gap: 16px;
        padding: 20px 20px calc(20px + env(safe-area-inset-bottom)); overflow-y: auto;
        border: 1px solid rgba(255,255,255,.2); border-radius: 30px 30px 0 0;
        background: rgba(28,28,30,.98); color: var(--text);
    }
    .mobile-model-sheet-head { display: grid; grid-template-columns: 44px 1fr 44px; align-items: center; }
    .mobile-model-sheet-head h2 { grid-column: 2; margin: 0; color: var(--text); font-size: 25px; line-height: 1.15; text-align: center; }
    .mobile-model-sheet-close {
        grid-column: 3; width: 44px; height: 44px; border: 0; border-radius: 50%;
        background: rgba(255,255,255,.1); color: var(--text); font-size: 34px; font-weight: 300; line-height: 1; cursor: pointer;
    }
    .mobile-model-options { display: flex; flex-direction: column; gap: 5px; }
    .mobile-model-option, .mobile-model-group {
        min-height: 58px; width: 100%; border: 0; border-radius: 16px; background: transparent;
        color: var(--text); font: inherit; font-size: 22px; text-align: left;
    }
    .mobile-model-option { padding: 0 15px; cursor: pointer; }
    .mobile-model-option.active, .mobile-model-group.active { background: color-mix(in srgb, var(--accent) 15%, transparent); }
    .mobile-model-group { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 12px; padding: 8px 12px 8px 15px; }
    .mobile-model-variants {
        display: grid; grid-template-columns: repeat(var(--variant-count, 1), minmax(0, 1fr)); min-width: 0; width: calc(var(--variant-count, 1) * 68px); max-width: 100%; padding: 3px;
        border-radius: 22px; background: rgba(255,255,255,.1);
    }
    .mobile-model-variants button {
        height: 40px; border: 0; border-radius: 19px; background: transparent; color: var(--text-dim);
        font: inherit; font-size: 16px; cursor: pointer;
    }
    .mobile-model-variants button.active { background: var(--bg-primary); color: var(--text); box-shadow: 0 1px 5px rgba(0,0,0,.2); }
    .mobile-model-info {
        min-height: 132px; padding: 17px; border: 1px solid rgba(255,255,255,.14); border-radius: 20px;
        background: rgba(255,255,255,.06);
    }
    .mobile-model-info .model-info-title { margin-bottom: 5px; font-size: 20px; }
    .mobile-model-info .model-info-description { font-size: 14px; }
    .mobile-model-apply {
        min-height: 56px; border: 0; border-radius: 28px; background: var(--accent); color: #fff;
        font: inherit; font-size: 20px; font-weight: 650; cursor: pointer;
    }
    [data-theme="light"] .mobile-chat-actions-menu {
        border-color: rgba(0,0,0,.08); background: rgba(255,255,255,.94); color: var(--text);
    }
    [data-theme="light"] .mobile-model-sheet { border-color: rgba(0,0,0,.08); background: rgba(250,250,252,.98); }
    [data-theme="light"] .mobile-model-sheet-close, [data-theme="light"] .mobile-model-variants { background: rgba(0,0,0,.07); }
    [data-theme="light"] .mobile-model-info { border-color: rgba(0,0,0,.08); background: rgba(255,255,255,.75); }
}

@media (max-width: 799px) {
    .chat-menu {
        position: absolute;
        right: 16px;
        top: 50%;
        transform: translateY(-50%);
        margin-left: 0;
    }

    body:not(.chat-open) .chat-menu {
        display: none;
    }

    .chat-menu-dropdown {
        right: 0;
    }
}

/* ── Confirm modal ── */
.confirm-modal {
    display: none;
    position: fixed;
    z-index: 10011;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    background: var(--bg-secondary);
    border: 1px solid var(--border-hover);
    border-radius: 16px;
    padding: 24px;
    width: 380px;
    max-width: calc(100vw - 48px);
    box-shadow: 0 24px 64px rgba(0, 0, 0, 0.65);
}

.confirm-modal.open {
    display: block;
}

.confirm-modal-title {
    font-size: 15px;
    font-weight: 600;
    color: var(--text);
    margin-bottom: 8px;
}

.confirm-modal-desc {
    font-size: 13px;
    color: var(--text-dim);
    margin-bottom: 20px;
    line-height: 1.5;
}

.confirm-modal-actions {
    display: flex;
    gap: 8px;
}

.confirm-modal-btn {
    flex: 1;
    padding: 9px;
    border-radius: 10px;
    border: none;
    font-size: 13px;
    font-weight: 600;
    font-family: inherit;
    cursor: pointer;
    transition: opacity 0.15s;
}

.confirm-modal-btn:hover {
    opacity: 0.85;
}

.confirm-modal-btn.danger {
    background: #ef4444;
    color: #fff;
}

.confirm-modal-btn.cancel {
    background: var(--bg-tertiary);
    border: 1px solid var(--border);
    color: var(--text-dim);
}

.confirm-modal-btn.primary {
    background: var(--accent);
    color: #fff;
}

.confirm-modal-btn:disabled {
    opacity: 0.4;
    cursor: not-allowed;
}

.confirm-modal-btn:disabled:hover {
    opacity: 0.4;
}

.add-app-modal .confirm-modal-desc {
    margin-bottom: 14px;
}

.add-app-card {
    display: flex;
    align-items: center;
    gap: 12px;
    min-height: 68px;
    padding: 10px;
    margin-bottom: 12px;
    border-radius: 14px;
    border: 1px solid var(--border);
    background: var(--bg-tertiary);
}

.add-app-card-icon {
    width: 48px;
    height: 48px;
    border-radius: 12px;
    font-size: 18px;
}

.add-app-card-name {
    min-width: 0;
    overflow: hidden;
    color: var(--text);
    font-size: 15px;
    font-weight: 600;
    line-height: 1.3;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.add-app-visibility {
    display: flex;
    align-items: center;
    gap: 12px;
    min-height: 62px;
    margin-bottom: 18px;
    cursor: pointer;
    user-select: none;
}

.add-app-visibility input {
    position: absolute;
    width: 1px;
    height: 1px;
    opacity: 0;
    pointer-events: none;
}

.add-app-checkbox {
    width: 22px;
    height: 22px;
    border: 2px solid var(--text-muted);
    border-radius: 6px;
    color: #fff;
    display: flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    transition: background 0.15s, border-color 0.15s, transform 0.15s;
}

.add-app-checkbox svg {
    width: 15px;
    height: 15px;
    opacity: 0;
    transform: scale(0.65);
    transition: opacity 0.15s, transform 0.15s;
}

.add-app-visibility input:checked + .add-app-checkbox {
    background: var(--accent);
    border-color: var(--accent);
}

.add-app-visibility input:checked + .add-app-checkbox svg {
    opacity: 1;
    transform: scale(1);
}

.add-app-visibility input:focus-visible + .add-app-checkbox {
    outline: 3px solid color-mix(in srgb, var(--accent) 30%, transparent);
    outline-offset: 2px;
}

.add-app-visibility-copy {
    display: flex;
    min-width: 0;
    flex-direction: column;
    gap: 2px;
}

.add-app-visibility-title {
    color: var(--text);
    font-size: 14px;
    font-weight: 500;
}

.add-app-visibility-desc {
    color: var(--text-dim);
    font-size: 12px;
    line-height: 1.4;
}

.add-app-error {
    display: none;
    margin: -8px 0 14px;
    color: var(--red, #ef4444);
    font-size: 12px;
    line-height: 1.4;
}

.add-app-error.visible {
    display: block;
}

/* Account deletion requires typed confirmation and deliberately carries more
   context than the compact yes/no confirm modal. */
.delete-profile-modal {
    width: 440px;
    max-height: calc(100dvh - 32px);
    overflow-y: auto;
}

.delete-profile-heading {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 10px;
}

.delete-profile-heading .confirm-modal-title {
    margin-bottom: 0;
}

.delete-profile-icon {
    width: 36px;
    height: 36px;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    border-radius: 10px;
    color: var(--red, #ef4444);
    background: rgba(239, 68, 68, 0.1);
}

.delete-profile-lead {
    color: var(--red, #ef4444);
    font-weight: 600;
    margin-bottom: 14px;
}

.delete-profile-warning-list {
    display: flex;
    flex-direction: column;
    gap: 9px;
    padding: 12px;
    margin-bottom: 16px;
    border: 1px solid rgba(239, 68, 68, 0.22);
    border-radius: 12px;
    background: rgba(239, 68, 68, 0.07);
}

.delete-profile-warning-row {
    display: flex;
    align-items: flex-start;
    gap: 9px;
    color: var(--text-dim);
    font-size: 12px;
    line-height: 1.45;
}

.delete-profile-warning-dot {
    width: 5px;
    height: 5px;
    margin-top: 6px;
    border-radius: 50%;
    background: var(--red, #ef4444);
    flex-shrink: 0;
}

.delete-profile-label {
    display: block;
    margin-bottom: 7px;
    color: var(--text-dim);
    font-size: 12px;
    font-weight: 600;
}

.delete-profile-input {
    box-sizing: border-box;
    width: 100%;
    height: 42px;
    padding: 0 12px;
    border: 1px solid var(--border);
    border-radius: 10px;
    outline: none;
    background: var(--bg-primary);
    color: var(--text);
    font-family: inherit;
    font-size: 14px;
    font-weight: 600;
    line-height: 1;
    letter-spacing: 0.08em;
    transition: border-color 0.15s, box-shadow 0.15s;
}

.delete-profile-input:focus {
    border-color: var(--red, #ef4444);
    box-shadow: 0 0 0 3px rgba(239, 68, 68, 0.1);
}

.delete-profile-input:disabled {
    opacity: 0.55;
}

.delete-profile-status {
    min-height: 18px;
    padding: 6px 1px 8px;
    color: var(--text-muted);
    font-size: 12px;
    line-height: 1.35;
}

.delete-profile-status.error {
    color: var(--red, #ef4444);
}

.delete-profile-apple {
    display: none;
    padding: 12px;
    margin-bottom: 14px;
    border: 1px solid rgba(245, 158, 11, 0.3);
    border-radius: 12px;
    background: rgba(245, 158, 11, 0.08);
}

.delete-profile-apple.open {
    display: block;
}

.delete-profile-apple-title {
    margin-bottom: 4px;
    color: #f59e0b;
    font-size: 12px;
    font-weight: 700;
}

.delete-profile-apple-desc {
    color: var(--text-dim);
    font-size: 12px;
    line-height: 1.4;
}

.delete-profile-apple-actions {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-top: 9px;
}

.delete-profile-apple-actions a,
.delete-profile-apple-actions button {
    border: none;
    background: none;
    padding: 0;
    color: var(--accent);
    font-family: inherit;
    font-size: 12px;
    font-weight: 600;
    line-height: 1.3;
    text-decoration: none;
    cursor: pointer;
}

.delete-profile-apple-actions a:hover,
.delete-profile-apple-actions button:hover {
    text-decoration: underline;
}

.pwa-install-modal {
    display: none;
    position: fixed;
    z-index: 10012;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 380px;
    max-width: calc(100vw - 48px);
    background: var(--bg-secondary);
    border: 1px solid var(--border-hover);
    border-radius: 16px;
    padding: 22px;
    box-shadow: 0 24px 64px rgba(0, 0, 0, 0.65);
}

.pwa-install-modal.open {
    display: block;
}

.pwa-install-close {
    position: absolute;
    top: 12px;
    right: 12px;
    width: 30px;
    height: 30px;
    display: flex;
    align-items: center;
    justify-content: center;
    border: 0;
    border-radius: 50%;
    background: var(--bg-tertiary);
    color: var(--text-dim);
    cursor: pointer;
}

.pwa-install-icon {
    width: 44px;
    height: 44px;
    display: flex;
    align-items: center;
    justify-content: center;
    margin-bottom: 14px;
    border-radius: 12px;
    background: var(--accent);
    color: #fff;
}

.pwa-install-title {
    padding-right: 34px;
    margin-bottom: 8px;
    color: var(--text);
    font-size: 16px;
    font-weight: 650;
}

.pwa-install-desc {
    margin-bottom: 16px;
    color: var(--text-dim);
    font-size: 13px;
    line-height: 1.5;
}

.pwa-install-steps {
    display: grid;
    gap: 10px;
    margin-bottom: 18px;
}

.pwa-install-image {
    display: block;
    width: 100%;
    max-height: min(42vh, 430px);
    object-fit: contain;
    border: 1px solid var(--border);
    border-radius: 12px;
    background: #111820;
}

.pwa-install-step {
    display: flex;
    align-items: center;
    gap: 10px;
    min-height: 38px;
    padding: 10px 12px;
    border: 1px solid var(--border);
    border-radius: 12px;
    background: var(--bg-tertiary);
    color: var(--text);
    font-size: 13px;
    line-height: 1.35;
}

.pwa-install-step svg {
    flex: 0 0 auto;
    color: var(--accent);
}

.pwa-install-ok {
    width: 100%;
}

/* Info-modal — info-only variant of .confirm-modal: title is centered,
   no header bar / close-X (backdrop-click + Esc handle dismiss). Used
   for the invite-code modal and similar simple "show data + copy" UIs. */
.info-modal {
    width: 340px;
    text-align: center;
}

.info-modal .confirm-modal-title {
    font-size: 14px;
    color: var(--text-dim);
    font-weight: 500;
    margin-bottom: 4px;
}

.info-modal-value {
    font-size: 36px;
    font-weight: 700;
    letter-spacing: 8px;
    font-family: ui-monospace, SFMono-Regular, monospace;
    color: var(--text);
    margin: 8px 0 20px;
    user-select: all;
}

.info-modal-hint {
    margin-top: 14px;
    font-size: 12px;
    color: var(--text-dim);
    line-height: 1.4;
}

/* Invite code — restrained Fork-blue treatment with a small amount of motion. */
.invite-code-modal {
    width: 340px;
    padding: 26px 24px 22px;
    border-color: rgba(0, 122, 255, 0.24);
}

.invite-code-modal.open {
    animation: invite-modal-in 0.32s ease-out both;
}

.invite-code-heading {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 11px;
}

.invite-code-emblem {
    flex: 0 0 auto;
    width: 58px;
    height: 58px;
    margin: 0;
    display: grid;
    place-items: center;
    color: #fff;
    border: 1px solid var(--accent-light);
    border-radius: 20px;
    background: var(--accent);
    box-shadow: 0 10px 26px rgba(0, 122, 255, 0.24);
    animation: invite-rocket-flight 2.8s ease-in-out infinite;
}

.invite-code-rocket {
    display: block;
}

.invite-code-modal .confirm-modal-title {
    color: var(--text-secondary);
    font-weight: 600;
    margin: 0;
    text-align: center;
}

.invite-code-modal .info-modal-value {
    color: var(--accent);
}

.invite-code-modal .info-modal-hint {
    margin-top: 12px;
}

.invite-code-modal #inviteCopyBtn {
    min-height: 38px;
}

@keyframes invite-modal-in {
    from { opacity: 0; transform: translate(-50%, calc(-50% + 8px)) scale(0.98); }
    to { opacity: 1; transform: translate(-50%, -50%) scale(1); }
}

@keyframes invite-rocket-flight {
    0%, 100% { transform: translateY(1px); }
    50% { transform: translateY(-5px); }
}

@media (prefers-reduced-motion: reduce) {
    .invite-code-modal.open,
    .invite-code-emblem {
        animation: none;
    }
}

.chat-context-btn {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 16px;
    background: transparent;
    border: none;
    border-radius: 10px;
    color: var(--text-secondary);
    font-size: 15px;
    font-weight: 500;
    cursor: pointer;
    white-space: nowrap;
    overflow: hidden;
    min-width: 200px;
    max-width: 280px;
    justify-content: center;
    transition: background 0.15s;
}

/* Hover only on real pointers. On touch, tapping the pill to open the switcher
   makes iOS apply a sticky :hover — this translucent overlay would replace the
   pill's opaque background and make it see-through until the next tap elsewhere. */
@media (hover: hover) {
    .chat-context-btn:hover {
        background: rgba(255, 255, 255, 0.08);
        color: var(--text-primary);
    }
}

.chat-context-btn span {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
}

.chat-context-btn .chat-context-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 24px;
    width: 24px;
    height: 24px;
    font-family: "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", sans-serif;
    font-size: 22px;
    line-height: 1;
}

.chat-context-icon .chat-topic-photo {
    width: 24px;
    height: 24px;
}

.chat-context-btn svg {
    flex-shrink: 0;
    opacity: 0.6;
    transition: transform 0.15s;
}

/* ── Universal iframe loader ── */
.iframe-loader-overlay {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--bg-primary);
    z-index: 1;
}

.iframe-loader-dot {
    width: 24px;
    height: 24px;
    border: 2px solid rgba(255, 255, 255, 0.1);
    border-top-color: var(--accent);
    border-radius: 50%;
    animation: iframe-spin 0.7s linear infinite;
}

@keyframes iframe-spin {
    to {
        transform: rotate(360deg);
    }
}

[data-theme="light"] .iframe-loader-dot {
    border-color: rgba(0, 0, 0, 0.08);
    border-top-color: var(--accent);
}

/* ── New chat button ── */
.chat-new-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    border: none;
    border-radius: 8px;
    background: transparent;
    color: var(--text-dim);
    cursor: pointer;
    transition: background 0.15s, color 0.15s;
    flex-shrink: 0;
}

.chat-new-btn:hover {
    background: rgba(255, 255, 255, 0.08);
    color: var(--text-primary);
}

[data-theme="light"] .chat-new-btn:hover {
    background: rgba(0, 0, 0, 0.05);
    color: var(--text);
}

/* ── Chat segmented control (iOS style) ── */
.chat-seg {
    display: flex;
    background: rgba(255, 255, 255, 0.08);
    backdrop-filter: blur(20px) saturate(1.25);
    -webkit-backdrop-filter: blur(20px) saturate(1.25);
    border-radius: 9px;
    padding: 3px;
    position: relative;
    overflow: hidden;
    cursor: pointer;
}

.chat-seg-slider {
    position: absolute;
    top: 3px;
    bottom: 3px;
    background: var(--accent);
    border-radius: 7px;
    transition: left 0.25s cubic-bezier(0.4, 0, 0.2, 1), width 0.25s cubic-bezier(0.4, 0, 0.2, 1);
    pointer-events: none;
}

.chat-seg-btn {
    flex: 1;
    padding: 6px 20px;
    border: none;
    border-radius: 7px;
    background: transparent;
    color: var(--text);
    font-size: 13px;
    font-weight: 500;
    cursor: pointer;
    transition: color 0.2s;
    white-space: nowrap;
    position: relative;
    z-index: 1;
}

.chat-seg-btn.active {
    color: #fff;
}

.chat-seg-btn:not(.active):hover {
    color: var(--text-secondary);
}

.chat-seg-btn:not(:last-child)::after {
    content: '';
    position: absolute;
    right: 0;
    top: 20%;
    height: 60%;
    width: 1px;
    background: rgba(255, 255, 255, 0.12);
    transition: opacity 0.2s;
}

.chat-seg-btn.active::after,
.chat-seg-btn:has(+ .chat-seg-btn.active)::after {
    opacity: 0;
}

[data-theme="light"] .chat-seg-btn:not(:last-child)::after {
    background: rgba(0, 0, 0, 0.12);
}

[data-theme="light"] .chat-seg {
    background: rgba(0, 0, 0, 0.06);
}

@media (max-width: 799px) {
    body.chat-open .chat-seg {
        background: rgba(24, 24, 28, 0.58);
        backdrop-filter: blur(24px) saturate(1.35);
        -webkit-backdrop-filter: blur(24px) saturate(1.35);
        width: 100%;
        height: 48px;
        box-sizing: border-box;
        align-items: stretch;
        padding: 3px;
        border: 1px solid rgba(255, 255, 255, 0.12);
        border-radius: 24px;
        box-shadow:
            0 8px 28px rgba(0, 0, 0, 0.18),
            inset 0 1px 0 rgba(255, 255, 255, 0.06);
    }

    body.chat-open .chat-seg-slider {
        border-radius: 20px;
    }

    body.chat-open .chat-seg-btn {
        padding: 0 12px;
        border-radius: 20px;
        line-height: 1;
    }

    body.chat-open .chat-seg-btn:not(:last-child)::after {
        top: 25%;
        height: 50%;
    }

    [data-theme="light"] body.chat-open .chat-seg {
        background: rgba(255, 255, 255, 0.62);
        border-color: rgba(0, 0, 0, 0.08);
        box-shadow:
            0 8px 28px rgba(0, 0, 0, 0.10),
            inset 0 1px 0 rgba(255, 255, 255, 0.72);
    }
}

@media (max-width: 359px) {
    body.chat-open .chat-seg-btn {
        padding-inline: 4px;
        font-size: 12px;
    }
}

/* ── Description panel (iframe) ── */
.chat-desc-panel {
    display: none;
    width: 100%;
    height: 100%;
    position: absolute;
    top: 0;
    left: 0;
}

.chat-desc-panel.visible {
    display: block;
}

.chat-media-panel {
    display: none;
    width: 100%;
    height: 100%;
    position: absolute;
    top: 0;
    left: 0;
    overflow: hidden;
}

.chat-media-panel.visible {
    display: block;
}

.chat-stats-panel {
    display: none;
    width: 100%;
    height: 100%;
    position: absolute;
    top: 0;
    left: 0;
    overflow: hidden;
}

.chat-stats-panel.visible {
    display: block;
}

.chat-close {
    position: fixed;
    top: 16px;
    right: 16px;
    width: 44px;
    height: 44px;
    border-radius: 50%;
    border: none;
    background: rgba(255, 255, 255, 0.1);
    backdrop-filter: blur(20px);
    -webkit-backdrop-filter: blur(20px);
    color: var(--text-dim);
    font-size: 24px;
    cursor: pointer;
    display: none;
    align-items: center;
    justify-content: center;
    transition: all 0.15s;
    z-index: 10001;
}

body.chat-open .chat-close {
    display: flex;
}

.chat-open .chat-context {
    display: block;
}

@media (max-width: 799px) {
    body.chat-open .chat-context {
        position: fixed;
        top: 12px;
        left: 50%;
        width: max-content;
        max-width: calc(100vw - 124px);
        transform: translateX(-50%);
        z-index: 1003;
        box-shadow: none;
    }

    body.chat-open .chat-context-btn {
        width: max-content;
        min-width: 0;
        max-width: 100%;
        height: 36px;
        gap: 4px;
        padding: 0 14px;
        border: 1px solid rgba(255, 255, 255, 0.12);
        border-radius: 18px;
        color: rgba(255, 255, 255, 0.9);
        font-family: inherit;
        font-size: 14px;
        font-weight: 600;
        box-shadow: 0 2px 12px rgba(0, 0, 0, 0.3);
    }
    body.chat-open .chat-context-btn:has(.chat-context-icon) {
        padding-left: 6px;
    }

    body.chat-open .chat-context-icon,
    body.chat-open .chat-context-icon .chat-topic-photo,
    body.chat-open .chat-context-icon .chat-app-icon {
        width: 20px;
        height: 20px;
        flex-basis: 20px;
    }
    body.chat-open .chat-context-icon {
        font-size: 18px;
    }
    body.chat-open .chat-context-icon .chat-topic-photo,
    body.chat-open .chat-context-icon .chat-app-icon {
        border-radius: 50%;
    }

    /* Keep the header controls on the same soft elevation as the composer-side
       circular button. */
    [data-theme="light"] body.chat-open .chat-context {
        box-shadow: none;
    }
    [data-theme="light"] body.chat-open .chat-context-btn {
        border-color: rgba(0, 0, 0, 0.08);
        box-shadow: rgba(0, 0, 0, 0.1) 0 4px 14px;
    }

}

@media (max-width: 799px) {
    body.chat-open .chat-close {
        display: none;
    }
}

.chat-close:hover {
    background: rgba(255, 255, 255, 0.2);
    color: var(--text);
}

/* ── Inline close button (mobile only, inside chat-bar) ── */
.chat-close-inline {
    width: 0;
    height: 52px;
    min-width: 0;
    opacity: 0;
    border-radius: 50%;
    border: 1px solid rgba(255, 255, 255, 0.12);
    background: rgba(30, 30, 30, 0.55);
    backdrop-filter: blur(20px);
    -webkit-backdrop-filter: blur(20px);
    color: rgba(255, 255, 255, 0.75);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    position: relative;
    overflow: hidden;
    pointer-events: none;
    transition:
        width 0.3s cubic-bezier(0.4, 0, 0.2, 1),
        opacity 0.3s cubic-bezier(0.4, 0, 0.2, 1),
        background 0.15s;
    padding: 0;
}

.chat-close-inline:hover {
    background: rgba(255, 255, 255, 0.16);
    color: #fff;
}

@media (max-width: 799px) {

    /* Always visible on mobile — bell by default, close when chat open */
    .chat-close-inline {
        width: 52px;
        opacity: 1;
        pointer-events: auto;
    }

    /* Bell icon: visible when chat closed, hidden when open */
    .cbr-bell {
        display: flex;
        align-items: center;
        justify-content: center;
    }

    .cbr-close {
        display: none;
    }

    .cbr-send {
        display: none;
    }

    body.chat-open .cbr-bell {
        display: none;
    }

    body.chat-open .cbr-close {
        display: flex;
        align-items: center;
        justify-content: center;
    }

    /* Mobile composer uses the separate right circle as Send. The legacy
       inline button stays available on desktop but must not consume textarea
       width on phones. */
    .chat-input-row .chat-send {
        display: none !important;
    }

    .chat-close-inline.send-mode {
        background: var(--accent);
        border-color: var(--accent);
        color: #fff;
    }

    .chat-close-inline.send-mode .cbr-bell,
    .chat-close-inline.send-mode .cbr-close {
        display: none !important;
    }

    .chat-close-inline.send-mode .cbr-send {
        display: flex;
        align-items: center;
        justify-content: center;
    }

    /* Bell badge */
    .cbr-bell-badge {
        display: none;
        position: absolute;
        top: 8px;
        right: 8px;
        width: 8px;
        height: 8px;
        border-radius: 50%;
        background: #ef4444;
    }

    .chat-close-inline.has-unread .cbr-bell-badge {
        display: block;
    }

    /* Notif modal open: show close icon, hide bell. With chat-input hidden in
       this mode the button is the only flex child — push it to the right. */
    .chat-close-inline.notif-close-mode {
        margin-left: auto;
    }

    .chat-close-inline.notif-close-mode .cbr-bell {
        display: none;
    }

    .chat-close-inline.notif-close-mode .cbr-close {
        display: flex;
        align-items: center;
        justify-content: center;
    }

    /* Real chats close through the top-left Back, so the X next to the
       composer stays only on the blank new-chat screen (body.chat-new). The
       circle still grows in as Send once there is a draft; the negative
       margin cancels the bar's 12px gap while it is collapsed. */
    body.chat-open:not(.chat-new):not(.chat-info-tab) :is(#chatBarRight, #dcBarRight):not(.send-mode) {
        width: 0;
        opacity: 0;
        border-width: 0;
        margin-left: -12px;
        pointer-events: none;
    }

    /* The composer arrives with the pushed chat screen. Skipped while the
       input has focus: iOS draws the caret at the untransformed position. */
    body.chat-open :is(#chatBar, #dcBar):not(:focus-within) {
        animation: chat-bar-push-in 0.34s cubic-bezier(0.32, 0.72, 0, 1);
    }

    /* Browser history already has a native screen transition in Safari. The
       flag lasts for this restored state so the composer cannot animate later. */
    body.chat-history-restored .chat {
        transition: none;
    }
    body.chat-history-restored.chat-open :is(#chatBar, #dcBar):not(:focus-within) {
        animation: none;
    }
}

@keyframes chat-bar-push-in {
    from { transform: translateX(100%); }
}

@media (max-width: 899px) {
    /* New Chat is an immediate entry point. Keep its composer settled even
       when focus changes after the native keyboard opens or closes. */
    body.chat-open-instant .chat { transition: none; }
    body.chat-open-instant.chat-open #chatBar { animation: none; }
}

@media (min-width: 900px) {
    .chat-close-inline {
        display: none;
    }
}

/* The chat title pill is a label, not a control. */
#chatContextBtn {
    cursor: default;
}

/* ── Desktop home hero (centered composer) ──
   Hidden everywhere by default; the wide-screen home block enables it and
   the chat-bar is reparented into #homeHeroSlot by JS. Mobile keeps the
   fixed-bottom bar untouched. */
.home-hero {
    display: none;
}

/* ── Input bar (independent from chat panel) ── */
.chat-bar {
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    display: flex;
    align-items: flex-end;
    padding: 16px 16px 10px;
    gap: 12px;
    background: transparent;
    z-index: 10001;
}

/* Bottom fade band — DISABLED. As an absolutely-positioned child of .chat-bar it
   stacked ABOVE the (non-positioned) input row, so its gradient darkened the lower
   edge of the input field instead of fading content behind it. The mobile chat
   panel is opaque (var(--bg-primary)) now, so the fade is redundant anyway.
   (Desktop already disabled this; kept off everywhere.) */
.chat-bar::before {
    display: none;
}

/* Desktop: input bar sits at the bottom of the sidebar area */
@media (min-width: 900px) {
    .chat-bar {
        right: auto;
        width: var(--chat-w, 600px);
        padding-bottom: 20px;
        transition: transform 0.25s cubic-bezier(0.4, 0, 0.2, 1);
    }
}

/* Hide chat-bar when an app is active (until chat is opened) — all screen sizes */
body.app-active .chat-bar {
    display: none;
}

body.app-active.chat-open .chat-bar {
    display: flex;
}

/* A user profile is a real page, not a dismissible layer over the home
   composer. Keep the global composer out of both profile render paths unless
   the user explicitly opens chat on top. */
body:has(.desktop.profile-open):not(.chat-open) .chat-bar,
body:has(.desktop.notifs-open):not(.chat-open) .chat-bar,
body.page-stack-open:not(.chat-open) .chat-bar {
    display: none !important;
}

/* Taskbar window buttons */
.chat-btn {
    width: 36px;
    height: 36px;
    background: var(--bg-tertiary);
    border: 1px solid var(--border);
    border-radius: 8px;
    color: var(--text-dim);
    font-size: 16px;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: all 0.15s;
    font-family: inherit;
    padding: 0;
}

.chat-btn:hover {
    border-color: var(--border-hover);
    color: var(--text);
}

.chat-btn.active {
    background: var(--accent);
    border-color: var(--accent);
    color: #fff;
}

.chat-btn.minimized {
    opacity: 0.5;
}

/* ── Taskbar Input ── */
.chat-input {
    flex: 0 1 800px;
    min-width: 0;
    display: flex;
    flex-direction: column;
}

/* Send recoil — input bobs 5px down then snaps back, like the message was
   just shot out of it. Paired with .msg.is-sending below for the matching
   "slide up from under the input" reveal on the bubble. */
@keyframes chat-input-recoil {
    0% {
        transform: translateY(0);
    }

    35% {
        transform: translateY(-5px);
    }

    100% {
        transform: translateY(0);
    }
}

.chat-input.is-sending {
    animation: chat-input-recoil 0.133s cubic-bezier(0.4, 0, 0.2, 1);
}

@keyframes chat-msg-emerge {
    from {
        transform: translateY(18px);
        opacity: 0;
    }

    to {
        transform: translateY(0);
        opacity: 1;
    }
}

.msg.is-sending {
    animation: chat-msg-emerge 0.133s cubic-bezier(0.4, 0, 0.2, 1);
}

/* Assistant replies (answer bubbles + reasoning rows) just fade in — no rise.
   Runs once on element creation: on reload the full message fades; while live
   the bubble is empty when it fades, then text types in. */
@keyframes chat-msg-fade {
    from { opacity: 0; }
    to { opacity: 1; }
}

.msg.assistant,
.msg.reasoning-msg {
    animation: chat-msg-fade 0.25s ease-out;
}

/* ── Media attachment preview (Telegram-style reply) ── */
.media-attach-preview {
    display: none;
    min-width: 0;
}

.media-attach-preview.has-media {
    display: block;
    margin-bottom: 6px;
}

.media-attach-bar {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 10px;
    background: rgba(20, 20, 20, 0.55);
    backdrop-filter: blur(24px);
    -webkit-backdrop-filter: blur(24px);
    border: 1px solid rgba(255, 255, 255, 0.1);
    border-radius: 12px;
    position: relative;
    overflow: hidden;
    max-width: 100%;
    box-sizing: border-box;
}

.media-attach-accent {
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    width: 3px;
    background: var(--accent);
    border-radius: 3px 0 0 3px;
}

.media-attach-thumb {
    width: 40px;
    height: 40px;
    border-radius: 6px;
    object-fit: cover;
    flex-shrink: 0;
}

.media-attach-info {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.media-attach-label {
    font-size: 12px;
    font-weight: 600;
    color: var(--accent);
}

.media-attach-prompt {
    font-size: 12px;
    color: var(--text-muted);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.media-attach-close {
    width: 24px;
    height: 24px;
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    background: none;
    border: none;
    color: var(--text-muted);
    cursor: pointer;
    font-size: 18px;
    border-radius: 50%;
    transition: all 0.15s;
}

.media-attach-close:hover {
    color: var(--text);
    background: rgba(255, 255, 255, 0.08);
}

/* ── Reply/quote preview in the composer ── */
.reply-preview {
    display: none;
    min-width: 0;
}
.reply-preview.has-reply {
    display: block;
    margin-bottom: 6px;
}
.reply-bar {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 10px;
    background: rgba(20, 20, 20, 0.55);
    backdrop-filter: blur(24px);
    -webkit-backdrop-filter: blur(24px);
    border: 1px solid rgba(255, 255, 255, 0.1);
    border-radius: 12px;
    position: relative;
    overflow: hidden;
    max-width: 100%;
    box-sizing: border-box;
}
.reply-accent {
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    width: 3px;
    background: var(--accent);
    border-radius: 3px 0 0 3px;
}
.reply-info {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 2px;
}
.reply-title {
    font-size: 12px;
    font-weight: 600;
    color: var(--accent);
}
.reply-excerpt {
    font-size: 12px;
    color: var(--text-muted);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.reply-close {
    width: 24px;
    height: 24px;
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    background: none;
    border: none;
    color: var(--text-muted);
    cursor: pointer;
    font-size: 18px;
    border-radius: 50%;
    transition: all 0.15s;
}
.reply-close:hover {
    color: var(--text);
    background: rgba(255, 255, 255, 0.08);
}

.chat-input .photo-preview {
    display: none;
    align-items: flex-start;
    gap: 8px;
    width: 100%;
    min-width: 0;
    padding: 4px 4px 6px;
    box-sizing: border-box;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scrollbar-width: none;
}

.chat-input .photo-preview::-webkit-scrollbar {
    display: none;
}

.chat-input .photo-preview.has-photos,
.chat-input .photo-preview.has-attachments {
    display: flex;
}

.chat-input-row {
    display: flex;
    flex-direction: column;
    gap: 0;
    border: 1px solid rgb(22 22 22);
    border-radius: 14px;
    padding: 6px 6px;
    min-height: 52px;
    cursor: text;
    transition:
        background 0.2s,
        border-color 0.15s,
        border-radius 0.3s cubic-bezier(0.4, 0, 0.2, 1);

    background: rgb(22 22 22);
}

.chat-input-top {
    display: flex;
    align-items: flex-end;
    gap: 0;
    width: 100%;
}

.chat-input-bottom {
    display: flex;
    align-items: center;
    padding: 2px 2px 2px 2px;
}

.model-selector {
    position: relative;
}

.model-selected {
    background: none;
    border: 1px solid transparent;
    color: var(--text-muted);
    font-size: 12px;
    font-family: inherit;
    padding: 2px 20px 2px 8px;
    border-radius: 8px;
    cursor: pointer;
    transition: all 0.15s;
    position: relative;
}

.model-selected::after {
    content: '';
    position: absolute;
    right: 7px;
    top: 50%;
    transform: translateY(-50%);
    border-left: 3.5px solid transparent;
    border-right: 3.5px solid transparent;
    border-bottom: 4px solid currentColor;
    opacity: 0.5;
}

.model-selected:hover,
.model-selector.open .model-selected {
    color: var(--text);
    background: rgba(255, 255, 255, 0.06);
}

.model-dropdown {
    display: none;
    position: absolute;
    bottom: 100%;
    left: 0;
    margin-bottom: 4px;
    background: var(--bg-primary);
    border: 1px solid var(--border);
    border-radius: 10px;
    padding: 4px;
    width: 244px;
    min-width: 244px;
    box-shadow: 0 -4px 20px rgba(0, 0, 0, 0.3);
    z-index: 100;
}

.model-selector.open .model-dropdown {
    display: flex;
    flex-direction: column;
}

.model-option {
    background: none;
    border: none;
    color: var(--text-muted);
    font-size: 13px;
    font-family: inherit;
    padding: 7px 12px;
    border-radius: 7px;
    cursor: pointer;
    text-align: left;
    transition: all 0.12s;
}

.model-option:hover {
    color: var(--text);
    background: rgba(255, 255, 255, 0.06);
}

.model-option+.model-option {
    margin-top: 2px;
}

.model-option.active {
    color: #fff;
    background: var(--accent);
}

.model-option-group {
    position: relative;
    display: grid;
    grid-template-columns: minmax(0, 76px) minmax(min-content, 1fr);
    align-items: center;
    gap: 8px;
    box-sizing: border-box;
    min-height: 32px;
    padding: 4px 5px 4px 12px;
    text-align: left;
}

.model-option-group.active {
    color: #fff;
    background: var(--accent);
}

.model-option-label {
    appearance: none;
    border: 0;
    padding: 3px 0;
    color: inherit;
    background: transparent;
    font: inherit;
    cursor: pointer;
    text-align: left;
}

.model-variant-switch {
    display: grid;
    grid-template-columns: repeat(var(--variant-count, 1), minmax(min-content, 1fr));
    min-width: 0;
    overflow: hidden;
    border: 1px solid var(--border);
    border-radius: 5px;
    background: rgba(0, 0, 0, 0.16);
}

.model-variant {
    min-width: 0;
    height: 22px;
    padding: 0 5px;
    border: 0;
    border-left: 1px solid var(--border);
    color: var(--text-muted);
    background: transparent;
    font: inherit;
    font-size: 10px;
    cursor: pointer;
}

.model-variant:first-child {
    border-left: 0;
}

.model-variant:hover,
.model-variant:focus-visible {
    color: var(--text);
    background: rgba(255, 255, 255, 0.1);
    outline: 0;
}

.model-variant.active {
    color: var(--accent);
    background: #fff;
}

.model-option-group.active .model-variant-switch {
    border-color: rgba(255, 255, 255, 0.35);
    background: rgba(0, 0, 0, 0.12);
}

.model-option-group.active .model-variant {
    color: rgba(255, 255, 255, 0.82);
    border-color: rgba(255, 255, 255, 0.28);
}

.model-option-group.active .model-variant.active {
    color: var(--accent);
    background: #fff;
}

.model-info-tooltip {
    display: none;
}

@media (hover: hover) and (pointer: fine) {
    .model-option-group .model-variant-switch {
        visibility: hidden;
        opacity: 0;
        pointer-events: none;
    }

    .model-option-group:hover .model-variant-switch,
    .model-option-group:focus-within .model-variant-switch {
        visibility: visible;
        opacity: 1;
        pointer-events: auto;
    }

    .model-info-tooltip {
        position: absolute;
        left: calc(100% + 8px);
        z-index: 101;
        width: 240px;
        padding: 11px 12px 12px;
        border: 1px solid var(--border);
        border-radius: 6px;
        color: var(--text);
        background: var(--bg-primary);
        box-shadow: 0 6px 22px rgba(0, 0, 0, 0.28);
        font-size: 11px;
        line-height: 1.35;
        pointer-events: none;
        transform: translateY(-50%);
    }

    .model-info-tooltip.visible {
        display: block;
    }
}

.model-info-title {
    margin-bottom: 3px;
    color: var(--text);
    font-size: 12px;
    font-weight: 600;
}

.model-info-description {
    min-height: 30px;
    color: var(--text-muted);
}

.model-info-metrics {
    display: flex;
    flex-direction: column;
    gap: 6px;
    margin-top: 10px;
    padding-top: 9px;
    border-top: 1px solid var(--border);
}

.model-info-metric {
    display: grid;
    grid-template-columns: 68px minmax(0, 1fr);
    align-items: center;
    gap: 8px;
}

.model-info-rating {
    display: flex;
    flex-direction: row;
    gap: 2px;
    width: 100%;
}

.model-info-rating-segment {
    flex: 1;
    height: 5px;
    border-radius: 1px;
    background: var(--border);
}

.model-info-rating-segment.active {
    background: var(--accent);
}

.model-info-metric-label {
    grid-column: 1;
    grid-row: 1;
    color: var(--text-muted);
    font-size: 9px;
    line-height: 1;
}

.model-info-rating {
    grid-column: 2;
    grid-row: 1;
}

/* Always opaque; dark-theme focus uses a slightly darker background. */
.chat-input-row:focus-within {
    background: rgb(14 14 14);
    border-color: var(--accent);
}

/* Opening the attachment chooser ends text-entry mode. Force the resting
   composer treatment even during WebKit's delayed focus repaint, and suppress
   the stale caret layer until the user explicitly taps the textarea again. */
body.attachment-actions-open .chat-input-row,
body.attachment-actions-open .chat-input-row:focus-within {
    background: rgb(22 22 22) !important;
    border-color: rgb(22 22 22) !important;
}

body.attachment-actions-open .chat-input-row textarea {
    caret-color: transparent !important;
}

.chat-attach,
.chat-location {
    width: 30px;
    height: 30px;
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    background: none;
    border: none;
    color: var(--text-muted);
    cursor: pointer;
    border-radius: 50%;
    transition: all 0.15s;
    margin-bottom: 5px;
}

.chat-attachment-actions {
    position: relative;
    flex-shrink: 0;
}

.attachment-actions-menu {
    position: absolute;
    left: -6px;
    bottom: calc(100% + 8px);
    z-index: 10002;
    display: none;
    grid-template-columns: repeat(2, minmax(104px, 1fr));
    gap: 6px;
    width: 232px;
    padding: 7px;
    border: 1px solid var(--accent);
    border-radius: 18px;
    background: var(--bg-primary);
    box-shadow:
        0 8px 24px rgba(0, 0, 0, 0.18),
        0 2px 6px rgba(0, 0, 0, 0.08);
}

.chat-attachment-actions.open .attachment-actions-menu {
    display: grid;
}

.attachment-action-card,
.attachment-action-location {
    border: 0;
    color: var(--text);
    font: inherit;
    cursor: pointer;
}

.attachment-action-card {
    min-height: 86px;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 8px;
    border-radius: 13px;
    background: var(--hover-overlay);
    font-size: 14px;
    font-weight: 550;
}

.attachment-action-location {
    min-height: 86px;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 8px;
    border-radius: 13px;
    background: var(--hover-overlay);
    color: var(--text);
    font-size: 14px;
    font-weight: 550;
}

.attachment-action-card:hover,
.attachment-action-card:focus-visible,
.attachment-action-location:hover,
.attachment-action-location:focus-visible {
    background: var(--hover-overlay-strong);
    color: var(--text);
    outline: none;
}

@media (max-width: 799px) {
    .attachment-actions-menu {
        width: 250px;
        padding: 8px;
        border-radius: 20px;
    }

    .attachment-action-card {
        min-height: 94px;
        font-size: 15px;
    }

    .attachment-action-location {
        min-height: 94px;
        font-size: 15px;
    }
}

[data-theme="light"] .attachment-actions-menu {
    box-shadow:
        0 7px 20px rgba(0, 0, 0, 0.1),
        0 1px 4px rgba(0, 0, 0, 0.05);
}

.chat-attach:hover,
.chat-location:hover {
    color: var(--text);
    background: rgba(255, 255, 255, 0.06);
}

.chat-location.is-loading {
    opacity: 0.45;
    pointer-events: none;
}

.chat-input-row textarea {
    flex: 1;
    background: none;
    border: none;
    color: var(--text);
    font-size: 14px;
    font-family: inherit;
    outline: none;
    min-width: 0;
    padding: 8px 4px 8px 4px;
    text-overflow: ellipsis;
    resize: none;
    overflow-y: hidden;
    max-height: 150px;
    height: 36px;
}

.chat-input-row textarea::placeholder {
    color: var(--text-muted);
    opacity: 1;
    text-overflow: ellipsis;
    overflow: hidden;
    white-space: nowrap;
    transition: opacity 0.32s ease;
}

.chat-input-row textarea.composer-placeholder-fade::placeholder {
    opacity: 0;
}

@media (prefers-reduced-motion: reduce) {
    .chat-input-row textarea::placeholder {
        transition: none;
    }
}

.chat-mic {
    width: 38px;
    height: 38px;
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    background: none;
    border: none;
    color: var(--text-muted);
    cursor: pointer;
    border-radius: 50%;
    transition: all 0.15s;
}

.chat-mic:hover {
    color: var(--text);
    background: rgba(255, 255, 255, 0.06);
}

.chat-mic.recording {
    color: #ef4444;
    animation: mic-pulse 1s ease-in-out infinite;
}

@keyframes mic-pulse {

    0%,
    100% {
        opacity: 1;
    }

    50% {
        opacity: 0.4;
    }
}

/* ── Voice Recording Overlay ── */
.voice-overlay {
    display: none;
    position: absolute;
    inset: 0;
    background: var(--bg);
    border-radius: inherit;
    align-items: center;
    gap: 10px;
    padding: 0 10px;
    z-index: 10;
}

.voice-overlay.active {
    display: flex;
}

.chat-input-row:has(.voice-overlay.active)> :not(.voice-overlay) {
    opacity: 0;
    pointer-events: none;
}

.voice-overlay-left {
    display: flex;
    align-items: center;
    gap: 6px;
    flex-shrink: 0;
}

.voice-rec-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: #ef4444;
    animation: mic-pulse 1s ease-in-out infinite;
}

.voice-timer {
    font-size: 13px;
    color: var(--text-muted);
    font-variant-numeric: tabular-nums;
    min-width: 32px;
}

.voice-waveform-canvas {
    flex: 1;
    height: 36px;
    min-width: 60px;
    display: block;
}

.voice-stop-btn {
    width: 32px;
    height: 32px;
    border-radius: 50%;
    background: #ef4444;
    border: none;
    color: #fff;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    transition: background 0.15s;
}

.voice-stop-btn:hover {
    background: #dc2626;
}

.chat-send {
    width: 38px;
    height: 38px;
    border-radius: 10px;
    background: var(--accent);
    border: none;
    color: #fff;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}

.chat-send:hover:not(:disabled) {
    background: var(--accent-light);
}

.chat-send:disabled {
    opacity: 0.3;
    cursor: not-allowed;
}

/* ── Window Manager ── */
.wm-window {
    position: fixed;
    display: flex;
    flex-direction: column;
    background: var(--bg-secondary);
    border: 1px solid var(--border);
    border-radius: 14px;
    box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);
    min-width: 320px;
    min-height: 200px;
    overflow: hidden;
}

.wm-window.wm-active {
    border-color: var(--border-hover);
    box-shadow: 0 12px 48px rgba(0, 0, 0, 0.5);
}

.wm-title-subtitle {
    font-size: 11px;
    color: var(--text-muted);
    opacity: 0.6;
    margin-left: 6px;
    font-weight: 400;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 120px;
}

.wm-window.wm-maximized {
    border-radius: 0;
}

.wm-titlebar {
    height: 36px;
    display: flex;
    align-items: center;
    padding: 0 12px;
    background: rgba(30, 30, 30, 0.1);
    border-bottom: 1px solid rgba(255, 255, 255, 0.06);
    cursor: grab;
    flex-shrink: 0;
    gap: 8px;
    user-select: none;
    transition: background 0.2s;
}

.wm-active .wm-titlebar {
    border-bottom: 1px solid var(--border);
}

.wm-titlebar:active {
    cursor: grabbing;
}

.wm-title-icon {
    font-size: 14px;
    flex-shrink: 0;
}

.wm-title-text {
    flex: 1;
    font-size: 13px;
    font-weight: 500;
    color: var(--text-dim);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.wm-title-actions {
    display: flex;
    gap: 2px;
    flex-shrink: 0;
    margin-right: 8px;
}

.wm-action-btn {
    width: 26px;
    height: 26px;
    border-radius: 6px;
    border: none;
    background: transparent;
    color: var(--text-muted);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: all 0.15s;
}

.wm-action-btn:hover {
    background: rgba(255, 255, 255, 0.08);
    color: var(--text);
}

.wm-title-buttons {
    display: flex;
    gap: 8px;
    flex-shrink: 0;
}

.wm-btn {
    width: 12px;
    height: 12px;
    border-radius: 50%;
    border: none;
    cursor: pointer;
    padding: 0;
    transition: opacity 0.15s;
}

.wm-btn:hover {
    opacity: 0.8;
}

.wm-btn-close {
    background: #ff5f57;
}

.wm-btn-minimize {
    background: #ffbd2e;
}

.wm-btn-maximize {
    background: #28c840;
}

.wm-content {
    flex: 1;
    display: flex;
    flex-direction: column;
}


/* Resize handles */
.wm-resize-handle {
    position: absolute;
    z-index: 2;
}

.wm-resize-n {
    top: -3px;
    left: 10px;
    right: 10px;
    height: 6px;
    cursor: n-resize;
}

.wm-resize-s {
    bottom: -3px;
    left: 10px;
    right: 10px;
    height: 6px;
    cursor: s-resize;
}

.wm-resize-e {
    top: 10px;
    right: -3px;
    bottom: 10px;
    width: 6px;
    cursor: e-resize;
}

.wm-resize-w {
    top: 10px;
    left: -3px;
    bottom: 10px;
    width: 6px;
    cursor: w-resize;
}

.wm-resize-ne {
    top: -3px;
    right: -3px;
    width: 14px;
    height: 14px;
    cursor: ne-resize;
}

.wm-resize-nw {
    top: -3px;
    left: -3px;
    width: 14px;
    height: 14px;
    cursor: nw-resize;
}

.wm-resize-se {
    bottom: -3px;
    right: -3px;
    width: 14px;
    height: 14px;
    cursor: se-resize;
}

.wm-resize-sw {
    bottom: -3px;
    left: -3px;
    width: 14px;
    height: 14px;
    cursor: sw-resize;
}

.desktop.wm-dragging iframe,
.wm-dragging .wm-content iframe,
body.wm-dragging iframe {
    pointer-events: none;
}

/* ── Mobile: backdrop behind bottom-sheet windows ── */
#wm-backdrop {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.55);
    z-index: 1099;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.3s ease;
}

#wm-backdrop.wm-backdrop-visible {
    opacity: 1;
    pointer-events: auto;
}

/* ── Mobile: windows become iOS-style bottom sheets ── */
@media (max-width: 799px) {
    .wm-window {
        left: 0 !important;
        right: 0 !important;
        bottom: 0 !important;
        top: auto !important;
        width: 100% !important;
        height: 88dvh !important;
        min-width: unset !important;
        min-height: unset !important;
        border-radius: 18px 18px 0 0 !important;
        box-shadow: 0 -4px 40px rgba(0, 0, 0, 0.5) !important;
        transform: translateY(100%);
        transition: transform 0.38s cubic-bezier(0.32, 0.72, 0, 1);
    }

    .wm-window.wm-sheet-open {
        transform: translateY(0);
    }

    .wm-resize-handle {
        display: none !important;
    }

    .wm-btn-minimize,
    .wm-btn-maximize {
        display: none !important;
    }

    /* Titlebar: transparent, no border, no blur */
    .wm-titlebar,
    .wm-active .wm-titlebar {
        cursor: default !important;
        height: 52px !important;
        padding: 0 12px !important;
        background: transparent !important;
        border-bottom: none !important;
        position: relative;
    }

    /* Hide emoji icon, center title via absolute positioning */
    .wm-title-icon {
        display: none !important;
    }

    .wm-title-text {
        position: absolute;
        left: 50%;
        transform: translateX(-50%);
        max-width: calc(100% - 96px);
        text-align: center;
        font-size: 14px;
        font-weight: 600;
        color: var(--text);
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
    }

    /* Move close button group to the right */
    .wm-title-buttons {
        order: 10;
        margin-left: auto;
    }

    /* Large circular close button with ✕ */
    .wm-btn-close {
        width: 32px !important;
        height: 32px !important;
        border-radius: 50% !important;
        background: rgba(255, 255, 255, 0.1) !important;
        position: relative;
    }

    .wm-btn-close::before,
    .wm-btn-close::after {
        content: "";
        position: absolute;
        top: 50%;
        left: 50%;
        width: 14px;
        height: 2px;
        background: rgba(255, 255, 255, 0.75);
        border-radius: 1px;
    }

    .wm-btn-close::before {
        transform: translate(-50%, -50%) rotate(45deg);
    }

    .wm-btn-close::after {
        transform: translate(-50%, -50%) rotate(-45deg);
    }
}

/* ── App Window ── */
.app-window-iframe {
    flex: 1;
    border: none;
    background: #fff;
    width: 100%;
}

/* ── Common UI ── */

.btn-sm {
    padding: 6px 12px;
    background: var(--bg-tertiary);
    border: 1px solid var(--border);
    border-radius: 6px;
    color: var(--text-dim);
    font-size: 12px;
    cursor: pointer;
    transition: all 0.15s;
}

.btn-sm:hover {
    border-color: var(--border-hover);
    color: var(--text);
}

/* ── Messages ── */
.messages {
    min-height: min-content;
    overflow-y: auto;
    scrollbar-width: none;
    padding: 20px 16px 10px 16px;
    display: flex;
    flex-direction: column;
    gap: 12px;
    width: 100%;
    max-width: 800px;
    /* Anchor for the overlay typing cursor (#forkCursor, position:absolute) */
    position: relative;
}

.messages::-webkit-scrollbar {
    display: none;
}

@media (min-width: 900px) {
    .messages {
        padding-top: 80px;
    }
}

.msg {
    max-width: 85%;
    padding: 10px 14px;
    border-radius: 14px;
    font-size: 14px;
    line-height: 1.55;
    white-space: pre-wrap;
    word-break: break-word;
    position: relative;
}

.msg-image-standalone,
.msg-photos-standalone {
    position: relative;
}

/* Actionable messages live inside a full-width interaction row. The bubble
   keeps its original dimensions/alignment, while the row provides a stable
   hover target across the otherwise empty part of the message column. */
.msg-action-row {
    width: 100%;
    display: flex;
    flex-shrink: 0;
}
.msg-action-row.is-user {
    justify-content: flex-end;
}
.msg-action-row.is-assistant {
    justify-content: flex-start;
}

/* Explicit message actions affordance for mouse/trackpad users. Touch keeps the
   existing tap gesture, so the trigger stays out of the mobile layout. */
.msg-action-trigger {
    display: none;
}

@media (hover: hover) and (pointer: fine) {
    /* Reserve the 28px action button plus its 8px gap inside the message-list
       width, while keeping the button itself outside the assistant text box. */
    .messages .msg.assistant {
        width: calc(100% - 36px);
        max-width: calc(100% - 36px);
    }

    .msg-action-trigger {
        display: flex;
        position: absolute;
        z-index: 9;
        top: 50%;
        right: -36px;
        width: 28px;
        height: 28px;
        padding: 0;
        border: 1px solid rgba(255, 255, 255, 0.09);
        border-radius: 9px;
        background: rgba(28, 28, 30, 0.72);
        backdrop-filter: blur(14px) saturate(140%);
        -webkit-backdrop-filter: blur(14px) saturate(140%);
        color: rgba(255, 255, 255, 0.78);
        box-shadow: 0 3px 12px rgba(0, 0, 0, 0.18);
        cursor: pointer;
        opacity: 0;
        pointer-events: none;
        transform: translateY(-50%) scale(0.92);
        transition: opacity 0.14s ease, transform 0.14s ease, background 0.14s ease, color 0.14s ease;
        align-items: center;
        justify-content: center;
    }

    .msg.user > .msg-action-trigger,
    .msg-photos-standalone > .msg-action-trigger {
        right: auto;
        left: -36px;
        top: 50%;
        transform: translateY(-50%) scale(0.92);
    }

    .msg-image-standalone > .msg-action-trigger {
        right: -36px;
    }

    /* Error cards own a dismiss control inside their top-right corner. Their
       generic message-actions trigger lives outside the card on the right,
       matching the external affordance used by standalone media. */
    .msg.error-msg > .msg-action-trigger {
        right: -36px;
        top: 50%;
        transform: translateY(-50%) scale(0.92);
    }

    /* The external action buttons sit 8px away from their message bubble.
       Bridge that visual gap with an invisible hit area so moving the pointer
       from the bubble to the button does not briefly drop the parent's :hover. */
    .msg.user > .msg-action-trigger::before,
    .msg-photos-standalone > .msg-action-trigger::before {
        content: "";
        position: absolute;
        top: -4px;
        right: -10px;
        bottom: -4px;
        left: 0;
    }

    .msg.assistant > .msg-action-trigger::before,
    .msg-image-standalone > .msg-action-trigger::before,
    .msg.error-msg > .msg-action-trigger::before {
        content: "";
        position: absolute;
        top: -4px;
        right: 0;
        bottom: -4px;
        left: -10px;
    }

    .msg:hover > .msg-action-trigger,
    .msg.msg-actions-hover > .msg-action-trigger,
    .msg:focus-within > .msg-action-trigger,
    .msg.msg-actions-open > .msg-action-trigger,
    .msg-image-standalone:hover > .msg-action-trigger,
    .msg-image-standalone.msg-actions-hover > .msg-action-trigger,
    .msg-image-standalone:focus-within > .msg-action-trigger,
    .msg-image-standalone.msg-actions-open > .msg-action-trigger,
    .msg-photos-standalone:hover > .msg-action-trigger,
    .msg-photos-standalone.msg-actions-hover > .msg-action-trigger,
    .msg-photos-standalone:focus-within > .msg-action-trigger,
    .msg-photos-standalone.msg-actions-open > .msg-action-trigger {
        opacity: 1;
        pointer-events: auto;
        transform: translateY(-50%) scale(1);
    }

    .msg-action-row:hover > .msg > .msg-action-trigger,
    .msg-action-row:hover > .msg-image-standalone > .msg-action-trigger,
    .msg-action-row:hover > .msg-photos-standalone > .msg-action-trigger,
    .msg-action-row:focus-within > .msg > .msg-action-trigger,
    .msg-action-row:focus-within > .msg-image-standalone > .msg-action-trigger,
    .msg-action-row:focus-within > .msg-photos-standalone > .msg-action-trigger {
        opacity: 1;
        pointer-events: auto;
        transform: translateY(-50%) scale(1);
    }

    .msg.user:hover > .msg-action-trigger,
    .msg.user.msg-actions-hover > .msg-action-trigger,
    .msg.user:focus-within > .msg-action-trigger,
    .msg.user.msg-actions-open > .msg-action-trigger,
    .msg-photos-standalone:hover > .msg-action-trigger,
    .msg-photos-standalone.msg-actions-hover > .msg-action-trigger,
    .msg-photos-standalone:focus-within > .msg-action-trigger,
    .msg-photos-standalone.msg-actions-open > .msg-action-trigger,
    .msg.error-msg:hover > .msg-action-trigger,
    .msg.error-msg.msg-actions-hover > .msg-action-trigger,
    .msg.error-msg:focus-within > .msg-action-trigger,
    .msg.error-msg.msg-actions-open > .msg-action-trigger {
        transform: translateY(-50%) scale(1);
    }

    .msg-action-trigger:hover,
    .msg-action-trigger:focus-visible {
        background: rgba(50, 50, 54, 0.9);
        color: #fff;
        outline: none;
    }

    [data-theme="light"] .msg-action-trigger {
        background: rgba(255, 255, 255, 0.88);
        border-color: rgba(0, 0, 0, 0.08);
        color: rgba(28, 28, 30, 0.62);
        box-shadow: 0 3px 12px rgba(0, 0, 0, 0.12);
    }

    [data-theme="light"] .msg-action-trigger:hover,
    [data-theme="light"] .msg-action-trigger:focus-visible {
        background: #fff;
        color: #1c1c1e;
    }
}

/* On touch devices a long-press on a bubble or empty space must not leave a stray
   "empty block" selection + iOS Copy/Look-Up bar — that gesture opens our own
   action menu instead. So suppress native selection across the message list and on
   user bubbles. EXCEPTION: the assistant's answer text stays natively selectable so
   a snippet can be copied directly (holding it selects text rather than opening our
   menu — see the touch long-press handler). Desktop (mouse) is unaffected. */
@media (hover: none) and (pointer: coarse) {
    .messages,
    .messages .msg.user {
        -webkit-user-select: none;
        user-select: none;
        -webkit-touch-callout: none;
    }
    /* …but the message text itself stays selectable, so a long-press picks out a
       snippet: the assistant's answer text and the user's own bubble text. The
       bubble container/padding around it stays unselectable (no stray "empty
       block" selection when holding the padding). */
    .messages .msg.assistant .msg-content {
        -webkit-user-select: text;
        user-select: text;
        -webkit-touch-callout: default;
    }
}

.msg.user {
    background: var(--accent);
    color: #fff;
    align-self: flex-end;
    border-bottom-right-radius: 4px;
}

/* Media reply preview inside user bubble */
.msg-media-reply {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 6px 8px;
    margin: -4px -4px 6px -4px;
    background: rgba(0, 0, 0, 0.15);
    border-radius: 8px;
    position: relative;
    overflow: hidden;
}

.msg-media-reply-accent {
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    width: 3px;
    background: rgba(255, 255, 255, 0.6);
    border-radius: 3px 0 0 3px;
}

.msg-media-reply-thumb {
    width: 32px;
    height: 32px;
    border-radius: 4px;
    object-fit: cover;
    flex-shrink: 0;
}

.msg-media-reply-label {
    font-size: 12px;
    font-weight: 600;
    color: rgba(255, 255, 255, 0.85);
}

/* ── In-bubble reply quote (points at the message being answered) ── */
.msg-reply-quote {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 5px 8px;
    margin: -2px -2px 6px -2px;
    background: rgba(0, 0, 0, 0.15);
    border-radius: 8px;
    position: relative;
    overflow: hidden;
    max-width: 100%;
    box-sizing: border-box;
}
.msg-reply-quote.is-linked {
    cursor: pointer;
}
.msg-reply-quote-accent {
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    width: 3px;
    background: rgba(255, 255, 255, 0.55);
    border-radius: 3px 0 0 3px;
}
.msg-reply-quote-text {
    font-size: 12px;
    line-height: 1.35;
    color: rgba(255, 255, 255, 0.8);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.msg.assistant .msg-reply-quote {
    background: rgba(255, 255, 255, 0.05);
}
.msg.assistant .msg-reply-quote-text {
    color: var(--text-muted);
}
.msg.assistant .msg-reply-quote-accent {
    background: var(--accent);
}

/* Brief highlight when a quoted message is scrolled into view */
.msg-flash {
    animation: msgFlash 1.2s ease-out;
    border-radius: 14px;
}
@keyframes msgFlash {
    0%, 30% { box-shadow: 0 0 0 3px rgba(255, 200, 60, 0.55); }
    100% { box-shadow: 0 0 0 3px rgba(255, 200, 60, 0); }
}

.msg-photos {
    display: flex;
    gap: 6px;
    margin-bottom: 6px;
    flex-wrap: wrap;
    max-width: 100%;
}

.msg-photos-standalone {
    display: flex;
    gap: 6px;
    flex-wrap: wrap;
    align-self: flex-end;
    max-width: 85%;
    justify-content: flex-end;
}

/* A single attachment is useful context, not a tiny gallery thumbnail. Keep
   multi-photo messages compact, but give one photo enough room to inspect. */
.msg-photos-single {
    width: min(280px, 100%);
}

.msg-photos-standalone.msg-photos-single {
    width: min(300px, 85%);
}

.msg-image-standalone {
    align-self: flex-start;
    max-width: 85%;
}

.msg-image-standalone.diagram-media-message {
    width: 100%;
    max-width: none;
    box-sizing: border-box;
}

.diagram-media-message .media-block {
    display: block;
    width: 100%;
}

.media-block {
    display: inline-flex;
    flex-direction: column;
}

.msg-photo {
    width: 80px;
    height: 80px;
    object-fit: cover;
    border-radius: 8px;
    border: 1px solid rgba(255, 255, 255, 0.2);
    cursor: pointer;
}

.msg-photo:hover {
    opacity: 0.85;
}

.msg-photos-single .msg-photo {
    width: 100%;
    height: auto;
    max-height: 340px;
    object-fit: contain;
    display: block;
    background: rgba(0, 0, 0, 0.12);
}

.msg.assistant {
    background: none;
    width: 100%;
    max-width: 100%;
    padding: 5px 0px 10px;
    font-size: 15px;
    align-self: flex-start;
    white-space: normal;
}

.msg.assistant.msg-error {
    background: rgba(220, 38, 38, 0.15);
    border: 1px solid rgba(220, 38, 38, 0.3);
    color: #fca5a5;
}

/* Markdown */
.msg.assistant .msg-content {
    line-height: inherit;
    width: 100%;
}

.msg.assistant p {
    margin: 0 0 8px 0;
}

.msg.assistant p:last-child {
    margin-bottom: 0;
}

.msg.assistant code {
    background: rgba(255, 255, 255, 0.08);
    padding: 1px 5px;
    border-radius: 4px;
    font-family: "SF Mono", Monaco, "Cascadia Code", monospace;
    font-size: 0.9em;
}

.msg.assistant pre {
    background: rgba(0, 0, 0, 0.3);
    border-radius: 8px;
    padding: 10px 12px;
    margin: 8px 0;
    overflow-x: auto;
}

.msg.assistant pre code {
    background: none;
    padding: 0;
    font-size: 12px;
    line-height: 1.5;
}

.msg.assistant ul,
.msg.assistant ol {
    margin: 6px 0;
    padding-left: 20px;
}

.msg.assistant li {
    margin: 2px 0;
}

.msg.assistant h1,
.msg.assistant h2,
.msg.assistant h3,
.msg.assistant h4 {
    margin: 10px 0 6px 0;
    line-height: 1.3;
}

.msg.assistant h1 {
    font-size: 1.3em;
}

.msg.assistant h2 {
    font-size: 1.15em;
}

.msg.assistant h3 {
    font-size: 1.05em;
}

.msg.assistant blockquote {
    border-left: 3px solid var(--accent);
    padding-left: 10px;
    margin: 6px 0;
    color: var(--text-dim);
}

.msg.assistant a {
    color: var(--accent-light);
    text-decoration: none;
}

.msg.assistant a:hover {
    text-decoration: underline;
}

.msg.assistant hr {
    border: none;
    border-top: 1px solid var(--border);
    margin: 10px 0;
}

.msg.assistant table {
    border-collapse: collapse;
    margin: 8px 0;
    table-layout: fixed;
    width: 100%;
}

.msg.assistant th,
.msg.assistant td {
    border: 1px solid #333333;
    padding: 4px 8px;
    font-size: 13px;
    overflow-wrap: anywhere;
    vertical-align: top;
    width: 1%;
}

.msg.assistant td {
    background: rgb(14 13 13 / 74%);
}

.msg.assistant th {
    background: rgba(255, 255, 255, 0.04);
}

.msg.assistant strong {
    font-weight: 600;
}

@media (min-width: 900px) {

    .msg,
    .msg.assistant,
    .msg.assistant .msg-content,
    .chat-input-row textarea {
        font-size: 16px;
    }

    .chat-input-row textarea {
        padding: 6px 4px 8px 4px;
    }

    .msg.assistant th,
    .msg.assistant td {
        font-size: 15px;
    }

    .msg.assistant pre code {
        font-size: 14px;
    }
}

.msg.system {
    background: transparent;
    color: var(--text-muted);
    font-size: 12px;
    text-align: center;
    align-self: center;
    max-width: 100%;
}

.msg.system.retryable-manager-error {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
}

.message-retry-btn {
    min-width: 76px;
    border: 1px solid var(--border);
    border-radius: 8px;
    padding: 7px 16px;
    background: var(--bg-tertiary);
    color: var(--text-dim);
    font: inherit;
    font-size: 12px;
    line-height: 1.2;
    cursor: pointer;
    transition: background 0.15s ease, color 0.15s ease, opacity 0.15s ease;
}

.message-retry-btn:hover,
.message-retry-btn:focus-visible {
    background: var(--hover-overlay-strong);
    color: var(--text);
    outline: none;
}

.message-retry-btn:disabled {
    cursor: default;
    opacity: 0.5;
}

.message-retry-status {
    color: var(--text-muted);
    font-size: 11px;
    line-height: 1.35;
}

.progress-recovery-actions {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 6px;
    margin-top: 10px;
}

.chat-invite-prompt {
    text-align: center;
    padding: 24px 16px;
    margin: 16px;
    background: var(--bg-tertiary);
    border-radius: 14px;
    border: 1px solid var(--border);
}

.chat-invite-title {
    font-size: 15px;
    font-weight: 600;
    color: var(--text);
    margin-bottom: 4px;
}

.chat-invite-sub {
    font-size: 13px;
    color: var(--text-muted);
    margin-bottom: 16px;
}

.chat-invite-form {
    display: flex;
    gap: 8px;
    justify-content: center;
    align-items: center;
}

.chat-invite-input {
    width: 140px;
    padding: 10px 12px;
    text-align: center;
    font-size: 18px;
    letter-spacing: 4px;
    text-transform: uppercase;
    font-family: monospace;
    border-radius: 10px;
    border: 1px solid var(--border);
    background: var(--bg-secondary);
    color: var(--text);
    outline: none;
}

.chat-invite-input:focus {
    border-color: var(--accent);
}

.chat-invite-btn {
    padding: 10px 20px;
    border-radius: 10px;
    border: none;
    background: var(--accent);
    color: #fff;
    font-size: 14px;
    font-weight: 500;
    font-family: inherit;
    cursor: pointer;
}

.chat-invite-error {
    color: #f87171;
    font-size: 12px;
    margin-top: 8px;
    min-height: 16px;
}

.chat-invite-or {
    font-size: 12px;
    color: var(--text-muted);
    margin-top: 12px;
}

.chat-invite-sub-btn {
    margin-top: 8px;
    min-width: 180px;
    padding: 10px 22px;
    border-radius: 10px;
    border: 1px solid var(--accent);
    background: var(--accent);
    color: #fff;
    font-size: 14px;
    font-weight: 600;
    font-family: inherit;
    cursor: pointer;
    box-shadow: 0 8px 20px rgba(0, 122, 255, 0.24);
    transition: background 0.15s, border-color 0.15s, box-shadow 0.15s, transform 0.15s;
}

.chat-invite-sub-btn:hover {
    background: var(--accent-light);
    border-color: var(--accent-light);
    box-shadow: 0 10px 24px rgba(0, 122, 255, 0.32);
    transform: translateY(-1px);
}

.chat-invite-sub-btn:focus-visible {
    outline: 2px solid rgba(64, 156, 255, 0.45);
    outline-offset: 2px;
}

.chat-loading {
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 40px 0;
    opacity: 0.5;
}

.chat-empty-state {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 12px;
    flex: 1;
    padding: 32px 24px 48px;
    text-align: center;
}

/* A blank chat is a viewport-level landing state, not the last item in the
   message flow. Centre it in the space between the header and composer. The
   composer reserve is updated from its real rendered height, including when
   the visual viewport shrinks for the mobile keyboard. */
.chat-body:has(#chatEmptyState) {
    justify-content: center !important;
    padding-bottom: var(--chat-composer-reserve, calc(var(--chat-h, 78px) + 35px));
    box-sizing: border-box;
}

.chat-body:has(#chatEmptyState)::before {
    display: none !important;
}

.messages:has(#chatEmptyState) {
    flex: 0 1 auto;
    min-height: 0;
    overflow: visible;
    padding: 0 18px !important;
}

#chatEmptyState {
    flex: 0 0 auto;
    width: 100%;
    max-width: 520px;
    gap: 10px;
    padding: 0;
    margin: 0 auto;
}

.chat-empty-mark {
    width: 48px;
    height: 48px;
    display: grid;
    place-items: center;
    color: var(--text-dim);
    margin-bottom: 2px;
}

.chat-empty-mark svg {
    width: 48px;
    height: 48px;
    display: block;
}

.chat-empty-title {
    color: var(--text);
    font-size: 24px;
    line-height: 1.2;
    font-weight: 720;
    letter-spacing: -0.02em;
}

#chatEmptyState .chat-empty-sub {
    max-width: 420px;
    color: var(--text-dim);
    font-size: 16px;
    line-height: 1.45;
}

@media (max-width: 520px) {
    #chatEmptyState {
        max-width: 420px;
        gap: 9px;
    }

    .chat-empty-mark,
    .chat-empty-mark svg {
        width: 44px;
        height: 44px;
    }

    .chat-empty-title {
        font-size: 22px;
    }

    #chatEmptyState .chat-empty-sub {
        font-size: 14px;
    }
}

.chat-retry-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 8px 18px;
    margin-top: 8px;
    background: var(--accent);
    color: #fff;
    border: 0;
    border-radius: 8px;
    font-size: 13px;
    font-weight: 500;
    cursor: pointer;
    transition: opacity 0.15s;
}

.chat-retry-btn:hover {
    opacity: 0.85;
}

.back-to-general {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    padding: 8px 16px;
    margin: 8px auto 4px;
    color: var(--secondary-text);
    font-size: 13px;
    cursor: pointer;
    border-radius: 8px;
    transition: color 0.15s;
    width: fit-content;
}

.back-to-general:hover {
    color: var(--accent);
}

.back-to-general .back-arrow {
    font-size: 15px;
}

/* ── Quick app launcher: typed-word matches in a blank new chat ── */
.app-quick-search {
    display: flex;
    flex-direction: column;
    gap: 6px;
    width: 100%;
    /* Match the composer width (.chat-input flex-basis / .messages max-width)
       so the matches line up with the input the user is typing in. */
    max-width: 800px;
    /* margin-top:auto drops the block to the bottom of the (full-height)
       messages area so matches sit just above the composer — near the input
       the user is typing in — instead of floating at the top of the empty
       chat. left/right auto keep it centered; .messages owns the overflow.
       Small bottom padding keeps the block low, hugging the composer. */
    margin: auto auto 0;
    /* No horizontal padding: .messages (16px) and .chat-bar (16px) share the
       same 800px-centered box, so dropping the inner pad makes the rows fill
       the messages content width and sit flush — left and right — with the
       composer's input box right below. */
    padding: 16px 0 12px;
}
.aqs-item {
    display: flex;
    align-items: center;
    gap: 12px;
    width: 100%;
    padding: 9px 12px;
    background: var(--bg-tertiary);
    border: 1px solid var(--border);
    border-radius: 12px;
    cursor: pointer;
    text-align: left;
    color: var(--text);
    font: inherit;
    transition: background 0.12s, border-color 0.12s;
}
.aqs-item:hover {
    background: var(--hover-overlay);
    border-color: var(--border-hover);
}
.aqs-icon {
    width: 34px;
    height: 34px;
    flex: 0 0 34px;
    border-radius: 9px;
    overflow: hidden;
}
.aqs-icon-img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}
.aqs-icon-ph {
    width: 100%;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 16px;
    font-weight: 600;
    color: #fff;
}
.aqs-name {
    flex: 1;
    min-width: 0;
    font-size: 14px;
    font-weight: 500;
    color: var(--text);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.aqs-arrow {
    flex: 0 0 auto;
    color: var(--text-muted);
}

/* ── Universal slide-out window presentation ──────────────────────────────
   Any sliding panel/iframe window (the messenger, app bottom-sheet modals, and
   future side panels) shares one mechanism: the off-screen + on-screen positions
   live in CSS keyed by `data-slide` (direction), and the ONLY state is the
   `.is-open` class. Toggling a class lets the browser interpolate the transform
   from wherever it currently is — so reopening mid-close reverses smoothly with
   no snap/jerk. JS never writes transform inline except for live drag tracking. */
.fork-native-modal-sheet {
    /* Material styles below are opt-in; default preserves existing surfaces. */
    will-change: transform;
    transition: transform .42s cubic-bezier(.32, .72, 0, 1);
}
.fork-native-modal-sheet[data-slide="right"]          { transform: translateX(100%); }
.fork-native-modal-sheet[data-modal-background="transparent"],
.fork-native-modal-sheet[data-modal-background="frosted"],
.fork-native-modal-sheet[data-modal-background="glass"] { background: transparent !important; }
.fork-native-modal-sheet[data-modal-background="frosted"]::before,
.fork-native-modal-sheet[data-modal-background="glass"]::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    border-radius: inherit;
    pointer-events: none;
    background: rgba(28, 28, 30, .68);
    -webkit-backdrop-filter: blur(20px) saturate(140%);
    backdrop-filter: blur(20px) saturate(140%);
}
.fork-native-modal-sheet[data-modal-background="glass"]::before {
    background: linear-gradient(145deg, rgba(255,255,255,.18), rgba(30,30,34,.35));
    box-shadow: inset 0 0 0 1px rgba(255,255,255,.25), inset 0 2px 2px rgba(255,255,255,.18);
    -webkit-backdrop-filter: blur(24px) saturate(160%);
    backdrop-filter: blur(24px) saturate(160%);
}
[data-theme="light"] .fork-native-modal-sheet[data-modal-background="frosted"]::before { background: rgba(248,248,250,.72); }
[data-theme="light"] .fork-native-modal-sheet[data-modal-background="glass"]::before { background: linear-gradient(145deg, rgba(255,255,255,.62), rgba(245,245,250,.28)); }
@media (prefers-reduced-transparency: reduce) {
    .fork-native-modal-sheet[data-modal-background="frosted"]::before,
    .fork-native-modal-sheet[data-modal-background="glass"]::before { background: #1c1c1e; -webkit-backdrop-filter: none; backdrop-filter: none; }
    [data-theme="light"] .fork-native-modal-sheet[data-modal-background="frosted"]::before,
    [data-theme="light"] .fork-native-modal-sheet[data-modal-background="glass"]::before { background: #f8f8fa; }
}
.fork-native-modal-sheet[data-slide="right"].is-open  { transform: translateX(0); }
.fork-native-modal-sheet[data-slide="left"]           { transform: translateX(-100%); }
.fork-native-modal-sheet[data-slide="left"].is-open   { transform: translateX(0); }
.fork-native-modal-sheet[data-slide="bottom"]         { transform: translateY(calc(100% + 32px)) scale(.985); }
.fork-native-modal-sheet[data-slide="bottom"].is-open { transform: translateY(0) scale(1); }
/* Centered desktop window: zoom + fade instead of a slide. Closed opacity is .01
   (not 0) so the sheet keeps a live compositor layer while warm/closed — Chrome
   skips fully-transparent subtrees and the first open would snap (see the modal
   warmup notes in runtime.js). */
.fork-native-modal-sheet[data-slide="center"] {
    transform: scale(.92);
    opacity: .01;
    transition: transform .34s cubic-bezier(.32, .72, 0, 1), opacity .3s ease,
                height .24s cubic-bezier(.32, .72, 0, 1);
}
.fork-native-modal-sheet[data-slide="center"].is-open { transform: scale(1); opacity: 1; }

/* ── Messenger window (adaptive standalone surface) ───────────────────────
   Narrow panels use the native-style full-screen push below. Desktop panels
   add `.fork-messenger-desktop` and turn the same persistent iframe into a
   centered, dismissible modal. Keeping one DOM/iframe instance preserves chat
   state and makes every reopen instant in both presentations. */
.fork-messenger {
    position: absolute;
    inset: 0;
    z-index: 10020;
    overflow: hidden;          /* clips the closed sheet off-screen */
    background: transparent;
    pointer-events: none;      /* click-through while closed; runtime sets auto on open */
}
/* The sheet is only a backdrop: the messenger iframe paints its own themed
   background over it. It shows while the window slides in and before the frame
   has painted, so it must MATCH messenger.html's `--bg` in both themes —
   anything else (it used to be a hard-coded #000) flashes on a light theme. */
.fork-messenger-sheet {
    position: absolute;
    inset: 0;
    background: #0b0b0f;
    overflow: hidden;
    transform: translateX(100%);                               /* closed: off-screen right */
    transition: transform .42s cubic-bezier(.32, .72, 0, 1);   /* iOS-push ease, no overshoot */
    will-change: transform;
}
[data-theme="light"] .fork-messenger-sheet { background: #fff; }
.fork-messenger-sheet.is-open { transform: translateX(0); }    /* open: flush left */
.fork-messenger-frame {
    width: 100%;
    height: 100%;
    border: 0;
    display: block;
    background: transparent;
}

/* Host-owned desktop chrome is hidden for the narrow/full-screen presentation,
   where the existing floating app toolbar supplies Back + title. */
.fork-messenger-modal-header {
    display: none;
}

/* Desktop messenger modal. The overlay sits above the app toolbar so every part
   of the app really is behind the frosted backdrop; the modal owns its title and
   close control instead of borrowing toolbar chrome. */
.fork-messenger.fork-messenger-desktop {
    z-index: 10035;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: clamp(32px, 6vh, 72px) clamp(32px, 7vw, 96px);
    background: rgba(8, 9, 13, 0);
    -webkit-backdrop-filter: blur(0);
    backdrop-filter: blur(0);
    transition: background .28s ease, -webkit-backdrop-filter .28s ease, backdrop-filter .28s ease;
}

.fork-messenger.fork-messenger-desktop.is-open {
    background: rgba(8, 9, 13, 0.46);
    -webkit-backdrop-filter: blur(16px) saturate(0.82);
    backdrop-filter: blur(16px) saturate(0.82);
}

.fork-messenger.fork-messenger-desktop .fork-messenger-sheet {
    position: relative;
    inset: auto;
    width: min(720px, 100%);
    height: min(840px, 100%);
    display: flex;
    flex-direction: column;
    border: 1px solid var(--border);
    border-radius: 24px;
    background: var(--bg-primary);
    box-shadow: 0 28px 90px rgba(0, 0, 0, 0.42), 0 4px 22px rgba(0, 0, 0, 0.22);
    transform: translateY(18px) scale(.965);
    opacity: 0;
    transition: transform .32s cubic-bezier(.32, .72, 0, 1), opacity .24s ease;
}

.fork-messenger.fork-messenger-desktop.is-open .fork-messenger-sheet {
    transform: translateY(0) scale(1);
    opacity: 1;
}

.fork-messenger.fork-messenger-desktop .fork-messenger-modal-header {
    position: relative;
    z-index: 9;
    height: 56px;
    flex: 0 0 56px;
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 0 14px 0 20px;
    border-bottom: 1px solid var(--border);
    background: var(--bg-primary);
}

.fork-messenger-modal-title {
    min-width: 0;
    flex: 1 1 auto;
    color: var(--text);
    font-size: 15px;
    font-weight: 600;
    line-height: 1.25;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.fork-messenger-modal-actions {
    position: relative;
    flex: 0 0 34px;
}

.fork-messenger-modal-actions[hidden] { display: none !important; }

.fork-messenger-modal-action,
.fork-messenger-modal-close {
    width: 34px;
    height: 34px;
    flex: 0 0 34px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: var(--bg-tertiary);
    color: var(--text-secondary);
    cursor: pointer;
    transition: background .15s ease, color .15s ease, transform .15s ease;
}

.fork-messenger-modal-close {
    position: relative;
}

.fork-messenger-modal-action:hover,
.fork-messenger-modal-close:hover {
    background: var(--hover-overlay-strong);
    color: var(--text);
}

.fork-messenger-modal-action:active,
.fork-messenger-modal-close:active { transform: scale(.94); }
.fork-messenger-modal-action:focus-visible,
.fork-messenger-modal-close:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}

.fork-messenger-action-menu {
    position: absolute;
    top: calc(100% + 8px);
    right: 0;
    z-index: 12;
    display: none;
    min-width: 210px;
    padding: 6px;
    border: 1px solid var(--border);
    border-radius: 14px;
    background: color-mix(in srgb, var(--bg-secondary) 94%, transparent);
    box-shadow: 0 14px 42px rgba(0, 0, 0, .28);
    -webkit-backdrop-filter: blur(24px) saturate(140%);
    backdrop-filter: blur(24px) saturate(140%);
}

.fork-messenger-modal-actions.open .fork-messenger-action-menu { display: block; }

.fork-messenger-action-item {
    width: 100%;
    min-height: 38px;
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 9px 11px;
    border: 0;
    border-radius: 9px;
    background: transparent;
    color: var(--text);
    font: 500 14px/1.25 -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
    text-align: left;
    cursor: pointer;
}

.fork-messenger-action-item:hover { background: var(--hover-overlay); }
.fork-messenger-action-item:disabled { opacity: .45; cursor: default; }
.fork-messenger-action-item.destructive { color: #ff453a; }
.fork-messenger-action-item svg { flex: 0 0 auto; }
.fork-messenger-application-actions {
    margin: -1px -1px 5px;
    padding: 1px 1px 5px;
    border-bottom: 1px solid var(--border);
}
.fork-messenger-application-actions[hidden] { display: none !important; }

.fork-messenger-action-confirm {
    width: 260px;
    max-width: calc(100vw - 56px);
    padding: 8px;
}

.fork-messenger-action-confirm[hidden] { display: none !important; }
.fork-messenger-action-confirm-title { color: var(--text); font-size: 14px; font-weight: 600; line-height: 1.3; }
.fork-messenger-action-confirm-desc { margin-top: 5px; color: var(--text-dim); font-size: 12px; line-height: 1.4; }
.fork-messenger-action-confirm-buttons { display: flex; justify-content: flex-end; gap: 7px; margin-top: 12px; }
.fork-messenger-action-confirm-button {
    min-height: 32px;
    padding: 7px 11px;
    border: 0;
    border-radius: 9px;
    background: var(--bg-tertiary);
    color: var(--text);
    font: 600 13px/1.2 -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
    cursor: pointer;
}
.fork-messenger-action-confirm-button:hover { background: var(--hover-overlay-strong); }
.fork-messenger-action-confirm-button.destructive { background: #ff453a; color: #fff; }

.fork-messenger-action-backdrop {
    position: absolute;
    inset: 56px 0 0;
    z-index: 8;
    display: none;
    background: transparent;
}
.fork-messenger-action-backdrop.open { display: block; }

.fork-messenger.fork-messenger-desktop .fork-messenger-frame {
    height: auto;
    min-height: 0;
    flex: 1 1 auto;
}

@media (prefers-reduced-motion: reduce) {
    .fork-messenger.fork-messenger-desktop,
    .fork-messenger.fork-messenger-desktop .fork-messenger-sheet {
        transition-duration: .01ms;
    }
}

/* ── Page windows (STANDALONE right-slide STACK) ──────────────────────────
   Same standalone slide mechanism as the messenger, but pages STACK: each
   Fork.page.open() builds a new overlay on top (iOS push-navigation). Higher
   z-index per level + the per-sheet background colour are set inline by
   runtime.js. The full-screen iframe sits BELOW the floating host toolbar
   (z-index 10030), which stays pinned visible so its back button + title show
   on top. Content is the app's own cached page.html. */
.fork-page {
    position: absolute;
    inset: 0;
    overflow: hidden;          /* clips the closed sheet off-screen */
    background: transparent;
    pointer-events: none;      /* click-through while closed; runtime sets auto on open */
}
.fork-page-sheet {
    position: absolute;
    inset: 0;
    overflow: hidden;
    /* Backdrop until the page iframe paints. runtime.js overrides it inline with the
       app's own bg colour when it has one; this themed default replaces the old
       hard-coded #000 fallback, which flashed black under a light app. */
    background: var(--bg-primary);
    transform: translateX(100%);                               /* closed: off-screen right */
    transition: transform .42s cubic-bezier(.32, .72, 0, 1);   /* iOS-push ease, no overshoot */
    will-change: transform;
}
.fork-page-sheet.is-open { transform: translateX(0); }         /* open: flush */
.fork-page-frame {
    width: 100%;
    height: 100%;
    border: 0;
    display: block;
    background: transparent;
}

/* ── Split view — automatic two-column layout on wide screens ─────────────
   runtime.js toggles `fork-split` on the app panel when the panel is wide
   (≥900px) AND the app has a registered split root or open split page. ALL
   geometry lives here: the app iframe shrinks to the left column and opted-in
   page overlays pin to the right-hand column. The messenger stays independent
   and opens above the complete layout as a desktop modal. */
.app-panel.fork-split {
    /* The APP keeps at most 812px (or 62% on smaller panels so the column never
       drops below ~38%); the window column takes ALL the remaining space. The
       app gives up `--fork-split-gap` of its own width to the gutter between
       them, so the column's width (and every sheet's slide distance) is
       unaffected by the divider. */
    --fork-split-app-w: min(812px, 62%);
    --fork-split-w: calc(100% - var(--fork-split-app-w));
    --fork-split-gap: 16px;
    --fork-split-ease: cubic-bezier(.32, .72, 0, 1);
}

/* NOTE 1: an iframe is a REPLACED element — when absolutely positioned with
   width:auto it takes its INTRINSIC 300px width instead of stretching between
   left/right. Size it with an explicit width, never left+right.
   NOTE 2: no width transition here — Chrome wedges a `100%` → `min(...)`
   width transition on the iframe (holds the old value indefinitely), and
   animating an iframe's width reflows the whole app every frame anyway. */
.app-panel.fork-split .app-tab-iframe {
    width: calc(var(--fork-split-app-w) - var(--fork-split-gap));
    right: auto;
}

/* ONLY pages that asked for the column get pinned into it: the standby root and
   pages opened with `split: true`. A default page keeps
   covering the whole panel (inset:0) — a full-screen slide-over, desktop and
   phone alike. The messenger is always a modal above this layout on desktop. */
.app-panel.fork-split .fork-page-split {
    left: auto;
    width: var(--fork-split-w);
    transition: transform .42s var(--fork-split-ease);
}

/* Column divider rides on the sheets (the overlays are transparent clippers) */
.app-panel.fork-split .fork-page-split .fork-page-sheet {
    border-left: 1px solid rgba(255, 255, 255, 0.08);
}

/* The app's own bottom chrome (tab bar + action button) belongs to the APP
   column — confine it so it never slides under the window column (nor into the
   gutter). Direct child only: page iframes host their own chrome
   inside their sheets. !important beats the inline right:0 from runtime.js.
   `.fork-search-window` opts out: that search field is docked inside the modal
   window, which is centered on the WHOLE panel, so clamping its right edge to
   the app column would squeeze the field off the window (runtime.js sets its
   left/right inset to the window's own). */
.app-panel.fork-split > .fork-bottom-chrome,
.app-panel.fork-split > .fork-search-chrome:not(.fork-search-window) {
    right: calc(var(--fork-split-w) + var(--fork-split-gap)) !important;
}

/* ── The gutter + its collapse toggle ─────────────────────────────────────
   A 16px strip of panel background between the two columns. The strip IS the
   button — full height, clickable anywhere, chevrons drawn at its middle: the
   affordance that says "this is a split window" and pushes the column back
   off-screen (»). Collapsed, the strip rides to the panel's right edge and the
   chevrons flip to « to bring it back. Built by runtime.js (splitEnsureDivider)
   and CSS-gated on `fork-split`, so it exists only while the column does. */
.fork-split-divider {
    display: none;
}

.app-panel.fork-split .fork-split-divider {
    display: block;
    position: absolute;
    top: 0;
    bottom: 0;
    right: var(--fork-split-w);
    width: var(--fork-split-gap);
    /* Above column pages (10000+), below the host toolbar (10030). */
    z-index: 10029;
    pointer-events: none;   /* the strip is decoration; only the button clicks */
    transition: right .42s var(--fork-split-ease);
}

/* A full-screen page (the default kind) covers BOTH columns, so the gutter and
   any split chrome must not float on top of it. */
.app-panel.fork-split:has(> .fork-page:not(.fork-page-split)) .fork-split-divider,
.app-panel.fork-split:has(> .fork-page:not(.fork-page-split)) .fork-split-chrome {
    display: none !important;
}

/* The button fills the gutter: the whole strip, full height, is the hit target,
   with the chevrons drawn straight into it — no badge, nothing overflowing.
   Drag it to move the split point; a click that never travels collapses. */
.fork-split-toggle {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    padding: 0;
    border: 0;
    border-radius: 0;
    background: transparent;
    color: var(--text-muted);
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: col-resize;
    pointer-events: auto;
    touch-action: none;   /* the pointer drag owns horizontal gestures */
    transition: background .15s, color .15s;
}

/* Collapsed there is nothing left to resize — the strip is a plain button again. */
.app-panel.fork-split.is-split-collapsed .fork-split-toggle { cursor: pointer; }

.fork-split-toggle:hover {
    background: var(--hover-overlay-strong);
    color: var(--text);
}

.fork-split-toggle:active { background: var(--hover-overlay); }

.fork-split-toggle svg {
    flex: 0 0 auto;
    transition: transform .42s var(--fork-split-ease);
}

/* Collapsed: the app takes the whole panel (snapped, never transitioned — see
   NOTE 2), the column slides out to the right, and the gutter rides along. */
.app-panel.fork-split.is-split-collapsed .app-tab-iframe {
    width: 100%;
}

.app-panel.fork-split.is-split-collapsed .fork-page-split {
    transform: translateX(100%);
}

.app-panel.fork-split.is-split-collapsed > .fork-bottom-chrome,
.app-panel.fork-split.is-split-collapsed > .fork-search-chrome:not(.fork-search-window) {
    right: 0 !important;
}

/* Split chrome belongs to the column — hide it when the column is gone
   (beats runtime.js's inline display:flex). */
.app-panel.fork-split.is-split-collapsed .fork-split-chrome {
    display: none !important;
}

.app-panel.fork-split.is-split-collapsed .fork-split-divider {
    right: 0;
}

/* While dragging, the strip must track the pointer exactly — no easing on its
   position, no text selection, and the whole panel keeps the resize cursor even
   when the pointer runs over an iframe. */
.app-panel.fork-split.is-split-dragging {
    cursor: col-resize;
    user-select: none;
}

.app-panel.fork-split.is-split-dragging .fork-split-divider {
    transition: none;
}

.app-panel.fork-split.is-split-dragging .fork-split-toggle {
    background: var(--hover-overlay-strong);
    color: var(--text);
}

/* Flush with the panel edge, the strip stays full-height and clickable; only the
   chevrons flip to point back at the column they bring in. */
.app-panel.fork-split.is-split-collapsed .fork-split-toggle svg {
    transform: rotate(180deg);
}

/* The permanent standby (root) page exists only while split view is on */
.fork-page-root {
    display: none;
}

.app-panel.fork-split .fork-page-root {
    display: block;
    pointer-events: auto;
}

/* Floating back button + title pill over the column — the column's own
   "toolbar" while a closable window (stacked page / messenger) is up. Sits a
   notch above the host toolbar (z 10030) but leaves its right edge (menu ⋯)
   free. Shown/hidden inline by runtime.js (display:flex / none). */
.fork-split-chrome {
    position: absolute;
    top: 10px;
    left: calc(100% - var(--fork-split-w, 380px) + 10px);
    right: 60px;
    z-index: 10031;
    display: none;
    align-items: center;
    gap: 10px;
    pointer-events: none;
}

.fork-split-chrome > * {
    pointer-events: auto;
}

.fork-split-title {
    height: 40px;
    line-height: 40px;
    padding: 0 16px;
    border-radius: 20px;
    border: 1px solid rgba(255, 255, 255, 0.12);
    /* Backdrop here is the opaque messenger sheet — blur was invisible. */
    background: rgba(30, 30, 30, 0.85);
    color: #fff;
    font-size: 14px;
    font-weight: 600;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 100%;
}

/* The messenger under this pill follows the theme, so the pill must too —
   same treatment as the toolbar family (.app-toolbar-title & co above). */
[data-theme="light"] .fork-split-title {
    background: linear-gradient(100deg, rgba(255, 255, 255, 0.92), rgba(255, 255, 255, 0.78));
    border-color: rgba(0, 0, 0, 0.08);
    color: rgba(20, 20, 20, 0.72);
    box-shadow: rgba(0, 0, 0, 0.1) 0 4px 14px;
}

/* ── Fork prompt inside the chat panel ──
   When the viewer clicks the title pill on someone else's already-added app,
   the chat panel slides in with body.chat-prompt set. The messages area
   is replaced with this card; the input bar / chat tabs / chat header are
   hidden so the panel reads as an info screen, not a real chat. */
/* In fork-prompt mode the chat header / desc / media panels don't apply.
   The chat-bar stays visible but the input row is deactivated (faded +
   pointer-events:none) so the viewer sees the field but can't type until
   they fork. Chat-context (segment control) stays visible too — the user
   can still switch to the Info tab. */
body.chat-prompt .chat-header,
body.chat-prompt .chat-desc-panel,
body.chat-prompt .chat-media-panel {
    display: none !important;
}

body.chat-prompt .chat-input-row {
    opacity: 0.45;
    pointer-events: none;
    cursor: default;
}

/* Strip focus-within glow when deactivated — the textarea can't actually
   receive focus, but if the browser still applies pseudo-class state we'd
   get a misleading "live" glow. */
body.chat-prompt .chat-input-row,
body.chat-prompt .chat-input-row:focus-within {
    border-color: var(--border) !important;
    background: var(--bg-tertiary, rgb(22 22 22)) !important;
}

/* Centre the fork-prompt vertically inside the chat panel.
   Default chat layout pushes content to the bottom (justify-content: flex-end)
   or pads it for the input bar — both leave the prompt sitting just above the
   missing input. Override to true vertical centering and drop the bottom inset
   that the (now-hidden) chat-bar would have reserved. The desktop ::before
   flex-spacer also has to go so the prompt isn't shoved down. */
body.chat-prompt .chat-body {
    justify-content: center !important;
}

body.chat-prompt .chat-body::before {
    display: none !important;
}

body.chat-prompt .messages {
    padding-bottom: 16px !important;
    flex: 0 0 auto;
}

.chat-prompt-card {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 14px;
    flex: 1;
    padding: 32px 28px 64px;
    text-align: center;
    max-width: 420px;
    margin: 0 auto;
}

.chat-prompt-icon {
    width: 64px;
    height: 64px;
    border-radius: 50%;
    background: var(--accent);
    color: #fff;
    display: flex;
    align-items: center;
    justify-content: center;
    margin-bottom: 4px;
    box-shadow: 0 6px 24px rgba(99, 102, 241, 0.32);
}

.chat-prompt-icon svg {
    width: 28px;
    height: 28px;
}

.chat-prompt-title {
    font-size: 17px;
    font-weight: 600;
    color: var(--text);
    line-height: 1.3;
}

.chat-prompt-desc {
    font-size: 13px;
    color: var(--text-muted);
    line-height: 1.55;
}

.chat-prompt-btn {
    margin-top: 12px;
    padding: 10px 28px;
    border: none;
    border-radius: 10px;
    background: var(--accent);
    color: #fff;
    font-size: 14px;
    font-weight: 600;
    font-family: inherit;
    cursor: pointer;
    transition: opacity 0.15s, transform 0.1s;
}

.chat-prompt-btn:hover {
    opacity: 0.9;
}

.chat-prompt-btn:active {
    transform: scale(0.97);
}

/* Inline button loader — used by withBtnLoader() in app.js for any primary
   action button that triggers an async call. The button keeps its width by
   sticking to a min-height that matches the original text-button so the
   layout doesn't jump. */
.btn-loading {
    cursor: default;
    pointer-events: none;
}

.btn-spinner {
    display: inline-block;
    width: 16px;
    height: 16px;
    border: 2px solid rgba(255, 255, 255, 0.35);
    border-top-color: #fff;
    border-radius: 50%;
    animation: btn-spinner-rotate 0.7s linear infinite;
    vertical-align: middle;
}

@keyframes btn-spinner-rotate {
    to { transform: rotate(360deg); }
}

/* Success state shown briefly between "Add to dashboard" and the follow-up
   fork prompt. Bigger green check, gentle pop-in to read as a confirmation
   rather than yet another ask. */
.chat-prompt-icon-success {
    background: #22c55e;
    box-shadow: 0 6px 24px rgba(34, 197, 94, 0.32);
    animation: chat-prompt-pop 0.32s cubic-bezier(0.16, 1, 0.3, 1);
}

.chat-prompt-icon-success svg {
    width: 32px;
    height: 32px;
}

@keyframes chat-prompt-pop {
    0% { transform: scale(0.4); opacity: 0; }
    60% { transform: scale(1.1); opacity: 1; }
    100% { transform: scale(1); opacity: 1; }
}

.chat-empty-sub {
    font-size: 13px;
    color: var(--text-muted);
}

.msg.context-switch {
    background: transparent;
    color: var(--text-muted);
    font-size: 12px;
    text-align: center;
    align-self: stretch;
    max-width: 100%;
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 8px 0;
    margin: 4px 0;
}

.msg.context-switch::before,
.msg.context-switch::after {
    content: "";
    flex: 1;
    height: 1px;
    background: var(--border);
}

.msg.no-tokens {
    background: rgba(239, 68, 68, 0.08);
    border: 1px solid rgba(239, 68, 68, 0.2);
    color: var(--red);
    align-self: stretch;
    max-width: 100%;
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 12px 16px;
    border-radius: var(--radius);
    font-size: 13px;
}

.no-tokens-icon {
    font-size: 18px;
    flex-shrink: 0;
}

.no-tokens-text {
    flex: 1;
}

/* Success state after top-up */
.msg.no-tokens-success {
    background: rgba(59, 130, 246, 0.08);
    border: 1px solid rgba(59, 130, 246, 0.2);
    color: #60a5fa;
    align-self: stretch;
    max-width: 100%;
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 12px 16px;
    border-radius: var(--radius);
    font-size: 13px;
}

.no-tokens-received {
    flex-shrink: 0;
    background: rgba(59, 130, 246, 0.15);
    border: 1px solid rgba(59, 130, 246, 0.35);
    color: #60a5fa;
    border-radius: 6px;
    padding: 5px 12px;
    font-size: 12px;
    font-weight: 500;
    cursor: pointer;
    transition: background 0.15s;
}

.no-tokens-received:hover {
    background: rgba(59, 130, 246, 0.25);
}

.no-tokens-fulfill {
    flex-shrink: 0;
    background: rgba(59, 130, 246, 0.15);
    border: 1px solid rgba(59, 130, 246, 0.35);
    color: #60a5fa;
    border-radius: 6px;
    padding: 5px 12px;
    font-size: 12px;
    font-weight: 500;
    cursor: pointer;
    transition: background 0.15s;
}

.no-tokens-fulfill:hover {
    background: rgba(59, 130, 246, 0.25);
}

/* Top-up modal */
.topup-modal-overlay {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.6);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 10000;
    padding: 20px;
}

.topup-modal {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 16px;
    padding: 28px 24px 24px;
    max-width: 340px;
    width: 100%;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 10px;
    text-align: center;
}

.topup-modal-icon {
    font-size: 36px;
    margin-bottom: 4px;
}

.topup-modal-title {
    font-size: 17px;
    font-weight: 600;
    color: var(--text);
}

.topup-modal-desc {
    font-size: 13px;
    color: var(--text-muted);
    line-height: 1.5;
    margin-bottom: 6px;
}

.topup-modal-btn {
    width: 100%;
    background: var(--accent);
    color: #fff;
    border: none;
    border-radius: 10px;
    padding: 12px;
    font-size: 14px;
    font-weight: 600;
    cursor: pointer;
    transition: opacity 0.15s;
}

.topup-modal-btn:hover {
    opacity: 0.88;
}

.topup-modal-btn:disabled {
    opacity: 0.5;
    cursor: default;
}

.topup-modal-cancel {
    background: none;
    border: none;
    color: var(--text-muted);
    font-size: 13px;
    cursor: pointer;
    padding: 4px 8px;
}

.topup-modal-cancel:hover {
    color: var(--text);
}

/* Generated images */
.generated-img-wrap {
    position: relative;
    display: inline-block;
    max-width: min(360px, 100%);
    margin: 6px 0;
    line-height: 0;
    flex-shrink: 0;
}

.generated-img-wrap.generated-diagram-wrap {
    display: block;
    width: 100%;
    max-width: none;
}

.generated-diagram-wrap .generated-img {
    width: 100%;
    height: 100%;
}

.generated-img-wrap.generating {
    flex-shrink: 0;
    max-width: min(360px, 100%);
    border-radius: 12px;
    overflow: hidden;
    background: #111;
}

.video-failed-card {
    padding: 12px 14px;
    text-align: left;
    line-height: normal;
    background: rgba(220, 38, 38, 0.1);
    border: 1px solid rgba(220, 38, 38, 0.25);
    border-radius: 12px;
    display: flex;
    flex-direction: column;
    height: fit-content;
}

.video-failed-title {
    font-size: 14px;
    font-weight: 600;
    color: #fca5a5;
    margin-bottom: 3px;
}

.video-failed-msg {
    font-size: 12px;
    color: var(--text-dim);
    line-height: 1.4;
}

.video-failed-code {
    display: flex;
    align-items: center;
    gap: 4px;
    margin-top: 8px;
    font-size: 11px;
    color: var(--text-muted);
    font-family: monospace;
}

.video-failed-copy {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: none;
    border: none;
    color: var(--text-muted);
    cursor: pointer;
    padding: 2px;
    border-radius: 4px;
}

.video-failed-copy:active {
    color: var(--text);
}

.media-failed-retry {
    align-self: flex-start;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    margin-top: 10px;
    padding: 7px 10px;
    border: 1px solid rgba(248, 113, 113, 0.3);
    border-radius: 8px;
    background: rgba(248, 113, 113, 0.12);
    color: #fca5a5;
    font-size: 12px;
    font-weight: 600;
    line-height: 1;
    cursor: pointer;
    transition: background 0.15s, border-color 0.15s, opacity 0.15s;
}

.media-failed-retry:hover {
    background: rgba(248, 113, 113, 0.2);
    border-color: rgba(248, 113, 113, 0.45);
}

.media-failed-retry:disabled {
    cursor: default;
    opacity: 0.55;
}

.media-failed-retry-error {
    margin-top: 8px;
    max-width: 260px;
}

/* Generated video player */
.video-player-wrap {
    position: relative;
    cursor: pointer;
    background: #111;
    border-radius: 12px;
    overflow: hidden;
    max-width: 100%;
}

.generated-video {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

.video-play-btn {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 52px;
    height: 52px;
    border-radius: 50%;
    border: none;
    background: rgba(0, 0, 0, 0.45);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition:
        opacity 0.2s,
        transform 0.15s;
    z-index: 2;
    padding-left: 3px;
}

.video-play-btn:active {
    transform: translate(-50%, -50%) scale(0.9);
}

/* Play and download wait for the first frame (see renderMediaMsg). */
.video-player-wrap .img-download-btn {
    transition: opacity 0.2s;
}

.video-player-wrap.is-loading .video-play-btn,
.video-player-wrap.is-loading .img-download-btn {
    opacity: 0;
    pointer-events: none;
}

.video-player-wrap.playing .video-play-btn {
    opacity: 0;
    pointer-events: none;
}

.video-player-wrap.playing:hover .video-play-btn {
    opacity: 1;
    pointer-events: auto;
}

.video-fs-btn {
    position: absolute;
    top: 8px;
    right: 42px;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    background: rgba(0, 0, 0, 0.55);
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    border-radius: 8px;
    border: none;
    color: #fff;
    cursor: pointer;
    z-index: 3;
}

/* Video edit (pencil) button — top-left corner (legacy) */
.video-edit-btn {
    position: absolute;
    top: 8px;
    left: 8px;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    background: rgba(0, 0, 0, 0.55);
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    border-radius: 8px;
    border: none;
    color: #fff;
    cursor: pointer;
    z-index: 3;
}

/* Video edit popup */
.video-edit-popup {
    position: absolute;
    bottom: calc(100% + 6px);
    left: 0;
    width: 240px;
    background: var(--bg-secondary);
    border-radius: 16px;
    box-shadow: 0 8px 32px rgba(0, 0, 0, 0.45), 0 0 0 1px rgba(255, 255, 255, 0.08);
    z-index: 100;
    overflow: hidden;
}

.vep-viewport {
    position: relative;
    overflow: hidden;
}

.vep-slider {
    display: flex;
    transition: transform 0.25s ease;
    will-change: transform;
}

.vep-screen {
    min-width: 100%;
    flex-shrink: 0;
    overflow-y: auto;
    scrollbar-width: thin;
}

.vep-screen::-webkit-scrollbar {
    width: 3px;
}

.vep-screen::-webkit-scrollbar-thumb {
    background: rgba(255, 255, 255, 0.15);
    border-radius: 3px;
}

.vep-header {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 12px 12px 8px;
    font-size: 13px;
    font-weight: 600;
    color: var(--text);
}

.vep-back {
    cursor: pointer;
    display: flex;
    align-items: center;
    color: var(--text-dim);
    transition: color 0.15s;
}

.vep-back:hover {
    color: var(--text);
}

.vep-divider {
    height: 1px;
    background: rgba(255, 255, 255, 0.06);
    margin: 0 12px 4px;
}

.vep-option {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 10px 12px;
    cursor: pointer;
    font-size: 13px;
    color: var(--text);
    transition: background 0.15s;
}

.vep-option:hover {
    background: rgba(255, 255, 255, 0.05);
}

.vep-value {
    color: var(--text-dim);
    display: flex;
    align-items: center;
    gap: 4px;
}

.vep-value svg {
    opacity: 0.5;
}

.vep-choice {
    padding: 10px 12px;
    cursor: pointer;
    font-size: 13px;
    color: var(--text);
    display: flex;
    justify-content: space-between;
    align-items: center;
    transition: background 0.15s;
}

.vep-choice:hover {
    background: rgba(255, 255, 255, 0.05);
}

.vep-choice.selected {
    color: var(--accent);
}

.vep-choice .vep-check {
    opacity: 0;
    transition: opacity 0.15s;
}

.vep-choice.selected .vep-check {
    opacity: 1;
}

.vep-submit-wrap {
    padding: 8px 12px 12px;
}

.vep-submit {
    width: 100%;
    padding: 10px;
    background: var(--accent);
    color: #fff;
    border: none;
    border-radius: 10px;
    font-size: 13px;
    font-weight: 600;
    cursor: pointer;
    transition: opacity 0.2s, transform 0.15s;
}

.vep-submit:hover {
    opacity: 0.9;
}

.vep-submit:active {
    transform: scale(0.97);
}

.vep-submit:disabled {
    opacity: 0.4;
    cursor: default;
    transform: none;
}

.vep-submit.hidden {
    display: none;
}

.vep-error {
    font-size: 12px;
    color: #f87171;
    padding: 0 0 8px;
    line-height: 1.4;
    max-width: 216px;
    word-wrap: break-word;
    overflow-wrap: break-word;
}

/* Video version group */
.video-version-group {
    display: flex;
    flex-direction: row;
    gap: 8px;
    align-items: flex-start;
}

/* Version column: thumbs + arrows side by side */
.video-version-col {
    display: flex;
    flex-direction: row;
    align-items: flex-start;
    gap: 4px;
}

.vv-arrow-row {
    display: flex;
    flex-direction: column;
    gap: 2px;
    margin-top: 2px;
}

.vv-arrow {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    background: rgba(255, 255, 255, 0.04);
    border: 1px solid rgba(255, 255, 255, 0.08);
    color: rgba(255, 255, 255, 0.4);
    cursor: pointer;
    border-radius: 50%;
    transition: opacity 0.2s, background 0.15s, color 0.15s;
    padding: 0;
    flex-shrink: 0;
}

.vv-arrow:hover {
    background: rgba(255, 255, 255, 0.12);
    color: #fff;
}

/* Version switching: crossfade + resize via a sizing wrapper */
.video-version-stage {
    position: relative;
    transition: width 0.4s ease, height 0.4s ease;
    overflow: hidden;
    border-radius: 12px;
    max-width: 100%;
}

.video-version-main {
    transition: opacity 0.35s ease;
}

.video-version-main.vv-hidden {
    position: absolute;
    top: 0;
    left: 0;
    opacity: 0;
    pointer-events: none;
}

/* 3D carousel container */
.video-version-thumbs {
    position: relative;
    perspective: 200px;
    min-width: 48px;
    transition: height 0.4s ease;
    overflow: hidden;
}

.video-version-thumb {
    position: absolute;
    left: 2px;
    top: 0;
    width: 44px;
    height: 34px;
    border-radius: 6px;
    overflow: hidden;
    cursor: pointer;
    border: 2px solid rgba(255, 255, 255, 0.12);
    background: #111;
    transition: transform 0.4s cubic-bezier(0.34, 1.56, 0.64, 1), opacity 0.35s ease, border-color 0.3s, box-shadow 0.3s;
    transform-style: preserve-3d;
    transform-origin: top center;
}

.video-version-thumb:hover {
    border-color: rgba(255, 255, 255, 0.35);
}

.video-version-thumb.active {
    border-color: #fff;
    box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.3), 0 2px 12px rgba(0, 0, 0, 0.5);
}

.video-version-thumb .vvt-video,
.video-version-thumb .vvt-img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    pointer-events: none;
    display: block;
}

.video-version-badge {
    position: absolute;
    bottom: 1px;
    left: 1px;
    background: rgba(0, 0, 0, 0.75);
    color: #fff;
    font-size: 8px;
    padding: 0 3px;
    border-radius: 3px;
    font-weight: 700;
    line-height: 14px;
}

.video-version-thumb .vvt-loader {
    width: 100%;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    background: linear-gradient(135deg, #1a1025, #0d1a2a);
}

.video-version-thumb .vvt-loader::after {
    content: '';
    width: 10px;
    height: 10px;
    border: 2px solid rgba(255, 255, 255, 0.2);
    border-top-color: #fff;
    border-radius: 50%;
    animation: vvt-spin 0.8s linear infinite;
}

/* Overflow "+N" indicator */
.vv-overflow {
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(255, 255, 255, 0.08) !important;
    border-color: rgba(255, 255, 255, 0.15) !important;
    cursor: pointer;
}

.vv-overflow-text {
    font-size: 11px;
    font-weight: 700;
    color: rgba(255, 255, 255, 0.6);
}

@keyframes vvt-spin {
    to {
        transform: rotate(360deg);
    }
}

/* Placeholder while video is in lightbox */
.video-lb-placeholder {
    border-radius: 12px;
    background: #111;
    margin: 6px 0;
}

/* Video lightbox */
.video-lightbox-video {
    max-width: 95vw;
    max-height: 85vh;
    background: #111;
    border-radius: 10px;
    object-fit: contain;
    display: block;
}

.video-lightbox-play {
    position: fixed;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 72px;
    height: 72px;
    border-radius: 50%;
    border: none;
    background: rgba(0, 0, 0, 0.45);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    padding-left: 4px;
    z-index: 10000;
    transition:
        opacity 0.2s,
        transform 0.15s;
}

.video-lightbox-play:active {
    transform: translate(-50%, -50%) scale(0.9);
}

/* Buffering: a spinner replaces the play button until frames arrive. */
.video-lightbox-spinner {
    position: fixed;
    top: 50%;
    left: 50%;
    width: 44px;
    height: 44px;
    margin: -22px 0 0 -22px;
    border: 3px solid rgba(255, 255, 255, 0.18);
    border-top-color: rgba(255, 255, 255, 0.85);
    border-radius: 50%;
    animation: media-gen-spin 0.8s linear infinite;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.2s;
    z-index: 10000;
}

.video-lightbox.is-buffering .video-lightbox-spinner {
    opacity: 1;
}

.video-lightbox.is-buffering .video-lightbox-play,
.video-lightbox.is-buffering.playing:hover .video-lightbox-play {
    opacity: 0;
    pointer-events: none;
}

/* When playing: hide all controls, show on hover */
.video-lightbox.playing .video-lightbox-play,
.video-lightbox.playing .lightbox-close,
.video-lightbox.playing .lightbox-download {
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.25s;
}

.video-lightbox.playing:hover .video-lightbox-play,
.video-lightbox.playing:hover .lightbox-close,
.video-lightbox.playing:hover .lightbox-download {
    opacity: 1;
    pointer-events: auto;
}

/* Loader overlay — sits on top of content, fades out when loaded */
.media-loader-overlay {
    position: absolute;
    inset: 0;
    z-index: 1;
    border-radius: 12px;
    overflow: hidden;
}

/* Generating placeholder: img-fx mosaic (static/img-fx.js) under an
   iOS-style "Generating image · 0:12" label; a spinner covers module loading. */
.media-gen-fallback,
.media-gen-fx {
    position: absolute;
    inset: 0;
    border-radius: inherit;
    overflow: hidden;
}

.has-gen-fx .media-gen-fallback {
    display: none;
}

.media-gen-pending { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; background: #0f0f0f; }
.media-gen-spinner { display: block; width: 26px; height: 26px; border: 2px solid rgba(255, 255, 255, 0.16); border-top-color: rgba(255, 255, 255, 0.75); border-radius: 50%; animation: media-gen-spin 0.8s linear infinite; }
.has-gen-info .media-gen-spinner { margin-bottom: 84px; }
.has-gen-info:not(.has-gen-fx) .media-gen-info { background: none; }
[data-theme="light"] .media-gen-pending { background: #f5f5f5; }
[data-theme="light"] .media-gen-spinner { border-color: rgba(0, 0, 0, 0.12); border-top-color: rgba(0, 0, 0, 0.6); }
@keyframes media-gen-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .media-gen-spinner, .video-lightbox-spinner { animation: none; } }

.imgfx-layer {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    display: block;
    pointer-events: none;
}

.imgfx-overlay {
    z-index: 1;
}

.media-gen-info {
    position: absolute;
    inset: 0;
    z-index: 2;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 7px;
    padding: 0 20px;
    text-align: center;
    line-height: 1.25;
    color: #fff;
    background: radial-gradient(ellipse 70% 42% at 50% 50%, rgba(10, 10, 10, 0.55), rgba(10, 10, 10, 0) 100%);
    pointer-events: none;
}

.media-gen-title {
    display: flex;
    max-width: 100%;
    font-size: 15px;
    font-weight: 600;
    white-space: pre;
}

.media-gen-label {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
}

.media-gen-time {
    flex-shrink: 0;
    font-variant-numeric: tabular-nums;
}

.media-gen-hint {
    font-size: 13px;
    opacity: 0.62;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 100%;
}

[data-theme="light"] .media-gen-info {
    color: #111;
    background: radial-gradient(ellipse 70% 42% at 50% 50%, rgba(245, 245, 245, 0.75), rgba(245, 245, 245, 0) 100%);
}

/* Dreamy gradient blur loader for video generation */
.video-dream-loader {
    position: relative;
    width: 100%;
    height: 100%;
    overflow: hidden;
    filter: blur(40px);
    background: #0a0a12;
}

.video-dream-blob {
    position: absolute;
    border-radius: 50%;
    mix-blend-mode: screen;
}

.video-dream-blob-1 {
    width: 70%;
    height: 70%;
    top: -10%;
    left: -10%;
    background: radial-gradient(circle,
            rgba(90, 50, 200, 0.8) 0%,
            transparent 70%);
    animation: dreamDrift1 8s ease-in-out infinite;
}

.video-dream-blob-2 {
    width: 60%;
    height: 60%;
    bottom: -10%;
    right: -10%;
    background: radial-gradient(circle,
            rgba(20, 140, 190, 0.7) 0%,
            transparent 70%);
    animation: dreamDrift2 10s ease-in-out infinite;
}

.video-dream-blob-3 {
    width: 50%;
    height: 50%;
    top: 30%;
    left: 30%;
    background: radial-gradient(circle,
            rgba(200, 60, 120, 0.7) 0%,
            transparent 70%);
    animation: dreamDrift3 12s ease-in-out infinite;
}

@keyframes dreamDrift1 {

    0%,
    100% {
        transform: translate(0, 0) scale(1);
    }

    33% {
        transform: translate(40%, 20%) scale(1.2);
    }

    66% {
        transform: translate(10%, 50%) scale(0.9);
    }
}

@keyframes dreamDrift2 {

    0%,
    100% {
        transform: translate(0, 0) scale(1);
    }

    33% {
        transform: translate(-30%, -20%) scale(1.1);
    }

    66% {
        transform: translate(-50%, 10%) scale(1.3);
    }
}

@keyframes dreamDrift3 {

    0%,
    100% {
        transform: translate(0, 0) scale(1);
    }

    33% {
        transform: translate(20%, -40%) scale(1.2);
    }

    66% {
        transform: translate(-30%, 20%) scale(0.8);
    }
}

/* Crossfade overlay: image loads invisibly on top of placeholder, then fades in */
.generated-img-reveal {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    border-radius: 12px;
    opacity: 0;
    transition: opacity 0.38s ease;
    display: block;
}

.generated-img-reveal.loaded {
    opacity: 1;
}

.generated-img-placeholder {
    width: 100%;
    height: 100%;
    display: block;
}

/* ── Lightbox ─────────────────────────────────────────────────────────── */
.lightbox-overlay {
    position: fixed;
    inset: 0;
    /* Match the host messenger photo viewer, above chat modals and chrome. */
    z-index: 12000;
    background: rgba(0, 0, 0, 0.92);
    display: flex;
    align-items: center;
    justify-content: center;
    opacity: 0;
    transition: opacity 0.22s ease;
    cursor: zoom-out;
}

.lightbox-overlay.visible {
    opacity: 1;
}

/* The composer normally sits above app content at z-index 10001. Hide it
   entirely while media is viewed so it cannot bleed through the lightbox. */
body.media-lightbox-open .chat-bar {
    display: none !important;
}

.lightbox-overlay img {
    max-width: 95vw;
    max-height: 95vh;
    border-radius: 10px;
    object-fit: contain;
    display: block;
    pointer-events: none;
    user-select: none;
}

.lightbox-close {
    position: fixed;
    top: 16px;
    left: 16px;
    width: 48px;
    height: 48px;
    background: rgba(255, 255, 255, 0.12);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    border: none;
    border-radius: 50%;
    color: #fff;
    font-size: 26px;
    line-height: 1;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background 0.15s;
    z-index: 10000;
}

.lightbox-close:hover {
    background: rgba(255, 255, 255, 0.22);
}

.lightbox-download {
    position: fixed;
    bottom: 24px;
    right: 24px;
    width: 48px;
    height: 48px;
    background: rgba(255, 255, 255, 0.12);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    border-radius: 50%;
    color: #fff;
    display: flex;
    align-items: center;
    justify-content: center;
    text-decoration: none;
    transition: background 0.15s;
    z-index: 10000;
}

.lightbox-download:hover {
    background: rgba(255, 255, 255, 0.22);
}

.generated-img {
    cursor: zoom-in;
}

.generated-img {
    max-width: 100%;
    max-height: 100%;
    border-radius: 12px;
    object-fit: contain;
    display: block;
}

.img-download-btn {
    position: absolute;
    top: 8px;
    right: 8px;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    background: rgba(0, 0, 0, 0.55);
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    border-radius: 8px;
    color: #fff;
    text-decoration: none;
}

.msg-meta {
    display: none;
    margin-top: 8px;
    padding-top: 6px;
    border-top: 1px solid rgba(255, 255, 255, 0.08);
    font-size: 11px;
    color: var(--text-muted);
    flex-wrap: wrap;
    gap: 4px;
}

.msg.meta-visible .msg-meta {
    display: flex;
}

.msg-meta .tag {
    display: inline-block;
    background: rgba(255, 255, 255, 0.06);
    padding: 1px 6px;
    border-radius: 3px;
    font-family: "SF Mono", Monaco, monospace;
}

.msg-files {
    margin-top: 4px;
    font-size: 11px;
    color: var(--green);
}

.msg-files span {
    display: inline-block;
    margin-right: 6px;
}

/* ── Photo thumbnails ── */
.photo-thumb {
    position: relative;
    flex-shrink: 0;
    width: 104px;
    height: 104px;
    border-radius: 14px;
    overflow: hidden;
    border: 1px solid var(--border);
}

.photo-thumb img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

.attach-remove {
    position: absolute;
    top: 2px;
    right: 2px;
    width: 18px;
    height: 18px;
    border-radius: 50%;
    background: rgba(0, 0, 0, 0.7);
    color: #fff;
    border: none;
    font-size: 12px;
    line-height: 1;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
}

.attach-remove:hover {
    background: var(--red);
}

.photo-thumb .attach-remove {
    top: 5px;
    right: 5px;
    width: 26px;
    height: 26px;
    font-size: 18px;
}

.photo-thumb.uploading::after {
    content: "";
    position: absolute;
    inset: 0;
    background: rgba(0, 0, 0, 0.4);
    border-radius: inherit;
}

.photo-thumb.uploading::before {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    width: 16px;
    height: 16px;
    margin: -8px 0 0 -8px;
    border: 2px solid rgba(255, 255, 255, 0.3);
    border-top-color: #fff;
    border-radius: 50%;
    animation: spin 0.6s linear infinite;
    z-index: 1;
}

@keyframes spin {
    to {
        transform: rotate(360deg);
    }
}

/* ── Description block attachments ── */
.desc-block-chip {
    position: relative;
    flex-shrink: 0;
    width: 88px;
    height: 88px;
    border-radius: 12px;
    background: var(--accent);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 7px;
    color: #fff;
}

.app-errors-attach-chip {
    position: relative;
    flex: 0 0 auto;
    min-width: 126px;
    height: 44px;
    padding: 0 34px 0 11px;
    border: 1px solid rgba(255, 77, 79, 0.32);
    border-radius: 12px;
    background: rgba(255, 77, 79, 0.12);
    color: #ff6b6d;
    display: flex;
    align-items: center;
    gap: 8px;
}
.app-errors-attach-icon { display: flex; flex: 0 0 auto; }
.app-errors-attach-label { color: var(--text); font-size: 13px; font-weight: 650; white-space: nowrap; }
.app-errors-attach-chip .attach-remove { top: 50%; right: 7px; transform: translateY(-50%); }

.desc-block-chip > svg {
    width: 26px;
    height: 26px;
}

.desc-block-chip > span {
    max-width: 68px !important;
    font-size: 11px;
}

.desc-block-chip .attach-remove {
    background: rgba(255, 255, 255, 0.9);
    color: #000;
    width: 22px;
    height: 22px;
    font-size: 14px;
}

.desc-block-chip .attach-remove:hover {
    background: #fff;
}

.msg-attachment-list {
    display: flex;
    flex-direction: column;
    gap: 6px;
    margin: 5px 0 7px;
}

.msg-attachment-card {
    appearance: none;
    border: 1px solid var(--border);
    background: rgba(127, 127, 127, 0.12);
    color: inherit;
    border-radius: 12px;
    min-width: 190px;
    max-width: 100%;
    padding: 10px 12px;
    display: flex;
    align-items: center;
    gap: 10px;
    text-align: left;
    cursor: pointer;
}

.msg-attachment-card:hover { background: rgba(127, 127, 127, 0.2); }
.msg-attachment-icon { flex: 0 0 auto; display: flex; color: var(--accent); }
.msg-attachment-copy { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.msg-attachment-title { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 600; }
.msg-attachment-subtitle { color: var(--text-muted); font-size: 11px; }

/* ── Element Picker Button ── */
.pick-element-btn {
    display: none;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    border-radius: 8px;
    border: none;
    background: none;
    color: var(--text-muted);
    cursor: pointer;
    padding: 0;
    flex-shrink: 0;
    transition: all 0.15s;
}

/* ── Annotate Screenshot Overlay ── */
.annotate-overlay {
    position: fixed;
    inset: 0;
    z-index: 10010;
    background: var(--bg-body, #000);
    display: flex;
    flex-direction: column;
}

.annotate-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 10px 16px;
    background: var(--bg-primary, #111);
    border-bottom: 1px solid var(--border, rgba(255, 255, 255, 0.1));
    flex-shrink: 0;
    font-size: 15px;
    font-weight: 600;
    color: var(--text, #fff);
}

.annotate-header-actions {
    display: flex;
    align-items: center;
    gap: 6px;
}

.annotate-tools-seg {
    display: flex;
    background: rgba(255, 255, 255, 0.08);
    border-radius: 8px;
    padding: 2px;
    position: relative;
}

.annotate-tool-btn {
    padding: 5px 10px;
    border-radius: 6px;
    border: none;
    background: none;
    color: var(--text-muted, #999);
    font-size: 12px;
    font-family: inherit;
    font-weight: 500;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    position: relative;
    z-index: 1;
    transition: color 0.15s;
}

.annotate-tool-btn.active {
    color: #fff;
}

.annotate-seg-indicator {
    position: absolute;
    top: 2px;
    height: calc(100% - 4px);
    background: var(--accent, #007aff);
    border-radius: 6px;
    transition: left 0.2s cubic-bezier(.4, 0, .2, 1), width 0.2s cubic-bezier(.4, 0, .2, 1);
    z-index: 0;
}

.annotate-separator {
    width: 1px;
    height: 20px;
    background: var(--border, rgba(255, 255, 255, 0.1));
    margin: 0 4px;
}

.annotate-color-btn {
    width: 22px;
    height: 22px;
    border-radius: 50%;
    border: 2px solid transparent;
    cursor: pointer;
    padding: 0;
    transition: border-color 0.1s;
}

.annotate-color-btn[data-color="#ffffff"] {
    border-color: rgba(255, 255, 255, 0.25);
}

.annotate-color-btn.active {
    border-color: #fff;
    box-shadow: 0 0 0 2px var(--accent, #007aff);
}

.annotate-color-btn:hover {
    border-color: rgba(255, 255, 255, 0.5);
}

.annotate-icon-btn {
    background: none;
    border: none;
    color: var(--text-muted, #999);
    cursor: pointer;
    padding: 5px;
    border-radius: 6px;
    display: flex;
    align-items: center;
}

.annotate-icon-btn:hover {
    color: var(--text, #fff);
    background: rgba(255, 255, 255, 0.08);
}

.annotate-action-btn {
    padding: 5px 12px;
    border-radius: 6px;
    border: none;
    background: var(--accent, #007aff);
    color: #fff;
    font-size: 12px;
    font-family: inherit;
    font-weight: 600;
    cursor: pointer;
}

.annotate-action-btn:hover {
    opacity: 0.85;
}

.annotate-close {
    background: none;
    border: none;
    color: var(--text-muted, #999);
    font-size: 22px;
    cursor: pointer;
    padding: 0 4px;
    margin-left: 8px;
}

.annotate-body {
    flex: 1;
    overflow: auto;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 16px;
}

#annotateCanvas {
    max-width: 100%;
    max-height: 100%;
    border-radius: 8px;
    cursor: crosshair;
}

.annotate-footer {
    padding: 12px 16px;
    display: flex;
    justify-content: center;
    flex-shrink: 0;
    border-top: 1px solid var(--border, rgba(255, 255, 255, 0.1));
}

.annotate-attach-btn {
    padding: 10px 32px;
    border-radius: 10px;
    border: none;
    background: var(--accent, #007aff);
    color: #fff;
    font-size: 15px;
    font-weight: 600;
    font-family: inherit;
    cursor: pointer;
}

.annotate-attach-btn:hover {
    opacity: 0.85;
}

.picker-banner {
    display: flex;
    align-items: center;
    gap: 8px;
    position: fixed;
    top: 0;
    right: 0;
    left: var(--chat-w, 600px);
    z-index: 900;
    padding: 6px 16px;
    background: #ef4444;
    color: #fff;
    font-size: 13px;
    font-weight: 500;
}

.picker-banner span {
    flex: 1;
}

.picker-banner button {
    background: none;
    border: none;
    color: rgba(255, 255, 255, 0.8);
    font-size: 18px;
    cursor: pointer;
    padding: 0 4px;
    line-height: 1;
}

.picker-banner button:hover {
    color: #fff;
}

@media (max-width: 799px) {
    .picker-banner {
        left: 0;
    }
}

body.chat-collapsed .picker-banner {
    left: 0;
}

body.app-active .pick-element-btn {
    display: flex;
}

.pick-element-btn:hover {
    color: var(--text);
    background: rgba(255, 255, 255, 0.08);
}

.pick-element-btn.active {
    color: var(--accent);
    background: rgba(0, 122, 255, 0.15);
}

[data-theme="light"] .pick-element-btn:hover {
    background: rgba(0, 0, 0, 0.06);
}

[data-theme="light"] .pick-element-btn.active {
    background: rgba(0, 122, 255, 0.1);
}

.element-attach-chip {
    position: relative;
    flex-shrink: 0;
    display: flex;
    align-items: center;
    gap: 6px;
    height: 44px;
    padding: 0 28px 0 10px;
    border-radius: 8px;
    background: rgba(99, 102, 241, 0.15);
    border: 1px solid rgba(99, 102, 241, 0.3);
    color: #a5b4fc;
}

.element-attach-label {
    font-size: 12px;
    max-width: 120px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* UI Element card in messages */
.ui-element-card {
    margin-top: 8px;
    padding: 10px 12px;
    border-radius: 8px;
    background: rgba(255, 255, 255, 0.12);
    border: 1px solid rgba(255, 255, 255, 0.18);
    font-size: 12px;
    line-height: 1.4;
}

.ui-el-tag {
    display: inline-block;
    padding: 1px 8px;
    border-radius: 4px;
    background: rgba(255, 255, 255, 0.2);
    color: #fff;
    font-size: 11px;
    font-weight: 600;
    font-family: 'SF Mono', Monaco, Menlo, monospace;
    margin-bottom: 6px;
}

.ui-el-path {
    color: rgba(255, 255, 255, 0.55);
    font-size: 11px;
    font-family: 'SF Mono', Monaco, Menlo, monospace;
    margin-bottom: 4px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.ui-el-text {
    color: rgba(255, 255, 255, 0.85);
    font-size: 12px;
}

[data-theme="light"] .ui-element-card {
    background: rgba(0, 0, 0, 0.06);
    border-color: rgba(0, 0, 0, 0.1);
}

[data-theme="light"] .ui-el-tag {
    background: rgba(0, 0, 0, 0.1);
    color: rgba(0, 0, 0, 0.7);
}

[data-theme="light"] .ui-el-path {
    color: rgba(0, 0, 0, 0.4);
}

[data-theme="light"] .ui-el-text {
    color: rgba(0, 0, 0, 0.6);
}

/* UI Element card inside user bubble (blue) — white text */
.msg.user .ui-element-card {
    background: rgba(255, 255, 255, 0.18);
    border-color: rgba(255, 255, 255, 0.25);
}

.msg.user .ui-el-tag {
    background: rgba(255, 255, 255, 0.25);
    color: #fff;
}

.msg.user .ui-el-path {
    color: rgba(255, 255, 255, 0.6);
}

.msg.user .ui-el-text {
    color: rgba(255, 255, 255, 0.9);
}

.element-attach-chip .attach-remove {
    position: absolute;
    top: -4px;
    right: -4px;
    background: rgba(255, 255, 255, 0.9);
    color: #000;
    width: 16px;
    height: 16px;
    font-size: 10px;
    border-radius: 50%;
    border: none;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    line-height: 1;
}

/* ── Log Button ── */
.log-btn {
    display: none;
    margin-top: 6px;
    padding: 2px 8px;
    background: rgba(255, 255, 255, 0.06);
    border: 1px solid var(--border);
    border-radius: 4px;
    color: var(--text-muted);
    font-size: 11px;
    cursor: pointer;
    transition: all 0.15s;
}

.msg.meta-visible .log-btn {
    display: inline-block;
}

.log-btn:hover {
    color: var(--accent-light);
    border-color: var(--accent);
}

.btn-logs {
    color: var(--accent-light);
    border-color: var(--accent);
}

.btn-logs:hover {
    background: var(--accent);
    color: #fff;
}

/* ── Thinking ── */
/* ── Thinking cursor indicator ── */
/* Match .msg.assistant font-size so the 1.15em cursor stays the exact same
   height when the bubble transitions from thinking → assistant. Otherwise users see
   a subtle size bump when the first text_delta lands. */
.msg.thinking {
    display: flex;
    align-items: center;
    justify-content: flex-start;
    background: transparent;
    align-self: flex-start;
    padding: 8px 4px;
    font-size: 15px;
}

@media (min-width: 900px) {
    .msg.thinking {
        font-size: 16px;
    }
}

@keyframes cursorBlink {

    0%,
    100% {
        opacity: 1;
    }

    50% {
        opacity: 0;
    }
}

@keyframes cursorPulse {

    0%,
    100% {
        opacity: 1;
    }

    50% {
        opacity: 0.25;
    }
}

.fork-cursor {
    /* OVERLAY cursor: one persistent element floating above the text, GLIDING
       to the caret via a transform transition — never re-inserted inline into
       the re-rendered markdown (removal + re-add restarted its animation and
       flashed every keystroke). */
    position: absolute;
    left: 0;
    top: 0;
    width: 8px;
    height: 19px;
    border-radius: 3px;
    background: var(--accent);
    pointer-events: none;
    will-change: transform;
    /* Snappy micro-glide: just enough to smooth the hop between characters,
       fast enough that the cursor is always ON the caret, never trailing it.
       No pulse/blink — a moving cursor should stay fully bright. */
    transition: transform 0.03s linear, height 0.03s linear;
}

/* Dot-to-bubble entrance — disabled, cursor transitions to text directly */
.msg.assistant.from-dot {}

/* ── Reasoning action row ── */
/* Persisted "Thinking…/Searching the web…" status that finalizes in place to
   "Thought · 5s" and stays above the answer. Active = spinner + pulsing label;
   done = static icon + steady label. */
.msg.reasoning-msg {
    background: none;
    align-self: flex-start;
    text-align: left;
    width: 100%;
    max-width: 100%;
    padding: 3px 0;
    margin: 0;
}

/* Tighten the gap between the finished "Thought · …" row and the answer that
   follows it (the .messages flex gap is 12px — pull the next msg up). */
.msg.reasoning-msg + .msg {
    margin-top: -8px;
}

.reasoning-row {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    font-size: 13px;
    line-height: 1.3;
    color: var(--text-muted);
}

.reasoning-row .reasoning-ic {
    width: 14px;
    height: 14px;
    flex: 0 0 auto;
    opacity: 0.75;
}

.reasoning-active .reasoning-label {
    animation: searchPulse 1.4s ease-in-out infinite;
}

.reasoning-spinner {
    width: 12px;
    height: 12px;
    flex: 0 0 auto;
    border: 2px solid var(--text-muted);
    border-top-color: transparent;
    border-radius: 50%;
    display: inline-block;
    animation: reasoningSpin 0.7s linear infinite;
}

/* Favicons of the sites a web search consulted — appended to the
   "Searching the web…" row live, kept in the finalized row. */
.reasoning-favs {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    margin-left: 4px;
}

.reasoning-fav {
    width: 16px;
    height: 16px;
    border-radius: 4px;
    display: block;
    background: rgba(120, 120, 128, 0.15);
}

.reasoning-fav.fav-pending {
    display: none;
}

.reasoning-fav.fav-in {
    animation: favIn 0.35s cubic-bezier(.34, 1.4, .64, 1);
}

@keyframes favIn {
    from {
        opacity: 0;
        transform: scale(0.4);
    }

    to {
        opacity: 1;
        transform: scale(1);
    }
}

@keyframes reasoningSpin {
    to {
        transform: rotate(360deg);
    }
}

/* Animated equalizer icon for the "Listening…" transcription status */
.listening-eq {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 2px;
    width: 14px;
    height: 14px;
    flex: 0 0 auto;
    color: var(--text-muted);
}

.listening-eq span {
    width: 2px;
    height: 4px;
    border-radius: 1px;
    background: currentColor;
    animation: listeningEq 1s ease-in-out infinite;
}

.listening-eq span:nth-child(1) {
    animation-delay: 0s;
}
.listening-eq span:nth-child(2) {
    animation-delay: 0.18s;
}
.listening-eq span:nth-child(3) {
    animation-delay: 0.36s;
}
.listening-eq span:nth-child(4) {
    animation-delay: 0.12s;
}

@keyframes listeningEq {
    0%,
    100% {
        height: 3px;
    }
    50% {
        height: 13px;
    }
}

@media (min-width: 900px) {
    .reasoning-row {
        font-size: 13.5px;
    }
}

.searching-status {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 13px;
    color: var(--text-muted);
    padding: 4px 0;
    animation: searchPulse 1.4s ease-in-out infinite;
}

.msg.assistant.bubble-loading .msg-content {
    color: var(--text);
    min-height: 1.4em;
}

@keyframes typingDots {
    0% {
        content: "";
    }

    25% {
        content: ".";
    }

    50% {
        content: "..";
    }

    75% {
        content: "...";
    }
}

.searching-status span {
    animation: searchPulse 1.4s ease-in-out infinite;
}

@keyframes searchPulse {

    0%,
    100% {
        opacity: 0.5;
    }

    50% {
        opacity: 1;
    }
}

/* ── Progress ── */
.msg.progress-msg {
    background: var(--bg-tertiary);
    align-self: flex-start;
    border-bottom-left-radius: 4px;
    padding: 12px 16px;
    width: 80%;
    max-width: 80%;
    min-width: 220px;
    border: 1px solid transparent;
    cursor: pointer;
}

.msg.progress-done {
    cursor: pointer;
}

.progress-container {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.progress-queue-container .progress-info {
    justify-content: flex-start;
}

.progress-queue-dot {
    width: 7px;
    height: 7px;
    flex: 0 0 7px;
    border-radius: 50%;
    background: var(--text-dim);
    opacity: 0.7;
}

.progress-queued {
    cursor: default !important;
}

/* Keep waiting builds together below all replies, including streamed messages.
   Equal order preserves their queue order; starting a build removes this class. */
.messages > .progress-queued {
    order: 1;
}

.progress-queued .progress-text {
    animation: none;
    background: none;
    -webkit-background-clip: unset;
    -webkit-text-fill-color: unset;
    background-clip: unset;
    color: var(--text-dim);
}

.progress-bar-row {
    display: flex;
    align-items: center;
    gap: 10px;
}

.progress-bar-row .progress-bar-track {
    flex: 1;
}

.progress-cancel-btn {
    width: 24px;
    height: 24px;
    border: none;
    border-radius: 50%;
    background: var(--bg-hover, rgba(255, 255, 255, 0.1));
    color: var(--text-dim);
    font-size: 16px;
    line-height: 24px;
    text-align: center;
    cursor: pointer;
    padding: 0;
    flex-shrink: 0;
    transition: background 0.15s, color 0.15s;
}

.progress-cancel-btn:hover {
    background: rgba(255, 80, 80, 0.2);
    color: #ff5050;
}

.progress-bar-track {
    width: 100%;
    height: 6px;
    background: rgba(255, 255, 255, 0.08);
    border-radius: 3px;
    overflow: hidden;
}

.progress-bar-fill {
    height: 100%;
    background: var(--accent);
    border-radius: 3px;
    /* JS drives a fractional width on every animation frame. */
    will-change: width;
    transform: translateZ(0);
}

.progress-info {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
}

.progress-text {
    font-size: 13px;
    color: var(--text-dim);
    background: linear-gradient(90deg,
            var(--text-dim),
            var(--accent-light),
            var(--text-dim));
    background-size: 200% 100%;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    background-clip: text;
    animation: thinking-shimmer 2s ease-in-out infinite;
}

.progress-percent {
    font-size: 13px;
    font-weight: 600;
    color: var(--text);
    font-variant-numeric: tabular-nums;
    min-width: 36px;
    text-align: right;
}

/* Right cluster of the progress row: generating-model label + percent. */
.progress-right {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-shrink: 0;
}

.progress-model {
    font-size: 11px;
    font-weight: 500;
    color: var(--text-dim);
    white-space: nowrap;
}

.progress-done .progress-text {
    animation: none;
    background: none;
    -webkit-background-clip: unset;
    -webkit-text-fill-color: unset;
    background-clip: unset;
    color: var(--accent-light);
}

.progress-done .progress-percent {
    color: var(--accent-light);
}

.app-done-simple {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 13px;
    font-weight: 500;
    color: var(--success, #34c759);
    cursor: pointer;
}

.app-done-simple:hover {
    opacity: 0.7;
}

/* ── App Done Card ── */
.app-done-card {
    display: flex;
    align-items: center;
    gap: 12px;
}

.app-done-icon-wrap {
    flex-shrink: 0;
    width: 44px;
    height: 44px;
    border-radius: 12px;
    overflow: hidden;
}

.app-done-icon-img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.app-done-icon-placeholder {
    width: 100%;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 20px;
    font-weight: 600;
    color: #fff;
    border-radius: 12px;
}

.app-done-info {
    flex: 1;
    min-width: 0;
}

.app-done-name {
    font-size: 14px;
    font-weight: 600;
    color: var(--text);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.app-done-subtitle {
    font-size: 12px;
    color: var(--text-dim);
    margin-top: 2px;
}

/* "Model · N tokens" line under the app name on the build-ready card. */
.app-done-meta {
    font-size: 11px;
    color: var(--text-muted);
    margin-top: 3px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.app-done-arrow {
    flex-shrink: 0;
    color: var(--text-dim);
    display: flex;
    align-items: center;
}

/* ── Task Steps ── */
.msg.task-list {
    background: var(--bg-tertiary);
    align-self: flex-start;
    border-bottom-left-radius: 4px;
    padding: 12px 16px;
    max-width: 90%;
}

.task-list-steps {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.task-step {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 13px;
    line-height: 1.4;
    transition: opacity 0.2s;
}

.task-step-icon {
    width: 18px;
    height: 18px;
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    font-size: 10px;
}

.task-step.pending .task-step-icon {
    border: 2px solid var(--text-muted);
    color: transparent;
}

.task-step.in_progress .task-step-icon {
    border: 2px solid var(--accent);
    color: transparent;
    animation: pulse-border 1.2s ease-in-out infinite;
}

.task-step.completed .task-step-icon {
    background: var(--green);
    color: #fff;
    border: none;
}

.task-step.error .task-step-icon {
    background: var(--red);
    color: #fff;
    border: none;
}

.task-step.completed .task-step-text {
    color: var(--text-dim);
}

.task-step.pending .task-step-text {
    color: var(--text-muted);
}

.task-step.in_progress .task-step-text {
    color: var(--text);
}

.task-step.error .task-step-text {
    color: var(--red);
}

@keyframes pulse-border {

    0%,
    100% {
        border-color: var(--accent);
    }

    50% {
        border-color: var(--accent-light);
    }
}

/* ── Responsive: narrow screens ── */
@media (max-width: 600px) {
    .chat-input {
        flex: 1 1 0;
        min-width: 0;
    }

    .public-profile-stats {
        gap: 4px;
    }

    .public-profile-stat {
        padding: 4px 6px;
    }

    .public-profile-stat-num {
        font-size: 14px;
    }

    .public-profile-stat-label {
        font-size: 7px;
    }
}

/* Personal chats occupy the same page, content column and composer as agents. */
.direct-chat-page { display: none; flex: 1; min-height: 0; flex-direction: column; }
body.direct-chat-open #chatPanel > :not(.direct-chat-page):not(.chat-right-gutter),
body.direct-chat-open #chatBar,
body.direct-chat-open #chatMore { display: none !important; }
body.direct-chat-open .direct-chat-page.open { display: flex; }
body:not(.direct-chat-open) #dcBar { display: none !important; }
/* Keep text, media and attachment controls above the page's close gutter. */
#dcMessages { z-index: 2; }
body.direct-chat-open .dc-header { display: block !important; max-width: calc(100% - 144px); }
.dc-header .chat-context-btn { max-width: 100%; }
.dc-header .chat-context-icon { position: relative; }
.dc-avatar { width: 20px; height: 20px; border-radius: 50%; object-fit: cover; }
.dc-avatar-placeholder { display: flex; align-items: center; justify-content: center; background: var(--accent); color: #fff; font-size: 12px; font-weight: 600; }
.dc-partner-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dc-actions-menu { position: absolute; top: calc(100% + 8px); right: 0; z-index: 5; min-width: 230px; padding: 6px; background: var(--bg-secondary); border: 1px solid var(--border); border-radius: 14px; box-shadow: 0 4px 12px rgba(0,0,0,.18); }
.dc-actions-menu[hidden] { display: none; }
#dcSendBtn:disabled { opacity: .4; cursor: default; }
@media (min-width: 800px) { #dcBarRight { display: none; } }
@media (max-width: 899px) {
    .direct-chat-page .dc-actions { display: block; position: absolute; top: 10px; right: 10px; z-index: 1004; }
}

.dc-photo-preview {
    display: flex;
    align-items: flex-start;
    gap: 6px;
    width: 100%;
    min-width: 0;
    padding: 4px 0 10px;
    box-sizing: border-box;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scrollbar-width: none;
}

.dc-photo-preview:empty {
    display: none;
}

.dc-photo-preview::-webkit-scrollbar {
    display: none;
}

.dc-photo-thumb-wrap {
    position: relative;
    display: inline-block;
}

.dc-photo-thumb {
    width: 56px;
    height: 56px;
    border-radius: 8px;
    object-fit: cover;
}

.dc-photo-thumb-remove {
    position: absolute;
    top: -5px;
    right: -5px;
    background: rgba(0, 0, 0, 0.65);
    border: none;
    color: #fff;
    border-radius: 50%;
    width: 18px;
    height: 18px;
    font-size: 12px;
    line-height: 1;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
}

.dc-file-thumb {
    position: relative; height: 44px; max-width: 190px; padding: 0 28px 0 10px;
    display: flex; align-items: center; gap: 7px; border-radius: 8px;
    background: var(--bg-secondary); border: 1px solid var(--border); font-size: 12px;
}
.dc-file-thumb span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ── Chat header bell button ──
   Hidden everywhere now — desktop has #dashboardNotifBtn on the home page that
   carries the unread state and opens the same notifs panel, so the in-chat
   bell duplicates that affordance. Mobile never showed it. JS still toggles
   .has-unread on the (hidden) element; that's harmless. The button is left
   in the DOM so future callers (e.g. an embed/standalone chat layout) can
   re-enable it with a targeted rule rather than a markup change. */
.chat-bell-btn {
    display: none;
    width: 36px;
    height: 36px;
    border-radius: 10px;
    border: none;
    background: transparent;
    color: var(--text-dim);
    cursor: pointer;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    position: relative;
    padding: 0;
    margin-left: auto;
    transition:
        background 0.15s,
        color 0.15s;
}

.chat-bell-btn:hover {
    background: rgba(255, 255, 255, 0.08);
    color: var(--text);
}

.chat-bell-btn.has-unread {
    color: #ef4444;
}

.chat-bell-badge {
    display: none;
    position: absolute;
    top: 6px;
    right: 6px;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: #ef4444;
}

.chat-bell-btn.has-unread .chat-bell-badge {
    display: block;
}

/* ── Notifications section panel ──
   Lives inside .desktop, layered like .profile-inline-panel. Visibility is
   gated by .desktop.notifs-open. Chat panel stays untouched, so chat & notifs
   coexist side-by-side on wide screens. */
/* ── Generic section panel ──
   Shared chrome for any "page" rendered inside .desktop. Mirrors the
   .profile-inline-panel layout so all sections (notifications, profile,
   future ones) align identically. Each section binds visibility via
   .desktop.<id>-open #<panelId> { display: block } below. */
.section-panel {
    display: none;
    position: absolute;
    inset: 0;
    z-index: 50;
    overflow-y: auto;
    overflow-x: hidden;
    scrollbar-width: thin;
    scrollbar-color: rgba(255, 255, 255, 0.1) transparent;
    padding: 6px 0 calc(var(--chat-h) + 32px);
}

.section-panel-content {
    margin: 0;
}

.section-panel-title {
    font-size: 22px;
    font-weight: 700;
    color: var(--text);
    letter-spacing: -0.3px;
    /* Left padding clears the global back-btn (top:10px left:10px, 36px wide)
       on mobile; matches the chat-bar margin on desktop. */
    padding: 16px 16px 14px 60px;
}

.section-panel-body {
    padding: 0 16px 90px;
}

@media (min-width: 900px) {

    /* Center the 800px content column in the desktop area (sidebar→right edge),
       exactly like the app grid (.desktop-icons) and .chat-bar — all three
       center within that same post-sidebar box, so the column lines up across
       the dashboard, chat and section views. No horizontal padding: the panel
       fills the desktop box (inset:0) just like .desktop-panels, and margin:0
       auto on the content does the centering. The clickable right gutter is
       rendered separately via position:fixed — see .section-right-gutter. */
    .section-panel {
        box-sizing: border-box;
    }

    .section-panel-content {
        max-width: 800px;
        margin: 0 auto;
    }

    /* Wide-screen title — bigger, with the right-gutter X on the right edge
       there's no back-btn to clear, so symmetrical horizontal padding. */
    .section-panel-title {
        font-size: 28px;
        padding: 16px 34px 18px;
    }
}

/* Right gutter positions the explicit X at the viewport edge. It is not a
   click-away target: section pages close only through Back/X. */
.section-right-gutter {
    display: none;
}

@media (min-width: 900px) {
    .section-right-gutter {
        position: fixed;
        top: 0;
        right: 0;
        bottom: 0;
        /* The content column is centered in the desktop box, so its right edge
           sits at 50vw + sidebar-w/2 + 400px. Start the gutter there (subtract
           the extra sidebar-w/2 vs. a plain viewport-centered column) so it
           covers only the empty space and never overlaps the column. */
        width: max(0px, calc(50vw - var(--sidebar-w) / 2 - 400px));
        pointer-events: none;
        z-index: 51;
    }

    /* X lives inside the gutter — anchored top-right. Inherits visual style
       from .home-close-hint, overrides its fixed positioning + display:none
       (the .home-close-hint base rule sits later in the file with the same
       specificity, so we !important the bits we need). */
    .section-right-gutter-x {
        position: absolute !important;
        top: 20px;
        right: 24px;
        display: flex !important;
        pointer-events: auto;
    }

    .section-right-gutter-x:hover {
        transform: scale(1.2);
        background: rgba(255, 255, 255, 0.18);
        color: #fff;
    }

    [data-theme="light"] .section-right-gutter-x:hover {
        background: rgba(0, 0, 0, 0.1);
        color: rgba(0, 0, 0, 0.6);
    }
}

/* Whatever section is open, the shared shell + its right gutter become
   visible. Per-section state lives entirely in JS — CSS only cares that
   "some" section is open. */
.desktop.section-open #sectionPanel {
    display: block;
}

.desktop.notifs-open #sectionPanel {
    background: #000;
}

[data-theme="light"] .desktop.notifs-open #sectionPanel {
    background: #fff;
}

@media (min-width: 900px) {
    .desktop.section-open #sectionRightGutter {
        display: block;
    }

    /* Section owns its own X — hide the global one so they don't stack…
       …UNLESS something layered on top (chat / PageStack) covers the gutter,
       in which case the global X is the only way to close the top layer. */
    .desktop.section-open~.home-close-hint {
        display: none !important;
    }

    /* The section's gutter X is hidden in app-active mode (so it can't steal
       clicks from the app), so when a section IS open over an active app the
       global X is the only close affordance — surface it. Same for the other
       cases where another layer (chat, pagestack, sidebar chat) sits
       on top of the section and covers its gutter. */
    body.app-active .desktop.section-open~.home-close-hint,
    body.chat-open .desktop.section-open~.home-close-hint,
    body.page-stack-open .desktop.section-open~.home-close-hint,
    body.sidebar-chat-open .desktop.section-open~.home-close-hint {
        display: flex !important;
    }

    /* But: when an app is active AND no actual overlay layer is on top of it
       (no chat, no page-stack, no sidebar chat), the section-open
       class is just leftover state from the section the user navigated FROM
       (e.g. opened an app from another user's /username profile). The app is
       on top — its own toolbar X is the close affordance. The global X must
       be hidden so it doesn't sit on top of the app's X (z-index:1200 vs the
       toolbar's ~20) and steal its clicks/hovers. */
    body.app-active:not(.chat-open):not(.page-stack-open):not(.sidebar-chat-open) .home-close-hint {
        display: none !important;
    }

    /* In app-active mode the app's own toolbar X (top-right) is the close
       affordance — the global #homeCloseHint stays hidden (per the rule
       above) so the two X's don't stack. The section's own right-gutter X
       is also hidden via `body.app-active #sectionRightGutter>...` near the
       top of the file, so the gutter can't steal clicks from the app. */
}

/* Mute the dashboard chrome while a section is the active view. */
.desktop.section-open .desktop-tabs,
.desktop.section-open .desktop-panels {
    opacity: 0;
    pointer-events: none;
}

/* ── Instagram-style notification items ── */
.notif-item {
    /* Tight horizontal rhythm: avatar, multi-line text block, contextual right slot. */
    padding: 8px 16px;
    font-size: 14px;
    color: var(--text);
    display: flex;
    align-items: center;
    gap: 12px;
    line-height: 1.35;
}

.notif-item.unread {
    background: rgba(0, 122, 255, 0.06);
}

.notif-clickable {
    cursor: pointer;
}

.notif-item.notif-clickable:hover {
    background: rgba(255, 255, 255, 0.04);
}

[data-theme="light"] .notif-item.notif-clickable:hover {
    background: rgba(0, 0, 0, 0.04);
}

.notif-item .notif-time {
    display: none;
}

/* Avatar: round 44px (Instagram is 40-48). */
.notif-avatar {
    width: 44px;
    height: 44px;
    border-radius: 50%;
    flex-shrink: 0;
    object-fit: cover;
}

.notif-avatar-placeholder {
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 14px;
    font-weight: 600;
    color: var(--text);
    background: var(--hover-overlay-strong);
}

/* Text column. Inline flow — name + verb + target on a single line (truncated if long).
   Date is conveyed by the section header above (Today / This week / Earlier). */
.notif-body {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.notif-name {
    font-size: 14px;
    font-weight: 600;
    color: var(--text);
    display: inline;
}

.notif-actor-link {
    color: var(--text);
    text-decoration: none;
}

.notif-actor-link:hover,
.notif-actor-link:focus-visible {
    color: var(--text);
    text-decoration: underline;
}

.notif-username {
    font-size: 13px;
    color: var(--text-muted);
    display: inline;
}

.notif-desc {
    font-size: 14px;
    color: var(--text);
    display: inline;
}

/* Per-event time hidden — date is grouped via .notif-section-title (Today / This week / Earlier). */
.notif-time-inline {
    display: none;
}

.notif-follow,
.notif-publish {
    padding: 8px 16px;
}

/* Follow-back button on the right — solid blue pill, compact. */
.notif-follow-btn {
    flex-shrink: 0;
    padding: 7px 16px;
    font-size: 13px;
    font-weight: 600;
    font-family: inherit;
    border: none;
    border-radius: 8px;
    background-color: var(--accent, #007aff);
    color: #fff;
    cursor: pointer;
    transition: opacity 0.15s;
}

.notif-follow-btn:hover {
    opacity: 0.85;
}

.notif-follow-btn.following,
.notif-follow-btn:disabled {
    background-color: var(--hover-overlay-strong);
    color: var(--text-dim);
    cursor: default;
    opacity: 1;
}

/* App-thumbnail on the right (for app_published) — square with rounded corners,
   matches Instagram's media thumbnail. */
.notif-app-icon {
    width: 44px;
    height: 44px;
    border-radius: 10px;
    flex-shrink: 0;
    object-fit: cover;
}

.notif-app-icon-letter {
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 15px;
    font-weight: 700;
    color: #fff;
}

@media (max-width: 799px) {

    /* When app is open: chat stays mounted but slid above the viewport (see rules
       above). Using transform instead of display:none lets the panel animate in. */
    body.app-active .chat {
        display: flex !important;
        transform: translateY(-100%);
        pointer-events: none;
    }

    /* When chat is open: slide the panel into view. */
    body.app-active.chat-open .chat {
        transform: translateY(0);
        pointer-events: auto;
    }
}

/* ── Mobile app notif button (outside chatPanel, fixed bottom-left) ── */
.mobile-app-notif-btn {
    display: none;
    position: fixed;
    bottom: 16px;
    left: 16px;
    z-index: 998;
    width: 40px;
    height: 40px;
    border-radius: 50%;
    border: 1px solid rgba(255, 255, 255, 0.12);
    background: rgba(20, 20, 20, 0.65);
    backdrop-filter: blur(20px);
    -webkit-backdrop-filter: blur(20px);
    color: #999;
    cursor: pointer;
    align-items: center;
    justify-content: center;
    padding: 0;
    box-shadow: 0 2px 12px rgba(0, 0, 0, 0.3);
}

.mobile-app-notif-badge {
    position: absolute;
    top: 2px;
    right: 2px;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: #ef4444;
    display: none;
}

.mobile-app-notif-btn.has-unread .mobile-app-notif-badge {
    display: block;
}

/* mobile-app-notif-btn removed — notifications accessible via chat header */

/* ── Mobile notification bell button ── */
.mobile-notif-btn {
    display: none;
    width: 44px;
    height: 44px;
    border-radius: 50%;
    border: 1px solid rgba(255, 255, 255, 0.12);
    background: rgba(30, 30, 30, 0.55);
    backdrop-filter: blur(20px);
    -webkit-backdrop-filter: blur(20px);
    color: rgba(255, 255, 255, 0.75);
    cursor: pointer;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    position: relative;
    padding: 0;
    box-shadow: 0 2px 52px rgba(0, 0, 0, 0.2);
}

.mobile-notif-btn.has-unread {
    color: #ef4444;
}

@media (max-width: 799px) {
    .mobile-notif-btn {
        display: flex;
    }
}

.mobile-notif-badge {
    display: none;
    position: absolute;
    top: 6px;
    right: 6px;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: #ef4444;
}

.mobile-notif-btn.has-unread .mobile-notif-badge {
    display: block;
}

/* ── Mobile notification modal ── */
.mobile-notif-backdrop {
    display: none;
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.55);
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    z-index: 2000;
}

.mobile-notif-backdrop.open {
    display: block;
}

.mobile-notif-modal {
    display: none;
    position: fixed;
    inset: 0;
    z-index: 2001;
    background: var(--bg-body, #000);
    flex-direction: column;
    overflow: hidden;
}

.mobile-notif-modal.open {
    display: flex;
}

.mobile-notif-header {
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 16px 20px;
    font-size: 17px;
    font-weight: 700;
    color: var(--text, #fff);
    flex-shrink: 0;
    position: relative;
}

.mobile-notif-close {
    position: absolute;
    right: 16px;
    top: 50%;
    transform: translateY(-50%);
    background: none;
    border: none;
    color: var(--text-muted, #999);
    font-size: 24px;
    cursor: pointer;
    padding: 4px;
    line-height: 1;
}

.mobile-notif-list {
    flex: 1;
    overflow-y: auto;
    padding: 0 0 calc(80px + env(safe-area-inset-bottom));
}

/* Date-bucket header (Today / This week / Earlier). */
.notif-section-title {
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.4px;
    color: var(--text-muted);
    padding: 16px 16px 6px;
}

.notif-section-title:first-child {
    padding-top: 8px;
}

.notif-follow-btn:disabled {
    opacity: 0.5;
    cursor: default;
}

.notif-follow-btn.following {
    background: rgba(255, 255, 255, 0.12);
    color: rgba(255, 255, 255, 0.7);
}

/* ── Error Card ── */
.error-msg {
    padding: 0 !important;
}

.error-card {
    position: relative;
    background: rgba(239, 68, 68, 0.08);
    border: 1px solid rgba(239, 68, 68, 0.25);
    border-radius: 12px;
    padding: 12px 16px;
    max-width: 420px;
}

.error-notice-card {
    display: flex;
    align-items: center;
    gap: 11px;
    width: min(420px, 100%);
    padding: 11px 12px;
    background: rgba(245, 158, 11, 0.07);
    border-color: rgba(245, 158, 11, 0.2);
}

.error-notice-icon {
    width: 30px;
    height: 30px;
    flex: 0 0 30px;
    display: grid;
    place-items: center;
    border-radius: 9px;
    color: #f59e0b;
    background: rgba(245, 158, 11, 0.12);
}

.error-notice-icon svg {
    width: 17px;
    height: 17px;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.8;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.error-notice-title {
    min-width: 0;
    flex: 1;
    color: var(--text);
    font-size: 13px;
    font-weight: 550;
    line-height: 1.35;
}

.error-view-btn {
    flex: 0 0 auto;
    min-height: 30px;
    padding: 0 11px;
    border: 1px solid rgba(245, 158, 11, 0.24);
    border-radius: 8px;
    background: rgba(245, 158, 11, 0.1);
    color: #f5a817;
    font: inherit;
    font-size: 12px;
    font-weight: 650;
    cursor: pointer;
    transition: background 0.15s ease, transform 0.15s ease;
}

.error-view-btn:hover {
    background: rgba(245, 158, 11, 0.17);
}

.error-view-btn:active {
    transform: scale(0.97);
}

.error-dismiss-btn {
    position: absolute;
    top: 8px;
    right: 8px;
    width: 22px;
    height: 22px;
    border: none;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.08);
    color: var(--text-muted);
    font-size: 15px;
    line-height: 22px;
    text-align: center;
    cursor: pointer;
    padding: 0;
    transition: background 0.15s, color 0.15s;
}

.error-dismiss-btn:hover {
    background: rgba(239, 68, 68, 0.2);
    color: #f87171;
}

.error-summary {
    color: #f87171;
    font-size: 13px;
    font-weight: 500;
    line-height: 1.4;
    word-break: break-word;
}

.error-location {
    color: var(--text-muted);
    font-size: 12px;
    font-family: ui-monospace, "SF Mono", monospace;
    margin-top: 4px;
}

.error-actions {
    display: flex;
    gap: 8px;
    margin-top: 10px;
}

.error-details-btn {
    background: rgba(255, 255, 255, 0.06);
    color: var(--text-dim);
    border: 1px solid rgba(255, 255, 255, 0.1);
    border-radius: 8px;
    padding: 6px 14px;
    font-size: 12px;
    cursor: pointer;
    transition: background 0.15s;
}

.error-details-btn:hover {
    background: rgba(255, 255, 255, 0.1);
}

.error-fix-btn {
    background: #ef4444;
    color: #fff;
    border: none;
    border-radius: 8px;
    padding: 6px 14px;
    font-size: 12px;
    font-weight: 600;
    cursor: pointer;
    transition: opacity 0.15s;
}

.error-fix-btn:hover {
    opacity: 0.85;
}

.error-fix-btn:disabled {
    opacity: 0.5;
    cursor: default;
}

/* Navigate widget */
.msg.navigate-widget-msg {
    align-self: flex-start;
    background: none;
    padding: 4px 0;
}

.navigate-btn {
    background: var(--accent, #6366f1);
    color: #fff;
    border: none;
    border-radius: 12px;
    padding: 10px 20px;
    font-size: 14px;
    font-weight: 600;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    gap: 6px;
}

.navigate-btn:hover {
    filter: brightness(1.1);
}

.navigate-btn:active {
    filter: brightness(0.9);
}

/* ══════════════════════════════════════════════
   Light Theme Overrides
═══════════════════════════════════════════════ */

/* Glass surfaces: tabs, chat bar, header */
[data-theme="light"] .desktop-tabs {
    background: rgba(255, 255, 255, 0.7);
    border-color: var(--border);
    box-shadow: 0 1px 8px rgba(0, 0, 0, 0.08);
}

[data-theme="light"] .desktop-tabs-indicator {
    background: rgba(0, 0, 0, 0.08);
}

[data-theme="light"] .desktop-tab {
    color: var(--text-dim);
}

[data-theme="light"] .desktop-tab.active {
    color: var(--text);
}

/* Desktop icon hover handled by the base `.desktop-icon:hover` rule via currentColor —
   no light-theme override needed. */

[data-theme="light"] .desktop-icon .icon-box {
    box-shadow: 0 1px 6px rgba(0, 0, 0, 0.12);
}

[data-theme="light"] .desktop-icon:hover .icon-box {
    box-shadow: 0 2px 12px rgba(0, 0, 0, 0.18);
}

[data-theme="light"] .desktop-icon .icon-label {
    font-weight: 500;
    background: linear-gradient(0deg, rgba(0, 0, 0) 0%, rgba(0, 0, 0, 0.35) 100%);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
}

/* Chat / taskbar */
[data-theme="light"] .chat-collapse-btn {
    background: rgba(0, 0, 0, 0.04);
    color: var(--text-muted);
}

[data-theme="light"] .chat-collapse-btn:hover {
    background: rgba(0, 0, 0, 0.08);
    color: var(--text);
    border-color: var(--border);
}

[data-theme="light"] .chat-header {
    background: rgba(255, 255, 255, 0.9);
}

[data-theme="light"] .chat-header::after {
    background: linear-gradient(to bottom, rgba(255, 255, 255, 0.3), transparent);
}

[data-theme="light"] .chat-header::before {
    color: var(--text);
}

[data-theme="light"] .chat {
    background: #fff;
}

/* Desktop chat sidebar */
@media (min-width: 900px) {
    [data-theme="light"] .chat {
        background: #fff !important;
        border-right-color: var(--border);
    }

    /* Opaque white — no frost. The backdrop-filter would be a no-op behind a
       solid layer, and dropping it saves a full-panel blur pass. */
    [data-theme="light"] .chat-body {
        background: #fff !important;
        backdrop-filter: none !important;
        -webkit-backdrop-filter: none !important;
    }
}

[data-theme="light"] .chat-bar {
    background: transparent;
}

[data-theme="light"] .chat-bar::before {
    background: linear-gradient(to bottom,
            transparent,
            rgba(255, 255, 255, 0.85));
}

[data-theme="light"] .chat-input-row {
    background: #fff !important;
    border-color: #d1d1d6 !important;
}

[data-theme="light"] .chat-input-row:focus-within {
    background: #fff !important;
    border-color: var(--accent) !important;
}

[data-theme="light"] body.attachment-actions-open .chat-input-row,
[data-theme="light"] body.attachment-actions-open .chat-input-row:focus-within,
[data-theme="light"] body.chat-prompt .chat-input-row,
[data-theme="light"] body.chat-prompt .chat-input-row:focus-within {
    background: #fff !important;
    border-color: #d1d1d6 !important;
}

[data-theme="light"] .sidebar-chat-btn {
    background: rgba(0, 0, 0, 0.06) !important;
}

[data-theme="light"] .sidebar-chat-btn:hover,
[data-theme="light"] .sidebar-chat-btn:focus-visible {
    background: rgba(0, 0, 0, 0.03) !important;
    border-color: rgba(0, 0, 0, 0.04) !important;
    box-shadow: 0 2px 8px rgba(0, 122, 255, 0.08) !important;
}

[data-theme="light"] .model-selected:hover,
[data-theme="light"] .model-selector.open .model-selected {
    background: rgba(0, 0, 0, 0.06);
}

[data-theme="light"] .model-dropdown {
    box-shadow: 0 -4px 20px rgba(0, 0, 0, 0.1);
}

[data-theme="light"] .model-option:hover {
    background: rgba(0, 0, 0, 0.06);
}

[data-theme="light"] .model-option.active {
    color: #fff;
    background: var(--accent);
}

[data-theme="light"] .model-variant-switch {
    border-color: rgba(0, 0, 0, 0.14);
    background: rgba(0, 0, 0, 0.05);
}

[data-theme="light"] .model-variant {
    color: var(--text-muted);
    border-color: rgba(0, 0, 0, 0.12);
}

[data-theme="light"] .model-option-group.active .model-variant {
    color: rgba(255, 255, 255, 0.82);
}

[data-theme="light"] .model-option-group.active .model-variant.active {
    color: var(--accent);
    background: #fff;
}

[data-theme="light"] .media-attach-bar {
    background: rgba(255, 255, 255, 0.9);
    border-color: var(--border);
}

[data-theme="light"] .reply-bar {
    background: rgba(255, 255, 255, 0.9);
    border-color: var(--border);
}

[data-theme="light"] .reply-close:hover {
    background: var(--hover-overlay-strong);
}

[data-theme="light"] .chat-send {
    color: #fff;
}

[data-theme="light"] .voice-bar {
    background: rgba(0, 0, 0, 0.15);
}

[data-theme="light"] .voice-overlay {
    background: var(--bg);
}

/* Public profile header */
[data-theme="light"] .public-profile {
    background: rgba(255, 255, 255, 0.92);
    border-color: var(--border);
}

[data-theme="light"] .desktop .section-panel {
    scrollbar-color: rgba(0, 0, 0, 0.15) transparent;
}

/* Desktop gradients */
[data-theme="light"] .desktop::before {
    background: linear-gradient(to bottom,
            color-mix(in srgb, var(--bg-body) 30%, transparent) 40%,
            transparent 100%);
}

[data-theme="light"] .desktop::after {
    background: linear-gradient(to top,
            color-mix(in srgb, var(--bg-body) 30%, transparent) 40%,
            transparent 100%);
}

/* Profile pill / dropdown */
[data-theme="light"] .profile-dropdown {
    background: var(--bg-primary);
    border-color: var(--border);
    box-shadow: 0 8px 30px rgba(0, 0, 0, 0.12);
}

[data-theme="light"] .profile-dropdown-item:hover {
    background: var(--hover-overlay);
}

[data-theme="light"] .profile-dropdown-item.danger:hover {
    background: rgba(255, 59, 48, 0.08);
}

/* Profile panel */
[data-theme="light"] .public-profile-name {
    color: var(--text);
}

[data-theme="light"] .public-profile-username {
    color: var(--text-dim);
}

/* Window manager windows */
[data-theme="light"] .wm-window {
    background: var(--bg-primary);
    border-color: var(--border);
    box-shadow: 0 8px 32px rgba(0, 0, 0, 0.12);
}

[data-theme="light"] .wm-titlebar {
    background: var(--bg-primary);
    border-color: var(--border);
}

[data-theme="light"] .wm-titlebar-title {
    color: var(--text);
}

/* Messages */
[data-theme="light"] .msg.assistant {
    color: var(--text);
}

[data-theme="light"] .msg.assistant th,
[data-theme="light"] .msg.assistant td {
    border-color: var(--border);
}

[data-theme="light"] .msg.assistant td {
    background: transparent;
}

[data-theme="light"] .msg.user {
    color: #fff;
}

/* Hide modals whose full styles are in lazy-loaded CSS modules.
   Without this, elements render unstyled until the module CSS arrives. */
.fork-modal-backdrop,
.fork-modal,
.share-modal,
.integrations-modal,
.trash-modal,
.settings-modal,
.asset-modal,
.sub-modal,
.report-modal {
    display: none;
}

/* Backdrop base — must be in app.css so confirm/clear-chat modals work
   even before lazy modules load. Module CSS can override with richer styles. */
.fork-modal-backdrop {
    position: fixed;
    inset: 0;
    z-index: 10010;
    /* Dim only, no blur: this opens full-viewport over running apps (games
       render beneath at 60fps), so a blur here re-filters every frame. */
    background: rgba(0, 0, 0, 0.6);
}

.fork-modal-backdrop.open {
    display: block;
}

/* ── Application errors host modal ──
   This surface deliberately lives in app.html rather than the Info iframe, so
   one modal covers the running app, desktop and chat. It uses the shared Fork
   backdrop but sits above the floating app toolbar as a true global dialog. */
.application-errors-backdrop {
    z-index: 10032;
}

.application-errors-modal {
    display: none;
    position: fixed;
    z-index: 10033;
    top: 50%;
    left: 50%;
    width: min(720px, calc(100vw - 48px));
    height: min(760px, calc(100dvh - 48px));
    min-height: 320px;
    transform: translate(-50%, -50%);
    flex-direction: column;
    overflow: hidden;
    color: var(--text);
    background: var(--bg-secondary);
    border: 1px solid var(--border-hover);
    border-radius: 22px;
    outline: none;
    box-shadow: 0 24px 72px rgba(0, 0, 0, 0.65);
}

.application-errors-modal.open {
    display: flex;
}

.application-errors-head {
    display: flex;
    align-items: center;
    gap: 12px;
    flex: 0 0 auto;
    padding: 20px 22px;
    border-bottom: 1px solid var(--border);
}

.application-errors-title {
    flex: 1;
    min-width: 0;
    margin: 0;
    color: var(--text);
    font-size: 20px;
    font-weight: 700;
    line-height: 1.2;
}

.application-errors-count {
    min-width: 36px;
    padding: 5px 11px;
    border-radius: 999px;
    color: #ff6961;
    background: rgba(255, 69, 58, 0.16);
    font-size: 14px;
    font-weight: 750;
    line-height: 1.2;
    text-align: center;
    font-variant-numeric: tabular-nums;
}

.application-errors-close {
    width: 40px;
    height: 40px;
    flex: 0 0 40px;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    border: 0;
    border-radius: 50%;
    color: var(--text);
    background: var(--hover-overlay-strong);
    cursor: pointer;
    transition: background 0.15s ease, transform 0.15s ease;
}

.application-errors-close:hover {
    background: rgba(255, 255, 255, 0.14);
}

.application-errors-close:active {
    transform: scale(0.94);
}

.application-errors-list {
    flex: 1;
    min-height: 0;
    display: flex;
    flex-direction: column;
    gap: 12px;
    overflow-y: auto;
    padding: 16px;
    overscroll-behavior: contain;
    scrollbar-width: thin;
}

.application-error-item {
    flex: 0 0 auto;
    display: grid;
    grid-template-columns: 22px minmax(0, 1fr);
    align-items: start;
    column-gap: 14px;
    padding: 16px;
    border: 1px solid var(--border);
    border-radius: 16px;
    background: var(--bg-tertiary);
    cursor: pointer;
    outline: none;
    transition: border-color 0.16s ease, background 0.16s ease, box-shadow 0.16s ease;
}

.application-error-item:hover,
.application-error-item:focus-visible {
    border-color: var(--border-hover);
}

.application-error-item.selected {
    border-color: rgba(255, 69, 58, 0.68);
    background: rgba(255, 69, 58, 0.09);
    box-shadow: inset 0 0 0 1px rgba(255, 69, 58, 0.16);
}

.application-error-content {
    min-width: 0;
}

.application-error-meta {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 10px;
}

.application-error-source {
    padding: 3px 9px;
    border-radius: 999px;
    color: #ff6961;
    background: rgba(255, 69, 58, 0.16);
    font-size: 11px;
    font-weight: 750;
    line-height: 1.2;
    letter-spacing: 0.04em;
    text-transform: uppercase;
}

.application-error-selected {
    width: 22px;
    height: 22px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 1px solid var(--border-hover);
    border-radius: 999px;
    color: transparent;
    background: var(--hover-overlay);
    transition: color 0.16s ease, border-color 0.16s ease, background 0.16s ease;
}

.application-error-selected svg {
    width: 14px;
    height: 14px;
    fill: none;
    stroke: currentColor;
    stroke-width: 2.5;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.application-error-item.selected .application-error-selected {
    color: #fff;
    border-color: #ff453a;
    background: #ff453a;
}

.application-error-time {
    margin-left: auto;
    color: var(--text-muted);
    font-size: 12px;
    font-variant-numeric: tabular-nums;
}

.application-error-message {
    color: var(--text);
    font-size: 15px;
    font-weight: 400;
    line-height: 1.42;
    overflow-wrap: anywhere;
}

.application-error-title {
    font-weight: 650;
}

.application-error-description {
    margin-left: 0.28em;
    white-space: pre-wrap;
}

.application-error-location {
    margin-top: 8px;
    color: var(--text-dim);
    font: 12px/1.4 ui-monospace, SFMono-Regular, Menlo, Monaco, monospace;
    overflow-wrap: anywhere;
}

.application-error-stack {
    margin-top: 11px;
}

.application-error-stack summary {
    color: var(--text-muted);
    font-size: 12px;
    cursor: pointer;
}

.application-error-stack,
.application-error-stack * {
    cursor: text;
}

.application-error-stack summary {
    cursor: pointer;
}

.application-error-stack pre {
    max-height: 220px;
    overflow: auto;
    margin: 8px 0 0;
    padding: 11px;
    border-radius: 10px;
    color: var(--text-dim);
    background: rgba(0, 0, 0, 0.24);
    font: 11px/1.5 ui-monospace, SFMono-Regular, Menlo, Monaco, monospace;
    white-space: pre-wrap;
    overflow-wrap: anywhere;
}

.application-errors-empty {
    margin: auto;
    padding: 36px 16px;
    color: var(--text-muted);
    font-size: 14px;
    text-align: center;
}

.application-errors-more {
    align-self: center;
    min-height: 40px;
    padding: 8px 15px;
    border: 1px solid var(--border-hover);
    border-radius: 10px;
    color: var(--text);
    background: var(--hover-overlay);
    font: inherit;
    font-size: 13px;
    cursor: pointer;
}

.application-errors-more:disabled {
    opacity: 0.55;
    cursor: default;
}

.application-errors-foot {
    display: flex;
    align-items: center;
    gap: 14px;
    flex: 0 0 auto;
    padding: 16px 18px 18px;
    border-top: 1px solid var(--border);
}

.application-errors-summary {
    flex: 1;
    color: var(--text-muted);
    font-size: 12px;
}

.application-errors-fix {
    min-height: 44px;
    padding: 10px 18px;
    border: 0;
    border-radius: 12px;
    color: #fff;
    background: #ff453a;
    font: inherit;
    font-size: 14px;
    font-weight: 700;
    cursor: pointer;
    transition: opacity 0.15s ease, transform 0.15s ease;
}

.application-errors-fix:hover:not(:disabled) {
    opacity: 0.9;
}

.application-errors-fix:active:not(:disabled) {
    transform: scale(0.98);
}

.application-errors-fix:disabled {
    opacity: 0.5;
    cursor: default;
}

[data-theme="light"] .application-errors-modal {
    box-shadow: 0 24px 72px rgba(0, 0, 0, 0.24);
}

[data-theme="light"] .application-errors-close:hover {
    background: rgba(0, 0, 0, 0.1);
}

[data-theme="light"] .application-error-stack pre {
    background: rgba(0, 0, 0, 0.05);
}

@media (max-width: 799px) {
    .application-errors-modal {
        top: max(12px, env(safe-area-inset-top));
        right: 12px;
        bottom: max(12px, env(safe-area-inset-bottom));
        left: 12px;
        width: auto;
        height: auto;
        min-height: 0;
        transform: none;
        border-radius: 20px;
    }

    .application-errors-head {
        padding: 16px;
    }

    .application-errors-foot {
        padding: 14px 16px 16px;
    }
}

/* ── Owner-only project table schema browser ── */
.project-tables-backdrop {
    z-index: 10034;
}

.project-tables-modal {
    display: none;
    position: fixed;
    z-index: 10035;
    top: 50%;
    left: 50%;
    width: min(820px, calc(100vw - 48px));
    height: min(760px, calc(100dvh - 48px));
    min-height: 360px;
    transform: translate(-50%, -50%);
    flex-direction: column;
    overflow: hidden;
    color: var(--text);
    background: var(--bg-secondary);
    border: 1px solid var(--border-hover);
    border-radius: 22px;
    outline: none;
    box-shadow: 0 24px 72px rgba(0, 0, 0, 0.65);
}

.project-tables-modal.open {
    display: flex;
}

.project-tables-head {
    display: flex;
    align-items: center;
    gap: 12px;
    flex: 0 0 auto;
    min-height: 76px;
    padding: 16px 18px 16px 22px;
    border-bottom: 1px solid var(--border);
}

.project-tables-head-icon,
.project-table-card-icon {
    display: grid;
    place-items: center;
    color: #c4b5fd;
    background: rgba(139, 92, 246, 0.12);
}

.project-tables-head-icon {
    width: 40px;
    height: 40px;
    flex: 0 0 40px;
    border-radius: 12px;
}

.project-tables-head-icon svg {
    width: 22px;
    height: 22px;
}

.project-tables-title {
    flex: 1;
    min-width: 0;
    margin: 0;
    color: var(--text);
    font-size: 20px;
    font-weight: 700;
    line-height: 1.2;
}

.project-tables-count {
    min-width: 36px;
    padding: 5px 11px;
    border-radius: 999px;
    color: #c4b5fd;
    background: rgba(139, 92, 246, 0.14);
    font-size: 14px;
    font-weight: 750;
    line-height: 1.2;
    text-align: center;
    font-variant-numeric: tabular-nums;
}

.project-tables-close {
    width: 40px;
    height: 40px;
    flex: 0 0 40px;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    border: 0;
    border-radius: 50%;
    color: var(--text);
    background: var(--hover-overlay-strong);
    cursor: pointer;
    transition: background 0.15s ease, transform 0.15s ease;
}

.project-tables-close:hover {
    background: rgba(255, 255, 255, 0.14);
}

.project-tables-close:active {
    transform: scale(0.94);
}

.project-tables-list {
    flex: 1;
    min-height: 0;
    display: flex;
    flex-direction: column;
    gap: 14px;
    overflow-y: auto;
    padding: 16px;
    overscroll-behavior: contain;
    scrollbar-width: thin;
}

.project-table-card {
    flex: 0 0 auto;
    overflow: hidden;
    border: 1px solid var(--border);
    border-radius: 16px;
    background: var(--bg-primary);
}

.project-table-card-head {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 15px 16px;
    border-bottom: 1px solid var(--border);
}

.project-table-card-icon {
    width: 34px;
    height: 34px;
    flex: 0 0 34px;
    border-radius: 10px;
}

.project-table-card-icon svg {
    width: 18px;
    height: 18px;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.8;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.project-table-card-head > div {
    min-width: 0;
}

.project-table-card-head h3 {
    overflow: hidden;
    margin: 0;
    color: var(--text);
    font: 650 14px/1.4 ui-monospace, SFMono-Regular, Menlo, Monaco, monospace;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.project-table-card-head p {
    margin: 4px 0 0;
    color: var(--text-muted);
    font-size: 11px;
    line-height: 1.35;
}

.project-table-fields {
    padding: 14px 16px 16px;
}

.project-table-fields h4 {
    margin: 0 0 8px;
    color: var(--text-muted);
    font-size: 11px;
    font-weight: 750;
    letter-spacing: 0.055em;
    line-height: 1.3;
    text-transform: uppercase;
}

.project-table-field {
    min-height: 38px;
    display: grid;
    grid-template-columns: minmax(120px, 0.85fr) minmax(140px, 1fr) minmax(165px, 0.7fr);
    align-items: center;
    gap: 12px;
    padding: 8px 10px;
    border-radius: 9px;
}

.project-table-field:nth-of-type(odd) {
    background: var(--hover-overlay);
}

.project-table-field > code {
    overflow: hidden;
    color: var(--text);
    font: 600 12px/1.35 ui-monospace, SFMono-Regular, Menlo, Monaco, monospace;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.project-table-field-type {
    overflow: hidden;
    color: #a5b4fc;
    font: 12px/1.35 ui-monospace, SFMono-Regular, Menlo, Monaco, monospace;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.project-table-field-badges {
    display: flex;
    justify-content: flex-end;
    gap: 5px;
}

.project-table-field-badge {
    padding: 3px 7px;
    border-radius: 999px;
    color: var(--text-muted);
    background: var(--hover-overlay-strong);
    font-size: 10px;
    font-weight: 700;
    line-height: 1.25;
    white-space: nowrap;
}

.project-table-field-badge.primary {
    color: #c4b5fd;
    background: rgba(139, 92, 246, 0.14);
}

.project-table-field-badge.unique {
    color: #7dd3fc;
    background: rgba(56, 189, 248, 0.12);
}

.project-table-constraints {
    display: grid;
    gap: 8px;
    padding: 12px 16px 16px;
    border-top: 1px solid var(--border);
}

.project-table-constraint {
    display: grid;
    grid-template-columns: 110px minmax(0, 1fr);
    gap: 10px;
    align-items: start;
}

.project-table-constraint strong {
    padding-top: 4px;
    color: var(--text-muted);
    font-size: 11px;
    font-weight: 650;
}

.project-table-constraint > div {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}

.project-table-constraint span {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    min-height: 27px;
    padding: 4px 8px;
    border-radius: 7px;
    color: var(--text-dim);
    background: var(--hover-overlay);
    font-size: 11px;
}

.project-table-constraint code {
    color: #c4b5fd;
    font: 600 11px/1.3 ui-monospace, SFMono-Regular, Menlo, Monaco, monospace;
}

.project-tables-empty {
    margin: auto;
    padding: 36px 18px;
    color: var(--text-muted);
    font-size: 14px;
    line-height: 1.45;
    text-align: center;
}

[data-theme="light"] .project-tables-modal {
    box-shadow: 0 24px 72px rgba(0, 0, 0, 0.24);
}

[data-theme="light"] .project-tables-close:hover {
    background: rgba(0, 0, 0, 0.1);
}

[data-theme="light"] .project-table-field-type {
    color: #5b48a7;
}

@media (max-width: 799px) {
    .project-tables-modal {
        top: max(12px, env(safe-area-inset-top));
        right: 12px;
        bottom: max(12px, env(safe-area-inset-bottom));
        left: 12px;
        width: auto;
        height: auto;
        min-height: 0;
        transform: none;
        border-radius: 20px;
    }

    .project-tables-head {
        min-height: 68px;
        padding: 12px 14px;
    }

    .project-tables-head-icon {
        display: none;
    }

    .project-tables-list {
        padding: 12px;
    }

    .project-table-field {
        grid-template-columns: minmax(100px, 0.8fr) minmax(0, 1fr);
        gap: 6px 10px;
    }

    .project-table-field-badges {
        grid-column: 1 / -1;
        justify-content: flex-start;
    }

    .project-table-constraint {
        grid-template-columns: 1fr;
        gap: 4px;
    }
}

/* ── Owner-only project source browser ── */
.project-files-backdrop {
    z-index: 10034;
}

.project-files-modal {
    display: none;
    position: fixed;
    z-index: 10035;
    top: 50%;
    left: 50%;
    width: min(1040px, calc(100vw - 48px));
    height: min(780px, calc(100dvh - 48px));
    min-height: 360px;
    transform: translate(-50%, -50%);
    flex-direction: column;
    overflow: hidden;
    color: var(--text);
    background: var(--bg-secondary);
    border: 1px solid var(--border-hover);
    border-radius: 22px;
    outline: none;
    box-shadow: 0 24px 72px rgba(0, 0, 0, 0.65);
}

.project-files-modal.open {
    display: flex;
}

.project-files-head {
    display: flex;
    align-items: center;
    gap: 12px;
    flex: 0 0 auto;
    min-height: 76px;
    padding: 16px 18px 16px 22px;
    border-bottom: 1px solid var(--border);
}

.project-files-title {
    flex: 1;
    min-width: 0;
    margin: 0;
    color: var(--text);
    font-size: 20px;
    font-weight: 700;
    line-height: 1.2;
}

.project-files-count {
    min-width: 36px;
    padding: 5px 11px;
    border-radius: 999px;
    color: #7dd3fc;
    background: rgba(56, 189, 248, 0.14);
    font-size: 14px;
    font-weight: 750;
    line-height: 1.2;
    text-align: center;
    font-variant-numeric: tabular-nums;
}

.project-files-close,
.project-files-back {
    width: 40px;
    height: 40px;
    flex: 0 0 40px;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    border: 0;
    border-radius: 50%;
    color: var(--text);
    background: var(--hover-overlay-strong);
    cursor: pointer;
    transition: background 0.15s ease, transform 0.15s ease;
}

.project-files-back {
    display: none;
}

.project-files-close:hover,
.project-files-back:hover {
    background: rgba(255, 255, 255, 0.14);
}

.project-files-close:active,
.project-files-back:active {
    transform: scale(0.94);
}

.project-files-body {
    flex: 1;
    min-height: 0;
    display: grid;
    grid-template-columns: minmax(230px, 300px) minmax(0, 1fr);
}

.project-files-sidebar {
    min-width: 0;
    overflow-y: auto;
    padding: 12px;
    border-right: 1px solid var(--border);
    overscroll-behavior: contain;
    scrollbar-width: thin;
}

.project-file-group + .project-file-group {
    margin-top: 16px;
}

.project-file-group h3 {
    margin: 0 8px 7px;
    color: var(--text-muted);
    font-size: 11px;
    font-weight: 750;
    letter-spacing: 0.055em;
    line-height: 1.3;
    text-transform: uppercase;
}

.project-file-row {
    width: 100%;
    min-width: 0;
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px;
    border: 1px solid transparent;
    border-radius: 11px;
    color: var(--text);
    background: transparent;
    font: inherit;
    text-align: left;
    cursor: pointer;
    outline: none;
    transition: border-color 0.14s ease, background 0.14s ease;
}

.project-file-row:hover,
.project-file-row:focus-visible {
    background: var(--hover-overlay);
}

.project-file-row.selected {
    border-color: rgba(56, 189, 248, 0.32);
    background: rgba(56, 189, 248, 0.1);
}

.project-file-row-icon {
    width: 30px;
    height: 30px;
    flex: 0 0 30px;
    display: grid;
    place-items: center;
    border-radius: 8px;
    color: #7dd3fc;
    background: rgba(56, 189, 248, 0.1);
}

.project-file-row-icon svg {
    width: 17px;
    height: 17px;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.8;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.project-file-row-copy {
    min-width: 0;
    display: flex;
    flex: 1;
    flex-direction: column;
    gap: 3px;
}

.project-file-row-copy strong {
    overflow: hidden;
    color: var(--text);
    font: 12px/1.35 ui-monospace, SFMono-Regular, Menlo, Monaco, monospace;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.project-file-row-copy small {
    color: var(--text-muted);
    font-size: 11px;
    line-height: 1.2;
}

.project-file-viewer {
    min-width: 0;
    min-height: 0;
    display: flex;
    flex-direction: column;
    background: var(--bg-primary);
}

.project-file-viewer-head {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 15px 18px;
    border-bottom: 1px solid var(--border);
}

.project-file-viewer-copy {
    flex: 1;
    min-width: 0;
}

.project-file-viewer-path {
    overflow: hidden;
    color: var(--text);
    font: 600 13px/1.4 ui-monospace, SFMono-Regular, Menlo, Monaco, monospace;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.project-file-viewer-meta {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-top: 7px;
    color: var(--text-muted);
    font-size: 11px;
}

.project-file-viewer-meta span:first-child {
    padding: 3px 7px;
    border-radius: 6px;
    color: #7dd3fc;
    background: rgba(56, 189, 248, 0.1);
    font-weight: 700;
}

.project-file-viewer-actions {
    min-width: 0;
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 8px;
}

.project-file-editor-status {
    max-width: 190px;
    overflow: hidden;
    color: var(--text-muted);
    font-size: 11px;
    line-height: 1.3;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.project-file-editor-status.error {
    color: #ff6961;
}

.project-file-editor-status.saved {
    color: #4ade80;
}

.project-file-action {
    min-height: 34px;
    padding: 7px 12px;
    border: 1px solid var(--border-hover);
    border-radius: 9px;
    font: inherit;
    font-size: 12px;
    font-weight: 700;
    cursor: pointer;
    transition: opacity 0.15s ease, transform 0.15s ease, background 0.15s ease;
}

.project-file-action.primary {
    color: #071018;
    border-color: #7dd3fc;
    background: #7dd3fc;
}

.project-file-action.secondary {
    color: var(--text);
    background: var(--hover-overlay);
}

.project-file-action:hover:not(:disabled) {
    filter: brightness(1.06);
}

.project-file-action:active:not(:disabled) {
    transform: scale(0.97);
}

.project-file-action:disabled {
    opacity: 0.45;
    cursor: default;
}

.project-file-viewer-content {
    flex: 1;
    min-height: 0;
    overflow: auto;
    overscroll-behavior: contain;
    scrollbar-width: thin;
}

.project-file-code {
    min-width: max-content;
    min-height: 100%;
    margin: 0;
    padding: 15px 0 28px;
    color: var(--text-dim);
    background: transparent;
    font: 12px/1.62 ui-monospace, SFMono-Regular, Menlo, Monaco, monospace;
    tab-size: 4;
    counter-reset: project-file-line;
}

.project-file-code code {
    display: block;
}

.project-file-code-line {
    display: block;
    min-height: 1.62em;
    padding: 0 20px 0 0;
    white-space: pre;
    counter-increment: project-file-line;
}

.project-file-code-line::before {
    content: counter(project-file-line);
    position: sticky;
    left: 0;
    display: inline-block;
    width: 48px;
    margin-right: 14px;
    padding-right: 10px;
    color: var(--text-muted);
    background: var(--bg-primary);
    border-right: 1px solid var(--border);
    text-align: right;
    user-select: none;
}

.project-file-editor-shell {
    width: 100%;
    min-width: 0;
    height: 100%;
    min-height: 100%;
    display: grid;
    grid-template-columns: 58px minmax(0, 1fr);
    overflow: hidden;
    background: var(--bg-primary);
}

.project-file-editor-lines {
    height: 100%;
    overflow: hidden;
    padding: 15px 10px 28px 0;
    color: var(--text-muted);
    border-right: 1px solid var(--border);
    background: var(--bg-primary);
    font: 12px/1.62 ui-monospace, SFMono-Regular, Menlo, Monaco, monospace;
    text-align: right;
    user-select: none;
}

.project-file-editor-lines span {
    display: block;
    height: 1.62em;
}

.project-file-editor {
    width: 100%;
    height: 100%;
    min-height: 100%;
    resize: none;
    overflow: auto;
    margin: 0;
    padding: 15px 20px 28px 14px;
    border: 0;
    border-radius: 0;
    outline: none;
    color: var(--text);
    background: var(--bg-primary);
    font: 12px/1.62 ui-monospace, SFMono-Regular, Menlo, Monaco, monospace;
    tab-size: 4;
    white-space: pre;
    overflow-wrap: normal;
}

.project-file-editor:focus {
    box-shadow: inset 0 0 0 1px rgba(125, 211, 252, 0.28);
}

.project-files-empty {
    margin: auto;
    padding: 36px 18px;
    color: var(--text-muted);
    font-size: 14px;
    line-height: 1.45;
    text-align: center;
}

[data-theme="light"] .project-files-modal {
    box-shadow: 0 24px 72px rgba(0, 0, 0, 0.24);
}

[data-theme="light"] .project-files-close:hover,
[data-theme="light"] .project-files-back:hover {
    background: rgba(0, 0, 0, 0.1);
}

#projectFilesModal.open ~ #confirmBackdrop {
    z-index: 10036;
}

#projectFilesModal.open ~ #confirmBackdrop + #confirmModal {
    z-index: 10037;
}

@media (max-width: 799px) {
    .project-files-modal {
        top: max(12px, env(safe-area-inset-top));
        right: 12px;
        bottom: max(12px, env(safe-area-inset-bottom));
        left: 12px;
        width: auto;
        height: auto;
        min-height: 0;
        transform: none;
        border-radius: 20px;
    }

    .project-files-head {
        min-height: 68px;
        padding: 12px 14px 12px 16px;
    }

    .project-files-body {
        display: block;
    }

    .project-files-sidebar,
    .project-file-viewer {
        width: 100%;
        height: 100%;
        border-right: 0;
    }

    .project-file-viewer {
        display: none;
    }

    .project-files-modal.viewing .project-files-sidebar {
        display: none;
    }

    .project-files-modal.viewing .project-file-viewer,
    .project-files-modal.viewing .project-files-back {
        display: flex;
    }

    .project-files-modal.viewing .project-files-back {
        align-items: center;
        justify-content: center;
    }

    .project-file-viewer-head {
        align-items: flex-start;
        flex-wrap: wrap;
        gap: 10px;
        padding: 12px 14px;
    }

    .project-file-viewer-actions {
        width: 100%;
    }

    .project-file-editor-status {
        margin-right: auto;
    }

}

/* Declarative hook for modal panels whose dynamic screens use
   animateDesktopModalHeight(). The attribute lives on the shared desktop modal
   component; individual modal modules only provide their content transitions. */
@media (min-width: 800px) {
    [data-animate-desktop-height][data-height-animating="true"] {
        will-change: height;
    }
}

/* Fallback styling for settings-modal so it can render with a loader
   before settings.css arrives. Module CSS overrides with richer styles. */
.settings-modal.open {
    display: flex;
    flex-direction: column;
    position: fixed;
    z-index: 10011;
    background: var(--bg-secondary);
    border: 1px solid var(--border);
}

@media (min-width: 800px) {
    .settings-modal.open {
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        width: 560px;
        max-width: 92vw;
        max-height: 92vh;
        border-radius: 18px;
    }
}

@media (max-width: 799px) {
    .settings-modal.open {
        left: 0;
        right: 0;
        bottom: 0;
        width: 100%;
        max-height: 80dvh;
        border-radius: 20px 20px 0 0;
    }
}

.settings-modal.open .settings-modal-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 18px 24px;
    border-bottom: 1px solid var(--border);
    flex-shrink: 0;
}

.settings-modal.open .settings-modal-title {
    font-size: 16px;
    font-weight: 600;
    color: var(--text);
}

.settings-modal.open .trash-modal-close {
    background: none;
    border: none;
    color: var(--text-muted);
    cursor: pointer;
    padding: 6px;
    border-radius: 8px;
    display: flex;
    align-items: center;
    justify-content: center;
}

.settings-modal.open .settings-modal-body {
    flex: 1;
    overflow-y: auto;
}

.settings-preload-loader {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 200px;
    padding: 40px 0;
}

/* Theme-aware spinner inside the settings preload — overrides .app-tab-spinner's
   white-on-dark colors so it's visible on the modal's --bg-secondary background. */
.settings-preload-loader .app-tab-spinner {
    border-color: var(--border);
    border-top-color: var(--text-secondary);
}

/* Modals */
[data-theme="light"] .fork-modal-backdrop {
    background: rgba(0, 0, 0, 0.35);
}

[data-theme="light"] .fork-modal,
[data-theme="light"] .confirm-modal,
[data-theme="light"] .share-modal,
[data-theme="light"] .trash-modal,
[data-theme="light"] .settings-modal,
[data-theme="light"] .asset-modal,
[data-theme="light"] .sub-modal {
    box-shadow: 0 16px 48px rgba(0, 0, 0, 0.15);
}

[data-theme="light"] .chat-close-inline {
    background: rgba(255, 255, 255, 0.85);
    border-color: var(--border);
    color: var(--text-muted);
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.06);
}

[data-theme="light"] .chat-close-inline.send-mode {
    background: var(--accent);
    border-color: var(--accent);
    color: #fff;
}

[data-theme="light"] .chat-close-inline:hover {
    background: #fff;
    color: var(--text);
}

/* Chat context selector */
[data-theme="light"] .chat-context-btn {
    color: var(--text-dim);
}

@media (hover: hover) {
    [data-theme="light"] .chat-context-btn:hover {
        background: rgba(0, 0, 0, 0.05);
        color: var(--text);
    }
}

@media (max-width: 799px) {
    [data-theme="light"] body.chat-open .chat-context-btn {
        background: linear-gradient(100deg, rgba(255, 255, 255, 0.92), rgba(255, 255, 255, 0.78));
        color: rgba(20, 20, 20, 0.72);
    }

    [data-theme="light"] body.chat-open .chat-menu-btn {
        background: rgba(0, 0, 0, 0.05);
        border-color: var(--border);
        color: var(--text);
    }
}

/* Chat three-dots menu */
[data-theme="light"] .chat-menu-btn:hover {
    background: rgba(0, 0, 0, 0.06);
}

[data-theme="light"] .logo-panel.open .logo-panel-body {
    background: var(--bg-primary);
    border-color: var(--border);
    box-shadow: 0 8px 30px rgba(0, 0, 0, 0.12);
}

[data-theme="light"] .logo-panel-item:hover {
    background: var(--hover-overlay);
}

[data-theme="light"] .logo-panel-item.danger {
    color: #dc2626;
}

[data-theme="light"] .logo-panel-item.danger:hover {
    background: rgba(220, 38, 38, 0.08);
}

[data-theme="light"] .chat-menu-dropdown {
    background: var(--bg-primary);
    border-color: var(--border);
    box-shadow: 0 8px 30px rgba(0, 0, 0, 0.12);
}

[data-theme="light"] .chat-menu-item {
    color: var(--text);
}

[data-theme="light"] .chat-menu-item:hover {
    background: var(--hover-overlay);
}

[data-theme="light"] .chat-menu-item.danger {
    color: #dc2626;
}

[data-theme="light"] .chat-menu-item.danger:hover {
    background: rgba(220, 38, 38, 0.08);
}

/* Input fields */
[data-theme="light"] .edit-profile-input {
    background: var(--bg-tertiary);
    border-color: var(--border);
    color: var(--text);
}

/* Buttons with white text on dark bg — keep them visible */
[data-theme="light"] .notif-follow-btn {
    background: var(--text);
    color: var(--bg-primary);
}

[data-theme="light"] .notif-follow-btn.following {
    background: var(--bg-tertiary);
    color: var(--text-dim);
}

/* Notification items */
[data-theme="light"] .notif-item {
    color: var(--text-dim);
    border-bottom-color: var(--border);
}

[data-theme="light"] .notif-item.unread {
    color: var(--text);
}

[data-theme="light"] .notif-name {
    color: var(--text);
}

[data-theme="light"] .notif-actor-link {
    color: var(--accent);
}

[data-theme="light"] .notif-actor-link:hover,
[data-theme="light"] .notif-actor-link:focus-visible {
    color: var(--accent-light);
}

[data-theme="light"] .notif-username {
    color: var(--text-muted);
}

[data-theme="light"] .notif-desc {
    color: var(--text-dim);
}

/* Mobile buttons */
[data-theme="light"] .mobile-notif-btn {
    background: rgba(255, 255, 255, 0.85);
    border-color: var(--border);
    color: var(--text-dim);
}

[data-theme="light"] .mobile-app-notif-btn {
    background: rgba(255, 255, 255, 0.85);
    border-color: var(--border);
    color: var(--text-dim);
}

/* Mobile notification modal */
[data-theme="light"] .mobile-notif-modal {
    background: #fff;
}

[data-theme="light"] .mobile-notif-header {
    color: var(--text);
}

[data-theme="light"] .mobile-notif-close {
    color: var(--text-dim);
}

[data-theme="light"] .notif-section-title {
    color: var(--text);
}

/* Error card */
[data-theme="light"] .error-details-btn {
    background: var(--bg-tertiary);
    border-color: var(--border);
}

[data-theme="light"] .error-details-btn:hover {
    background: var(--hover-overlay-strong);
}

/* Icon delete button */
[data-theme="light"] .icon-delete {
    background: rgba(0, 0, 0, 0.5);
    color: #fff;
}

/* Scrollbar */
[data-theme="light"] .chat-body {
    scrollbar-color: rgba(0, 0, 0, 0.15) transparent;
}

/* Context menu */
[data-theme="light"] .icon-context-menu {
    background: var(--bg-primary);
    border-color: var(--border);
    box-shadow: 0 8px 30px rgba(0, 0, 0, 0.12);
}

[data-theme="light"] .icon-context-item:hover {
    background: var(--hover-overlay);
}

/* Settings theme toggle */
.settings-theme-toggle {
    display: flex;
    align-items: center;
    gap: 0;
    background: var(--bg-tertiary);
    border: 1px solid var(--border);
    border-radius: 10px;
    padding: 3px;
    flex-shrink: 0;
}

.settings-theme-btn {
    padding: 5px 12px;
    border: none;
    background: transparent;
    color: var(--text-dim);
    font-size: 12px;
    font-family: inherit;
    font-weight: 500;
    border-radius: 7px;
    cursor: pointer;
    transition:
        background 0.2s,
        color 0.2s;
    display: flex;
    align-items: center;
    gap: 5px;
}

.settings-theme-btn.active {
    background: var(--bg-secondary);
    color: var(--text);
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}

[data-theme="light"] .settings-theme-btn.active {
    background: #fff;
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.1);
}

.settings-lang-select {
    appearance: none;
    -webkit-appearance: none;
    background: var(--bg-tertiary);
    border: 1px solid var(--border);
    border-radius: 10px;
    padding: 6px 28px 6px 12px;
    color: var(--text);
    font-size: 13px;
    font-family: inherit;
    font-weight: 500;
    cursor: pointer;
    flex-shrink: 0;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23888' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 8px center;
}

.settings-lang-select:focus {
    outline: none;
    border-color: var(--accent);
}

.settings-sub-btn {
    display: inline-block;
    padding: 8px 16px;
    border-radius: 8px;
    border: none;
    font-size: 13px;
    font-family: inherit;
    font-weight: 500;
    cursor: pointer;
    background: var(--accent);
    color: #fff;
    transition: opacity 0.15s;
}

.settings-sub-btn:hover {
    opacity: 0.85;
}

.settings-sub-btn.secondary {
    background: var(--bg-tertiary);
    color: var(--text-dim);
    border: 1px solid var(--border);
}

/* Profile back circle button */
.profile-back-circle {
    position: absolute;
    top: 10px;
    left: 10px;
    z-index: 101;
    width: 40px;
    height: 40px;
    border-radius: 50%;
    border: 1px solid rgba(255, 255, 255, 0.12);
    background: rgba(30, 30, 30, 0.55);
    backdrop-filter: blur(20px);
    -webkit-backdrop-filter: blur(20px);
    color: #fff;
    font-size: 18px;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 2px 12px rgba(0, 0, 0, 0.3);
}

[data-theme="light"] .profile-back-circle {
    background: rgba(255, 255, 255, 0.7);
    border-color: rgba(0, 0, 0, 0.08);
    color: #333;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

/* Profile page header (Followers/Following title) */
.profile-page-header {
    padding: 16px 0 12px;
}

.profile-page-title {
    font-size: 18px;
    font-weight: 600;
    color: var(--text);
    text-align: center;
}

/* Profile user list */
.profile-user-list {
    display: flex;
    flex-direction: column;
}

.profile-user-item {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 10px 4px;
    border-radius: 10px;
    transition: background 0.15s;
}

.profile-user-item.clickable {
    cursor: pointer;
}

.profile-user-item:hover {
    background: rgba(255, 255, 255, 0.06);
}

[data-theme="light"] .profile-user-item:hover {
    background: rgba(0, 0, 0, 0.04);
}

.profile-user-avatar {
    width: 46px;
    height: 46px;
    border-radius: 50%;
    object-fit: cover;
    flex-shrink: 0;
}

.profile-avatar-placeholder {
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--bg-tertiary);
    font-weight: 600;
    color: var(--text-muted);
    font-size: 16px;
}

.profile-user-info {
    flex: 1;
    min-width: 0;
}

.profile-user-name {
    font-size: 14px;
    font-weight: 500;
    color: var(--text);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.profile-user-username {
    font-size: 12px;
    color: var(--text-muted);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Follow button in user lists */
.follow-btn {
    flex-shrink: 0;
    padding: 6px 14px;
    font-size: 12px;
    font-weight: 600;
    font-family: inherit;
    border: none;
    border-radius: 8px;
    cursor: pointer;
    background: #fff;
    color: #000;
}

.follow-btn:hover {
    opacity: 0.85;
}

.follow-btn.following {
    background: rgba(255, 255, 255, 0.1);
    color: rgba(255, 255, 255, 0.6);
}

[data-theme="light"] .follow-btn {
    background: var(--text);
    color: var(--bg-primary);
}

[data-theme="light"] .follow-btn.following {
    background: var(--bg-tertiary);
    color: var(--text-dim);
}

/* Profile loading spinner */
.profile-spinner {
    display: flex;
    align-items: center;
    justify-content: center;
    height: calc(100vh - 58px - var(--chat-h) - 32px);
}

.wm-content .profile-spinner {
    height: 200px;
}

.profile-empty {
    text-align: center;
    color: var(--text-muted);
    padding: 32px 16px;
    font-size: 14px;
}

.profile-spinner::after {
    content: "";
    width: 28px;
    height: 28px;
    border: 2.5px solid rgba(128, 128, 128, 0.25);
    border-top-color: rgba(128, 128, 128, 0.7);
    border-radius: 50%;
    animation: profile-spin 0.7s linear infinite;
}

@keyframes profile-spin {
    to {
        transform: rotate(360deg);
    }
}

/* App proposal widget */
.msg.app-proposal-msg,
.msg.video-proposal-msg {
    align-self: stretch;
    padding: 0;
    background: none;
    border: none;
    max-width: 100%;
}

.app-proposal-card {
    background: var(--bg-secondary);
    border: 1px solid var(--border);
    border-radius: 16px;
    overflow: hidden;
}

/* ── Streaming proposal draft ─────────────────────────────────────────────
   The card goes up the moment the model STARTS emitting the propose_app call
   (widget.state === 'draft'): shimmer placeholders stand in for the title and
   description, then real fields fill in live via message_updated re-renders.
   The entrance animation lives on the OUTER .proposal-appear (set once at
   creation) so streaming innerHTML updates never re-trigger it. */
.app-proposal-msg.proposal-appear .app-proposal-card {
    animation: proposal-card-in .5s cubic-bezier(.16, 1, .3, 1) both;
}

@keyframes proposal-card-in {
    from {
        opacity: 0;
        transform: translateY(18px) scale(.97);
    }
}

.app-proposal-card .shimmer-line {
    display: inline-block;
    height: 0.85em;
    border-radius: 6px;
    background: linear-gradient(90deg,
            rgba(127, 127, 140, 0.14) 25%,
            rgba(127, 127, 140, 0.30) 50%,
            rgba(127, 127, 140, 0.14) 75%);
    background-size: 200% 100%;
    animation: proposal-shimmer 1.3s linear infinite;
    vertical-align: middle;
}

.app-proposal-desc .shimmer-line {
    display: block;
    margin: 6px 0;
}

@keyframes proposal-shimmer {
    from { background-position: 200% 0; }
    to   { background-position: -200% 0; }
}

/* Draft card reserves a little body height so it doesn't collapse to a strip
   before the first fields stream in. */
.app-proposal-card.draft .app-proposal-desc {
    min-height: 2.4em;
}

/* One-shot fade for a COMPLETE line replacing its shimmer (the server never
   ships half-typed values). Applied only to newly-arrived nodes — re-rendered
   older lines don't carry the class, so they never re-animate. */
.app-proposal-card .line-in {
    animation: proposal-line-in .38s cubic-bezier(.16, 1, .3, 1) both;
}

@keyframes proposal-line-in {
    from {
        opacity: 0;
        transform: translateY(6px);
    }
}

/* Trailing "next line being typed" shimmer bullet at the end of the list */
.app-proposal-features li.draft-next {
    opacity: .7;
}

/* Spinner at the bottom of the streaming card — lives where the Create/Cancel
   buttons will appear and stays up until the very moment they render (the
   finalize swap is instant, no fades). */
.app-proposal-draft-loader {
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 4px 20px 20px;
}

.app-proposal-draft-loader .reasoning-spinner {
    width: 22px;
    height: 22px;
    border-width: 2.5px;
}

.app-proposal-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 16px 20px 0;
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: var(--text-dim);
}

.app-proposal-agent-badge {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    flex-shrink: 0;
    padding: 4px 10px;
    border: 1px solid color-mix(in srgb, currentColor 45%, transparent);
    border-radius: 999px;
    color: #8ab8ff;
    background: linear-gradient(115deg, rgba(0, 122, 255, 0.14), rgba(126, 87, 255, 0.1));
    font-size: 12px;
    font-weight: 600;
    line-height: 18px;
    text-transform: none;
    letter-spacing: 0;
}

.app-proposal-agent-badge svg {
    width: 16px;
    height: 16px;
    flex-shrink: 0;
}

[data-theme="light"] .app-proposal-agent-badge {
    color: #0868d9;
    background: linear-gradient(115deg, rgba(0, 122, 255, 0.08), rgba(126, 87, 255, 0.06));
}

.app-proposal-agent-note {
    padding: 6px 20px 0;
    color: var(--text-dim);
    font-size: 12px;
    line-height: 1.4;
}

.app-proposal-title {
    font-size: 18px;
    font-weight: 700;
    color: var(--text);
    padding: 8px 20px 0;
}

.app-proposal-slug {
    font-size: 12px;
    color: var(--text-muted);
    padding: 2px 20px 0;
    font-family: 'SF Mono', Monaco, Menlo, monospace;
}

.app-proposal-desc {
    font-size: 14px;
    color: var(--text);
    line-height: 1.5;
    padding: 6px 20px 16px;
}

.app-proposal-features {
    list-style: none;
    padding: 0 20px 16px;
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: 2px;
}

/* "Open to everyone — no sign-in" badge on proposals with no_auth */
.app-proposal-noauth {
    margin: 0 20px 14px;
    padding: 8px 12px;
    border-radius: 10px;
    background: rgba(52, 199, 89, 0.12);
    color: #34c759;
    font-size: 13px;
    font-weight: 500;
}

.app-proposal-features li {
    font-size: 14px;
    color: var(--text);
    padding: 8px 0;
    border-bottom: 1px solid var(--border);
    display: flex;
    align-items: flex-start;
    gap: 10px;
    line-height: 1.4;
}

.app-proposal-features li:last-child {
    border-bottom: none;
}

.app-proposal-features li.fade-in {
    animation: proposalFadeIn 0.4s cubic-bezier(0.16, 1, 0.3, 1) both;
}

@keyframes proposalFadeIn {
    from {
        opacity: 0;
        transform: translateY(8px);
    }

    to {
        opacity: 1;
        transform: translateY(0);
    }
}

/* Feature markers are BULLET POINTS (small filled dots), not empty circles —
   outlined circles read as unchecked checkboxes. The dot keeps the full 18px
   footprint (scaled down) so text alignment never shifts, and during the build
   it GROWS into the accent checkmark via the transform transition. */
.app-proposal-features li::before {
    content: "";
    width: 18px;
    height: 18px;
    border-radius: 50%;
    background: var(--text-muted);
    transform: scale(0.45);
    flex-shrink: 0;
    margin-top: 1px;
    box-sizing: border-box;
    transition: background 0.3s ease, color 0.3s ease, transform 0.3s ease;
}

.app-proposal-features li.done::before {
    content: "\2713";
    transform: scale(1);
    background: var(--accent);
    color: #fff;
    font-size: 10px;
    font-weight: 700;
    display: flex;
    align-items: center;
    justify-content: center;
}

.app-proposal-features li.done {
    color: var(--text-dim, #888);
}

.app-proposal-buttons {
    display: flex;
    gap: 10px;
    padding: 0 20px 20px;
}

.app-proposal-create-btn {
    flex: 1;
    padding: 12px;
    border-radius: 12px;
    border: none;
    background: var(--accent);
    color: #fff;
    font-size: 15px;
    font-weight: 600;
    font-family: inherit;
    cursor: pointer;
}

.app-proposal-create-btn:hover {
    opacity: 0.85;
}

.app-proposal-create-btn:disabled {
    opacity: 0.5;
    cursor: default;
}

.app-proposal-cancel-btn {
    padding: 12px 20px;
    border-radius: 12px;
    border: 1px solid var(--border);
    background: var(--bg-tertiary);
    color: var(--text-dim);
    font-size: 15px;
    font-weight: 500;
    font-family: inherit;
    cursor: pointer;
}

.app-proposal-cancel-btn:hover {
    background: var(--hover-overlay-strong);
    color: var(--text);
}

/* Progress inside proposal card */
.app-proposal-progress-wrap {
    padding: 0 20px 20px;
    transition: opacity 0.3s ease;
}

.app-proposal-progress .progress-bar-track {
    background: var(--hover-overlay);
}

.app-proposal-progress .progress-text {
    color: var(--text-dim);
    background: linear-gradient(90deg, var(--text-dim), var(--accent-light, var(--accent)), var(--text-dim));
    background-size: 200% 100%;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    background-clip: text;
    animation: thinking-shimmer 2s ease-in-out infinite;
}

.app-proposal-progress .progress-percent {
    color: var(--text);
}

.app-proposal-status {
    color: var(--green, #22c55e);
    font-size: 14px;
    font-weight: 600;
    text-align: center;
    padding: 12px 20px;
}

.app-proposal-status.cancelled {
    color: #999;
}

.app-proposal-failure {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 10px;
}

.app-proposal-done-card {
    padding: 8px 20px 20px;
    margin: 0 -4px;
    border-radius: 12px;
    cursor: pointer;
}

.app-proposal-done-card:active {
    opacity: 0.7;
}

/* Clarify widget */
.msg.clarify-widget-msg {
    /* Tint only over the solid chat background; no per-frame blur. */
    background: rgba(255, 255, 255, 0.07);
    align-self: flex-start;
    border-bottom-left-radius: 4px;
    padding: 14px 16px;
}

.clarify-widget-question {
    font-size: 14px;
    color: var(--text);
    margin-bottom: 10px;
    line-height: 1.4;
}

/* Reports use the full message column; narrow screens scroll only the table. */
.msg.research-checkpoint-msg {
    width: 100%;
    max-width: 100%;
}

.research-table-scroll {
    max-width: 100%;
    overflow-x: auto;
    margin: 8px 0;
}

.clarify-widget-question .research-table-scroll table {
    min-width: 560px;
    margin: 0;
    table-layout: auto;
}

.clarify-widget-question .research-table-scroll th,
.clarify-widget-question .research-table-scroll td {
    width: auto;
    word-break: normal;
    overflow-wrap: normal;
}

/* Options widget */
.msg.options-widget-msg {
    background: rgba(255, 255, 255, 0.07);
    align-self: flex-start;
    border-bottom-left-radius: 4px;
    max-width: 90%;
    padding: 14px 16px;
    border: 1px solid rgba(255, 255, 255, 0.08);
    min-width: 260px;
}

.options-widget-prompt {
    font-size: 13px;
    color: var(--text-dim);
    margin-bottom: 10px;
    letter-spacing: 0.02em;
}

.options-widget-list {
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.options-widget-btn {
    background: rgba(255, 255, 255, 0.07);
    color: var(--text);
    border: 1px solid rgba(255, 255, 255, 0.08);
    border-radius: 12px;
    padding: 12px 18px;
    font-size: 15px;
    cursor: pointer;
    transition: all 0.2s ease;
    text-align: left;
    width: 100%;
}

.options-widget-btn:hover {
    background: rgba(0, 122, 255, 0.15);
    border-color: rgba(0, 122, 255, 0.4);
    color: #409cff;
    box-shadow: 0 0 20px rgba(0, 122, 255, 0.1);
}

.options-widget-btn:active {
    transform: scale(0.98);
}

.options-widget-btn.selected {
    background: rgba(0, 122, 255, 0.2);
    border-color: rgba(0, 122, 255, 0.5);
    color: #409cff;
    cursor: default;
}

.options-widget-btn:disabled {
    opacity: 0.35;
    cursor: default;
    pointer-events: none;
}

.options-widget-btn.selected:disabled {
    opacity: 1;
}

.options-custom-row {
    display: flex;
    gap: 6px;
}

.options-custom-input {
    flex: 1;
    background: rgba(255, 255, 255, 0.05);
    border: 1px dashed rgba(255, 255, 255, 0.15);
    border-radius: 12px;
    padding: 12px 18px;
    font-size: 15px;
    color: var(--text);
    outline: none;
    transition: border-color 0.2s;
}

.options-custom-input::placeholder {
    color: rgba(255, 255, 255, 0.25);
}

.options-custom-input:focus {
    border-color: rgba(56, 189, 248, 0.4);
    border-style: solid;
}

.options-custom-submit {
    width: 46px;
    min-width: 46px;
    padding: 0;
    text-align: center;
    font-size: 18px;
}

/* Light theme: clarify + options widgets */
[data-theme="light"] .msg.clarify-widget-msg {
    background: #f5f5fa;
}

[data-theme="light"] .msg.options-widget-msg {
    background: #f5f5fa;
    border-color: #e0e0ea;
}

[data-theme="light"] .options-widget-prompt {
    color: #555;
}

[data-theme="light"] .options-widget-btn {
    background: #fff;
    border-color: #d8d8e4;
    color: #222;
}

[data-theme="light"] .options-widget-btn:hover {
    background: rgba(79, 110, 247, 0.08);
    border-color: rgba(79, 110, 247, 0.4);
    color: #4f6ef7;
    box-shadow: 0 0 12px rgba(79, 110, 247, 0.08);
}

[data-theme="light"] .options-widget-btn.selected {
    background: rgba(79, 110, 247, 0.1);
    border-color: rgba(79, 110, 247, 0.4);
    color: #4f6ef7;
}

[data-theme="light"] .options-custom-input {
    background: #fff;
    border-color: #d8d8e4;
    color: #222;
}

[data-theme="light"] .options-custom-input::placeholder {
    color: #aaa;
}

[data-theme="light"] .options-custom-input:focus {
    border-color: rgba(79, 110, 247, 0.5);
}

/* ══════════════════════════════════════════════════════════════════
   SIDEBAR LAYOUT — mobile layout everywhere, sidebar on wide screens
   ══════════════════════════════════════════════════════════════════ */

/* Sidebar, dashboard pills and close hint are enabled only on wide screens.
   The dashboard profile card remains visible on narrow web layouts. */
.sidebar {
    display: none !important;
}

.home-close-hint,
.dashboard-pill {
    display: none;
}

/* ── Anonymous (logged-out) viewer ──────────────────────────────────────────
   Public profile browsing only: no sidebar, no composer, no own dashboard.
   Collapsing --sidebar-w to 0 removes the left offset that every fixed element
   (.desktop / .chat-bar / .chat) applies on wide screens, so the profile fills
   the viewport instead of leaving a gap where the (hidden) sidebar was. */
body.anon { --sidebar-w: 0px; }
body.anon .sidebar { display: none !important; }
body.anon .chat-bar,
body.anon .home-hero,
body.anon .dashboard-pill,
body.anon #desktopIcons,
body.anon #panelPrivate .desktop-panel-title { display: none !important; }
body.anon .back-btn,
body.anon .profile-actions-btn,
body.anon .profile-actions-dropdown { display: none !important; }
/* Profile/overlay desktop rules below can otherwise re-enable the universal
   close affordance after this anonymous block through a more-specific selector. */
body.anon .home-close-hint { display: none !important; }

/* Sign-in affordance — the only way back to auth from a logged-out profile. */
.anon-signin-btn { display: none; }
body.anon .anon-signin-btn {
    display: inline-flex;
    align-items: center;
    position: fixed;
    top: 14px;
    right: 16px;
    z-index: 2000;
    padding: 9px 20px;
    border: none;
    border-radius: 22px;
    background: var(--accent);
    color: #fff;
    font-family: inherit;
    font-size: 14px;
    font-weight: 600;
    cursor: pointer;
    box-shadow: 0 2px 12px rgba(0, 0, 0, 0.25);
    transition: transform 0.12s ease, filter 0.12s ease;
}
body.anon .anon-signin-btn:hover { filter: brightness(1.08); }
body.anon .anon-signin-btn:active { transform: scale(0.97); }

/* Room for two-line chat previews; a saved desktop width leaves at least half
   the viewport for content. Keep the preference separate from the effective width
   so anonymous mode can still override --sidebar-w to zero. */
@media (min-width: 900px) {
    :root {
        --sidebar-default-w: clamp(344px, 24vw, 416px);
        --sidebar-w: clamp(256px, var(--sidebar-preferred-w, var(--sidebar-default-w)), min(600px, 50vw));
    }
}

@media (min-width: 900px) and (max-width: 1800px) {
    :root {
        --sidebar-default-w: 344px;
    }
}

/* Wide screens: show sidebar, offset everything right */
@media (min-width: 900px) {
    /* ── Sidebar: fixed left ── */
    .sidebar {
        display: flex !important;
        flex-direction: column;
        position: fixed;
        left: 0;
        top: 0;
        bottom: 0;
        width: var(--sidebar-w);
        /* Plain translucency, no backdrop-filter: a full-height blur column
           re-ran on every background-canvas frame. The aurora glowing through
           unblurred at 0.8 alpha reads the same. */
        background: rgba(10, 10, 10, 0.8);
        border-right: 1px solid var(--border);
        z-index: 1100;
        overflow: hidden;
    }

    /* Keep top breathing room inside the clickable profile row so its
       hover and selection backgrounds reach the top edge of the sidebar. */
    .sidebar-profile {
        padding: 0;
        flex-shrink: 0;
    }

    /* Shimmer placeholder before profile loads — same box as loaded profile */
    .sidebar-profile:empty::before {
        content: '';
        display: block;
        height: 93px;
        border-radius: 0;
        background: linear-gradient(90deg, var(--hover-overlay) 25%, var(--hover-overlay-strong) 50%, var(--hover-overlay) 75%);
        background-size: 200% 100%;
        animation: sidebar-shimmer 1.5s ease-in-out infinite;
    }

    @keyframes sidebar-shimmer {
        0% {
            background-position: 200% 0;
        }

        100% {
            background-position: -200% 0;
        }
    }

    .sidebar-profile-identity {
        position: relative;
        display: flex;
        align-items: center;
        gap: 8px;
        /* Reserve the shortcut gutter even when Ctrl is not held. */
        padding: 21px 6px 20px 16px;
        border-radius: 0;
        cursor: pointer;
        transition: background 0.15s;
    }

    .sidebar-profile-identity:hover {
        background: var(--hover-overlay);
    }

    /* Profile active state — the same quiet gray as selected chat items */
    .sidebar-profile.active .sidebar-profile-identity,
    .sidebar-profile.active .sidebar-profile-identity:hover {
        background: var(--hover-overlay-strong);
        border-radius: 0;
    }

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

    .sidebar-profile-info {
        flex: 1;
        min-width: 0;
        overflow: hidden;
    }

    .sidebar-profile-name {
        font-size: 16px;
        font-weight: 600;
        color: var(--text);
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
    }

    .sidebar-profile-social {
        display: flex;
        gap: 10px;
        margin-top: 4px;
        line-height: 1.2;
        white-space: nowrap;
    }

    .sidebar-profile-stat {
        min-width: 0;
        white-space: nowrap;
    }

    .sidebar-profile-stat-num {
        font-size: 13px;
        font-weight: 700;
        color: var(--text);
        margin-right: 3px;
    }

    .sidebar-profile-stat-label {
        font-size: 10px;
        font-weight: 500;
        color: var(--text-dim);
    }

    .sidebar-chats-header {
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: 12px;
        padding: 6px 12px 0 16px;
        flex-shrink: 0;
    }

    .sidebar-chats-title {
        margin: 0;
        font-size: 14px;
        font-weight: 500;
        line-height: 20px;
        color: var(--text-dim);
    }

    .sidebar-new-chat-btn {
        position: relative;
        width: 32px;
        height: 32px;
        padding: 0;
        border: 0;
        border-radius: 50%;
        background: transparent;
        color: var(--text-dim);
        cursor: pointer;
        display: flex;
        align-items: center;
        justify-content: center;
        transition: background 0.1s, color 0.1s;
        flex-shrink: 0;
    }

    .sidebar-new-chat-btn .sidebar-chat-icon {
        width: 32px;
        height: 32px;
        border-radius: inherit;
        background: transparent;
        color: inherit;
    }

    .sidebar-new-chat-btn:hover {
        background: var(--hover-overlay-strong);
        color: var(--text);
    }

    .sidebar-new-chat-btn.active,
    .sidebar-new-chat-btn.active:hover {
        color: var(--accent);
    }

    .sidebar-new-chat-btn:focus-visible {
        outline: 2px solid var(--accent);
        outline-offset: 2px;
    }

    .sidebar-chats {
        flex: 1;
        overflow-y: auto;
        padding: 0 0 4px;
        display: flex;
        flex-direction: column;
        gap: 0;
    }

    /* (Removed: legacy app-active sidebar overrides — the navigation sidebar is
       now hidden entirely in app-active mode, so the "active app row", the
       hidden section-header, and the per-element overrides for .sidebar-chats
       contents are all dead code.) */

    .sidebar-chat-item {
        padding: 14px 20px 14px 11px;
        border-radius: 0;
        font-size: 13px;
        color: var(--text-dim);
        cursor: pointer;
        display: flex;
        align-items: center;
        gap: 10px;
        transition: background 0.1s, color 0.1s;
        position: relative;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
        flex-shrink: 0;
    }

    /* Keep the 1px spacing inside each row so hover/selection fills it too. */
    .sidebar-chat-item:not(:last-child) {
        padding-bottom: 15px;
    }

    /* Inset hairlines align with the text, leaving the icon column clear. */
    .sidebar-chat-item:not(:last-child)::after {
        content: '';
        position: absolute;
        left: 61px; /* 11px padding + 40px icon + 10px gap */
        right: 20px;
        bottom: 0;
        height: 1px;
        background: rgba(128, 128, 128, 0.28);
        transform: scaleY(0.5);
        transform-origin: bottom;
        pointer-events: none;
    }

    .sidebar-chat-item.active::after,
    .sidebar-chat-item:hover::after,
    .sidebar-chat-item:has(+ .sidebar-chat-item.active)::after,
    .sidebar-chat-item:has(+ .sidebar-chat-item:hover)::after {
        opacity: 0;
    }

    .sidebar-chat-item:hover {
        background: var(--hover-overlay);
        color: var(--text);
        box-shadow: inset 0 0.5px 0 rgba(128, 128, 128, 0.28),
                    inset 0 -0.5px 0 rgba(128, 128, 128, 0.28);
    }

    .sidebar-chat-item:first-child:hover {
        box-shadow: inset 0 -0.5px 0 rgba(128, 128, 128, 0.28);
    }

    .sidebar-chat-item:last-child:hover {
        box-shadow: inset 0 0.5px 0 rgba(128, 128, 128, 0.28);
    }

    .sidebar-chat-item:only-child:hover {
        box-shadow: none;
    }

    /* Selection is a gray one step stronger than hover, not the accent. */
    .sidebar-chat-item.active {
        color: var(--text);
        background: var(--hover-overlay-strong);
    }

    .sidebar-chat-icon {
        width: 22px;
        height: 22px;
        border-radius: 6px;
        flex-shrink: 0;
        display: flex;
        align-items: center;
        justify-content: center;
        font-size: 12px;
        background: rgba(255, 255, 255, 0.06);
        color: var(--text-dim);
    }

    .sidebar-chat-item.active .sidebar-chat-icon {
        color: var(--text);
    }

    .chat-topic-emoji {
        font-family: "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", sans-serif;
        font-size: 15px;
        line-height: 1;
    }

    /* New Chat, profile and chat shortcuts share the same small keycap. */
    body.ctrl-chat-hint .sidebar-chat-item[data-ctrl-num] {
        overflow: visible;
    }
    body.ctrl-chat-hint .sidebar-new-chat-btn[data-ctrl-num]::before,
    body.ctrl-chat-hint .sidebar-chat-item[data-ctrl-num]::before,
    body.ctrl-chat-hint .sidebar-profile-identity[data-ctrl-num]::before {
        content: attr(data-ctrl-num);
        position: absolute;
        left: 0;
        top: 50%;
        transform: translateY(-50%);
        width: 12px;
        height: 12px;
        border-radius: 3px;
        background: var(--accent);
        color: #fff;
        display: flex;
        align-items: center;
        justify-content: center;
        font-size: 10px;
        font-weight: 700;
        font-variant-numeric: tabular-nums;
        font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
        line-height: 1;
        pointer-events: none;
        z-index: 1;
    }
    body.ctrl-chat-hint .sidebar-new-chat-btn[data-ctrl-num]::before {
        left: -14px;
    }
    body.ctrl-chat-hint #panelPrivate .desktop-panel-title[data-ctrl-num]::after,
    body.ctrl-chat-hint #desktopIcons .desktop-icon[data-ctrl-num]::before {
        content: attr(data-ctrl-num);
        display: inline-flex;
        align-items: center;
        justify-content: center;
        width: 16px;
        height: 16px;
        border-radius: 4px;
        background: var(--accent);
        color: #fff;
        font: 700 11px/1 -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
        pointer-events: none;
    }
    body.ctrl-chat-hint #panelPrivate .desktop-panel-title[data-ctrl-num]::after {
        margin-left: 10px;
        vertical-align: middle;
    }
    body.ctrl-chat-hint #desktopIcons .desktop-icon[data-ctrl-num] { background: var(--hover-overlay); }
    body.ctrl-chat-hint #desktopIcons .desktop-icon[data-ctrl-num]::before {
        position: absolute;
        top: 12px;
        right: 12px;
        z-index: 1;
    }
    /* Settings has a bare gear <svg> (no icon chip), so swap it for a keycap. */
    body.ctrl-chat-hint .dashboard-settings-btn[data-ctrl-num] > svg {
        visibility: hidden;
    }
    body.ctrl-chat-hint .dashboard-settings-btn[data-ctrl-num]::before {
        content: attr(data-ctrl-num);
        position: absolute;
        left: 50%;
        top: 50%;
        transform: translate(-50%, -50%);
        width: 22px;
        height: 22px;
        border-radius: 6px;
        background: var(--accent);
        color: #fff;
        display: inline-flex;
        align-items: center;
        justify-content: center;
        font-size: 12px;
        font-weight: 700;
        line-height: 1;
        flex-shrink: 0;
        font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
    }

    /* Dashboard pills have fixed-size icons, so turn the icon itself
       into the keycap without changing the pill's layout. */
    body.ctrl-chat-hint .dashboard-notif-icon[data-ctrl-num],
    body.ctrl-chat-hint .dashboard-token-icon[data-ctrl-num] {
        background: var(--accent);
        color: #fff;
        font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
    }
    body.ctrl-chat-hint .dashboard-notif-icon[data-ctrl-num] > *,
    body.ctrl-chat-hint .dashboard-token-icon[data-ctrl-num] > * {
        display: none;
    }
    body.ctrl-chat-hint .dashboard-notif-icon[data-ctrl-num]::before,
    body.ctrl-chat-hint .dashboard-token-icon[data-ctrl-num]::before {
        content: attr(data-ctrl-num);
        font-size: 12px;
        font-weight: 700;
        line-height: 1;
    }

    .sidebar-chat-copy {
        display: flex;
        flex-direction: column;
        gap: 1px;
        flex: 1;
        min-width: 0;
    }

    .sidebar-chat-name,
    .sidebar-chat-preview,
    .sidebar-chat-date {
        display: block;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
        min-width: 0;
    }

    .sidebar-chat-item .sidebar-chat-name {
        font-size: 14px;
        line-height: 20px;
        font-weight: 500;
        color: var(--text);
    }

    .sidebar-chat-preview {
        min-height: 18px;
        font-size: 13px;
        line-height: 18px;
        color: var(--text-dim);
    }

    .sidebar-chat-date {
        margin-top: 1px;
        font-size: 11px;
        line-height: 16px;
        color: var(--text-muted);
    }

    .sidebar-chat-item .sidebar-chat-icon {
        width: 40px;
        height: 40px;
        border-radius: 11px;
        font-size: 26px;
    }
    .sidebar-chat-item .sidebar-chat-icon svg { width: 21px; height: 21px; }
    .sidebar-chat-item .chat-app-icon {
        width: 40px;
        height: 40px;
        flex-basis: 40px;
        border-radius: 11px;
        font-size: 20px;
    }

    /* Blinking caret while a new chat's title types into the sidebar
       (see _typeOutChatName in app.js). */
    .sidebar-chat-item.is-typing .sidebar-chat-name::after {
        content: '';
        display: inline-block;
        width: 1px;
        height: 0.95em;
        margin-left: 1px;
        vertical-align: text-bottom;
        background: currentColor;
        opacity: 0.8;
        animation: sidebarChatCaret 0.9s steps(1) infinite;
    }

    @keyframes sidebarChatCaret {
        0%, 50% { opacity: 0.8; }
        50.01%, 100% { opacity: 0; }
    }

    /* Matching home pills: notifications left, subscription and settings right. */
    .dashboard-pill {
        position: absolute;
        top: 24px;
        z-index: 6;
        display: flex;
        align-items: stretch;
        height: 42px;
        border: 0;
        border-radius: 999px;
        background: var(--bg-secondary);
        box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
        overflow: hidden;
        flex-shrink: 0;
    }

    [data-theme="light"] .dashboard-pill {
        border: 1px solid var(--border);
        box-shadow: none;
    }

    .dashboard-notifications { left: 24px; }
    .dashboard-account { right: 24px; }

    .desktop.section-open .dashboard-pill,
    body.chat-open .dashboard-pill,
    body.sidebar-chat-open .dashboard-pill,
    body.page-stack-open .dashboard-pill {
        display: none;
    }

    .dashboard-notif-btn,
    .dashboard-subscription-btn,
    .dashboard-settings-btn {
        display: flex;
        position: relative;
        align-items: center;
        justify-content: center;
        border: 0;
        background: transparent;
        color: var(--text);
        font: inherit;
        cursor: pointer;
        transition: background 0.15s, color 0.15s;
    }

    .dashboard-notif-btn:hover,
    .dashboard-subscription-btn:hover,
    .dashboard-settings-btn:hover {
        background: var(--hover-overlay);
    }

    .dashboard-notif-btn:focus-visible,
    .dashboard-subscription-btn:focus-visible,
    .dashboard-settings-btn:focus-visible {
        outline: 2px solid var(--accent);
        outline-offset: -3px;
    }

    [data-theme="light"] .dashboard-notif-btn:focus,
    [data-theme="light"] .dashboard-subscription-btn:focus,
    [data-theme="light"] .dashboard-settings-btn:focus {
        outline: none;
    }

    [data-theme="light"] .dashboard-notif-btn:focus-visible,
    [data-theme="light"] .dashboard-subscription-btn:focus-visible,
    [data-theme="light"] .dashboard-settings-btn:focus-visible {
        background: var(--hover-overlay);
    }

    .dashboard-notif-btn {
        gap: 8px;
        padding: 0 14px;
        border-radius: 999px;
        font-size: 14px;
        font-weight: 500;
        line-height: 20px;
        white-space: nowrap;
    }

    .dashboard-notif-badge {
        display: none;
        width: 8px;
        height: 8px;
        border-radius: 50%;
        background: #ef4444;
        flex-shrink: 0;
    }

    .dashboard-notif-btn.has-unread .dashboard-notif-badge {
        display: inline-block;
    }

    .dashboard-subscription-btn {
        gap: 7px;
        padding: 0 14px;
        border-radius: 999px 0 0 999px;
    }

    .dashboard-notif-icon,
    .dashboard-token-icon {
        display: flex;
        align-items: center;
        justify-content: center;
        width: 22px;
        height: 22px;
        border-radius: 6px;
        color: var(--accent);
        flex-shrink: 0;
    }

    .dashboard-token-balance {
        font-size: 14px;
        font-weight: 600;
        font-variant-numeric: tabular-nums;
        line-height: 20px;
        white-space: nowrap;
    }

    .dashboard-settings-btn {
        width: 44px;
        padding: 0;
        border-radius: 0 999px 999px 0;
        color: var(--text-dim);
    }

    [data-theme="light"] .dashboard-settings-btn::after {
        content: '';
        position: absolute;
        left: 0;
        top: 10px;
        bottom: 10px;
        width: 1px;
        background: color-mix(in srgb, var(--text) 14%, transparent);
    }

    .dashboard-settings-btn:hover {
        color: var(--text);
    }

    /* Styled 1:1 with .chat-input-row to look like the chat input field —
       clicking feels like focusing the input and expanding it into the chat.
       Sits at the bottom of the sidebar, slightly darker than its background. */
    .sidebar-chat-btn {
        display: none;
        flex-direction: column;
        align-items: stretch;
        gap: 0;
        width: auto;
        margin: 0 12px 14px;
        padding: 6px;
        border-radius: 14px;
        background: rgba(59, 59, 59, 0.29);
        font-family: inherit;
        color: var(--text);
        cursor: pointer;
        border: 1px solid transparent;
        transform: translateY(0);
        box-shadow: 0 0 0 rgba(0, 0, 0, 0);
        transition: background 0.2s, transform 0.15s, box-shadow 0.2s, border-color 0.15s;
    }

    .sidebar-chat-btn:hover,
    .sidebar-chat-btn:focus-visible {
        background: rgba(59, 59, 59, 0.29);
        border-color: rgba(255, 255, 255, 0.04);
        transform: translateY(-1px);
        box-shadow: 0 2px 8px rgba(0, 122, 255, 0.1);
        outline: none;
    }

    .sidebar-chat-btn-top {
        display: flex;
        align-items: center;
        gap: 0;
        width: 100%;
    }

    .sidebar-chat-btn-bottom {
        display: flex;
        align-items: center;
        padding: 2px 2px 2px 2px;
    }

    .sidebar-chat-btn-attach {
        width: 30px;
        height: 30px;
        flex-shrink: 0;
        display: flex;
        align-items: center;
        justify-content: center;
        color: var(--text-muted);
        border-radius: 50%;
    }

    .sidebar-chat-btn-placeholder {
        flex: 1;
        min-width: 0;
        padding: 8px 4px;
        color: var(--text-muted);
        font-size: 14px;
        font-weight: 400;
        text-align: left;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }

    .sidebar-chat-btn-model {
        color: var(--text-muted);
        font-size: 12px;
        padding: 2px 20px 2px 8px;
        border-radius: 8px;
        position: relative;
    }

    .sidebar-chat-btn-model::after {
        content: '';
        position: absolute;
        right: 7px;
        top: 50%;
        transform: translateY(-50%);
        border-left: 3.5px solid transparent;
        border-right: 3.5px solid transparent;
        border-bottom: 4px solid currentColor;
        opacity: 0.5;
    }

    body.app-active:not(.sidebar-profile-open):not(.sidebar-chat-open) .sidebar-chat-btn {
        display: flex;
    }

    /* ── Offset all fixed elements by sidebar width ── */
    .desktop {
        left: var(--sidebar-w) !important;
    }

    .chat-bar {
        left: var(--sidebar-w) !important;
    }

    .chat {
        left: var(--sidebar-w) !important;
    }

    .desktop::before,
    .desktop::after {
        display: none !important;
    }

    .desktop-panel.active {
        display: flex;
        flex-direction: column;
        align-items: center;
        box-sizing: border-box;
    }

    .desktop-panel-title {
        display: block !important;
        width: 100%;
        max-width: 800px;
        padding: 65px 18px 18px;
        font-size: 28px;
        font-weight: 700;
        color: var(--text);
        letter-spacing: -0.3px;
    }

    .desktop-icons {
        max-width: 800px;
        width: 100%;
        padding-top: 0;
        padding-bottom: 120px;
        justify-content: space-between;
        grid-template-columns: repeat(auto-fill, 154px) !important;
    }

    .desktop-icon {
        --iconbox-h: 134px;
    }

    .desktop-icon .icon-box {
        width: 134px;
        height: 134px;
        border-radius: 24px;
    }

    .desktop-icon .icon-box.icon-logo img {
        border-radius: 24px;
    }

    .profile-apps-strip {
        grid-template-columns: repeat(auto-fill, 154px);
        max-width: 674px;
    }

    .profile-apps-grid {
        grid-template-columns: repeat(auto-fill, 154px);
        justify-content: space-between;
    }

    #publicProfile {
        display: none !important;
    }

    /* ── Home screen: chat slides down from above ── */
    /* Panel stays mounted so it can animate down from the top — uses transform.
       Spans from sidebar to the viewport right so the opaque panel covers the
       full right area. The narrower content column lives inside chat-body via a
       max-width centered child (see .chat-body > * rules above). Width stays wide
       even while the panel is offscreen, so closing animates transform and opacity —
       there's no width snap mid-slide. */
    .chat {
        display: flex;
        left: var(--sidebar-w) !important;
        right: 0 !important;
        width: auto !important;
        max-width: none !important;
        margin-left: 0 !important;
        margin-right: 0 !important;
        border-right: none;
        transform: translateY(-100%);
        opacity: 0;
        pointer-events: none;
        transition: transform 0.32s cubic-bezier(0.16, 1, 0.3, 1),
                    opacity 0.32s cubic-bezier(0.16, 1, 0.3, 1);
        will-change: transform, opacity;
    }

    /* Shorter exit; reset the full entrance offset once the panel is invisible. */
    body.chat-closing:not(.chat-open) .chat {
        transform: translateY(-16.667%);
    }

    body.chat-open .chat {
        transform: translateY(0);
        opacity: 1;
        pointer-events: auto;
    }

    /* On first send the dashboard drops out beneath the opening chat. JS moves
       the composer into its fixed container and animates its own flight to the
       bottom, then resets the covered dashboard when the chat is fully open. */
    body.home-send-transition #panelPrivate {
        pointer-events: none;
        will-change: transform;
        animation: desktop-home-send-down 0.26s cubic-bezier(0.16, 1, 0.3, 1) forwards;
    }

    @keyframes desktop-home-send-down {
        from {
            transform: translate3d(0, 0, 0);
        }

        to {
            transform: translate3d(0, calc(100vh + 160px), 0);
        }
    }

    /* Desktop occupies the area to the right of the sidebar. */
    .desktop {
        left: var(--sidebar-w) !important;
        right: 0 !important;
    }

    /* Restore mobile bottom gradient */
    .desktop::after {
        display: block;
    }

    /* Chat-bar follows the same centered column as .desktop-icons. */
    .chat-bar {
        left: var(--sidebar-w) !important;
        right: 0 !important;
        width: auto !important;
        max-width: 800px;
        margin-left: auto;
        margin-right: auto;
    }

    /* Bottom fade now radiates from the input field's own shadow (see the
       .chat-input-row box-shadow below) instead of a full-width gradient band,
       so the gradient pseudo-element is disabled on desktop. */
    .chat-bar::before {
        display: none;
    }

    /* The fade pools below the field itself: a large, soft shadow in the page
       background colour sitting under the input, spilling off the bottom edge
       of the screen and darkening the chat content behind it. --bg-primary
       tracks the theme (#0a0a0a dark / #ffffff light). Floating state only —
       the centered hero composer keeps a clean edge. */
    .chat-bar:not(.in-hero) .chat-input-row {
        box-shadow: 0 40px 50px 30px var(--bg-primary);
    }

    /* ── Home hero: composer centered on the start screen ──
       JS (chat-bar hero logic in app.js) parks #chatBar inside #homeHeroSlot
       while the dashboard is at the top with no overlay open. The bar becomes
       a static in-flow block that scrolls away with the panel; once the hero
       is fully above the viewport the bar returns to its fixed bottom slot
       and .bar-pop slides it up from the bottom edge. */
    .home-hero {
        display: grid;
        /* Independent rows: the greeting's position never depends on the
           composer's height or whether it is currently mounted in the slot.
           108px reserves the normal desktop composer footprint. */
        grid-template-rows: minmax(max-content, calc(32vh - 68px)) minmax(108px, auto);
        align-content: start;
        width: 100%;
        max-width: 800px;
        /* Composer center lands at ~1/3 of the viewport (raised from ~center)
           so more of the apps grid is visible on the start screen. The +px
           constant keeps the center proportional across viewport heights
           (offsets ~half the centered bar's height) and is the knob for
           nudging the bar up/down by a fixed amount. */
        min-height: calc(32vh + 40px);
        box-sizing: border-box;
        flex-shrink: 0;
    }

    /* "Fork" wordmark centered above the composer. Lives
       inside .home-hero so it scrolls away with the composer; hidden on mobile
       because .home-hero itself is display:none below 900px.
       Uses the monospace font from logo variant 01C. */
    .home-hero-greeting {
        align-self: end;
        display: flex;
        align-items: center;
        justify-content: center;
        font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;
        font-size: 42px;
        font-weight: 800;
        letter-spacing: -0.02em;
        line-height: 1.1;
        color: var(--text);
        /* Keep the wordmark above the independently positioned composer row. */
        margin: 0 0 65px;
        padding: 0 16px;
    }

    /* Variant 01C: the blue dot follows the wordmark at its baseline. */
    .home-hero-greeting-cursor {
        width: 10px;
        height: 10px;
        margin-left: 6px;
        margin-bottom: 6px;
        align-self: flex-end;
        border-radius: 50%;
        background: var(--accent);
    }

    /* Plain block (NOT flex): the bar carries `width: auto !important` from the
       wide-screen rules above, which as a flex item would shrink-to-content —
       as a block-level child it stretches to the slot's full width instead. */
    .home-hero-slot {
        width: 100%;
    }

    .chat-bar.in-hero {
        position: static;
        margin: 0;
        /* Same side padding as the floating bar so the input row keeps the
           exact same width in both states. */
        padding: 0 16px;
        transform: none;
        transition: none;
        z-index: auto;
    }

    /* The returning composer flies above the closing chat until it reaches
       its reserved dashboard slot. */
    .home-composer-flight {
        position: fixed;
        z-index: 10001;
        pointer-events: none;
    }

    .home-composer-flight .chat-bar {
        pointer-events: auto;
    }

    /* Centered composer is ~40% taller than the floating one — more room to
       type, Claude-style. The floating state keeps the compact height. */
    .chat-bar.in-hero .chat-input-row textarea {
        min-height: 68px;
        padding: 10px 4px 8px 4px;
    }

    /* In the tall centered box the action buttons must sit at the TOP, level
       with the first line of the placeholder — not sink to the bottom (which
       is what the default flex-end alignment does once the textarea grows).
       The per-button nudges center each icon on the ~16px text line: the
       attach (30px) sits slightly lower to match the first line's optical
       center, while the taller mic (38px) lifts a hair. */
    .chat-bar.in-hero .chat-input-top {
        align-items: flex-start;
    }

    .chat-bar.in-hero .chat-attach,
    .chat-bar.in-hero .chat-location {
        margin-top: 5px;
        margin-bottom: 0;
    }

    .chat-bar.in-hero .chat-mic {
        margin-top: -1px;
    }

    .chat-bar.in-hero::before {
        display: none;
    }

    .chat-bar.bar-pop {
        animation: chat-bar-pop 0.3s cubic-bezier(0.16, 1, 0.3, 1);
    }

    @keyframes chat-bar-pop {
        from {
            transform: translateY(calc(100% + 40px));
        }

        to {
            transform: translateY(0);
        }
    }

    /* Transient chat overlays can still use the desktop as a click-away area.
       Profile pages do not: their background keeps the normal cursor and the
       page closes only through Back/X. */
    body.chat-open .desktop,
    body.sidebar-chat-open .desktop {
        cursor: pointer;
    }

    /* Universal close hint button. Default colors target the dark theme (which
       is the app default — light theme is opt-in via [data-theme="light"]).
       Light-theme override below flips to dark X on light translucent. */
    .home-close-hint {
        display: none;
        position: fixed;
        top: 20px;
        right: 24px;
        width: 36px;
        height: 36px;
        border-radius: 50%;
        background: rgba(255, 255, 255, 0.1);
        color: rgba(255, 255, 255, 0.6);
        align-items: center;
        justify-content: center;
        z-index: 1200;
        cursor: pointer;
        transition: transform 0.2s, background 0.2s, color 0.2s;
    }

    [data-theme="light"] .home-close-hint {
        background: rgba(0, 0, 0, 0.06);
        color: rgba(0, 0, 0, 0.35);
    }

    body.chat-open .home-close-hint,
    .desktop.profile-open~.home-close-hint,
    body.sidebar-profile-open .home-close-hint,
    body.sidebar-chat-open .home-close-hint,
    body.page-stack-open .home-close-hint {
        display: flex;
    }

    body.chat-open .desktop:hover~.home-close-hint,
    body:has(.page-stack-right-gutter:hover) #homeCloseHint,
    body.chat-open .home-close-hint:hover,
    .desktop.profile-open~.home-close-hint:hover,
    body.sidebar-profile-open .home-close-hint:hover,
    body.page-stack-open .home-close-hint:hover {
        transform: scale(1.2);
        background: rgba(255, 255, 255, 0.18);
        color: #fff;
    }

    [data-theme="light"] body.chat-open .desktop:hover~.home-close-hint,
    [data-theme="light"] body:has(.page-stack-right-gutter:hover) #homeCloseHint,
    [data-theme="light"] body.chat-open .home-close-hint:hover,
    [data-theme="light"] .desktop.profile-open~.home-close-hint:hover,
    [data-theme="light"] body.sidebar-profile-open .home-close-hint:hover,
    [data-theme="light"] body.page-stack-open .home-close-hint:hover {
        background: rgba(0, 0, 0, 0.1);
        color: rgba(0, 0, 0, 0.6);
    }

    /* Chat-right-gutter hover still scales the X — same as profile/notif gutters.
       Color/background come from the theme-aware base + universal hover rules
       above (no chat-specific override needed). */
    body:has(#chatRightGutter:hover) #homeCloseHint,
    body.app-active:has(#sectionRightGutter:hover) #homeCloseHint {
        transform: scale(1.2);
        background: rgba(255, 255, 255, 0.18);
        color: #fff;
    }

    [data-theme="light"] body:has(#chatRightGutter:hover) #homeCloseHint,
    [data-theme="light"] body.app-active:has(#sectionRightGutter:hover) #homeCloseHint {
        background: rgba(0, 0, 0, 0.1);
        color: rgba(0, 0, 0, 0.6);
    }

    /* Panel layout (padding-right + content max-width) lives on the shared
       .section-panel rules — no profile-specific override needed. */

    /* Hide the mobile back-btn on desktop — #homeCloseHint (the X on the right)
       replaces it for all overlay states. */
    .back-btn {
        display: none !important;
    }

    /* Hide profile header bar (info is in content) */
    .desktop.profile-open .profile-open-header {
        display: none !important;
    }

    /* Show the chat resize/collapse handle only when chat is actually visible
       as a column next to the app — i.e. sidebar-chat-open / sidebar-appchat-open.
       Hide on home (no app) and in pure app-fullscreen (no chat overlay). */
    body:not(.app-active) .chat-resize-handle,
    body.app-active:not(.sidebar-chat-open):not(.sidebar-appchat-open) .chat-resize-handle {
        display: none !important;
    }

    /* Hide chat header and logo-panel (duplicated in sidebar) */
    .chat-header {
        display: none !important;
    }

    .chat-context {
        display: none !important;
    }

    .logo-panel {
        display: none !important;
    }

    /* ── When app IS active: hide the navigation sidebar entirely; the app
       fills the full viewport width. The round chat-bubble button opens the
       chat as a left column beside the app. ── */
    body.app-active .sidebar {
        display: none !important;
    }

    body.app-active .desktop::after {
        display: none !important;
    }

    /* Chat hidden by default when app active */
    body.app-active .chat {
        display: none !important;
        max-width: none;
        margin: 0;
        right: 0 !important;
    }

    body.app-active.chat-open .chat {
        display: none !important;
    }

    body.app-active .chat-bar {
        display: none !important;
        max-width: none;
        margin: 0;
        right: 0 !important;
    }

    body.app-active.chat-open .chat-bar {
        display: none !important;
    }

    /* App iframe spans full width — sidebar is hidden in app-active. */
    body.app-active .desktop {
        left: 0 !important;
        transition: left 0.25s cubic-bezier(0.4, 0, 0.2, 1);
    }

    /* The app title is centered independently from the left/right controls. */
    body.app-active .app-toolbar-title {
        display: inline-flex;
        position: absolute;
        left: 50%;
        top: 2px;
        max-width: min(60%, 480px);
        transform: translateX(-50%);
        cursor: pointer;
    }

    body.app-active .app-toolbar-chat-btn {
        position: absolute;
        top: 0;
        left: 0;
    }

    /* A pushed page needs Back in the first slot; keep chat beside it. */
    body.app-active .app-tab-toolbar:has(.app-toolbar-back:not(.close-mode)) .app-toolbar-chat-btn {
        left: 48px;
    }

    /* sidebar-chat-open is the home-view centered chat overlay. In app-active
       there's no sidebar to host the "Chat" button anymore, so this combination
       is effectively legacy — sidebar-appchat-open is the only chat mode here.
       Hide app panels if it ever fires anyway (defensive). */
    body.app-active.sidebar-chat-open .desktop-panels {
        display: none !important;
    }

    /* ── Sidebar profile open: undo app-active expansion, show profile normally ── */
    body.sidebar-profile-open .desktop-panels {
        display: none !important;
    }

    body.sidebar-profile-open #sectionPanel {
        display: block !important;
    }

    /* Mirror the sidebar-profile rules for the notifications section so
       opening Activity from the sidebar in app-active mode reveals the
       section panel over the app (same UX as profile). */
    body.app-active .desktop.notifs-open .desktop-panels {
        display: none !important;
    }

    body.app-active .desktop.notifs-open #sectionPanel {
        display: block !important;
    }

    /* Same mirror for edit-profile — so opening "Edit profile" from the
       settings modal while an app is active reveals the section panel
       (without this, .desktop.edit-profile-open is set but #sectionPanel
       stays hidden by `body.app-active #sectionPanel { display:none !important }`). */
    body.app-active .desktop.edit-profile-open .desktop-panels {
        display: none !important;
    }

    body.app-active .desktop.edit-profile-open #sectionPanel {
        display: block !important;
    }

    body.app-active.sidebar-profile-open .desktop::after {
        display: none !important;
    }

    /* Resize handle at the chat/desktop boundary when app active — drag it
       to grow/shrink the left chat column (--chat-w drives it). */
    body.app-active .chat-resize-handle {
        display: block;
        left: calc(var(--chat-w, 600px) - 3px);
        cursor: col-resize;
    }

    .sidebar-resize-handle {
        position: absolute;
        top: 0;
        right: 0;
        bottom: 0;
        width: 8px;
        z-index: 1;
        cursor: col-resize;
        touch-action: none;
    }

    .sidebar-resize-handle:hover,
    .sidebar-resize-handle:focus-visible,
    body.sidebar-resizing .sidebar-resize-handle {
        background: var(--border);
        outline: none;
    }

    body.sidebar-resizing,
    body.sidebar-resizing * {
        cursor: col-resize !important;
        user-select: none !important;
        -webkit-user-select: none !important;
    }

    body.sidebar-resizing iframe {
        pointer-events: none !important;
    }

    body.sidebar-resizing .desktop,
    body.sidebar-resizing .chat,
    body.sidebar-resizing .chat-bar {
        transition: none !important;
    }

    body.app-active .chat-resize-handle:hover,
    body.app-active .chat-resize-handle.dragging {
        background: rgba(255, 255, 255, 0.08);
    }

    /* Collapsed: hide sidebar + chat, app fullscreen */
    body.app-active.chat-collapsed .sidebar {
        display: none !important;
    }

    body.app-active.chat-collapsed .chat {
        display: none !important;
    }

    body.app-active.chat-collapsed .chat-bar {
        display: none !important;
    }

    body.app-active.chat-collapsed .desktop {
        left: 0 !important;
    }

    body.app-active.chat-collapsed .chat-resize-handle {
        left: 0 !important;
    }

    /* Hide chat header/context when sidebar shown (not when chat replaces sidebar) */
    body.app-active:not(.sidebar-chat-open) .chat-header {
        display: none !important;
    }

    body.app-active .chat-context {
        display: none !important;
    }

    body.app-active .logo-panel {
        display: none !important;
    }

    /* Show chat header + context only for app chats (not general) */
    body.app-active.sidebar-chat-open .chat.app-chat .chat-header {
        display: flex !important;
    }

    body.app-active.sidebar-chat-open .chat.app-chat .chat-context {
        display: flex !important;
    }

    /* Hide "В главный чат" link on desktop when app active */
    body.app-active .back-to-general {
        display: none !important;
    }

    /* Back button in chat-header — hidden by default */
    .sidebar-back-btn {
        display: none;
        width: 40px;
        height: 40px;
        border-radius: 50%;
        border: 1px solid rgba(255, 255, 255, 0.12);
        background: #1e1e1e;
        color: #fff;
        cursor: pointer;
        align-items: center;
        justify-content: center;
        flex-shrink: 0;
        padding: 0;
        box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
        transition: background 0.15s, transform 0.15s;
    }

    .sidebar-back-btn svg {
        width: 18px;
        height: 18px;
    }

    .sidebar-back-btn:hover {
        background: #323232;
        transform: scale(1.05);
    }

    .sidebar-back-btn:active {
        transform: scale(0.95);
    }

    [data-theme="light"] .sidebar-back-btn {
        background: #fff;
        border-color: rgba(0, 0, 0, 0.08);
        color: rgba(20, 20, 20, 0.72);
        box-shadow: 0 4px 14px rgba(0, 0, 0, 0.1);
    }

    [data-theme="light"] .sidebar-back-btn:hover {
        background: #f0f0f0;
        color: rgba(20, 20, 20, 0.92);
    }

    /* ── App chat replaces sidebar (sidebar-appchat-open) ── */
    body.app-active.sidebar-appchat-open .sidebar {
        display: none !important;
    }

    body.app-active.sidebar-appchat-open:not(.chat-collapsed) .chat {
        display: flex !important;
        left: 0 !important;
        width: var(--chat-w, 400px) !important;
        transform: none !important;
        opacity: 1;
        pointer-events: auto !important;
    }

    body.app-active.sidebar-appchat-open:not(.chat-collapsed) .chat-bar {
        display: flex !important;
        left: 0 !important;
        right: auto !important;
        width: var(--chat-w, 400px) !important;
    }

    /* In the left-menu chat the composer sits in a narrow column against the
       sidebar edge, not floating over centered content — so it drops the
       pooled bottom shadow that the centered chat uses. */
    body.app-active.sidebar-appchat-open:not(.chat-collapsed) .chat-bar .chat-input-row {
        box-shadow: none;
    }

    body.app-active.sidebar-appchat-open:not(.chat-collapsed) .desktop {
        left: var(--chat-w, 400px) !important;
    }

    /* In sidebar-appchat-open the chat replaces the sidebar — when chat is
       also collapsed there's no left column at all, so the desktop should
       start at viewport-left rather than at the (hidden) sidebar slot. */
    body.app-active.sidebar-appchat-open.chat-collapsed .desktop {
        left: 0 !important;
    }

    body.app-active.sidebar-appchat-open .chat-header {
        display: flex !important;
    }

    body.app-active.sidebar-appchat-open .chat.app-chat .chat-context {
        display: flex !important;
    }

    body.app-active.sidebar-appchat-open .sidebar-back-btn {
        display: flex;
    }

    body.app-active.sidebar-appchat-open .chat-resize-handle {
        left: calc(var(--chat-w, 400px) - 3px);
    }
}

/* ── Sidebar: light theme ── */
@media (min-width: 900px) {
    [data-theme="light"] .sidebar {
        background: var(--bg-sidebar);
        border-right: 1px solid #ece7e7;
        transition: background-color 0.32s ease;
    }

    [data-theme="light"] body:is(.chat-open, .sidebar-chat-open, .sidebar-appchat-open):not(.chat-collapsed) .sidebar {
        background-color: #f7f7fa;
    }
}

@media (min-width: 900px) and (prefers-reduced-motion: reduce) {
    [data-theme="light"] .sidebar {
        transition: none;
    }
}

[data-theme="light"] .sidebar-chat-item {
    color: var(--text-dim);
}

[data-theme="light"] .sidebar-chat-item:not(.active) .sidebar-chat-name {
    color: #292929;
}

[data-theme="light"] .sidebar-chat-item:hover {
    background: var(--hover-overlay);
    color: var(--text);
}

[data-theme="light"] .sidebar-chat-item.active {
    background: var(--hover-overlay-strong);
    color: var(--text);
}

[data-theme="light"] .sidebar-chat-icon {
    background: rgba(0, 0, 0, 0.05);
    color: var(--text-dim);
}

[data-theme="light"] .sidebar-new-chat-btn .sidebar-chat-icon {
    background: transparent;
    color: inherit;
}

.sidebar-chat-icon.chat-topic-emoji,
.sidebar-chat-item.active .sidebar-chat-icon.chat-topic-emoji,
[data-theme="light"] .sidebar-chat-icon.chat-topic-emoji,
[data-theme="light"] .sidebar-chat-item.active .sidebar-chat-icon.chat-topic-emoji {
    background: transparent;
    border-radius: 0;
}

/* Ctrl-hold "page the chat list" popovers (see app.js). Global default is
   hidden so the lazily-created elements never flash on mobile; shown only when
   Ctrl is held (body.ctrl-chat-hint) and JS marks them .is-on. */
.chat-nav-hint {
    display: none;
    position: fixed;
    z-index: 1200; /* above the sidebar (z-index: 1100) */
    align-items: center;
    gap: 5px;
    padding: 3px 8px 3px 4px;
    border-radius: 999px;
    background: var(--accent);
    color: #fff;
    font-size: 10px;
    font-weight: 600;
    line-height: 1.5;
    white-space: nowrap;
    box-shadow: 0 4px 14px rgba(0, 0, 0, 0.28);
    pointer-events: none;
}
body.ctrl-chat-hint .chat-nav-hint.is-on {
    display: inline-flex;
}
.chat-nav-hint kbd {
    font-family: inherit;
    font-size: 10px;
    font-weight: 700;
    background: rgba(255, 255, 255, 0.24);
    border-radius: 4px;
    padding: 1px 5px;
    line-height: 1.4;
}

/* ── Message action menu (hold / right-click) ── */
.msg-action-backdrop {
    position: fixed;
    inset: 0;
    z-index: 10040;
    background: transparent;
}
.msg-action-menu {
    position: fixed;
    z-index: 10041;
    min-width: 168px;
    padding: 6px;
    background: rgba(28, 28, 30, 0.92);
    backdrop-filter: blur(28px) saturate(150%);
    -webkit-backdrop-filter: blur(28px) saturate(150%);
    border: 1px solid rgba(255, 255, 255, 0.12);
    border-radius: 14px;
    box-shadow: 0 12px 40px rgba(0, 0, 0, 0.45);
    display: flex;
    flex-direction: column;
    gap: 2px;
    animation: msgActionIn 0.12s ease-out;
    transform-origin: top left;
}
@keyframes msgActionIn {
    from { opacity: 0; transform: scale(0.94); }
    to { opacity: 1; transform: scale(1); }
}
.msg-action-item {
    display: flex;
    align-items: center;
    gap: 11px;
    padding: 9px 12px;
    background: none;
    border: none;
    border-radius: 9px;
    color: var(--text, #fff);
    font-size: 14px;
    font-weight: 500;
    text-align: left;
    cursor: pointer;
    transition: background 0.12s;
}
.msg-action-date {
    padding: 6px 12px 8px;
    border-bottom: 1px solid rgba(255, 255, 255, 0.1);
    color: var(--text-muted, rgba(255, 255, 255, 0.55));
    font-size: 11px;
    line-height: 1.3;
    white-space: nowrap;
}
.msg-action-item svg {
    flex-shrink: 0;
    opacity: 0.85;
}
.msg-action-item:hover {
    background: rgba(255, 255, 255, 0.1);
}
.msg-action-item:active {
    background: rgba(255, 255, 255, 0.16);
}
.msg-action-item.destructive {
    color: #ff453a;
}
[data-theme="light"] .msg-action-menu {
    background: rgba(255, 255, 255, 0.95);
    border-color: var(--border);
    box-shadow: 0 12px 40px rgba(0, 0, 0, 0.18);
}
[data-theme="light"] .msg-action-date {
    border-bottom-color: rgba(0, 0, 0, 0.08);
}
[data-theme="light"] .msg-action-item {
    color: var(--text);
}
[data-theme="light"] .msg-action-item:hover {
    background: rgba(0, 0, 0, 0.06);
}
[data-theme="light"] .msg-action-item:active {
    background: rgba(0, 0, 0, 0.1);
}

/* Transient "Copied" confirmation pill */
.copy-flash {
    position: fixed;
    left: 50%;
    bottom: 96px;
    transform: translateX(-50%) translateY(8px);
    z-index: 10050;
    padding: 8px 16px;
    background: rgba(28, 28, 30, 0.92);
    backdrop-filter: blur(24px);
    -webkit-backdrop-filter: blur(24px);
    border: 1px solid rgba(255, 255, 255, 0.12);
    border-radius: 999px;
    color: #fff;
    font-size: 13px;
    font-weight: 600;
    opacity: 0;
    transition: opacity 0.2s, transform 0.2s;
    pointer-events: none;
}
.copy-flash.show {
    opacity: 1;
    transform: translateX(-50%) translateY(0);
}
[data-theme="light"] .copy-flash {
    background: rgba(40, 40, 42, 0.95);
}

/* ── Foreground alarm ──
   A visible-session enhancement only; the copy deliberately says so. */
.fork-alarm-foreground {
    position: fixed;
    z-index: 10060;
    top: max(12px, env(safe-area-inset-top));
    left: 50%;
    width: min(620px, calc(100vw - 24px));
    transform: translate(-50%, -20px) scale(.98);
    opacity: 0;
    pointer-events: none;
    transition: opacity .24s ease, transform .32s cubic-bezier(.2,.8,.2,1);
}
.fork-alarm-foreground.is-visible {
    transform: translate(-50%, 0) scale(1);
    opacity: 1;
    pointer-events: auto;
}
.fork-alarm-card {
    width: 100%;
    min-height: 82px;
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 12px 14px;
    color: #fff;
    text-align: left;
    font: inherit;
    border: 1px solid rgba(255,255,255,.13);
    border-radius: 22px;
    background: linear-gradient(135deg, rgba(31,31,34,.96), rgba(16,16,18,.93));
    box-shadow: 0 18px 55px rgba(0,0,0,.42), inset 0 1px rgba(255,255,255,.06);
    backdrop-filter: blur(28px) saturate(150%);
    -webkit-backdrop-filter: blur(28px) saturate(150%);
    cursor: pointer;
}
.fork-alarm-icon {
    position: relative;
    width: 54px;
    height: 54px;
    flex: 0 0 54px;
    display: grid;
    place-items: center;
    border-radius: 17px;
    color: #ffb23f;
    background: linear-gradient(145deg, rgba(255,178,63,.23), rgba(255,130,45,.11));
    box-shadow: inset 0 0 0 1px rgba(255,181,74,.16);
}
.fork-alarm-icon svg { width: 29px; height: 29px; }
.fork-alarm-icon path { stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.fork-alarm-copy { min-width: 0; flex: 1; display: flex; flex-direction: column; }
.fork-alarm-kicker {
    margin-bottom: 2px;
    color: #ffb23f;
    font-size: 11px;
    line-height: 1.2;
    font-weight: 760;
    letter-spacing: .08em;
    text-transform: uppercase;
}
.fork-alarm-title {
    overflow: hidden;
    color: #fff;
    font-size: 17px;
    line-height: 1.25;
    font-weight: 680;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.fork-alarm-status { display: flex; align-items: center; gap: 6px; margin-top: 4px; color: rgba(255,255,255,.55); font-size: 11px; }
.fork-alarm-status i { width: 6px; height: 6px; border-radius: 50%; background: #4cd964; box-shadow: 0 0 0 3px rgba(76,217,100,.12); }
.fork-alarm-countdown {
    display: flex;
    align-items: center;
    gap: 3px;
    flex: 0 0 auto;
    padding: 9px 12px;
    border-radius: 14px;
    background: rgba(255,255,255,.075);
    font-variant-numeric: tabular-nums;
}
.fork-alarm-countdown b { min-width: 24px; font-size: 20px; line-height: 1; font-weight: 690; text-align: center; }
.fork-alarm-countdown em { color: rgba(255,255,255,.42); font-size: 17px; font-style: normal; animation: forkAlarmColon 1s steps(1) infinite; }
.fork-alarm-stop { display: none; flex: 0 0 auto; padding: 10px 14px; border-radius: 13px; background: #fff; color: #151515; font-size: 13px; font-weight: 700; }
.fork-alarm-foreground.is-ringing .fork-alarm-card { border-color: rgba(255,107,76,.34); background: linear-gradient(135deg, rgba(74,27,21,.97), rgba(31,16,16,.96)); }
.fork-alarm-foreground.is-ringing .fork-alarm-icon { color: #fff; background: linear-gradient(145deg, #ff6b4c, #ef3f36); animation: forkAlarmBell .72s ease-in-out infinite; }
.fork-alarm-foreground.is-ringing .fork-alarm-kicker { color: #ff8a72; }
.fork-alarm-foreground.is-ringing .fork-alarm-status i { background: #ff755f; box-shadow: 0 0 0 3px rgba(255,117,95,.14); }
.fork-alarm-foreground.is-ringing .fork-alarm-countdown { display: none; }
.fork-alarm-foreground.is-ringing .fork-alarm-stop { display: block; }
@keyframes forkAlarmColon { 50% { opacity: .28; } }
@keyframes forkAlarmBell { 0%,100% { transform: rotate(0); } 25% { transform: rotate(7deg); } 75% { transform: rotate(-7deg); } }

@media (max-width: 600px) {
    .fork-alarm-foreground { top: max(8px, env(safe-area-inset-top)); width: calc(100vw - 16px); }
    .fork-alarm-card { min-height: 74px; gap: 10px; padding: 10px; border-radius: 19px; }
    .fork-alarm-icon { width: 48px; height: 48px; flex-basis: 48px; border-radius: 15px; }
    .fork-alarm-title { font-size: 15px; }
    .fork-alarm-kicker, .fork-alarm-status { font-size: 10px; }
    .fork-alarm-countdown { padding: 8px 9px; }
    .fork-alarm-countdown b { min-width: 20px; font-size: 18px; }
    .fork-alarm-stop { max-width: 112px; padding: 9px 11px; text-align: center; }
}

@media (prefers-reduced-motion: reduce) {
    .fork-alarm-foreground, .fork-alarm-icon, .fork-alarm-countdown em { animation: none !important; transition: none !important; }
}

/* A live external fork-ssh agent owns development turns. This intentionally
   overrides the normal blue focus ring in every theme/composer placement. */
body.ssh-agent-active .chat-input-row,
body.ssh-agent-active .chat-input-row:focus-within,
[data-theme="light"] body.ssh-agent-active .chat-input-row,
[data-theme="light"] body.ssh-agent-active .chat-input-row:focus-within,
body.ssh-agent-active.attachment-actions-open .chat-input-row,
body.ssh-agent-active.attachment-actions-open .chat-input-row:focus-within {
    border-color: #eab308 !important;
    box-shadow: 0 0 0 1px rgba(234, 179, 8, 0.16) !important;
}

/* ── Fork.prompt — universal host input sheet (ui.prompt, runtime.js) ── */
.fork-prompt-overlay {
    position: fixed;
    inset: 0;
    z-index: 10040; /* above pages (10000+), modals/messenger (10020), toolbar (10030) */
    display: flex;
    align-items: flex-end;
    justify-content: center;
    background: var(--backdrop-color);
    opacity: 0;
    transition: opacity 0.24s ease;
}
.fork-prompt-overlay.is-open {
    opacity: 1;
}
.fork-prompt-sheet {
    position: relative;
    width: 100%;
    max-width: 640px;
    background: var(--bg-secondary);
    border: 1px solid var(--border);
    border-bottom: none;
    border-radius: 22px 22px 0 0;
    padding: 20px 20px calc(16px + env(safe-area-inset-bottom, 0px));
    box-shadow: 0 -18px 60px var(--shadow-heavy);
    transform: translateY(28px);
    opacity: 0;
    transition:
        transform 0.3s cubic-bezier(0.16, 1, 0.3, 1),
        opacity 0.22s ease;
}
.fork-prompt-overlay.is-open .fork-prompt-sheet {
    transform: translateY(0);
    opacity: 1;
}
@media (min-width: 768px) {
    .fork-prompt-overlay {
        align-items: center;
        padding: 24px;
    }
    .fork-prompt-sheet {
        max-width: 520px;
        border-radius: 22px;
        border-bottom: 1px solid var(--border);
        padding-bottom: 18px;
    }
}
.fork-prompt-close {
    position: absolute;
    top: 14px;
    right: 14px;
    width: 30px;
    height: 30px;
    border-radius: 50%;
    border: none;
    cursor: pointer;
    background: var(--hover-overlay);
    color: var(--text-dim);
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background 0.15s ease, color 0.15s ease;
}
.fork-prompt-close:hover {
    background: var(--hover-overlay-strong);
    color: var(--text);
}
.fork-prompt-title {
    font-size: 19px;
    font-weight: 700;
    color: var(--text);
    padding-right: 40px;
}
.fork-prompt-subtitle {
    font-size: 14px;
    line-height: 1.4;
    color: var(--text-dim);
    margin-top: 4px;
    padding-right: 40px;
}
.fork-prompt-input {
    display: block;
    width: 100%;
    margin-top: 14px;
    min-height: 88px;
    max-height: 40vh;
    resize: none;
    border: 1px solid var(--border);
    border-radius: 14px;
    padding: 12px 14px;
    background: var(--bg-primary);
    color: var(--text);
    font-family: inherit;
    font-size: 15px;
    line-height: 1.45;
    outline: none;
    transition: border-color 0.15s ease;
}
.fork-prompt-input:focus {
    border-color: var(--accent);
}
.fork-prompt-input::placeholder {
    color: var(--text-muted);
}
.fork-prompt-actions {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-top: 12px;
}
.fork-prompt-mic {
    width: 42px;
    height: 42px;
    border-radius: 50%;
    border: 1px solid var(--border);
    background: var(--bg-tertiary);
    color: var(--text-dim);
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}
.fork-prompt-mic:hover {
    color: var(--text);
    border-color: var(--border-hover);
}
.fork-prompt-mic.recording {
    background: var(--red);
    border-color: var(--red);
    color: #fff;
    animation: forkPromptPulse 1.2s ease infinite;
}
.fork-prompt-mic.busy {
    pointer-events: none;
    color: var(--text-dim);
}
.fork-prompt-mic.busy svg {
    display: none;
}
.fork-prompt-mic.busy::after {
    content: "";
    width: 16px;
    height: 16px;
    border: 2px solid currentColor;
    border-top-color: transparent;
    border-radius: 50%;
    animation: forkPromptSpin 0.7s linear infinite;
}
.fork-prompt-rec-timer {
    display: none;
    font-size: 13px;
    color: var(--red);
    font-variant-numeric: tabular-nums;
}
.fork-prompt-sheet.is-recording .fork-prompt-rec-timer {
    display: block;
}
.fork-prompt-send {
    margin-left: auto;
    width: 44px;
    height: 44px;
    border-radius: 50%;
    border: none;
    background: var(--accent);
    color: #fff;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: background 0.15s ease, opacity 0.15s ease;
}
.fork-prompt-send:hover:not(:disabled) {
    background: var(--accent-light);
}
.fork-prompt-send:disabled {
    opacity: 0.4;
    cursor: default;
}
@keyframes forkPromptPulse {
    0%, 100% { box-shadow: 0 0 0 0 rgba(239, 68, 68, 0.4); }
    50% { box-shadow: 0 0 0 8px rgba(239, 68, 68, 0); }
}
@keyframes forkPromptSpin {
    to { transform: rotate(360deg); }
}

/* The Info surface owns the full chat panel height. On desktop the composer is
   removed completely. Mobile keeps only its detached close circle so there is
   always an obvious way back from the app chat. */
@media (min-width: 800px) {
    body.chat-info-tab.chat-open #chatBar,
    body.chat-info-tab.sidebar-appchat-open #chatBar {
        display: none !important;
    }
}

@media (max-width: 799px) {
    body.chat-info-tab.chat-open #chatBar,
    body.chat-info-tab.sidebar-appchat-open #chatBar {
        display: flex !important;
        justify-content: flex-end;
        pointer-events: none;
    }

    body.chat-info-tab.chat-open #chatInputArea,
    body.chat-info-tab.sidebar-appchat-open #chatInputArea {
        display: none !important;
    }

    body.chat-info-tab.chat-open #chatBarRight,
    body.chat-info-tab.sidebar-appchat-open #chatBarRight {
        width: 52px;
        min-width: 52px;
        margin-left: auto;
        opacity: 1;
        pointer-events: auto;
    }

    body.chat-info-tab.chat-open #chatBarRight .cbr-bell,
    body.chat-info-tab.chat-open #chatBarRight .cbr-send,
    body.chat-info-tab.sidebar-appchat-open #chatBarRight .cbr-bell,
    body.chat-info-tab.sidebar-appchat-open #chatBarRight .cbr-send {
        display: none !important;
    }

    body.chat-info-tab.chat-open #chatBarRight .cbr-close,
    body.chat-info-tab.sidebar-appchat-open #chatBarRight .cbr-close {
        display: flex !important;
        align-items: center;
        justify-content: center;
    }
}

/* Info console keeps the error viewer's geometry, with neutral log styling. */
.application-console-modal { --console-secondary: #aaa; }
[data-theme="light"] .application-console-modal { --console-secondary: #666; }
.application-console-modal .application-error-time,
.application-console-modal .application-errors-summary,
.application-console-modal .application-errors-empty { color: var(--console-secondary); }
.application-console-modal .application-errors-count { color: var(--text); background: var(--hover-overlay-strong); }
.application-console-toolbar { display: flex; align-items: center; gap: 12px; padding: 12px 22px; border-bottom: 1px solid var(--border); }
.application-console-toolbar > div { flex: 1; color: var(--console-secondary); font-size: 12px; }
.application-console-toolbar select { max-width: 45%; min-height: 36px; border: 1px solid var(--border-hover); border-radius: 9px; background: var(--bg-tertiary); color: var(--text); padding: 6px 10px; font: inherit; font-size: 13px; }
.application-console-event { flex: 0 0 auto; padding: 16px; border: 1px solid var(--border); border-radius: 16px; background: var(--bg-tertiary); }
.application-console-event summary { cursor: pointer; list-style: none; }
.application-console-event summary::-webkit-details-marker { display: none; }
.application-console-event summary:focus-visible { outline: 2px solid var(--console-secondary); outline-offset: 6px; border-radius: 4px; }
.application-console-level { font-size: 11px; font-weight: 700; letter-spacing: .04em; color: var(--console-secondary); }
.application-console-level.level-error { color: #ff6961; }
.application-console-level.level-warn { color: #dba63e; }
.application-console-chevron { margin-left: auto; color: var(--console-secondary); }
.application-console-event[open] .application-console-chevron { transform: rotate(180deg); }
.application-console-message { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3; overflow: hidden; white-space: pre-wrap; overflow-wrap: anywhere; margin-top: 10px; font-size: 14px; line-height: 1.5; }
.application-console-event[open] .application-console-message { display: block; }
.application-console-details { white-space: pre-wrap; overflow-wrap: anywhere; max-height: 440px; overflow: auto; margin: 12px 0 0; padding: 12px; border-radius: 9px; background: var(--bg-secondary); color: var(--console-secondary); font: 12px/1.55 ui-monospace, SFMono-Regular, Menlo, monospace; user-select: text; -webkit-user-select: text; }
.application-console-refresh { width: auto; min-width: 100px; margin: 0; }
.application-console-status:not([hidden]) { display: flex; align-items: center; gap: 12px; padding: 12px 22px; font-size: 12px; color: var(--console-secondary); }
.application-console-status button { margin-left: auto; flex-shrink: 0; padding: 8px 12px; border: 1px solid var(--border-hover); border-radius: 8px; color: var(--text); background: var(--bg-tertiary); cursor: pointer; }
[data-theme="light"] .application-console-level.level-error { color: #bf3028; }
[data-theme="light"] .application-console-level.level-warn { color: #996900; }
@media (max-width: 600px) {
    .application-console-toolbar { padding: 12px 16px; }
    .application-console-toolbar select { font-size: 16px; }
}

/* Catalog rows support arbitrary groups and unavailable models. */
.model-options { display: flex; flex-direction: column; max-height: min(60vh, 480px); overflow-y: auto; }
.model-option, .model-option-label, .mobile-model-option, .mobile-model-variants button { overflow-wrap: anywhere; }
/* Variants break only between words (the row's inherited "anywhere" split "Sonnet"). */
.model-variant { min-height: 22px; height: auto; padding-top: 4px; padding-bottom: 4px; overflow-wrap: normal; }
.model-dropdown [aria-disabled="true"], .mobile-model-sheet [aria-disabled="true"] { opacity: .45; cursor: not-allowed; }
.model-catalog-notice { padding: 8px 12px; font-size: 12px; color: var(--text-muted); }
.model-disabled-reason { margin-top: 6px; font-size: 12px; color: var(--text-muted); }

/* Agent apps use the platform chat as their root surface. The app keeps running. */
.app-chat-launch > .app-tab-iframe { visibility: hidden !important; pointer-events: none !important; }
.app-chat-launch > .app-tab-loader { display: none; }
.app-chat-launch > .fork-messenger > .fork-messenger-sheet { transition: none; }

.icon-build-spinner { fill: none; stroke: #fff; stroke-width: 3; stroke-linecap: round; stroke-dasharray: 40 105; transform-origin: 30px 30px; animation: icon-build-spin 1s linear infinite; }
@keyframes icon-build-spin { to { transform: rotate(360deg); } }

/* ── Chat actions (⋯) left of the close X ── */
.chat-more {
    display: none;
}

.chat-more-btn {
    width: 36px;
    height: 36px;
    border: none;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.1);
    color: rgba(255, 255, 255, 0.6);
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: transform 0.2s, background 0.2s, color 0.2s;
}

.chat-more-btn:hover,
.chat-more.open .chat-more-btn {
    background: rgba(255, 255, 255, 0.18);
    color: #fff;
}

[data-theme="light"] .chat-more-btn {
    background: rgba(0, 0, 0, 0.06);
    color: rgba(0, 0, 0, 0.35);
}

[data-theme="light"] .chat-more-btn:hover,
[data-theme="light"] .chat-more.open .chat-more-btn {
    background: rgba(0, 0, 0, 0.1);
    color: rgba(0, 0, 0, 0.6);
}

.chat-more-menu {
    display: none;
    position: absolute;
    top: calc(100% + 8px);
    right: 0;
    min-width: 200px;
    padding: 6px;
    background: var(--bg-secondary);
    border: 1px solid rgba(255, 255, 255, 0.08);
    border-radius: 14px;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
}

[data-theme="light"] .chat-more-menu {
    border-color: rgba(0, 0, 0, 0.07);
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
}

.chat-more.open .chat-more-menu {
    display: block;
}

.chat-more-item {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    padding: 10px 12px;
    border: none;
    border-radius: 9px;
    background: transparent;
    color: var(--text);
    font: inherit;
    font-size: 14px;
    text-align: left;
    cursor: pointer;
}

.chat-more-item:hover {
    background: rgba(255, 255, 255, 0.07);
}

.chat-more-item.danger {
    color: #ef4444;
}

.chat-more-item[hidden] {
    display: none;
}

[data-theme="light"] .chat-more-item:hover {
    background: rgba(0, 0, 0, 0.05);
}

@media (min-width: 800px) and (max-width: 899px) {
    body.chat-open .chat-more {
        display: block;
        position: fixed;
        top: 16px;
        right: 68px;
        z-index: 10001;
    }

    body.chat-open .chat-more-btn {
        width: 44px;
        height: 44px;
    }
}

@media (min-width: 900px) {
    body.chat-open .chat-more {
        display: block;
        position: fixed;
        top: 20px;
        right: 68px;
        z-index: 1200;
    }
}

body.page-stack-open .chat-more,
body.anon .chat-more {
    display: none !important;
}

/* App conversations keep a launchable title above their existing controls. */
.chat-seg-shell {
    display: contents;
}
.chat.app-chat .chat-context {
    display: block !important;
    max-width: calc(100% - 96px);
}
.chat-app-launch {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    width: 100%;
    margin-bottom: 6px;
}
.chat-app-launch #chatContextLabel {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.chat-topic-photo {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: center;
    border-radius: 6px;
}
.sidebar-chat-item .chat-topic-photo { border-radius: 11px; }
.chat-app-icon {
    display: inline-flex;
    width: 24px;
    height: 24px;
    flex: 0 0 24px;
    border-radius: 6px;
    object-fit: cover;
    vertical-align: middle;
}
.chat-app-icon-placeholder {
    align-items: center;
    justify-content: center;
    background: var(--accent);
    color: white;
    font-size: 13px;
    font-weight: 600;
}
.chat.app-chat .messages { padding-top: 120px; }
@media (min-width: 900px) {
    .chat.app-chat .chat-context,
    body.app-active.sidebar-chat-open .chat.app-chat .chat-context,
    body.app-active.sidebar-appchat-open .chat.app-chat .chat-context {
        display: grid !important;
        grid-template-columns: minmax(0, 1fr) max-content minmax(0, 1fr);
        align-items: center;
        gap: 8px;
        top: 0;
        left: 0;
        right: 0;
        width: 100%;
        max-width: none;
        height: 68px;
        padding: 0 12px;
        box-sizing: border-box;
        transform: none;
        background: var(--bg-primary);
        border-bottom: 1px solid var(--border);
    }

    .chat.app-chat .chat-app-launch {
        grid-column: 1;
        width: auto;
        min-width: 0;
        max-width: none;
        margin: 0;
        padding: 6px 0;
        justify-content: flex-start;
        font-size: 14px;
    }

    .chat.app-chat .chat-seg {
        grid-column: 2;
        justify-self: center;
    }

    .chat.app-chat .chat-seg-btn {
        padding: 6px 10px;
    }

    .chat.app-chat .chat-header {
        width: 100%;
        height: 68px;
    }

    body.app-active.sidebar-appchat-open .chat.app-chat .chat-context {
        padding-left: 60px;
        padding-right: 60px;
    }

    body.app-active.sidebar-appchat-open .chat.app-chat .chat-app-launch {
        display: none;
    }

    .chat.app-chat .messages {
        padding-top: 86px;
    }

    [data-theme="light"] .chat.app-chat .chat-context,
    [data-theme="light"] .chat.app-chat .chat-header {
        background: #fff;
    }

    body.app-active.sidebar-appchat-open .chat.app-chat .chat-context,
    [data-theme="light"] body.app-active.sidebar-appchat-open .chat.app-chat .chat-context {
        background: transparent;
        border-bottom: 0;
        pointer-events: none;
    }

    body.app-active.sidebar-appchat-open .chat.app-chat .chat-seg-shell {
        display: block;
        grid-column: 2;
        justify-self: center;
        padding: 6px;
        border-radius: 16px;
        background: var(--bg-secondary);
        box-shadow: 0 2px 10px var(--shadow-color);
        pointer-events: auto;
    }

    body.app-active.sidebar-appchat-open .chat.app-chat .chat-seg {
        background: var(--bg-tertiary);
        backdrop-filter: none;
        -webkit-backdrop-filter: none;
        pointer-events: auto;
    }

    body.app-active.sidebar-appchat-open .chat.app-chat .chat-header,
    [data-theme="light"] body.app-active.sidebar-appchat-open .chat.app-chat .chat-header {
        background: transparent;
        border-bottom: 0;
        pointer-events: none;
    }

    body.app-active.sidebar-appchat-open .chat.app-chat .chat-header::after {
        display: none;
    }

    body.app-active.sidebar-appchat-open .chat.app-chat .sidebar-back-btn {
        pointer-events: auto;
    }
}
@media (max-width: 899px) {
    body.chat-open .chat.app-chat .chat-body { padding-top: 72px; }
    body.chat-open .chat.app-chat .messages { padding-top: 20px; }

    /* One centered mobile pill: app icon followed by the section switcher. */
    body.chat-open .chat.app-chat .chat-context {
        display: flex !important;
        align-items: center;
        gap: 2px;
        top: 12px;
        width: max-content;
        height: 36px;
        max-width: calc(100vw - 112px);
        padding: 3px 4px;
        border: 1px solid rgba(255, 255, 255, 0.12);
        border-radius: 18px;
        background: rgba(30, 30, 30, 0.78);
        box-shadow: 0 2px 12px rgba(0, 0, 0, 0.3);
    }
    [data-theme="light"] body.chat-open .chat.app-chat .chat-context {
        border-color: rgba(0, 0, 0, 0.08);
        background: linear-gradient(100deg, rgba(255, 255, 255, 0.92), rgba(255, 255, 255, 0.78));
        box-shadow: 0 4px 14px rgba(0, 0, 0, 0.1);
    }
    body.chat-open .chat.app-chat .chat-app-launch {
        flex: 0 0 28px;
        width: 28px;
        min-width: 28px;
        max-width: 28px;
        height: 28px;
        margin: 0;
        padding: 0;
        border: 0;
        border-radius: 50%;
        background: transparent;
        box-shadow: none;
    }
    body.chat-open .chat.app-chat #chatContextLabel { display: none; }
    body.chat-open .chat.app-chat .chat-seg-shell {
        display: block;
        flex: 1 1 auto;
        min-width: 0;
    }
    body.chat-open .chat.app-chat .chat-seg {
        height: 28px;
        padding: 0;
        border: 0;
        border-radius: 14px;
        background: transparent;
        box-shadow: none;
        backdrop-filter: none;
        -webkit-backdrop-filter: none;
    }
    body.chat-open .chat.app-chat .chat-seg-btn {
        flex: 1 1 auto;
        min-width: 0;
        padding: 0 6px;
        border-radius: 14px;
        font-family: inherit;
        font-size: 12px;
    }
    body.chat-open .chat.app-chat .chat-seg-slider {
        top: 0;
        bottom: 0;
        border-radius: 14px;
    }
}
@media (max-width: 359px) {
    body.chat-open .chat.app-chat .chat-seg-btn {
        padding-inline: 4px;
        font-size: 11px;
    }
}

/* Mobile home: chats first, apps second, with shared header and bottom tabs. */
.mobile-home-header, .mobile-home-tabs, .mobile-home-new-chat, .mobile-home-empty { display: none; }
@media (max-width: 899px) {
    :root {
        --mobile-home-surface: #000;
        --mobile-home-header-h: calc(72px + env(safe-area-inset-top, 0px));
        /* Height of the browser's bottom controls that full-height screens now
           extend under (0 where the units are unsupported); scroll lists add it
           so their last rows can still be lifted above those controls. */
        --mobile-browser-chrome: 0px;
        --mobile-browser-chrome: calc(100lvh - 100svh);
        --mobile-home-screen-extra: 0px;
        --mobile-home-bottom-space: calc(172px + env(safe-area-inset-bottom, 0px) + var(--mobile-browser-chrome) + var(--mobile-home-screen-extra));
        --mobile-home-bottom-shade-height: calc(128px + env(safe-area-inset-bottom, 0px) + var(--mobile-browser-chrome) + var(--mobile-home-screen-extra));
        background: var(--mobile-home-surface);
    }
    @supports (height: 100lvh) {
        :root {
            --mobile-home-screen-extra: max(0px, calc(var(--mobile-home-physical-height, 100lvh) - 100lvh));
        }
    }
    [data-theme="light"] { --mobile-home-surface: #fff; }
    /* The root paints the surface color, so an opaque body would hide the
       aurora canvas (z-index:-1 sits between the two). Let it show through. */
    html.bg-aurora-gl:not([data-theme="light"]) body { background: transparent; }
    /* Safari can crop nonempty fixed layers at the dynamic viewport. Anchor
       content to the document and let it reach the physical display bottom when
       the browser reports an lvh shorter than the screen. */
    body { height: 100vh; height: 100lvh; min-height: var(--mobile-home-physical-height, 0px); }
    .desktop, #chatPanel, .page-stack-layer, .mobile-notif-modal {
        position: absolute;
        bottom: auto;
        height: 100vh;
        height: 100lvh;
        min-height: var(--mobile-home-physical-height, 0px);
    }
    /* Section tabs need the same clearance above their content as the home
       header, otherwise Safari paints their first rows under the status bar. */
    .section-panel { top: env(safe-area-inset-top, 0px); }
    .mobile-home-header {
        position: fixed;
        inset: 0 0 auto;
        z-index: 30;
        height: var(--mobile-home-header-h);
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: 12px;
        padding: env(safe-area-inset-top, 0px) 18px 0;
        background: color-mix(in srgb, var(--mobile-home-surface) 88%, transparent);
        backdrop-filter: blur(18px);
        -webkit-backdrop-filter: blur(18px);
        transition: background-color 220ms ease, backdrop-filter 220ms ease, -webkit-backdrop-filter 220ms ease;
    }
    body[data-mobile-home-tab="apps"] .mobile-home-header:not(.is-apps-scrolled) {
        background: transparent;
        backdrop-filter: blur(0px);
        -webkit-backdrop-filter: blur(0px);
    }
    .mobile-home-brand {
        display: inline-flex;
        align-items: baseline;
        gap: 5px;
        border: 0;
        padding: 0;
        background: none;
        color: var(--text);
        font: 800 34px/1.2 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
        letter-spacing: -0.68px;
        cursor: pointer;
    }
    .mobile-home-dot { width: 8px; height: 8px; border-radius: 50%; background: #007aff; }
    body[data-mobile-home-tab="apps"] .mobile-home-brand,
    .desktop.notifs-open .section-panel-title {
        font-family: inherit;
        font-size: 30px;
        font-weight: 800;
        line-height: 1.2;
        letter-spacing: -0.6px;
    }
    body[data-mobile-home-tab="apps"] .mobile-home-dot { display: none; }
    .mobile-home-account { display: flex; align-items: center; gap: 4px; flex-shrink: 0; }
    .mobile-home-balance, .mobile-home-settings {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        min-height: 44px;
        border: 0;
        border-radius: 22px;
        background: var(--hover-overlay);
        color: var(--text);
        font: inherit;
        cursor: pointer;
    }
    .mobile-home-balance { min-width: 60px; padding: 0 13px; font-size: 14px; font-weight: 600; font-variant-numeric: tabular-nums; white-space: nowrap; }
    .mobile-home-settings { width: 44px; color: var(--text-dim); }
    .mobile-home-balance:active, .mobile-home-settings:active { background: var(--hover-overlay-strong); }
    body:not([data-mobile-home-tab="apps"]) #sidebar {
        display: flex !important;
        position: absolute;
        inset: 0 0 auto;
        height: 100vh;
        height: 100lvh;
        min-height: var(--mobile-home-physical-height, 0px);
        z-index: 10;
        flex-direction: column;
        width: auto;
        padding-top: var(--mobile-home-header-h);
        background: var(--mobile-home-surface);
        overflow: hidden;
    }
    #sidebar .sidebar-profile, #sidebar .sidebar-resize-handle,
    #sidebar .sidebar-chats-header, #sidebar .sidebar-chat-btn { display: none; }
    #sidebarChats { flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain; padding: 0 0 var(--mobile-home-bottom-space); }
    #sidebarChats .sidebar-chat-item {
        position: relative;
        display: flex;
        align-items: center;
        gap: 14px;
        min-height: 104px;
        padding: 15px 18px;
        color: var(--text);
        cursor: pointer;
        -webkit-tap-highlight-color: transparent;
    }
    #sidebarChats .sidebar-chat-item::after { content: ''; position: absolute; inset: auto 18px 0 86px; height: 0.5px; background: var(--border); }
    #sidebarChats .sidebar-chat-item:last-child::after { display: none; }
    #sidebarChats .sidebar-chat-item:active { background: var(--hover-overlay); }
    #sidebarChats .sidebar-chat-icon { display: flex; align-items: center; justify-content: center; flex: 0 0 54px; width: 54px; height: 54px; border-radius: 15px; background: var(--hover-overlay); font-size: 34px; }
    #sidebarChats .sidebar-chat-icon svg { width: 27px; height: 27px; }
    #sidebarChats .chat-topic-photo, #sidebarChats .chat-app-icon { width: 54px; height: 54px; border-radius: 15px; object-fit: cover; }
    #sidebarChats .chat-app-icon { flex: 0 0 54px; }
    #sidebarChats .chat-app-icon-placeholder { font-size: 24px; }
    #sidebarChats .sidebar-chat-item:focus-visible { outline: 2px solid var(--accent); outline-offset: -3px; }
    #sidebarChats .sidebar-chat-copy { display: flex; flex-direction: column; flex: 1; min-width: 0; gap: 3px; }
    #sidebarChats .sidebar-chat-name, #sidebarChats .sidebar-chat-preview, #sidebarChats .sidebar-chat-date { display: block; min-width: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
    #sidebarChats .sidebar-chat-name { color: var(--text); font-size: 17px; font-weight: 600; line-height: 22px; }
    #sidebarChats .sidebar-chat-preview { min-height: 20px; color: var(--text-dim); font-size: 14px; line-height: 20px; }
    #sidebarChats .sidebar-chat-date { color: var(--text-muted); font-size: 12px; line-height: 17px; }
    .mobile-home-empty { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 16px; min-height: 100%; padding: 32px; color: var(--text-muted); text-align: center; font-size: 15px; }
    .mobile-home-empty button { min-height: 44px; padding: 0 18px; border: 0; border-radius: 22px; background: var(--hover-overlay); color: var(--accent); font: inherit; cursor: pointer; }
    /* A wide fixed bottom control makes Safari clip page painting above its
       browser toolbar. These floats sit outside the scrolling lists, so an
       absolute position tied to dvh keeps them pinned without that clipping. */
    .mobile-home-tabs {
        display: flex;
        position: absolute;
        z-index: 60;
        top: calc(100vh - 64px - env(safe-area-inset-bottom, 0px));
        top: calc(100dvh - 64px - env(safe-area-inset-bottom, 0px));
        bottom: auto;
        left: 50%;
        transform: translateX(-50%);
        width: min(460px, calc(100% - 16px));
        height: 64px;
        padding: 4px;
        border: 1px solid var(--border);
        border-radius: 34px;
        background: var(--floating-panel-bg);
        backdrop-filter: blur(24px) saturate(150%);
        -webkit-backdrop-filter: blur(24px) saturate(150%);
        box-shadow: 0 4px 24px var(--shadow-color);
        overflow: hidden;
    }
    .mobile-home-tab-indicator {
        position: absolute;
        top: 4px;
        bottom: 4px;
        left: 4px;
        width: calc((100% - 8px) / 4);
        border-radius: 29px;
        transform: translateX(calc(var(--mobile-home-active-tab, 0) * 100%));
        transition: transform 460ms cubic-bezier(0.22, 1, 0.36, 1);
        pointer-events: none;
    }
    .mobile-home-tab-glass {
        display: block;
        width: 100%;
        height: 100%;
        border: 0;
        border-radius: inherit;
        background: linear-gradient(145deg, rgba(255, 255, 255, 0.18), rgba(255, 255, 255, 0.07) 55%, rgba(255, 255, 255, 0.12));
        box-shadow: inset 0 0 0 0.5px rgba(255, 255, 255, 0.07), 0 3px 10px rgba(0, 0, 0, 0.15);
        backdrop-filter: blur(16px) saturate(180%);
        -webkit-backdrop-filter: blur(16px) saturate(180%);
    }
    [data-theme="light"] .mobile-home-tab-glass {
        background: linear-gradient(145deg, rgba(255, 255, 255, 0.8), rgba(255, 255, 255, 0.35) 55%, rgba(255, 255, 255, 0.6));
        box-shadow: inset 0 0 0 0.5px rgba(255, 255, 255, 0.28), 0 2px 9px rgba(0, 0, 0, 0.1);
    }
    .mobile-home-tab { display: flex; flex: 1; min-width: 0; flex-direction: column; align-items: center; justify-content: center; gap: 3px; padding: 4px 10px; border: 0; border-radius: 29px; background: none; color: var(--text-muted); font: inherit; font-size: 11px; font-weight: 600; cursor: pointer; z-index: 1; transition: color 180ms; }
    .mobile-home-tab[aria-selected="true"] { color: var(--accent); }
    .mobile-home-tab span { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    .mobile-home-new-chat { display: inline-flex; position: absolute; z-index: 60; left: 50%; bottom: auto; transform: translateX(-50%); align-items: center; justify-content: center; gap: 8px; min-height: 48px; max-width: calc(100% - 40px); padding: 0 22px; border: 1px solid var(--border); border-radius: 26px; background: color-mix(in srgb, var(--bg-secondary) 90%, transparent); color: var(--text); backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px); box-shadow: 0 4px 20px var(--shadow-color); font: inherit; font-size: 15px; font-weight: 600; white-space: nowrap; cursor: pointer; }
    .mobile-home-new-chat {
        top: calc(100vh - 140px - env(safe-area-inset-bottom, 0px));
        top: calc(100dvh - 140px - env(safe-area-inset-bottom, 0px));
        opacity: 1;
        visibility: visible;
        transition: opacity 200ms ease, transform 240ms cubic-bezier(0.22, 1, 0.36, 1), visibility 0s linear;
    }
    body[data-mobile-home-tab="apps"] .mobile-home-new-chat { display: none; }
    .mobile-home-new-chat.is-scroll-hidden {
        opacity: 0;
        transform: translate(-50%, 12px);
        visibility: hidden;
        pointer-events: none;
        transition-delay: 0s, 0s, 240ms;
    }
    .mobile-home-tab:focus-visible, .mobile-home-new-chat:focus-visible, .mobile-home-brand:focus-visible, .mobile-home-balance:focus-visible, .mobile-home-settings:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
    #publicProfile { display: none; }
    #panelPrivate { padding-top: var(--mobile-home-header-h); padding-bottom: var(--mobile-home-bottom-space); }
    #panelPrivate .desktop-icons { padding-bottom: 0; }
    #panelPrivate .desktop-empty { min-height: calc(100dvh - var(--mobile-home-header-h) - var(--mobile-home-bottom-space)); }
    body:not([data-mobile-home-tab="apps"]) #panelPrivate,
    body:not([data-mobile-home-tab="apps"]) #bgDots { display: none; }
    /* The aurora belongs to the apps grid only: profiles and other sections
       opened above it keep the plain surface. */
    body:has(.desktop.section-open) #bgDots,
    body.sidebar-profile-open #bgDots { display: none; }
    body:not(.chat-open):not(.sidebar-appchat-open) #chatBar { display: none !important; }
    body:is(.anon, .app-active, .chat-open, .sidebar-chat-open, .sidebar-appchat-open, .page-stack-open) :is(#sidebar, .mobile-home-header, .mobile-home-tabs, .mobile-home-new-chat),
    body:has(.desktop.section-open, .mobile-notif-modal.open) :is(#sidebar, .mobile-home-header, .mobile-home-tabs, .mobile-home-new-chat) { display: none !important; }
    .desktop:not(.section-open)::before { display: none; }

    /* Notifications and the own profile are tabs: the tab bar stays over them
       (the #mainApp id outranks the hide rule above), the tab root needs no
       Back button, and the content clears the floating bar. */
    .mobile-home-tab { position: relative; }
    .mobile-home-tab.has-unread::after { content: ''; position: absolute; top: 7px; left: calc(50% + 7px); width: 8px; height: 8px; border-radius: 50%; background: #ff3b30; box-shadow: 0 0 0 2px var(--mobile-home-surface); }
    body:is([data-mobile-home-tab="notifications"], [data-mobile-home-tab="profile"]):has(.desktop.section-open):not(.anon, .app-active, .chat-open, .sidebar-chat-open, .sidebar-appchat-open, .page-stack-open) #mainApp .mobile-home-tabs { display: flex !important; }
    body:is([data-mobile-home-tab="notifications"], [data-mobile-home-tab="profile"]):has(.desktop.section-open:not(.profile-other, .edit-profile-open)):not(.app-active, .chat-open, .page-stack-open) #backBtn { display: none !important; }
    body:is([data-mobile-home-tab="notifications"], [data-mobile-home-tab="profile"]) .desktop.section-open:not(.profile-other) .section-panel-title { padding-left: 18px; }
    body:is([data-mobile-home-tab="notifications"], [data-mobile-home-tab="profile"]) .desktop.section-open #sectionPanel { padding-bottom: calc(96px + env(safe-area-inset-bottom, 0px) + var(--mobile-browser-chrome) + var(--mobile-home-screen-extra)); }

    /* A pronounced bottom shadow sits below the floating controls without
       becoming fully opaque over the content behind Safari's browser chrome. */
    #sidebar::after,
    #desktop::after,
    #chatPanel::after,
    .page-stack-layer::after,
    .mobile-notif-modal::after {
        content: "";
        display: block;
        position: absolute;
        inset: auto 0 0;
        height: var(--mobile-home-bottom-shade-height);
        background: linear-gradient(to bottom,
            transparent,
            rgba(0, 0, 0, 0.55) 45%,
            rgba(0, 0, 0, 0.8));
        z-index: 5;
        pointer-events: none;
    }
    /* Section panels use z-index:50; the shade must cover their content too. */
    #desktop::after { z-index: 55; }
    .page-stack-content, .mobile-notif-list {
        padding-bottom: var(--mobile-home-bottom-shade-height);
    }
    body.chat-open.kb-open #chatPanel::after {
        height: 64px;
    }
}
@media (prefers-reduced-motion: reduce) {
    .mobile-home-header, .mobile-home-tab, .mobile-home-tab-indicator, .mobile-home-new-chat { transition: none; }
}

/* Queue metadata belongs to the outgoing message, including attachment-only sends. */
.message-queue-status { display:flex; align-items:center; justify-content:flex-end; gap:8px; margin-top:6px; font-size:12px; line-height:18px; opacity:.75; }
.message-queue-status button { border:0; background:transparent; color:inherit; font:inherit; font-size:18px; min-width:28px; min-height:28px; padding:0; cursor:pointer; }
.message-queued { opacity:.75; }
.msg-photos-standalone .message-queue-status { color:var(--text-secondary); }
