/* ===========================================================================
 * FhGenie Pro — Fraunhofer-themed dark UI
 * ========================================================================= */

@font-face {
    font-family: 'IBM Plex Sans';
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url('./libs/fonts/ibm-plex-sans-400.woff2') format('woff2');
}
@font-face {
    font-family: 'IBM Plex Sans';
    font-style: normal;
    font-weight: 500;
    font-display: swap;
    src: url('./libs/fonts/ibm-plex-sans-500.woff2') format('woff2');
}
@font-face {
    font-family: 'IBM Plex Sans';
    font-style: normal;
    font-weight: 600;
    font-display: swap;
    src: url('./libs/fonts/ibm-plex-sans-600.woff2') format('woff2');
}
@font-face {
    font-family: 'IBM Plex Mono';
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url('./libs/fonts/ibm-plex-mono-400.woff2') format('woff2');
}

:root {
    --accent: #179C7D;
    --accent-hover: #1FB390;
    --accent-soft: rgba(23, 156, 125, 0.12);
    --accent-ring: rgba(23, 156, 125, 0.35);

    --danger: #E5484D;
    --danger-soft: rgba(229, 72, 77, 0.14);

    --radius-sm: 6px;
    --radius-md: 10px;
    --radius-lg: 14px;
    --radius-xl: 18px;

    /* Shared spacing for response cards (single .bot-message and
       multi .compare-card siblings). Change here, both surfaces update. */
    --card-margin-block: 24px;
    --card-max-width: 100%;
    --card-gutter-inline: 48px;
    --card-padding-inline: 16px;
    --card-padding-block-start: 10px;
    --card-padding-block-end: 12px;

    --font-sans: 'IBM Plex Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
    --font-mono: 'IBM Plex Mono', ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

    /* Bootstrap components (.btn/.tooltip/.popover/modals/dropdowns) hard-set
       font-family to these vars. Without re-pointing them, popups fall back to
       Bootstrap's system stack — invisible on mac/Win, but a visibly wrong
       font on KDE Linux. Reuse the IBM Plex tokens so every component matches. */
    --bs-font-sans-serif: var(--font-sans);
    --bs-font-monospace: var(--font-mono);
    --bs-body-font-family: var(--font-sans);

    /* Curated tint palette reused by the compare surface (dark defaults;
       light theme overrides below). */
    --tab-tint-accent: #179C7D;
    --tab-tint-blue: #5B8DEF;
    --tab-tint-violet: #B07AE0;
    --tab-tint-terracotta: #E08A6B;
    --tab-tint-amber: #D8B947;
    --tab-tint-teal: #5DBCB1;
    /* Preset (Special Chat) tab identity — navy default. Light theme below. */
    --tab-tint-navy: #4A63D0;
}

/* Dark surface/text tokens + Bootstrap overrides */
[data-bs-theme="dark"] {
    --bg-base: #0F1311;
    --bg-surface: #161B19;
    --bg-elevated: #1E2522;
    --bg-input: #111614;

    --border-subtle: #262D2A;
    --border-strong: #36403C;

    --text-primary: #ECEFEE;
    --text-secondary: #A8B0AD;
    --text-tertiary: #6B7572;

    /* Non-current match tone. Bumped from the old near-black #2C4D44 so every
       hit is clearly visible against the dark base, while staying dimmer than
       the bright --highlight-bg-current used for the focused match. */
    --highlight-bg: #3F8571;
    --highlight-bg-current: #1FB390;
    --highlight-fg-current: #0F1311;

    --shadow-soft: 0 1px 2px rgba(0, 0, 0, .4), 0 8px 24px rgba(0, 0, 0, .25);

    --bs-body-bg: var(--bg-base);
    --bs-body-color: var(--text-primary);
    --bs-border-color: var(--border-subtle);
    --bs-primary: var(--accent);
    --bs-primary-rgb: 23, 156, 125;
    --bs-link-color: var(--accent);
    --bs-link-hover-color: var(--accent-hover);
    --bs-secondary-bg: var(--bg-elevated);
    --bs-tertiary-bg: var(--bg-elevated);
}

/* Light theme tokens */
[data-bs-theme="light"] {
    --bg-base: #FFFFFF;
    --bg-surface: #F5F7F6;
    --bg-elevated: #EAEEED;
    --bg-input: #FFFFFF;

    --border-subtle: #DCE2E0;
    --border-strong: #B6C0BC;

    --text-primary: #0F1311;
    --text-secondary: #4A5550;
    --text-tertiary: #828B87;

    --highlight-bg: #A5DDCB;
    --highlight-bg-current: var(--accent);
    --highlight-fg-current: #FFFFFF;

    --shadow-soft: 0 1px 2px rgba(15, 19, 17, .08), 0 8px 24px rgba(15, 19, 17, .06);

    --bs-body-bg: var(--bg-base);
    --bs-body-color: var(--text-primary);
    --bs-border-color: var(--border-subtle);
    --bs-primary: var(--accent);
    --bs-primary-rgb: 23, 156, 125;
    --bs-link-color: var(--accent);
    --bs-link-hover-color: var(--accent-hover);
    --bs-secondary-bg: var(--bg-elevated);
    --bs-tertiary-bg: var(--bg-elevated);

    /* Per-tab tint palette — slightly deeper for legibility on white. */
    --tab-tint-accent: #1B8C72;
    --tab-tint-blue: #3F6FCC;
    --tab-tint-violet: #8E5BC4;
    --tab-tint-terracotta: #C76A47;
    --tab-tint-amber: #A88E1F;
    --tab-tint-teal: #2F8E84;
    /* Preset (Special Chat) tab identity — navy, deepened for white. */
    --tab-tint-navy: #39499E;
}

* { box-sizing: border-box; }

html, body {
    height: 100%;
    margin: 0;
}

body {
    background-color: var(--bg-base);
    color: var(--text-primary);
    font-family: var(--font-sans);
    font-size: 14px;
    line-height: 1.55;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    overflow: hidden;
}

::selection {
    background: var(--accent-ring);
    color: var(--text-primary);
}

/* Scrollbars */
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
    background: var(--border-strong);
    border-radius: 6px;
    border: 2px solid transparent;
    background-clip: content-box;
}
::-webkit-scrollbar-thumb:hover {
    background: var(--text-tertiary);
    background-clip: content-box;
    border: 2px solid transparent;
}

/* ===========================================================================
 * Layout
 * ========================================================================= */

#app-shell {
    display: flex;
    height: 100vh;
    width: 100vw;
}

#col-left {
    width: 280px;
    flex-shrink: 0;
    background-color: var(--bg-surface);
    border-right: 1px solid var(--border-subtle);
    display: flex;
    flex-direction: column;
    height: 100vh;
    position: relative;
    min-width: 200px;
    max-width: 600px;
}

.sidebar-resize-handle {
    position: absolute;
    top: 0;
    right: -3px;
    width: 6px;
    height: 100%;
    cursor: col-resize;
    z-index: 50;
    background: transparent;
    transition: background-color .12s;
}

.sidebar-resize-handle:hover,
.sidebar-resize-handle.is-dragging {
    background: var(--accent-soft);
}

body.is-resizing-sidebar {
    cursor: col-resize;
    user-select: none;
}
body.is-resizing-sidebar iframe {
    pointer-events: none;
}

body.sidebar-collapsed #col-left { display: none; }
/* Toggle button: icon reflects what the click will do */
#sidebar-toggle .bi-layout-sidebar-inset { display: inline-block; }
#sidebar-toggle .bi-layout-sidebar { display: none; }
body.sidebar-collapsed #sidebar-toggle .bi-layout-sidebar-inset { display: none; }
body.sidebar-collapsed #sidebar-toggle .bi-layout-sidebar { display: inline-block; }

.sidebar-header {
    padding: 18px 16px 12px;
    display: flex;
    flex-direction: column;
    gap: 10px;
}

/* Source: https://upload.wikimedia.org/wikipedia/de/e/ee/Fraunhofer-Gesellschaft_2009_logo.svg */
.fraunhofer-logo {
    width: 150px;
    max-width: 100%;
    height: auto;
    display: block;
    margin-left: 4px;
    color: #231f20; /* drives the wordmark fill via currentColor */
}

[data-bs-theme="dark"] .fraunhofer-logo {
    color: #ECEFEE; /* matches --text-primary in dark theme */
}

/* Inner shading sits on top of the green base; in light mode it's white,
   in dark mode it matches the surrounding surface so the iconic 3D
   Fraunhofer striations stay readable instead of collapsing to a blob. */
.fraunhofer-logo .fraunhofer-logo-shading {
    fill: #ffffff;
}

[data-bs-theme="dark"] .fraunhofer-logo .fraunhofer-logo-shading {
    fill: var(--bg-surface);
}

.wordmark {
    font-size: 18px;
    font-weight: 600;
    letter-spacing: -0.01em;
    color: var(--text-primary);
    padding: 4px 6px;
}

.wordmark::before {
    content: '';
    display: inline-block;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--accent);
    margin-right: 8px;
    vertical-align: middle;
    box-shadow: 0 0 12px var(--accent-ring);
}

.sidebar-search {
    position: relative;
    padding: 0 16px 12px;
    display: flex;
    align-items: center;
    gap: 8px;
}

.sidebar-search > .bi-search {
    position: absolute;
    left: 28px;
    color: var(--text-tertiary);
    pointer-events: none;
    font-size: 14px;
}

.sidebar-search input {
    flex: 1;
    height: 34px;
    padding: 0 12px 0 32px;
    background: var(--bg-input);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-md);
    color: var(--text-primary);
    font-family: var(--font-sans);
    font-size: 13px;
    outline: none;
    transition: border-color .15s, box-shadow .15s;
}

.sidebar-search input::placeholder { color: var(--text-tertiary); }

.sidebar-search input:focus {
    border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--accent-ring);
}

.search-toggle {
    font-size: 14px;
    color: var(--text-tertiary);
    cursor: pointer;
    padding: 6px;
    border-radius: 6px;
    transition: color .15s, background-color .15s;
}

.search-toggle:hover { color: var(--text-secondary); background: var(--bg-elevated); }

.search-toggle.active {
    color: var(--accent);
    background: var(--accent-soft);
}

#list-wrapper {
    flex: 1;
    overflow-y: auto;
    padding: 4px 8px 8px;
}

.chat-group-label {
    padding: 14px 10px 6px;
    font-size: 11px;
    font-weight: 600;
    color: var(--text-tertiary);
    text-transform: uppercase;
    letter-spacing: 0.06em;
}

#chat-list .list-group-item {
    position: relative;
    display: flex;
    align-items: center;
    gap: 4px;
    padding: 4px 10px;
    margin: 0 0 1px;
    border: 0;
    border-radius: var(--radius-md);
    background: transparent;
    color: var(--text-secondary);
    cursor: pointer;
    transition: background-color .12s, color .12s;
}

#chat-list .list-group-item:hover {
    background: var(--bg-elevated);
    color: var(--text-primary);
}

#chat-list .search-empty-state {
    padding: 10px 12px;
    color: var(--text-tertiary);
    font-style: italic;
    font-size: 0.9em;
    text-align: center;
}

#chat-list .list-group-item.active {
    background: var(--accent-soft);
    color: var(--text-primary);
    border-left: 2px solid var(--accent);
    padding-left: 8px;
}

#chat-list .list-group-item.is-multi-selected {
    background: var(--accent-soft);
    color: var(--text-primary);
    box-shadow: inset 0 0 0 1px var(--accent);
}

#chat-list .list-group-item.is-multi-selected.active {
    box-shadow: inset 0 0 0 1px var(--accent);
}

/* Arrow-key cursor: a dashed ring so it reads as a movable *cursor*, distinct
   from `.active` (accent left-bar) and `.is-multi-selected` (solid inset ring). */
#chat-list .list-group-item.kbd-focus {
    outline: 2px dashed var(--accent);
    outline-offset: -2px;
    border-radius: inherit;
}


/* Running chat: a full-row treatment (accent left-bar + softly pulsing tint)
   so it's obvious even when the title is still empty/"Untitled". Mirrors the
   .active look (same border-left + padding-left) so an active+running row
   doesn't shift. No width is spent on a right-side indicator. */
#chat-list .list-group-item.is-streaming {
    background: var(--accent-soft);
    color: var(--text-primary);
    border-left: 2px solid var(--accent);
    padding-left: 8px;
    animation: pulse-row 1.6s ease-in-out infinite;
}

@keyframes pulse-row {
    0%, 100% { background-color: rgba(23, 156, 125, 0.10); }
    50%      { background-color: rgba(23, 156, 125, 0.22); }
}

/* Unread (a reply finished while the user wasn't looking): a leading accent
   dot + bold title, mirroring the All Chats view. The running indicator is a
   full-row tint (see .is-streaming above); this is a static leading dot
   (::before), so they don't collide. A running chat wins over unread anyway —
   the JS only adds .is-unread when the chat isn't streaming. */
#chat-list .list-group-item.is-unread > a {
    font-weight: 600;
    color: var(--text-primary);
}

#chat-list .list-group-item.is-unread::before {
    content: '';
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--accent);
    flex: 0 0 auto;
}

@keyframes pulse-dot {
    0%, 100% { opacity: 0.5; transform: scale(0.85); }
    50%      { opacity: 1;   transform: scale(1.1);  }
}

#chat-list .list-group-item a {
    display: block;
    overflow: hidden;
    white-space: nowrap;
    flex: 1;
    font-size: 12px;
    text-decoration: none;
    color: inherit;
    -webkit-mask-image: linear-gradient(90deg, #000 88%, transparent);
}

/* Untitled chats (auto-titling failed / legacy null titles): show the
   placeholder muted + italic so it reads as a placeholder, not a real name. */
#chat-list .list-group-item a.untitled { color: var(--text-tertiary); font-style: italic; }
.tab.untitled .tab-title { font-style: italic; opacity: .7; }

#chat-list .list-group-item i {
    flex: 0 0 auto;
    padding: 2px 6px;
    color: var(--text-tertiary);
    font-size: 12px;
    border-radius: 4px;
    transition: color .12s, background-color .12s;
}

#chat-list .list-group-item i:hover { color: var(--text-primary); background: var(--border-subtle); }

/* In-project: flat list, no date-bucket headers */
.in-project-flat .chat-group-label { display: none; }

/* Per-row relative date (only rendered inside a project) */
#chat-list .list-group-item .chat-row-date {
    flex: 0 0 auto;
    margin-left: auto;
    padding: 0 6px;
    font-size: 11px;
    color: var(--text-tertiary);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}
#chat-list .list-group-item:hover .chat-row-date,
#chat-list .list-group-item.active .chat-row-date {
    color: var(--text-secondary);
}

/* In-project header chat count */
.sidebar-inproject-count {
    margin-left: 4px;
    font-size: 12px;
    color: var(--text-tertiary);
    font-variant-numeric: tabular-nums;
}
.sidebar-inproject-count:empty { display: none; }

.sidebar-projects-actions {
    display: flex;
    flex-direction: column;
    gap: 6px;
    padding: 12px 4px 4px;
}

/* Sidebar Library header (PROJECTS label + new button) */
.sidebar-projects-header {
    display: flex;
    flex-direction: column;
    gap: 6px;
    padding: 8px 4px 4px;
}
.sidebar-projects-header[hidden] { display: none; }
.sidebar-projects-header-row {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 4px 6px;
}
.sidebar-projects-title {
    flex: 1;
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--text-tertiary);
}
.sidebar-projects-new-btn {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    height: 24px;
    padding: 0 8px;
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-sm);
    background: transparent;
    color: var(--text-secondary);
    font-size: 11px;
    cursor: pointer;
    transition: background-color .12s, color .12s, border-color .12s;
}
.sidebar-projects-new-btn:hover {
    color: var(--accent);
    border-color: var(--accent);
    background: var(--accent-soft);
}
.sidebar-projects-sort-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 24px;
    height: 24px;
    padding: 0;
    border: 0;
    border-radius: var(--radius-sm);
    background: transparent;
    color: var(--text-secondary);
    font-size: 13px;
    cursor: pointer;
    transition: background-color .12s, color .12s;
}
.sidebar-projects-sort-btn:hover {
    color: var(--accent);
    background: var(--accent-soft);
}

/* Library view: flat clickable project tiles */
.project-tile {
    display: flex;
    align-items: center;
    gap: 6px;
    width: 100%;
    padding: 4px 8px;
    margin: 1px 0;
    border: 0;
    border-radius: var(--radius-sm);
    background: transparent;
    color: var(--text-primary);
    text-align: left;
    cursor: pointer;
    transition: background-color .12s;
}
.project-tile:hover { background: var(--bg-elevated); }
.project-tile .project-tile-icon { color: var(--text-tertiary); font-size: 13px; }
.project-tile .project-tile-name {
    flex: 1;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    font-size: 12px;
}
.project-tile .project-tile-count {
    font-size: 11px;
    color: var(--text-tertiary);
    font-family: var(--font-mono);
}
/* Notebook (RAG-enabled project) marker — sits right after the name. */
.project-tile .project-tile-rag-badge {
    flex: 0 0 auto;
    font-size: 11px;
    margin-left: 4px;
    color: var(--accent, var(--text-secondary));
}
.project-tile .project-tile-files-count {
    font-size: 10px;
    color: var(--text-tertiary);
    font-family: var(--font-mono);
}
.project-tile .project-tile-files-count[hidden] { display: none; }
.project-tile .project-tile-enter {
    color: var(--text-tertiary);
    font-size: 12px;
}
.project-tile .project-tile-edit,
.project-tile .project-tile-files,
.project-tile .project-tile-delete {
    opacity: 0;
    transition: opacity .12s, color .12s, background-color .12s;
    font-size: 12px;
    padding: 4px;
    border-radius: 4px;
    cursor: pointer;
}
.project-tile:hover .project-tile-edit,
.project-tile:hover .project-tile-files,
.project-tile:hover .project-tile-delete { opacity: 0.85; }
.project-tile .project-tile-files:hover { opacity: 1; color: var(--accent); background: var(--accent-soft); }
.project-tile .project-tile-edit:hover  { opacity: 1; color: var(--accent); background: var(--accent-soft); }
.project-tile .project-tile-delete:hover { opacity: 1; color: var(--danger); background: var(--danger-soft); }
.project-tile.is-drop-target {
    background: var(--accent-soft);
    box-shadow: inset 0 0 0 1px var(--accent-ring);
}

/* Sidebar in-project header (back arrow + project name) */
.sidebar-inproject-header {
    position: sticky;
    top: 0;
    z-index: 2;
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 10px;
    background: var(--bg-base);
    border-bottom: 1px solid var(--border-subtle);
}
.sidebar-inproject-header[hidden] { display: none; }
.sidebar-inproject-back {
    width: 24px;
    height: 24px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 0;
    border-radius: var(--radius-sm);
    background: transparent;
    color: var(--text-secondary);
    cursor: pointer;
}
.sidebar-inproject-back:hover { background: var(--border-subtle); color: var(--text-primary); }
.sidebar-inproject-name {
    flex: 1;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    font-size: 13px;
    font-weight: 600;
    color: var(--text-primary);
}
.sidebar-inproject-header > i {
    color: var(--text-tertiary);
    font-size: 12px;
    padding: 4px;
    border-radius: 4px;
    cursor: pointer;
    transition: color .12s, background-color .12s;
}
.sidebar-inproject-header > i.sidebar-inproject-edit:hover {
    color: var(--accent);
    background: var(--accent-soft);
}
.sidebar-inproject-header > i.sidebar-inproject-delete:hover {
    color: var(--danger);
    background: var(--danger-soft);
}
.sidebar-inproject-header > .sidebar-inproject-files {
    background: none;
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
    color: var(--text-secondary);
    font-size: 12px;
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 3px 8px;
    cursor: pointer;
}
.sidebar-inproject-header > .sidebar-inproject-files:hover {
    background: var(--accent-soft);
    color: var(--accent);
}

/* Topbar "In project: X" chip — mirrors .temp-chat-chip */
.active-project-chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    height: 28px;
    padding: 0 10px 0 12px;
    background: var(--accent-soft);
    border: 1px solid var(--accent-ring);
    border-radius: 999px;
    font-size: 12px;
    color: var(--text-secondary);
    cursor: pointer;
}
.active-project-chip[hidden] { display: none; }
.active-project-chip i { color: var(--accent); }
/* Context-only variant: the chat belongs to a project/notebook we are NOT
   drilled into. Quieter neutral tint so "this chat lives in X / click to open"
   reads distinct from the accent-soft "you are inside X" drill-in state. */
.active-project-chip.is-context {
    background: color-mix(in srgb, var(--bg-surface) 70%, transparent);
    border-color: var(--border-subtle);
}
.active-project-chip.is-context i { color: var(--text-secondary); }
/* Trailing action glyph — covers both the bi-x-lg (leave) and
   bi-box-arrow-in-right (enter) icons via the shared class. */
.active-project-chip .active-project-chip-x {
    margin-left: 4px;
    font-size: 10px;
    opacity: 0.7;
}
.active-project-chip.is-context .active-project-chip-x { font-size: 11px; }
.active-project-chip:hover .active-project-chip-x { opacity: 1; }

/* Project sections */
.project-section {
    margin: 8px 0 4px;
}

.project-section-toggle {
    width: 100%;
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 10px;
    border: 0;
    border-radius: var(--radius-sm);
    background: transparent;
    color: var(--text-secondary);
    font-size: 12px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    cursor: pointer;
    transition: background-color .12s, color .12s;
}

.project-section-toggle:hover { background: var(--bg-elevated); color: var(--text-primary); }

.project-section-toggle .bi-chevron-down,
.project-section-toggle .bi-chevron-right {
    font-size: 11px;
    color: var(--text-tertiary);
}

.project-section-toggle .project-section-name {
    flex: 1;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
}

.project-section-list {
    padding-left: 8px;
    border-left: 1px dashed var(--border-subtle);
    margin-left: 14px;
}

.project-section-newchat {
    margin: 4px 0 4px 8px;
    height: 28px;
    padding: 0 10px;
    border: 1px dashed var(--border-subtle);
    background: transparent;
    color: var(--text-tertiary);
    border-radius: var(--radius-sm);
    cursor: pointer;
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 12px;
    transition: color .12s, border-color .12s, background-color .12s;
}

.project-section-newchat:hover {
    color: var(--accent);
    border-color: var(--accent);
    background: var(--accent-soft);
}

.move-to-project-popover {
    position: absolute;
    z-index: 1100;
    min-width: 200px;
    max-width: 260px;
    background: var(--bg-elevated);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-soft);
    padding: 6px;
}

.move-to-project-popover[hidden] { display: none; }

.move-to-project-popover-list {
    max-height: 280px;
    overflow-y: auto;
}

.move-to-project-popover button {
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
    padding: 8px 10px;
    border: 0;
    border-radius: var(--radius-sm);
    background: transparent;
    color: var(--text-primary);
    font-size: 13px;
    text-align: left;
    cursor: pointer;
    transition: background-color .1s;
}

.move-to-project-popover button:hover { background: var(--border-subtle); }
.move-to-project-popover button.active { background: var(--accent-soft); }

/* Inline "New project" input row (sidebar) */
.project-new-inline-row {
    display: flex;
    align-items: center;
    gap: 4px;
    padding: 0 2px;
}

.project-new-inline-row[hidden] { display: none; }

.project-new-inline-row input {
    flex: 1;
    min-width: 0;
    height: 32px;
    padding: 0 10px;
    border-radius: var(--radius-sm);
    border: 1px solid var(--border-subtle);
    background: var(--bg-elevated);
    color: var(--text-primary);
    font-size: 13px;
}

.project-new-inline-row input:focus {
    outline: none;
    border-color: var(--accent);
    box-shadow: 0 0 0 2px var(--accent-ring);
}

.project-inline-icon-btn {
    width: 32px;
    height: 32px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 0;
    border-radius: var(--radius-sm);
    background: transparent;
    color: var(--text-secondary);
    cursor: pointer;
    transition: background-color .12s, color .12s;
}

.project-inline-icon-btn:hover {
    background: var(--border-subtle);
    color: var(--text-primary);
}

.project-inline-icon-btn[data-action="confirm"]:hover { color: var(--accent); }
.project-inline-icon-btn[data-action="cancel"]:hover { color: var(--danger); }

.project-inline-error {
    color: var(--danger);
    font-size: 12px;
    padding: 2px 4px 0;
}

.project-inline-error[hidden] { display: none; }

/* Hover-revealed edit/delete icons on project section header */
.project-section-toggle .project-section-edit,
.project-section-toggle .project-section-delete {
    opacity: 0;
    transition: opacity .12s, color .12s, background-color .12s;
    font-size: 12px;
    padding: 4px;
    border-radius: 4px;
    cursor: pointer;
}

.project-section-toggle:hover .project-section-edit,
.project-section-toggle:hover .project-section-delete {
    opacity: 0.85;
}

.project-section-toggle .project-section-edit:hover {
    opacity: 1;
    color: var(--accent);
    background: var(--accent-soft);
}

.project-section-toggle .project-section-delete:hover {
    opacity: 1;
    color: var(--danger);
    background: var(--danger-soft);
}

/* Project field styles — shared by the Manage-notebook modal's Settings
   section (name / system-prompt inputs + their labels). */
.project-edit-label {
    font-size: 11px;
    color: var(--text-tertiary);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    margin: 0;
}

.project-edit-name,
.project-edit-preprompt {
    width: 100%;
    padding: 6px 8px;
    border-radius: var(--radius-sm);
    border: 1px solid var(--border-subtle);
    background: var(--bg-base);
    color: var(--text-primary);
    font-family: var(--font-sans);
    font-size: 13px;
    resize: vertical;
}

.project-edit-name:focus,
.project-edit-preprompt:focus {
    outline: none;
    border-color: var(--accent);
    box-shadow: 0 0 0 2px var(--accent-ring);
}

/* Temporary chat banner chip in topbar */
.temp-chat-chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    height: 28px;
    padding: 0 12px;
    background: color-mix(in srgb, var(--tab-tint-amber) 12%, transparent);
    border: 1px solid color-mix(in srgb, var(--tab-tint-amber) 35%, transparent);
    border-radius: 999px;
    font-size: 12px;
    color: var(--text-secondary);
}

.temp-chat-chip[hidden] { display: none; }

.temp-chat-chip i { color: var(--tab-tint-amber); }

/* "Save chat" action inside the temporary-chat chip */
.temp-chat-save-btn {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    margin-left: 4px;
    padding: 0 8px;
    height: 20px;
    background: var(--tab-tint-amber);
    border: none;
    border-radius: 999px;
    color: #1c1c1c;
    font-size: 11px;
    cursor: pointer;
}

.temp-chat-save-btn:hover { filter: brightness(1.08); }

.temp-chat-save-btn i { color: #1c1c1c; }

/* Pill buttons (sidebar) */
.pill-btn {
    width: 100%;
    height: 36px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    padding: 0 14px;
    border-radius: 999px;
    border: 1px solid transparent;
    background: var(--bg-elevated);
    color: var(--text-primary);
    font-family: var(--font-sans);
    font-weight: 500;
    font-size: 13px;
    cursor: pointer;
    transition: background-color .12s, border-color .12s, color .12s, box-shadow .12s;
}

.pill-btn:hover { background: var(--border-subtle); }

.pill-btn:disabled {
    opacity: .45;
    cursor: not-allowed;
}

.pill-btn-accent {
    background: var(--accent);
    color: #fff;
}
.pill-btn-accent:hover { background: var(--accent-hover); }

.pill-btn-danger { color: var(--danger); }
.pill-btn-danger:not(:disabled):hover {
    background: var(--danger-soft);
    color: var(--danger);
}

/* ===========================================================================
 * Main column
 * ========================================================================= */

.col-right {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    background: var(--bg-base);
    height: 100vh;
}

.topbar {
    min-height: 56px;
    flex-shrink: 0;
    padding: 8px 18px;
    border-bottom: 1px solid var(--border-subtle);
    background: var(--bg-surface);
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    position: relative;
    z-index: 10;
}

.topbar-left,
.topbar-right {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px;
    min-width: 0;
}

/* Profile pill */
.profile-pill-wrap {
    position: relative;
    display: inline-flex;
}

.profile-pill {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    height: 32px;
    padding: 0 12px;
    background: var(--bg-elevated);
    border: 1px solid var(--border-subtle);
    border-radius: 999px;
    color: var(--text-primary);
    font-family: var(--font-sans);
    font-size: 13px;
    font-weight: 500;
    cursor: pointer;
    transition: border-color .12s, background-color .12s;
}

.profile-pill:hover { border-color: var(--border-strong); }

.profile-pill[aria-expanded="true"] {
    border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--accent-ring);
}

.profile-pill-dot {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--accent);
    box-shadow: 0 0 8px var(--accent-ring);
}

.profile-pill .bi-chevron-down {
    font-size: 11px;
    color: var(--text-tertiary);
    transition: transform .15s;
}

.profile-pill[aria-expanded="true"] .bi-chevron-down {
    transform: rotate(180deg);
}

/* Modified-state: pill itself signals "settings differ from active profile". */
.profile-pill.is-modified {
    border-color: #eab308;
    background: rgba(234, 179, 8, 0.10);
}

.profile-pill.is-modified:hover {
    border-color: #ca8a04;
}

.profile-pill.is-modified .profile-pill-dot {
    background: transparent;
    box-shadow: none;
    color: #eab308;
    width: auto;
    height: auto;
    font-size: 13px;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 4px;
    padding: 1px 2px;
    transition: background-color .12s, color .12s;
}

.profile-pill.is-modified .profile-pill-dot:hover {
    background: rgba(234, 179, 8, 0.18);
    color: #ca8a04;
}

.profile-menu {
    position: absolute;
    top: calc(100% + 6px);
    right: 0;
    min-width: 240px;
    background: var(--bg-elevated);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-soft);
    padding: 6px;
    z-index: 100;
}

.profile-menu[hidden] { display: none; }

.profile-menu-list {
    max-height: 300px;
    overflow-y: auto;
}

.profile-menu-item {
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
    padding: 8px 10px;
    border: 0;
    border-radius: var(--radius-sm);
    background: transparent;
    color: var(--text-primary);
    font-size: 13px;
    text-align: left;
    cursor: pointer;
    transition: background-color .1s;
}

.profile-menu-item:hover { background: var(--border-subtle); }

.profile-menu-item.active { background: var(--accent-soft); }

.profile-menu-item .check {
    margin-left: auto;
    color: var(--accent);
    font-size: 14px;
    visibility: hidden;
}

.profile-menu-item.active .check { visibility: visible; }

.profile-menu-divider {
    height: 1px;
    background: var(--border-subtle);
    margin: 6px 4px;
}

.profile-menu-section-label {
    padding: 6px 10px 2px;
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--text-tertiary, var(--text-secondary));
}

/* A team entry in the pill menu carries a small mode chip (Parallel/Discussion)
   right-aligned after the name. */
.profile-menu-item .team-mode-chip {
    margin-left: auto;
    font-size: 10px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .03em;
    padding: 1px 6px;
    border-radius: 999px;
    background: var(--border-subtle);
    color: var(--text-secondary);
}

.profile-menu-action {
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
    padding: 8px 10px;
    border: 0;
    border-radius: var(--radius-sm);
    background: transparent;
    color: var(--text-secondary);
    font-size: 13px;
    text-align: left;
    cursor: pointer;
    transition: background-color .1s, color .1s;
}

.profile-menu-action:hover {
    background: var(--border-subtle);
    color: var(--text-primary);
}

/* Header controls */
.control-group {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    height: 32px;
    padding: 0 4px;
    flex-shrink: 0;
}

.control-label {
    font-size: 11px;
    color: var(--text-tertiary);
    text-transform: uppercase;
    letter-spacing: 0.06em;
    margin: 0;
    font-weight: 500;
}

.control-select {
    height: 28px;
    padding: 0 28px 0 10px;
    background-color: var(--bg-elevated);
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23A8B0AD'%3E%3Cpath d='M3.5 6l4.5 4.5L12.5 6'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 8px center;
    background-size: 12px;
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-sm);
    color: var(--text-primary);
    font-family: var(--font-sans);
    font-size: 12px;
    cursor: pointer;
    appearance: none;
    -webkit-appearance: none;
    transition: border-color .12s, box-shadow .12s;
}

.control-select:hover { border-color: var(--border-strong); }

.control-select:focus {
    outline: none;
    border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--accent-ring);
}

.control-select option {
    background: var(--bg-elevated);
    color: var(--text-primary);
}

.control-group-temp { gap: 10px; }

/* The `hidden` attribute must override .control-group's `display: inline-flex`
   (style.css:1224); otherwise setRowVisible(false) on the temperature row
   (fhgenie-pro.js:16913) has no visual effect and temperature stays shown for
   reasoning models. */
.control-group[hidden] { display: none !important; }

.control-range {
    -webkit-appearance: none;
    appearance: none;
    width: 100px;
    height: 4px;
    background: var(--border-subtle);
    border-radius: 2px;
    cursor: pointer;
    outline: none;
}

.control-range::-webkit-slider-thumb {
    -webkit-appearance: none;
    appearance: none;
    width: 14px;
    height: 14px;
    border-radius: 50%;
    background: var(--accent);
    border: 2px solid var(--bg-base);
    cursor: pointer;
    transition: transform .12s, box-shadow .12s;
}

.control-range::-webkit-slider-thumb:hover {
    box-shadow: 0 0 0 4px var(--accent-ring);
}

.control-range::-moz-range-thumb {
    width: 14px;
    height: 14px;
    border-radius: 50%;
    background: var(--accent);
    border: 2px solid var(--bg-base);
    cursor: pointer;
}

.control-readout {
    font-family: var(--font-mono);
    font-size: 12px;
    color: var(--text-secondary);
    min-width: 26px;
    text-align: right;
}

.control-readout-muted {
    font-size: 11px;
    color: var(--text-muted, var(--text-secondary));
    opacity: .7;
    font-style: italic;
    margin-left: 6px;
    white-space: nowrap;
}

/* Dim the whole temperature row (slider + readout + hint) when the slider
   is disabled. Browsers already grey a disabled <input type=range>, but the
   readout/hint don't follow on their own. Covers both the toolbar control
   group and the profile-form container. */
#temperature-container:has(input:disabled),
#profile-form-temperature-container:has(input:disabled) {
    opacity: 0.55;
}

.icon-btn {
    width: 32px;
    height: 32px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: transparent;
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
    color: var(--text-secondary);
    cursor: pointer;
    transition: background-color .12s, color .12s, border-color .12s;
}

/* Always-on sync indicator pill (topbar). Spinner-only by design: a subtle dot
   when synced, a spinner while syncing, a danger dot on error. Kept quiet so it
   never competes with the primary controls. */
.sync-pill {
    display: inline-flex;
    align-items: center;
    justify-content: center;   /* center the single indicator */
    width: 28px;               /* fixed footprint — matches the 28px height */
    height: 28px;
    padding: 0;
    background: transparent;
    border: 1px solid transparent;
    border-radius: 999px;
    color: var(--text-tertiary);
    cursor: pointer;
    transition: background-color .12s, border-color .12s;
}
.sync-pill[hidden] { display: none; }
.sync-pill:hover { background: var(--bg-elevated); border-color: var(--border-subtle); }

.sync-pill-dot {
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--text-tertiary);
}
.sync-pill-spinner {
    width: 12px;
    height: 12px;
    border-radius: 50%;
    border: 2px solid var(--accent-soft);
    border-top-color: var(--accent);
    animation: sync-spin .7s linear infinite;
    display: none;
}
/* Label kept in the DOM (useful for aria-live) but never affects size. */
.sync-pill-label { display: none; }

/* Synced: faint accent dot (just confirmation). */
.sync-pill.is-synced .sync-pill-dot { background: var(--accent); }

/* Syncing: show the spinner, hide the dot, label "Syncing…". */
.sync-pill.is-syncing .sync-pill-spinner { display: inline-block; }
.sync-pill.is-syncing .sync-pill-dot { display: none; }
.sync-pill.is-syncing { color: var(--text-secondary); }

/* Error: danger dot + faint danger tint so it stands out within the fixed
   footprint; tooltip carries the message. */
.sync-pill.is-error .sync-pill-dot { background: var(--text-danger); }
.sync-pill.is-error { color: var(--text-danger); background: var(--danger-soft); }
/* Synced-but-undecodable: likely-wrong sync password. No --warning token exists
   today, so use an amber literal with a var fallback. */
.sync-pill.is-warning .sync-pill-dot { background: var(--text-warning, #d08700); }
.sync-pill.is-warning { color: var(--text-warning, #d08700); background: rgba(208, 135, 0, .12); }

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

/* Sync activity (Settings → Storage & Sync): only a one-line latest-outcome
   summary plus a prominent inline error remain here — the full searchable
   history moved to the Sync Log window (opened by the topbar pill). */

/* Sync Log window (modal): a full-size, monospace, scrollable list of cycle
   markers + per-chat upload/download lines, VS-Code-Output-panel style. */
.sync-log-entries {
    font-family: var(--font-mono, ui-monospace, monospace);
    font-size: 12px;
    line-height: 1.6;
    color: var(--text-secondary);
    white-space: pre-wrap;
    word-break: break-word;
}
.sync-log-entry { white-space: pre-wrap; }
.sync-log-entry.is-chat { color: var(--text-primary); }
.sync-log-entry.is-error { color: var(--text-danger); }
.sync-log-entry.is-warning { color: var(--text-warning, #d08700); }
.sync-log-entry[hidden] { display: none; }
.sync-log-empty { color: var(--text-tertiary); font-style: italic; }

/* Context meter chip */
.context-meter-wrap {
    position: relative;
    display: inline-flex;
}

.context-meter {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    height: 32px;
    padding: 0 12px;
    background: var(--bg-elevated);
    border: 1px solid var(--border-subtle);
    border-radius: 999px;
    color: var(--text-primary);
    font-family: var(--font-sans);
    font-size: 12px;
    font-weight: 500;
    cursor: pointer;
    transition: border-color .12s, background-color .12s;
}

.context-meter:hover { border-color: var(--border-strong); }

.context-meter[aria-expanded="true"] {
    border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--accent-ring);
}

.context-meter > i {
    font-size: 13px;
    color: var(--text-tertiary);
}

.context-meter-text {
    font-family: var(--font-mono);
    font-size: 11px;
    color: var(--text-secondary);
    white-space: nowrap;
}

.context-meter-bar {
    display: inline-block;
    width: 56px;
    height: 4px;
    background: var(--border-subtle);
    border-radius: 2px;
    overflow: hidden;
}

.context-meter-fill {
    display: block;
    height: 100%;
    width: 0%;
    background: var(--accent);
    transition: width .2s ease, background-color .15s;
}

.context-meter.warn .context-meter-fill { background: #d6a437; }
.context-meter.danger .context-meter-fill { background: #d05656; }
.context-meter.warn .context-meter-text { color: #d6a437; }
.context-meter.danger .context-meter-text { color: #d05656; }

/* "Compact" button — appears beside the context meter once usage crosses the
   warn threshold, emphasised under danger. Same pill shape as the meter. */
.compact-now-btn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    height: 32px;
    padding: 0 12px;
    margin-left: 6px;
    background: var(--bg-elevated);
    border: 1px solid #d6a437;
    border-radius: 999px;
    color: #d6a437;
    font-family: var(--font-sans);
    font-size: 12px;
    font-weight: 600;
    cursor: pointer;
    white-space: nowrap;
    transition: border-color .12s, background-color .12s, color .12s, box-shadow .12s;
}
.compact-now-btn[hidden] { display: none; }
.compact-now-btn > i { font-size: 13px; }
.compact-now-btn:hover {
    background: rgba(214, 164, 55, .12);
    border-color: #d6a437;
}
.compact-now-btn:disabled {
    opacity: .5;
    cursor: not-allowed;
}
/* Danger emphasis: solid red so it reads as the obvious next action. */
.compact-now-btn.danger {
    background: #d05656;
    border-color: #d05656;
    color: #fff;
    box-shadow: 0 0 0 3px rgba(208, 86, 86, .25);
}
.compact-now-btn.danger:hover { background: #c14747; }

.context-popover {
    position: absolute;
    top: calc(100% + 6px);
    right: 0;
    min-width: 240px;
    background: var(--bg-elevated);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-soft);
    padding: 10px 12px;
    z-index: 100;
    font-size: 12px;
}

.context-popover[hidden] { display: none; }

.context-popover-header {
    font-weight: 600;
    font-size: 12px;
    color: var(--text-primary);
    margin-bottom: 8px;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--text-tertiary);
}

.context-popover-rows {
    list-style: none;
    margin: 0;
    padding: 0;
}

.context-popover-rows li {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 12px;
    padding: 4px 0;
    color: var(--text-secondary);
}

.context-popover-rows li > span:last-child {
    font-family: var(--font-mono);
    color: var(--text-primary);
    font-variant-numeric: tabular-nums;
}

.context-popover-rows .cp-source {
    font-size: 0.85em;
    color: var(--text-secondary);
    opacity: 0.7;
    margin-left: 4px;
}

.context-popover-totals {
    margin-top: 8px;
    padding-top: 8px;
    border-top: 1px solid var(--border-subtle);
}

.context-popover-totals > div {
    display: flex;
    justify-content: space-between;
    gap: 12px;
    padding: 2px 0;
    color: var(--text-secondary);
}

.context-popover-totals > div > span:last-child {
    font-family: var(--font-mono);
    color: var(--text-primary);
    font-variant-numeric: tabular-nums;
    font-weight: 600;
}

.icon-btn:hover {
    background: var(--bg-elevated);
    color: var(--text-primary);
    border-color: var(--border-subtle);
}

.icon-btn i { font-size: 16px; }

/* Topbar system-prompt icon: highlighted when a per-chat override is active. */
.icon-btn.is-active {
    color: var(--accent);
    border-color: var(--accent);
    background: var(--accent-soft);
}
.icon-btn.is-active:hover {
    color: var(--accent-hover);
    border-color: var(--accent);
}

/* ===========================================================================
 * System-prompt inspector modal
 * ========================================================================= */

/* Resolved-model row — doubles as the badge diagnostic. */
.sysprompt-resolved {
    display: flex;
    align-items: baseline;
    gap: 10px;
}
.sysprompt-resolved-label {
    font-size: 12px;
    font-weight: 600;
    color: var(--text-secondary);
    text-transform: uppercase;
    letter-spacing: .04em;
}
.sysprompt-resolved-model {
    font-family: var(--font-mono);
    font-size: 14px;
    font-weight: 600;
    color: var(--accent);
}

/* Layer breakdown — one card per composition layer. */
.sysprompt-layers {
    display: flex;
    flex-direction: column;
    gap: 10px;
}
.sysprompt-layer {
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-sm);
    background: var(--bg-elevated);
    overflow: hidden;
}
.sysprompt-layer-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 8px;
    padding: 6px 10px;
    border-bottom: 1px solid var(--border-subtle);
}
.sysprompt-layer-label {
    font-size: 12px;
    font-weight: 600;
    color: var(--text-primary);
}
.sysprompt-layer-note {
    font-size: 11px;
    color: var(--text-secondary);
    font-style: italic;
}
.sysprompt-layer-body {
    padding: 8px 10px;
    font-family: var(--font-mono);
    font-size: 12px;
    line-height: 1.5;
    white-space: pre-wrap;
    word-break: break-word;
    max-height: 160px;
    overflow: auto;
    color: var(--text-primary);
}
.sysprompt-layer-body.is-empty {
    color: var(--text-secondary);
    font-style: italic;
}
.sysprompt-gateway-note {
    font-size: 12px;
    color: var(--text-secondary);
    font-style: italic;
}

/* "Override active" pill next to the editor label. */
.sysprompt-override-badge {
    font-size: 11px;
    font-weight: 600;
    color: var(--accent);
    background: var(--accent-soft);
    border: 1px solid var(--accent);
    border-radius: 999px;
    padding: 1px 8px;
}

#sysprompt-textarea {
    font-family: var(--font-mono);
    font-size: 12px;
    line-height: 1.5;
}

/* ===========================================================================
 * Chat
 * ========================================================================= */

#chat-container {
    flex: 1;
    overflow-y: auto;
    position: relative;
    scroll-behavior: smooth;
}

#chat-container > div > *:last-child {
    margin-bottom: 0;
}

.user-message,
.bot-message:not(.compare-card-body) {
    position: relative;
    margin: var(--card-margin-block) auto;
    max-width: min(var(--card-max-width), calc(100% - 2 * var(--card-gutter-inline)));
    padding: 0 24px;
    word-wrap: break-word;
}

.user-message {
    text-align: left;
    margin-left: auto;
    margin-right: 24px;
    max-width: min(80%, 880px);
    background: var(--accent-soft);
    border: 1px solid rgba(23, 156, 125, 0.25);
    border-radius: 16px 16px 4px 16px;
    padding: 12px 16px;
}

.bot-message:not(.compare-card-body) {
    max-width: min(var(--card-max-width), calc(100% - 2 * var(--card-gutter-inline)));
    transition: max-width .15s ease;
    background: var(--bg-elevated);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-md);
    padding: var(--card-padding-block-start) var(--card-padding-inline) var(--card-padding-block-end);
}

.bot-message:not(.compare-card-body)::before {
    content: '';
    position: absolute;
    inset: 0 0 auto 0;
    height: 3px;
    background: var(--accent);
    border-top-left-radius: inherit;
    border-top-right-radius: inherit;
}

/* ---------------------------------------------------------------------
   Idle GPU tile-memory fix (render virtualization).

   The chat history in #chat-container is never windowed: applyTabToView
   appends one element per message and nothing removes off-screen ones, so
   a long chat is a giant raster-expensive subtree (hljs code blocks +
   KaTeX span trees) held resident at 2x Retina DPR. On macOS occlusion /
   display-power / GPU-memory-pressure transitions the compositor tile
   budget shrinks and is blown past even while the app sits idle ->
   recurring "tile memory limits exceeded".

   content-visibility:auto makes Chromium skip layout/paint/raster (and
   tile/layer allocation) for rows that are off-screen, bounding the
   resident tile footprint regardless of the environmental trigger. The
   DOM stays fully intact, so scroll save/restore, the chat-overview and
   floating IntersectionObservers, in-flight detach/re-attach, branch
   switchers, collapsibles, and TOC/search scrollIntoView all keep working
   untouched. contain-intrinsic-size keeps scrollHeight / the scrollbar
   stable; the `auto` keyword makes Chromium remember each row's real
   rendered size, so there is no scroll jump when a row is revisited.
   Scoped to direct children of the scroll container; inner
   .compare-card-body bot-messages live inside an already-virtualized
   .compare-set and must not be skipped independently.
   --------------------------------------------------------------------- */
#chat-container > .user-message,
#chat-container > .bot-message:not(.compare-card-body),
#chat-container > .compare-set {
    content-visibility: auto;
}
#chat-container > .user-message {
    contain-intrinsic-size: auto 90px;
}
#chat-container > .bot-message:not(.compare-card-body) {
    /* Placeholder height estimate for never-yet-rendered off-screen rows;
       content-visibility:auto re-measures the real height once a row scrolls
       into view, so this only needs to be a reasonable average. */
    contain-intrinsic-size: auto 600px;
}
#chat-container > .compare-set {
    contain-intrinsic-size: auto 520px;
}

/* Never skip a row that is actively streaming: its height changes on
   every chunk and the stick-to-bottom logic (ce.scrollTop =
   ce.scrollHeight) relies on an accurate scrollHeight. content-visibility
   here also drops paint containment for the streaming row so nothing in a
   live answer is clipped while it grows. */
#chat-container > .user-message.is-streaming,
#chat-container > .bot-message.is-streaming,
#chat-container > .compare-set.is-streaming,
#chat-container > .compare-set[data-streaming="true"] {
    content-visibility: visible;
}

/* Force a specific transcript row to fully render even while off-screen. The
   in-chat find bar adds this to the row containing the current match before
   scrolling to it, so scrollIntoView lands on the real match rather than the
   content-visibility:auto intrinsic-size placeholder (and the hit is actually
   painted). Only one row carries it at a time; it is removed when the match
   changes or the search clears, so the paint/tile saving is otherwise intact. */
#chat-container > .cv-force-visible {
    content-visibility: visible;
}

/* Cap the rasterized size of embedded message images so a single large
   base64 image (e.g. a 2.27 MB PNG) can't blow the GPU compositor tile/overlay
   budget — the confirmed cause of the open-time freeze + viz "Invalid mailbox /
   ProduceOverlay non-existent mailbox" errors. Without this, marked emits
   <img> with no size constraint and the compositor rasterizes at natural
   pixels × Retina DPR. Excludes the classed attachment thumbnails and agent
   avatars, which carry their own explicit sizing. */
.user-message img:not(.attachment-chip-thumb):not(.agent-avatar),
.bot-message img:not(.attachment-chip-thumb):not(.agent-avatar) {
    max-width: 100%;
    max-height: 60vh;
    height: auto;
}

.user-message > *:first-child,
.bot-message > *:first-child { margin-top: 0; }

.user-message p,
.bot-message p { margin: 0 0 0.75em; }

.user-message p:last-child,
.bot-message p:last-child { margin-bottom: 0; }

.bot-message h1, .bot-message h2, .bot-message h3 {
    font-weight: 600;
    line-height: 1.3;
    margin-top: 1.4em;
    margin-bottom: .5em;
    letter-spacing: -0.01em;
}

.bot-message h1 { font-size: 1.5rem; }
.bot-message h2 { font-size: 1.25rem; }
.bot-message h3 { font-size: 1.1rem; }

.bot-message ul, .bot-message ol { padding-left: 1.5rem; }

.bot-message blockquote {
    border-left: 3px solid var(--accent);
    background: var(--accent-soft);
    margin: 0 0 0.75em;
    padding: 0.5em 1em;
    color: var(--text-secondary);
    border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
}

.bot-message a { color: var(--accent); }
.bot-message a:hover { color: var(--accent-hover); }

.bot-message code:not(.hljs) {
    font-family: var(--font-mono);
    font-size: .88em;
    padding: 0.15em 0.4em;
    background: var(--bg-elevated);
    border: 1px solid var(--border-subtle);
    border-radius: 4px;
    color: var(--text-primary);
}

.bot-message pre {
    margin: 0;
    padding: 0;
}

.code-block {
    position: relative;
    margin: 12px 0;
    border-radius: var(--radius-md);
    background: var(--bg-elevated);
    border: 1px solid var(--border-subtle);
    overflow: hidden;
}

.bot-message .code-block,
.compare-card-body .code-block {
    background: var(--bg-base);
}

.code-block pre {
    margin: 0;
    padding: 14px 16px;
    white-space: pre-wrap;
    overflow-wrap: anywhere;
    font-family: var(--font-mono);
    font-size: 12.5px;
    line-height: 1.55;
    background: transparent;
}

.code-block code.hljs {
    background: transparent;
    padding: 0;
    color: var(--text-primary);
}

.copy-code-btn {
    position: absolute;
    top: 8px;
    right: 8px;
    width: 28px;
    height: 28px;
    padding: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 1px solid var(--border-subtle);
    background: var(--bg-base);
    color: var(--text-secondary);
    border-radius: var(--radius-sm);
    font-size: 12px;
    line-height: 1;
    cursor: pointer;
    opacity: 0;
    transition: opacity .15s, background-color .12s, color .12s, border-color .12s;
}

.code-block:hover .copy-code-btn { opacity: 1; }

.copy-code-btn:hover { color: var(--text-primary); border-color: var(--border-strong); }

.copy-code-btn.copied {
    border-color: var(--accent);
    background: var(--accent-soft);
    color: var(--accent);
    opacity: 1;
}

.copy-code-btn.with-caret {
    border-radius: var(--radius-sm) 0 0 var(--radius-sm);
    border-right: 0;
    right: 30px;
}

.copy-code-menu-btn {
    position: absolute;
    top: 8px;
    right: 8px;
    width: 22px;
    height: 28px;
    padding: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 1px solid var(--border-subtle);
    background: var(--bg-base);
    color: var(--text-secondary);
    border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
    font-size: 12px;
    line-height: 1;
    cursor: pointer;
    opacity: 0;
    transition: opacity .15s, background-color .12s, color .12s, border-color .12s;
}

.code-block:hover .copy-code-menu-btn,
.code-block.menu-open .copy-code-menu-btn { opacity: 1; }

.code-block.menu-open { overflow: visible; }

.copy-code-menu-btn:hover { color: var(--text-primary); border-color: var(--border-strong); }

.copy-code-menu-btn.open {
    background: var(--bg-elevated);
    color: var(--text-primary);
}

.copy-code-menu {
    position: absolute;
    top: 40px;
    right: 8px;
    min-width: 200px;
    background: var(--bg-elevated);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-soft);
    padding: 4px;
    z-index: 3;
}

.copy-code-menu[hidden] { display: none; }

/* Tables */
.table-block {
    position: relative;
    margin: 12px 0;
}

.table-block > table {
    margin: 0 !important;
}

.copy-table-controls {
    position: absolute;
    top: 8px;
    right: 8px;
    display: inline-flex;
    gap: 0;
    opacity: 0;
    transition: opacity .15s;
    z-index: 2;
}

.table-block:hover .copy-table-controls,
.table-block.menu-open .copy-table-controls,
.copy-table-controls:focus-within {
    opacity: 1;
}

.copy-table-btn,
.copy-table-menu-btn {
    width: 28px;
    height: 28px;
    padding: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 1px solid var(--border-subtle);
    background: var(--bg-base);
    color: var(--text-secondary);
    font-size: 12px;
    line-height: 1;
    cursor: pointer;
    transition: background-color .12s, color .12s, border-color .12s;
}

.copy-table-btn {
    border-radius: var(--radius-sm) 0 0 var(--radius-sm);
    border-right: 0;
}

.copy-table-menu-btn {
    border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
    width: 22px;
}

.copy-table-btn:hover,
.copy-table-menu-btn:hover {
    color: var(--text-primary);
    border-color: var(--border-strong);
}

.copy-table-btn.copied {
    border-color: var(--accent);
    background: var(--accent-soft);
    color: var(--accent);
}

.copy-table-menu-btn.open {
    background: var(--bg-elevated);
    color: var(--text-primary);
}

.copy-table-menu {
    position: absolute;
    top: 40px;
    right: 8px;
    min-width: 180px;
    background: var(--bg-elevated);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-soft);
    padding: 4px;
    z-index: 3;
}

.copy-table-menu[hidden] { display: none; }

.copy-table-menu-item {
    display: block;
    width: 100%;
    padding: 7px 10px;
    border: 0;
    border-radius: var(--radius-sm);
    background: transparent;
    color: var(--text-primary);
    font-size: 12.5px;
    text-align: left;
    cursor: pointer;
    transition: background-color .1s;
}

.copy-table-menu-item:hover { background: var(--border-subtle); }

.copy-table-menu-action { color: var(--text-secondary); font-size: 12px; }

.copy-table-menu-sep {
    height: 1px;
    background: var(--border-subtle);
    margin: 4px 4px;
}

/* Smart-copy menus (code block + advanced copy dialog) */
.copy-menu-item {
    display: block;
    width: 100%;
    padding: 7px 10px;
    border: 0;
    border-radius: var(--radius-sm);
    background: transparent;
    color: var(--text-primary);
    font-size: 12.5px;
    text-align: left;
    cursor: pointer;
    transition: background-color .1s;
    line-height: 1.2;
    height: auto;
}

.copy-menu-item:hover { background: var(--border-subtle); }

.copy-menu-detected {
    padding: 6px 10px 4px;
    font-size: 11.5px;
    color: var(--text-tertiary);
    text-transform: uppercase;
    letter-spacing: .04em;
}

.copy-menu-sep {
    height: 1px;
    background: var(--border-subtle);
    margin: 4px 4px;
}

.bot-message table {
    width: 100%;
    margin: 12px 0;
    border-collapse: collapse;
    font-size: 13px;
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-sm);
    overflow: hidden;
}

.bot-message th,
.bot-message td {
    padding: 8px 12px;
    text-align: left;
    border-bottom: 1px solid var(--border-subtle);
}

.bot-message th {
    background: var(--bg-elevated);
    color: var(--text-primary);
    font-weight: 600;
}

.bot-message tr:last-child td { border-bottom: 0; }

[data-bs-theme="dark"] .bot-message tr:nth-child(even) { background: rgba(255, 255, 255, 0.02); }
[data-bs-theme="light"] .bot-message tr:nth-child(even) { background: rgba(15, 19, 17, 0.025); }

/* Reasoning collapsible */
details.reasoning {
    margin-bottom: 0.5rem;
    padding: 0.5rem 0.75rem;
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-sm);
    background: var(--bg-elevated);
    color: var(--text-secondary);
    font-size: 13px;
}

details.reasoning > summary {
    cursor: pointer;
    font-weight: 500;
    color: var(--text-secondary);
    user-select: none;
}

details.reasoning[open] > summary { margin-bottom: 0.5rem; color: var(--text-primary); }

/* Completed reasoning → inline auto-collapsed toggle, rendered above the
 * answer (🧠 Reasoning). Mirrors details.reasoning above. */
details.reasoning-done {
    margin-bottom: 0.75rem;
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-sm);
    background: var(--bg-elevated);
    color: var(--text-secondary);
    font-size: 13px;
    overflow: hidden;
}

details.reasoning-done > summary {
    cursor: pointer;
    user-select: none;
    padding: 0.4rem 0.75rem;
    font-weight: 500;
    color: var(--text-secondary);
    list-style: none;
}

details.reasoning-done > summary::-webkit-details-marker { display: none; }

details.reasoning-done[open] > summary {
    color: var(--text-primary);
    border-bottom: 1px solid var(--border-subtle);
}

.reasoning-done-body {
    padding: 0.5rem 0.75rem;
    color: var(--text-secondary);
}

.reasoning-done-body > :first-child { margin-top: 0; }
.reasoning-done-body > :last-child { margin-bottom: 0; }

/* Legacy hidden slot — kept inert for any older restored markup */
.reasoning-slot[hidden] { display: none; }

/* ===========================================================================
 * Composer
 * ========================================================================= */

.composer-wrap {
    flex-shrink: 0;
    padding: 12px 24px 18px;
    background: var(--bg-base);
    position: relative;
}

.composer {
    max-width: calc(100% - 48px);
    transition: max-width .15s ease;
    margin: 0 auto;
    background: var(--bg-input);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-xl);
    padding: 8px 8px 8px 8px;
    display: flex;
    align-items: flex-end;
    gap: 8px;
    transition: border-color .15s, box-shadow .15s;
}

.composer:focus-within {
    border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--accent-ring);
}

body.ui-temporary-chat .composer:focus-within {
    border-color: var(--tab-tint-amber);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--tab-tint-amber) 35%, transparent);
}

/* Command mode (slash-menu open): flip the composer into a distinct, CLI-like
   blue state — recolored box + glow, monospace input, and a `›` prompt marker.
   Placed AFTER the temp-chat rule so command mode wins the rare
   temp-chat-while-typing-`/` overlap (equal specificity → source order). */
body.ui-command-mode .composer,
body.ui-command-mode .composer:focus-within {
    border-color: var(--tab-tint-blue);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--tab-tint-blue) 35%, transparent);
}
body.ui-command-mode #user-input {
    font-family: var(--font-mono);
}
body.ui-command-mode .composer::before {
    content: '›';
    align-self: flex-end;
    padding: 6px 0 8px 4px;
    color: var(--tab-tint-blue);
    font-family: var(--font-mono);
    font-weight: 700;
}
body.ui-command-mode .slash-cmd-item.active {
    border-left-color: var(--tab-tint-blue);
}
body.ui-command-mode .slash-cmd-item.active .slash-cmd-name {
    color: var(--tab-tint-blue);
}

/* Temporary chats: retint every composer accent (teal) cue to amber, matching
   the tab + focus ring, so the provisional state reads across the whole input. */

/* Send button — amber fill, dark glyph (white is illegible on amber).
   :not(.ui-chat-busy) so the red stop affordance still wins while streaming. */
body.ui-temporary-chat:not(.ui-chat-busy) .composer-send {
    background: var(--tab-tint-amber);
    color: #1c1c1c;
}
body.ui-temporary-chat:not(.ui-chat-busy) .composer-send:hover {
    background: color-mix(in srgb, var(--tab-tint-amber), #000 12%);
}

/* Attach-menu open + N-picker active — amber soft wash + amber text. */
body.ui-temporary-chat .composer-attach-menu[aria-expanded="true"],
body.ui-temporary-chat .composer-n-picker .n-pick.active {
    background: color-mix(in srgb, var(--tab-tint-amber) 12%, transparent);
    color: var(--tab-tint-amber);
}

/* Paper-context segmented toggle (lives inside .composer) — scoped under
   .composer so app-wide segmented controls are unaffected. */
body.ui-temporary-chat .composer .segmented-option.active {
    background: var(--tab-tint-amber);
    color: #1c1c1c;
}
body.ui-temporary-chat .composer .segmented-option:focus-visible {
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--tab-tint-amber) 35%, transparent);
}

/* Drag-and-drop target highlight. */
body.ui-temporary-chat .composer-wrap.is-drop-target .composer {
    border-color: var(--tab-tint-amber);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--tab-tint-amber) 35%, transparent);
}
body.ui-temporary-chat .composer-wrap.is-drop-target::after {
    background: color-mix(in srgb, var(--tab-tint-amber) 12%, transparent);
    border-color: var(--tab-tint-amber);
    color: var(--tab-tint-amber);
}

/* Recovered (interrupted-generation) banner + restore button. */
body.ui-temporary-chat .composer-recovered {
    border-left-color: var(--tab-tint-amber);
}
body.ui-temporary-chat .composer-recovered > .bi-arrow-counterclockwise,
body.ui-temporary-chat .composer-recovered-restore {
    color: var(--tab-tint-amber);
}
body.ui-temporary-chat .composer-recovered-restore {
    border-color: var(--tab-tint-amber);
}
body.ui-temporary-chat .composer-recovered-restore:hover {
    background: var(--tab-tint-amber);
    color: #1c1c1c;
}

/* Discussion mode is purple: re-point the green accent tokens to violet within
   the discussion content surface (chat container, roster, composer) so every
   accent cue — selection pills, strategy cards, slot/synth select focus rings,
   ::selection, consensus chips, synthesis box, roster toggle, primary buttons,
   composer — reads purple. Scoped to the content roots (not <body>) so the
   sidebar + tab strip keep their normal green, like the temp-chat treatment.
   Toggled per tab via applyDiscussionSurfaceForTab; discussions are never
   temporary, so this never co-occurs with the .ui-temporary-chat amber. */
body.discussion-surface #chat-container,
body.discussion-surface #discussion-roster,
body.discussion-surface .composer-wrap {
    --accent: var(--tab-tint-violet);
    --accent-hover: color-mix(in srgb, var(--tab-tint-violet), #000 12%);
    --accent-soft: color-mix(in srgb, var(--tab-tint-violet) 12%, transparent);
    --accent-ring: color-mix(in srgb, var(--tab-tint-violet) 35%, transparent);
    --tab-tint-accent: var(--tab-tint-violet);
}

/* Send-button glyph: white is illegible on the violet fill the token override
   paints, so force a dark glyph. :not(.ui-chat-busy) so the red stop
   affordance still wins while streaming. */
body.discussion-surface:not(.ui-chat-busy) .composer-send { color: #1c1c1c; }

.composer-attach {
    width: 32px;
    height: 32px;
    flex-shrink: 0;
    border: 0;
    border-radius: 50%;
    background: var(--bg-elevated);
    color: var(--text-secondary);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 14px;
    transition: background-color .12s, color .12s;
}
.composer-attach:hover { background: var(--border-subtle); color: var(--text-primary); }
.composer-attach:disabled { opacity: 0.5; cursor: not-allowed; }

.composer-main {
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: 6px;
    min-width: 0;
}

.attachment-strip {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    padding: 4px 0 2px;
}

.attachment-chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 4px 6px 4px 10px;
    background: var(--bg-elevated);
    border: 1px solid var(--border-subtle);
    border-radius: 999px;
    font-size: 12px;
    max-width: 280px;
    color: var(--text-primary);
}
.attachment-chip-icon { color: var(--text-tertiary); font-size: 13px; flex-shrink: 0; }
/* Image attachments render a thumbnail of their data-URI in place of the icon. */
.attachment-chip.has-thumb { padding-left: 4px; }
.attachment-chip-thumb {
    width: 28px;
    height: 28px;
    object-fit: cover;
    border-radius: 6px;
    flex-shrink: 0;
    display: block;
    background: var(--bg-elevated);
}
.attachment-chip-name {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.attachment-chip-size {
    color: var(--text-tertiary);
    font-family: var(--font-mono);
    font-size: 11px;
    flex-shrink: 0;
}
.attachment-chip-remove {
    width: 18px;
    height: 18px;
    border: 0;
    border-radius: 50%;
    background: transparent;
    color: var(--text-tertiary);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 12px;
    line-height: 1;
    padding: 0;
    flex-shrink: 0;
}
.attachment-chip-remove:hover { background: var(--danger-soft); color: var(--danger); }
.attachment-chip.is-loading { opacity: 0.6; }
.attachment-chip.is-error {
    border-color: var(--danger);
    color: var(--danger);
}
.attachment-chip.is-error .attachment-chip-icon,
.attachment-chip.is-error .attachment-chip-size { color: var(--danger); }
/* Soft, non-blocking warning (e.g. an 'other' file that looks binary): the
   file still stages and sends, but the amber chip + tooltip flag it. */
.attachment-chip.is-warning { border-color: #c08401; }
.attachment-chip.is-warning .attachment-chip-icon { color: #c08401; }

.attachment-chip-save {
    width: 18px;
    height: 18px;
    border: 0;
    border-radius: 50%;
    background: transparent;
    color: var(--text-tertiary);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 11px;
    line-height: 1;
    padding: 0;
    flex-shrink: 0;
}
.attachment-chip-save:hover { background: var(--accent-soft); color: var(--accent); }
.attachment-chip-save.is-saved { color: var(--accent); }

/* Carried-over attachments from earlier turns of this chat — sits above the
 * staged strip. A live carried file is IN CONTEXT: re-sent in full on every
 * turn (and counting tokens each turn). Accent-tinted so it reads as "active",
 * clearly distinct from the neutral staged chips and from removed chips.
 * Removal is deliberate — right-click → "Remove from context" — so there is no
 * easy inline X here. */
.attachment-strip-carried {
    padding-bottom: 0;
}
.carried-strip-label {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-size: 11px;
    color: var(--accent);
    font-weight: 600;
    letter-spacing: 0.02em;
    align-self: center;
    margin-right: 2px;
    white-space: nowrap;
}
.carried-strip-label .bi { font-size: 12px; }
.attachment-strip-carried .attachment-chip {
    background: var(--accent-soft);
    border-color: var(--accent);
    color: var(--text-primary);
    cursor: default;
}
.attachment-strip-carried .attachment-chip .attachment-chip-icon {
    color: var(--accent);
    font-size: 12px;
}
/* Removed from context: a persistent exclusion (survives restart). Muted +
   struck-through, carrying a Re-add affordance instead of being sent. */
.attachment-strip-carried .attachment-chip.is-removed {
    background: transparent;
    border-style: dashed;
    border-color: var(--border-subtle);
    color: var(--text-tertiary);
    opacity: 0.6;
}
.attachment-strip-carried .attachment-chip.is-removed .attachment-chip-name {
    text-decoration: line-through;
}
.attachment-strip-carried .attachment-chip.is-removed .attachment-chip-icon {
    color: var(--text-tertiary);
}
/* Task 14: lazy-blob content-fetch state (see patchContentChip in
 * fhgenie-pro.js / broadcastContentState in main.js). Deliberately placed
 * AFTER the .attachment-strip-carried icon-color rule above — both have equal
 * (0,3,0) specificity, so source order decides, and these need to win there
 * too (a carried chip is the primary place these states show up). */
.attachment-chip.is-absent .attachment-chip-icon { color: var(--text-tertiary); }
.attachment-chip.is-fetching .attachment-chip-icon {
    color: var(--accent);
    animation: sync-spin 1.2s linear infinite;
}
.attachment-chip.is-unavailable { border-color: var(--danger); }
.attachment-chip.is-unavailable .attachment-chip-icon,
.attachment-chip.is-unavailable .attachment-chip-name { color: var(--danger); }
.attachment-chip-readd {
    width: 18px;
    height: 18px;
    border: 0;
    border-radius: 50%;
    background: transparent;
    color: var(--text-tertiary);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 12px;
    line-height: 1;
    padding: 0;
    flex-shrink: 0;
}
.attachment-chip-readd:hover { background: var(--accent-soft); color: var(--accent); }

/* Read-only chip strip on persisted user messages */
.attachment-strip-readonly {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    padding: 0 0 6px;
}
.attachment-strip-readonly .attachment-chip {
    cursor: pointer;
    opacity: 0.92;
}
.attachment-strip-readonly .attachment-chip:hover {
    border-color: var(--accent);
    opacity: 1;
}

/* Composer attach split-button caret */
.composer-attach-menu {
    width: 18px;
    height: 32px;
    flex-shrink: 0;
    border: 0;
    border-radius: 999px;
    background: var(--bg-elevated);
    color: var(--text-secondary);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 10px;
    margin-left: -6px;
    margin-right: 2px;
    transition: background-color .12s, color .12s;
}
.composer-attach-menu:hover { background: var(--border-subtle); color: var(--text-primary); }
.composer-attach-menu:disabled { opacity: 0.5; cursor: not-allowed; }
.composer-attach-menu[aria-expanded="true"] { background: var(--accent-soft); color: var(--accent); }

/* Files popover (project library + recent quick-pick) */
.files-popover {
    position: absolute;
    z-index: 1100;
    min-width: 280px;
    max-width: 360px;
    background: var(--bg-elevated);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-soft);
    padding: 6px;
    display: flex;
    flex-direction: column;
    gap: 6px;
}
.files-popover[hidden] { display: none; }
.files-popover-search input {
    width: 100%;
    padding: 6px 10px;
    background: var(--bg-base);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-sm);
    color: var(--text-primary);
    font-size: 13px;
    outline: none;
}
.files-popover-search input:focus { border-color: var(--accent); }
.files-popover-section[hidden] { display: none; }
.files-popover-section-label {
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--text-tertiary);
    padding: 4px 6px 2px;
}
.files-popover-list {
    max-height: 220px;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    gap: 2px;
}
.files-popover-item {
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
    padding: 6px 8px;
    border: 0;
    border-radius: var(--radius-sm);
    background: transparent;
    color: var(--text-primary);
    font-size: 13px;
    text-align: left;
    cursor: pointer;
    transition: background-color .1s;
}
.files-popover-item:hover { background: var(--border-subtle); }
.files-popover-item.is-staged { opacity: 0.5; cursor: default; }
.files-popover-item-name {
    flex: 1;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.files-popover-item-tokens {
    color: var(--text-tertiary);
    font-family: var(--font-mono);
    font-size: 11px;
    flex-shrink: 0;
}
.files-popover-empty {
    padding: 8px;
    color: var(--text-tertiary);
    font-size: 12px;
    text-align: center;
}

/* Manage-notebook — Sources list (ported from the old floating project-files
   panel; lives in the roomy right column of #notebook-edit-view so it flexes to
   fill the column height rather than capping at a fixed max-height). */
#notebook-edit-view .notebook-modal-list {
    flex: 1 1 0;
    min-height: 0;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    gap: 2px;
}
/* Rows read as an aligned table: name flexes + ellipsises, every other
   column is fixed-width with a consistent right edge so tokens, status, and
   actions line up down the list rather than raggedly tracking content width. */
#notebook-edit-view .notebook-modal-row {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 6px 8px;
    border-radius: var(--radius-sm);
    font-size: 13px;
    color: var(--text-primary);
    cursor: pointer;
}
#notebook-edit-view .notebook-modal-row:hover { background: var(--border-subtle); }
#notebook-edit-view .notebook-modal-row.active { background: var(--accent-soft, var(--border-subtle)); }
#notebook-edit-view .notebook-modal-row .kind-icon {
    flex-shrink: 0;
    width: 16px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--text-tertiary);
}
#notebook-edit-view .notebook-modal-row .name {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
/* Storage column: a link icon (path in its title) for linked files, a danger
   warning when that path is missing on disk, empty for copied files. The fixed
   width holds the column even when empty so copied/linked rows stay aligned. */
#notebook-edit-view .notebook-modal-row .storage {
    flex-shrink: 0;
    width: 16px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 12px;
    color: var(--text-tertiary);
}
#notebook-edit-view .notebook-modal-row .storage.missing { color: var(--danger); }
/* Library row storage badge: a small link/missing icon sitting inline after the
   file name (the Sources `.storage` rule above is scoped to the notebook view,
   so the Library needs its own). Copied files render no badge. */
.all-chats-row-title .storage {
    margin-left: 6px;
    display: inline-flex;
    align-items: center;
    font-size: 12px;
    color: var(--text-tertiary);
}
.all-chats-row-title .storage.missing { color: var(--danger); }
#notebook-edit-view .notebook-modal-row .tokens {
    color: var(--text-tertiary);
    font-family: var(--font-mono);
    font-size: 11px;
    flex-shrink: 0;
    min-width: 56px;
    text-align: right;
}
#notebook-edit-view .notebook-modal-row .rag-pill {
    font-size: 11px;
    color: var(--text-secondary);
    white-space: nowrap;
    flex-shrink: 0;
    min-width: 120px;
    text-align: right;
}
/* Indexing progress bar — sits in the right-aligned rag-pill slot while a
   file is embedding, replaced by the plain status text once settled. */
#notebook-edit-view .notebook-modal-row .rag-pill .rag-progress {
    display: inline-block;
    vertical-align: middle;
    width: 72px;
    height: 6px;
    border-radius: 3px;
    background: var(--border-subtle);
    overflow: hidden;
}
#notebook-edit-view .notebook-modal-row .rag-pill .rag-progress-fill {
    display: block;
    height: 100%;
    width: 0;
    background: var(--accent);
    border-radius: 3px;
    transition: width 0.3s ease;
}
#notebook-edit-view .notebook-modal-row .rag-pill .rag-progress-count {
    margin-left: 6px;
    vertical-align: middle;
    font-variant-numeric: tabular-nums;
}
/* Unknown total (before the first batch lands): pulse an indeterminate fill. */
#notebook-edit-view .notebook-modal-row .rag-pill .rag-progress.indeterminate .rag-progress-fill {
    width: 40%;
    animation: rag-progress-indeterminate 1.1s ease-in-out infinite;
}
@keyframes rag-progress-indeterminate {
    0%   { transform: translateX(-110%); }
    100% { transform: translateX(260%); }
}
#notebook-edit-view .notebook-modal-row .reindex,
#notebook-edit-view .notebook-modal-row .remove {
    width: 20px;
    height: 20px;
    border: 0;
    border-radius: 50%;
    background: transparent;
    color: var(--text-tertiary);
    cursor: pointer;
    font-size: 12px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}
#notebook-edit-view .notebook-modal-row .reindex:hover { background: var(--border-subtle); color: var(--text-primary); }
#notebook-edit-view .notebook-modal-row .remove:hover { background: var(--danger-soft); color: var(--danger); }
#notebook-edit-view .notebook-modal-empty {
    padding: 8px;
    color: var(--text-tertiary);
    font-size: 12px;
    text-align: center;
}
#notebook-edit-view .notebook-modal-add {
    display: flex;
    align-items: center;
    gap: 6px;
    width: 100%;
    margin-top: 6px;
    flex: 0 0 auto;
    padding: 6px 8px;
    border: 1px dashed var(--border-subtle);
    border-radius: var(--radius-sm);
    background: transparent;
    color: var(--text-secondary);
    font-size: 13px;
    cursor: pointer;
}
#notebook-edit-view .notebook-modal-add:hover {
    border-color: var(--accent);
    color: var(--accent);
}
/* Type column: a fixed-width, muted human-readable kind label sitting between
   the name and the tokens count (mirrored by the header's .col-kind). */
#notebook-edit-view .notebook-modal-row .kind-label {
    flex-shrink: 0;
    width: 64px;
    color: var(--text-tertiary);
    font-size: 11px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
/* Action buttons share a fixed-width, right-aligned slot so every row's
   token/rag columns line up regardless of which buttons it carries. */
#notebook-edit-view .notebook-modal-row .row-actions {
    flex-shrink: 0;
    width: 72px;
    display: flex;
    gap: 4px;
    justify-content: flex-end;
    align-items: center;
}
/* Notes read as distinct from imported files: a journal-toned icon + a subtle
   left accent. */
#notebook-edit-view .notebook-modal-row.is-note .kind-icon { color: var(--accent); }
#notebook-edit-view .notebook-modal-row.is-note {
    border-left: 2px solid var(--accent-soft, var(--border-subtle));
    padding-left: 6px;
}

/* Header row — caption styling, aligned to the rows via matching column
   widths. Exempt from the row click handler (different class). */
#notebook-edit-view .notebook-modal-header {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 4px 8px;
    flex: 0 0 auto;
    border-bottom: 1px solid var(--border-subtle);
    font-size: 10px;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--text-tertiary);
    position: sticky;
    top: 0;
    background: var(--bg-base);
    z-index: 1;
}
#notebook-edit-view .notebook-modal-header .col-icon { width: 16px; flex-shrink: 0; }
#notebook-edit-view .notebook-modal-header .col-name { flex: 1; min-width: 0; }
#notebook-edit-view .notebook-modal-header .col-storage { width: 16px; flex-shrink: 0; }
#notebook-edit-view .notebook-modal-header .col-kind { width: 64px; flex-shrink: 0; }
#notebook-edit-view .notebook-modal-header .col-tokens { min-width: 56px; flex-shrink: 0; text-align: right; }
#notebook-edit-view .notebook-modal-header .col-rag { min-width: 120px; flex-shrink: 0; text-align: right; }
#notebook-edit-view .notebook-modal-header .col-actions { width: 72px; flex-shrink: 0; }
/* Sortable header cells: pointer + an arrow indicator on the active column. */
#notebook-edit-view .notebook-modal-header .col[data-sort-key] { cursor: pointer; }
#notebook-edit-view .notebook-modal-header .col[data-sort-key]:hover { color: var(--text-secondary); }
#notebook-edit-view .notebook-modal-header .col[data-sort-key].col-tokens,
#notebook-edit-view .notebook-modal-header .col[data-sort-key].col-rag {
    justify-content: flex-end;
}
#notebook-edit-view .notebook-modal-header .col.sorted { color: var(--text-secondary); }
#notebook-edit-view .notebook-modal-header .col.sorted .col-label::after {
    content: '\2191'; /* ↑ */
    margin-left: 3px;
    font-size: 9px;
}
#notebook-edit-view .notebook-modal-header .col.sorted.desc .col-label::after { content: '\2193'; /* ↓ */ }

/* Group subheading ("Notes" / "Files") preceding each non-empty group. */
#notebook-edit-view .notebook-modal-group {
    flex: 0 0 auto;
    padding: 6px 8px 2px;
    font-size: 10px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--text-tertiary);
}

/* The two source-adding affordances share a row under the list. */
#notebook-edit-view .notebook-sources-actions {
    display: flex;
    gap: 6px;
    flex: 0 0 auto;
}
#notebook-edit-view .notebook-sources-actions .notebook-modal-add { margin-top: 6px; }

/* Drag-over affordance on the sources column. */
#notebook-edit-view .notebook-edit-sources.drag-over {
    outline: 2px dashed var(--accent);
    outline-offset: -4px;
    border-radius: var(--radius-sm);
}

/* Sidebar files icon + count badge on a project section */
.project-section-files {
    color: var(--text-tertiary);
    cursor: pointer;
    font-size: 13px;
    padding: 0 2px;
}
.project-section-files:hover { color: var(--accent); }
.project-section-files-count {
    font-size: 10px;
    color: var(--text-tertiary);
    font-family: var(--font-mono);
    margin-left: 2px;
}

/* All files / Storage manager modal */
.all-files-list {
    max-height: 60vh;
    overflow-y: auto;
}
.all-files-group-header {
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--text-tertiary);
    padding: 10px 4px 4px;
    border-bottom: 1px solid var(--border-subtle);
    margin-bottom: 4px;
}
.all-files-group-header:first-child { padding-top: 2px; }
.all-files-row {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 6px 6px;
    border-radius: var(--radius-sm);
    font-size: 13px;
    color: var(--text-primary);
}
.all-files-row:hover { background: var(--border-subtle); }
.all-files-row.selected { background: var(--accent-ring); }
.all-files-row .all-files-select {
    flex-shrink: 0;
    cursor: pointer;
    margin: 0;
}
.all-files-row .name {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.all-files-row .meta {
    color: var(--text-tertiary);
    font-family: var(--font-mono);
    font-size: 11px;
    flex-shrink: 0;
    white-space: nowrap;
}
.all-files-row .remove {
    width: 22px;
    height: 22px;
    border: 0;
    border-radius: 50%;
    background: transparent;
    color: var(--text-tertiary);
    cursor: pointer;
    font-size: 12px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}
.all-files-row .remove:hover { background: var(--danger-soft); color: var(--danger); }
.all-files-empty {
    padding: 18px 8px;
    color: var(--text-tertiary);
    font-size: 13px;
    text-align: center;
}

#chat-list .list-group-item[draggable="true"] { cursor: grab; }
#chat-list .list-group-item.is-dragging {
    opacity: 0.5;
    cursor: grabbing;
}

.project-section.is-drop-target > .project-section-toggle,
.project-section.is-drop-target > .project-section-list,
.project-section.is-drop-target > .project-tile,
.ungrouped-section.is-drop-target {
    background: var(--accent-soft);
    box-shadow: inset 0 0 0 1px var(--accent-ring);
    border-radius: var(--radius-md);
}

/* Importing a chat file by dropping it onto the sidebar list. */
#list-wrapper.is-drop-target {
    background: var(--accent-soft);
    box-shadow: inset 0 0 0 2px var(--accent);
    border-radius: var(--radius-md);
    outline: 2px dashed var(--accent);
    outline-offset: -6px;
}

.composer-wrap.is-drop-target .composer {
    border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--accent-ring);
}
.composer-wrap.is-drop-target::after {
    content: 'Drop files to attach';
    position: absolute;
    inset: 12px 24px 18px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--accent-soft);
    border: 1px dashed var(--accent);
    border-radius: var(--radius-xl);
    pointer-events: none;
    color: var(--accent);
    font-weight: 500;
    z-index: 2;
}

#user-input {
    flex: 0 0 auto;
    min-height: 24px;
    max-height: calc(15 * 1.5em + 16px);
    overflow-y: auto;
    padding: 8px 0;
    background: transparent;
    border: 0;
    outline: 0;
    resize: none;
    color: var(--text-primary);
    font-family: var(--font-sans);
    font-size: 14px;
    line-height: 1.5;
}

.composer-expand-toolbar {
    display: flex;
    align-items: center;
    gap: 10px;
    padding-bottom: 10px;
    flex-wrap: wrap;
}
.composer-expand-toolbar .composer-expand-hint {
    color: var(--text-tertiary);
    font-size: 12px;
    margin-left: auto;
}
.composer-expand-monaco {
    height: 70vh;
    min-height: 320px;
    border: 1px solid var(--border-default);
    border-radius: 6px;
    overflow: hidden;
}

.app-context-menu {
    position: fixed;
    z-index: 2000;
    min-width: 180px;
    margin: 0;
    padding: 4px;
    list-style: none;
    background: var(--bg-elevated, #fff);
    color: var(--text-primary);
    border: 1px solid var(--border-default);
    border-radius: 6px;
    box-shadow: 0 6px 24px rgba(0, 0, 0, 0.18);
    font-size: 13px;
    user-select: none;
}
.app-context-menu[hidden] { display: none; }
.app-context-menu-item {
    padding: 6px 12px;
    border-radius: 4px;
    cursor: pointer;
    white-space: nowrap;
}
.app-context-menu-item:hover { background: var(--border-subtle); color: var(--text-primary); }
.app-context-menu-item.is-disabled {
    opacity: 0.5;
    cursor: not-allowed;
}
.app-context-menu-item.is-disabled:hover { background: transparent; color: inherit; }
.app-context-menu-sep {
    height: 1px;
    margin: 4px 6px;
    background: var(--border-default);
}

/* Advanced copy dialog */
.advanced-copy-backdrop {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.36);
    z-index: 2400;
}
.advanced-copy-backdrop[hidden] { display: none; }

.advanced-copy-dialog {
    position: fixed;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    z-index: 2401;
    width: min(560px, calc(100vw - 32px));
    max-height: calc(100vh - 64px);
    display: flex;
    flex-direction: column;
    background: var(--bg-elevated);
    color: var(--text-primary);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-soft);
    padding: 16px;
    gap: 12px;
    font-size: 13px;
}
.advanced-copy-dialog[hidden] { display: none; }

.advanced-copy-header {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
}
.advanced-copy-title {
    font-size: 14px;
    font-weight: 600;
}
.advanced-copy-detected {
    font-size: 11.5px;
    color: var(--text-tertiary);
    text-transform: uppercase;
    letter-spacing: .04em;
}

.advanced-copy-blocks {
    display: flex;
    flex-direction: column;
    gap: 2px;
    max-height: 40vh;
    overflow-y: auto;
    padding: 4px;
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-sm);
    background: var(--bg-base);
}
.advanced-copy-row {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 4px 6px;
    border-radius: var(--radius-sm);
    cursor: pointer;
    transition: background-color .12s;
}
.advanced-copy-row:hover { background: var(--border-subtle); }
.advanced-copy-row input[type="checkbox"] { margin: 0; flex: 0 0 auto; }
.advanced-copy-block-label {
    flex: 0 0 auto;
    font-weight: 500;
    color: var(--text-primary);
}
.advanced-copy-block-preview {
    flex: 1 1 auto;
    color: var(--text-tertiary);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
}

.advanced-copy-format {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 12px;
}
.advanced-copy-format label {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    cursor: pointer;
}
.advanced-copy-row-label {
    font-weight: 500;
    color: var(--text-secondary);
    margin-right: 4px;
}

.advanced-copy-join label {
    display: inline-flex;
    align-items: center;
    gap: 6px;
}
.advanced-copy-join-select {
    padding: 3px 6px;
    background: var(--bg-base);
    color: var(--text-primary);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-sm);
    font-size: 12.5px;
}

.advanced-copy-actions {
    display: flex;
    justify-content: flex-end;
    gap: 8px;
}

/* "Convert to discussion" roster picker — hand-rolled modal hosting the shared
   .discussion-setup panel. Chrome mirrors the advanced-copy dialog. */
.convert-discussion-backdrop {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.36);
    z-index: 2400;
}
.convert-discussion-dialog {
    position: fixed;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    z-index: 2401;
    width: min(560px, calc(100vw - 32px));
    max-height: calc(100vh - 64px);
    display: flex;
    flex-direction: column;
    background: var(--bg-elevated);
    color: var(--text-primary);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-soft);
    padding: 16px;
    gap: 12px;
    font-size: 13px;
}
.convert-discussion-header {
    display: flex;
    flex-direction: column;
    gap: 4px;
}
.convert-discussion-title {
    font-size: 14px;
    font-weight: 600;
}
.convert-discussion-sub {
    font-size: 12px;
    color: var(--text-secondary);
}
.convert-discussion-body {
    overflow-y: auto;
    min-height: 0;
}
.convert-discussion-actions {
    display: flex;
    justify-content: flex-end;
    gap: 8px;
}

#user-input::placeholder { color: var(--text-tertiary); }

.composer-send {
    width: 32px;
    height: 32px;
    flex-shrink: 0;
    border: 0;
    border-radius: 50%;
    background: var(--accent);
    color: #fff;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: background-color .12s, transform .08s;
    font-size: 14px;
}

.composer-send:hover { background: var(--accent-hover); }
.composer-send:active { transform: scale(0.95); }

body.ui-chat-busy .composer-send {
    background: var(--danger);
}
body.ui-chat-busy .composer-send:hover {
    background: var(--danger);
    filter: brightness(1.1);
}
body.ui-chat-busy #user-input {
    opacity: 0.5;
}

.composer-hint {
    max-width: calc(100% - 48px);
    margin: 6px auto 0;
    padding: 0 4px;
    font-size: 11px;
    color: var(--text-tertiary);
    text-align: center;
    user-select: none;
}

.composer-recovered {
    max-width: calc(100% - 48px);
    margin: 8px auto 0;
    padding: 6px 10px;
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 12px;
    color: var(--text-secondary);
    background: var(--surface-2, rgba(127, 127, 127, 0.06));
    border-left: 3px solid var(--accent);
    border-radius: 4px;
    user-select: none;
}

.composer-recovered[hidden] {
    display: none;
}

.composer-recovered > .bi-arrow-counterclockwise {
    color: var(--accent);
    font-size: 14px;
    flex: 0 0 auto;
}

.composer-recovered-text {
    flex: 1 1 auto;
    line-height: 1.35;
}

.composer-recovered-restore {
    flex: 0 0 auto;
    background: transparent;
    border: 1px solid var(--accent);
    color: var(--accent);
    padding: 2px 8px;
    border-radius: 3px;
    cursor: pointer;
    font-size: 12px;
    line-height: 1.4;
    display: inline-flex;
    align-items: center;
    gap: 4px;
}

.composer-recovered-restore:hover {
    color: var(--text-primary);
    background: var(--accent);
}

.composer-recovered-restore .bi-pencil {
    font-size: 11px;
}

.composer-recovered-dismiss {
    flex: 0 0 auto;
    background: transparent;
    border: 0;
    color: var(--text-tertiary);
    padding: 2px 6px;
    border-radius: 3px;
    cursor: pointer;
    font-size: 13px;
    line-height: 1;
}

.composer-recovered-dismiss:hover {
    color: var(--text-primary);
    background: rgba(127, 127, 127, 0.12);
}

.composer-hint-busy {
    color: var(--accent);
    font-weight: 500;
    animation: composer-hint-pulse 1.4s ease-in-out infinite;
}

/* Transient nudge when a side-by-side compare-set must be picked before the
   conversation can continue. Reuses the busy-hint pulse cadence in danger
   colour so it reads as a block, not background activity. */
.composer-hint-warn {
    color: var(--danger);
    font-weight: 500;
    animation: composer-hint-pulse 1.4s ease-in-out infinite;
}

@keyframes composer-hint-pulse {
    0%, 100% { opacity: 1; }
    50%      { opacity: 0.55; }
}

/* ===========================================================================
 * Tab strip — chip-style tabs sitting above the chat pane
 * ========================================================================= */

.tab-strip {
    position: relative;
    display: flex;
    align-items: stretch;
    gap: 0;
    padding: 6px 8px 0;
    background: linear-gradient(to bottom, var(--bg-elevated) 0%, var(--bg-base) 100%);
    border-top: 1px solid var(--border-subtle);
    border-bottom: 1px solid var(--border-subtle);
    flex-shrink: 0;
}

.tab-list-scroll {
    position: relative;
    flex: 1;
    min-width: 0;
    overflow-x: auto;
    scrollbar-width: none;            /* standards / Firefox */
    -webkit-mask-image: linear-gradient(to right, transparent 0, #000 16px, #000 calc(100% - 16px), transparent 100%);
            mask-image: linear-gradient(to right, transparent 0, #000 16px, #000 calc(100% - 16px), transparent 100%);
}
/* The strip caps inline tabs at MAX_VISIBLE_TABS and overflows the rest into
   the >>+N popover, so the strip never needs a visible scrollbar. Hide the
   chrome but keep overflow-x:auto as a silent swipe fallback on narrow windows. */
.tab-list-scroll::-webkit-scrollbar { display: none; }

.tab-list {
    display: flex;
    align-items: stretch;
    gap: 0;
    min-width: 0;
}

.tab {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 8px 16px 9px 16px;
    /* Flex to fill the strip: few tabs sit near MAX_TAB_WIDTH, many shrink to
       the min — the JS inline-count guarantees they never cross it before
       spilling into the +N popover. overflow-x:auto on .tab-list-scroll is the
       silent fallback if a render briefly outruns the width. */
    flex: 1 1 auto;
    min-width: var(--min-tab-width, 132px);
    max-width: 240px;
    border: 0;
    border-radius: var(--radius-md) var(--radius-md) 0 0;
    background: transparent;
    color: var(--text-secondary);
    cursor: pointer;
    font-size: 12.5px;
    letter-spacing: 0.01em;
    user-select: none;
    transition: background-color .15s ease, color .15s ease;
    animation: tab-enter .14s ease both;
}

/* Newly shown tabs fade + rise in rather than popping into place. */
@keyframes tab-enter {
    from { opacity: 0; transform: translateY(2px); }
    to   { opacity: 1; transform: translateY(0); }
}

/* Per-tab identity top rail. Every tab gets a dim rail in its own type
   color (--tab-self-color, set by the type rules below); hover brightens it,
   the active tab makes it full-strength with a bloom (.tab.active::before
   further down), and streaming swaps in the animated comet (.tab.is-streaming
   ::before). This single ::before replaces the old newspaper-column separator. */
.tab::before {
    content: '';
    position: absolute;
    top: 0;
    left: 8px;
    right: 8px;
    height: 2px;
    border-radius: 1px;
    background: color-mix(in srgb, var(--tab-self-color, var(--accent)) 40%, transparent);
    transition: background-color .15s ease, box-shadow .15s ease, opacity .15s ease;
}
.tab:hover::before {
    background: color-mix(in srgb, var(--tab-self-color, var(--accent)) 65%, transparent);
}

/* Inactive tabs carry a faint wash in their own identity color so each tab is
   individually recognizable, while staying well below the active tab's
   strength (the active tab gets a much stronger wash + bloom + bold title). */
.tab:not(.active) {
    background: color-mix(in srgb, var(--tab-self-color, var(--accent)) 7%, transparent);
}

.tab:hover:not(.active) {
    color: var(--text-primary);
    background: color-mix(in srgb, var(--tab-self-color, var(--accent)) 13%, transparent);
}

/* Active tab — folder silhouette emerging from the chat surface */
.tab.active {
    color: var(--text-primary);
    background: var(--bg-base);
    box-shadow:
        inset 1px 0 0 0 color-mix(in srgb, var(--border-subtle) 65%, transparent),
        inset -1px 0 0 0 color-mix(in srgb, var(--border-subtle) 65%, transparent),
        0 -1px 7px -3px var(--accent-ring);
}

.tab.active .tab-title {
    font-weight: 500;
}

/* Full-strength identity top rail with a soft bloom underneath — the active
   tab's rail is bright where inactive tabs' are dim. */
.tab.active::before {
    background: var(--tab-self-color, var(--accent));
    box-shadow: 0 0 8px 0 color-mix(in srgb, var(--tab-self-color, var(--accent)) 60%, transparent);
    opacity: 1;
}

/* Active tab covers the strip's bottom hairline at its position */
.tab.active::after {
    content: '';
    position: absolute;
    left: 0;
    right: 0;
    bottom: -1px;
    height: 1px;
    background: var(--bg-base);
    pointer-events: none;
}

/* Streaming — persistent low-alpha rail with a soft comet shimmering across.
   Layer 1 (animated): symmetric soft hump that slides linearly.
   Layer 2 (static): low-alpha accent rail so the line is always visible. */
.tab.is-streaming::before {
    content: '';
    position: absolute;
    top: 0;
    left: 8px;
    right: 8px;
    height: 2px;
    background-image:
        linear-gradient(
            90deg,
            transparent 0%,
            var(--accent) 50%,
            transparent 100%
        ),
        linear-gradient(
            90deg,
            color-mix(in srgb, var(--accent) 35%, transparent),
            color-mix(in srgb, var(--accent) 35%, transparent)
        );
    background-size: 50% 100%, 100% 100%;
    background-repeat: no-repeat, no-repeat;
    background-position: -60% 0, 0 0;
    border-radius: 1px;
    opacity: 1;
    width: auto;
    animation: tab-streaming-rail 2.4s linear infinite;
}

@keyframes tab-streaming-rail {
    0%   { background-position: -60% 0, 0 0; }
    100% { background-position: 160% 0, 0 0; }
}

/* Tag indicator — left-edge ribbon. Reuses the inline background-color
   set by renderTabs() (selector unchanged), no JS change required. */
.tab .tab-tag-dot {
    position: absolute;
    left: 4px;
    top: 6px;
    bottom: 6px;
    width: 3px;
    height: auto;
    border-radius: 2px;
    flex: 0 0 auto;
}

.tab .tab-title {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    flex: 1;
    min-width: 0;
}

.tab .tab-title.is-editing {
    cursor: text;
    background: var(--bg-base);
    border-radius: var(--radius-sm);
    box-shadow: 0 0 0 2px var(--accent-ring);
    padding: 0 4px;
    outline: none;
}

/* Close — circular hit area, danger wash on hover */
.tab .tab-close {
    opacity: 0;
    transition: opacity .12s, background-color .12s, color .12s;
    width: 18px;
    height: 18px;
    padding: 0;
    border-radius: 50%;
    border: 0;
    background: transparent;
    color: var(--text-tertiary);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    line-height: 1;
    flex: 0 0 auto;
}
.tab .tab-close i.bi-x-lg { font-size: 11px; }

.tab:hover .tab-close, .tab.active .tab-close { opacity: 1; }
.tab .tab-close:hover { background: var(--danger-soft); color: var(--danger); }

/* New-tab — dashed plus that solidifies and rotates on hover */
.tab-new {
    width: 28px;
    height: 28px;
    margin-left: 8px;
    align-self: center;
    border-radius: var(--radius-md);
    background: transparent;
    border: 1px dashed var(--border-strong);
    color: var(--text-tertiary);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    transition: background-color .18s ease, color .18s ease, border-color .18s ease;
}
.tab-new i {
    display: inline-flex;
    transition: transform .18s ease;
}
.tab-new:hover:not(:disabled) {
    background: var(--accent-soft);
    border-style: solid;
    border-color: var(--accent);
    color: var(--accent);
}
.tab-new:hover:not(:disabled) i { transform: rotate(90deg); }
.tab-new:disabled { opacity: 0.4; cursor: not-allowed; }

/* Overflow chevron — sibling of .tab-new, lives outside the scrolling region
   so it stays visible. Visibility toggled by renderTabs() via [hidden]. */
.tab-overflow {
    width: auto;
    min-width: 28px;
    height: 28px;
    margin-left: 4px;
    padding: 0 8px;
    gap: 4px;
    align-self: center;
    border-radius: var(--radius-md);
    background: transparent;
    border: 1px solid var(--border-subtle);
    color: var(--text-tertiary);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    transition: background-color .15s ease, color .15s ease, border-color .15s ease;
}
.tab-overflow[hidden] { display: none; }
.tab-overflow i { font-size: 12px; }
.tab-overflow .tab-overflow-count {
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.01em;
    line-height: 1;
}
.tab-overflow .tab-overflow-count:empty { display: none; }
.tab-overflow:hover {
    background: var(--accent-soft);
    border-color: var(--accent);
    color: var(--accent);
}
.tab-overflow.is-open {
    background: var(--accent-soft);
    border-color: var(--accent);
    color: var(--accent);
}

/* Popover anchored under the .tab-strip's right edge. Reuses the chat-overview
   list aesthetic so it feels native. The strip has position: relative — this
   absolutely positions relative to the strip. */
.tab-overflow-popover {
    position: absolute;
    top: 100%;
    right: 8px;
    margin-top: 4px;
    z-index: 50;
    width: 320px;
    max-height: 360px;
    overflow-y: auto;
    background: var(--bg-surface);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-md);
    box-shadow: 0 8px 24px -8px rgba(0,0,0,0.18), 0 2px 4px rgba(0,0,0,0.08);
    padding: 6px 0;
}
.tab-overflow-popover[hidden] { display: none; }

.tab-overflow-entry {
    position: relative;
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 6px 10px 6px 14px;
    cursor: pointer;
    color: var(--text-secondary);
    font-size: 12.5px;
    transition: background-color .12s ease, color .12s ease;
}
.tab-overflow-entry:hover {
    background: var(--accent-soft);
    color: var(--text-primary);
}
.tab-overflow-entry.is-active {
    background: var(--accent-soft);
    color: var(--text-primary);
}
.tab-overflow-entry-bar {
    position: absolute;
    left: 0;
    top: 6px;
    bottom: 6px;
    width: 3px;
    border-radius: 2px;
    background: var(--tab-color-fallback, var(--accent));
}
.tab-overflow-entry.is-streaming .tab-overflow-entry-bar {
    background: linear-gradient(
        to bottom,
        var(--accent) 0%,
        color-mix(in srgb, var(--accent) 35%, transparent) 100%
    );
}
.tab-overflow-entry-tag-dot {
    flex: 0 0 8px;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: transparent;
}
.tab-overflow-entry-title {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.tab-overflow-entry.is-active .tab-overflow-entry-title {
    font-weight: 500;
}
.tab-overflow-entry-close {
    flex: 0 0 18px;
    width: 18px;
    height: 18px;
    padding: 0;
    border-radius: 50%;
    border: 0;
    background: transparent;
    color: var(--text-tertiary);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    line-height: 1;
    opacity: 0;
    transition: opacity .12s, background-color .12s, color .12s;
}
.tab-overflow-entry-close i { font-size: 11px; }
.tab-overflow-entry:hover .tab-overflow-entry-close,
.tab-overflow-entry.is-active .tab-overflow-entry-close {
    opacity: 1;
}
.tab-overflow-entry-close:hover {
    background: var(--danger-soft);
    color: var(--danger);
}

/* ---------------------------------------------------------------------------
 * Per-tab identity color now maps to chat TYPE, not a random per-id hue:
 *   • normal     → green accent (the --tab-self-color fallback to --accent)
 *   • preset     → navy (--tab-tint-navy), or a per-preset custom color set
 *                  inline by renderTabs() when preset is the effective type
 *   • discussion → violet  (.tab.is-discussion, below)
 *   • temporary  → amber   (.tab.is-temporary, below)
 * --tab-self-color drives the unified wash + top-rail + bloom defined above.
 *
 * The is-preset rule is placed BEFORE is-discussion / is-temporary so those
 * win by source order when a chat is both (e.g. a discussion-mode preset →
 * violet). renderTabs() only sets the inline custom color when preset is the
 * effective type, so an inline value never defeats the amber/violet treatment.
 * ------------------------------------------------------------------------- */
.tab.is-preset { --tab-self-color: var(--tab-tint-navy); }
.tab.is-preset .tab-preset-icon {
    color: var(--tab-self-color);
    flex: 0 0 auto;
}

/* Active tab: strong identity wash over the chat surface (the rail + bloom
   come from .tab.active::before above). Stronger than the inactive 7% wash so
   the active tab dominates regardless of which palette color it carries. */
.tab.active {
    background: color-mix(in srgb, var(--tab-self-color, var(--accent)) 16%, var(--bg-base));
}

.tab.active .tab-tag-dot {
    box-shadow: 0 0 0 1px color-mix(in srgb, var(--tab-self-color, var(--accent)) 60%, transparent);
}

/* ---------------------------------------------------------------------------
 * Temporary (memory-only) chats: amber identity so they read as
 * provisional/unsaved at a glance — the tab strip is the only place a temp
 * chat is visible (it never hits the DB or the sidebar). Overriding
 * --tab-self-color (rather than setting background directly) makes the unified
 * wash + rail render amber for BOTH inactive and active states. Placed after
 * the palette rules so it wins on equal specificity. */
.tab.is-temporary {
    --tab-self-color: var(--tab-tint-amber);
}
.tab.is-temporary .tab-temp-icon {
    color: var(--tab-tint-amber);
    flex: 0 0 auto;
}

/* Discussion chats: violet identity (mirrors .tab.is-temporary amber). Same
   mechanism — override --tab-self-color so the wash + rail render violet for
   both inactive and active. is-discussion + is-temporary never co-occur. */
.tab.is-discussion {
    --tab-self-color: var(--tab-tint-violet);
}
.tab.is-discussion .tab-discussion-icon {
    color: var(--tab-tint-violet);
    flex: 0 0 auto;
}

/* "Do not sync" marker (20260637). Orthogonal to the type icon (a discussion
   can also be local-only), so it does NOT override --tab-self-color — it just
   adds a muted cloud-slash glyph and slightly desaturates the tab so it reads
   as "kept off your other devices" without fighting the type color. */
.tab.is-local-only {
    opacity: 0.92;
}
.tab .tab-local-only-icon {
    color: var(--text-muted, #8a8a8a);
    flex: 0 0 auto;
    opacity: 0.85;
}
.tab.active .tab-local-only-icon {
    opacity: 1;
}

/* ---------------------------------------------------------------------------
 * Tab-nav hover-strips: thin vertical click targets flanking the chat
 * container that switch to the prev/next tab. Idle they're a barely-there
 * gradient hint; on hover they expand and pulse in the target tab's color.
 * ------------------------------------------------------------------------- */
.tab-nav-zone {
    display: flex;
    flex: 1 1 auto;
    min-height: 0;
    min-width: 0;
    position: relative;
}

.tab-nav-strip {
    flex: 0 0 auto;
    width: 6px;
    align-self: stretch;
    padding: 0;
    margin: 0;
    border: 0;
    background: transparent;
    cursor: pointer;
    position: relative;
    overflow: hidden;
    color: inherit;
    transition: width 180ms ease, background-color 180ms ease;
    --tab-nav-color: var(--accent);
}

.tab-nav-strip[hidden] { display: none; }
.tab-nav-strip[aria-disabled="true"] { opacity: 0.35; cursor: default; }

#tab-nav-prev {
    background: linear-gradient(
        to right,
        color-mix(in srgb, var(--tab-nav-color) 18%, transparent) 0%,
        transparent 100%
    );
}
#tab-nav-next {
    background: linear-gradient(
        to left,
        color-mix(in srgb, var(--tab-nav-color) 18%, transparent) 0%,
        transparent 100%
    );
}

.tab-nav-strip:hover,
.tab-nav-strip:focus-visible {
    width: 18px;
    outline: none;
}

#tab-nav-prev:hover,
#tab-nav-prev:focus-visible {
    background: linear-gradient(
        to right,
        color-mix(in srgb, var(--tab-nav-color) 55%, transparent) 0%,
        color-mix(in srgb, var(--tab-nav-color) 12%, transparent) 60%,
        transparent 100%
    );
    box-shadow: inset 2px 0 0 0 var(--tab-nav-color);
}
#tab-nav-next:hover,
#tab-nav-next:focus-visible {
    background: linear-gradient(
        to left,
        color-mix(in srgb, var(--tab-nav-color) 55%, transparent) 0%,
        color-mix(in srgb, var(--tab-nav-color) 12%, transparent) 60%,
        transparent 100%
    );
    box-shadow: inset -2px 0 0 0 var(--tab-nav-color);
}

.tab-nav-pulse {
    position: absolute;
    top: 30%;
    bottom: 30%;
    left: 50%;
    width: 2px;
    transform: translateX(-50%);
    background: var(--tab-nav-color);
    border-radius: 2px;
    opacity: 0;
    pointer-events: none;
    transition: opacity 160ms ease;
}

.tab-nav-strip:hover .tab-nav-pulse,
.tab-nav-strip:focus-visible .tab-nav-pulse {
    opacity: 0.6;
    animation: tab-nav-pulse 1.6s ease-in-out infinite;
}

@keyframes tab-nav-pulse {
    0%, 100% { opacity: 0.2; }
    50%      { opacity: 0.7; }
}

/* On narrow viewports the strips would crowd the chat — hide them. */
@media (max-width: 600px) {
    .tab-nav-strip { display: none; }
}

body.ui-search-mode .composer-wrap {
    display: none;
}

body.ui-search-mode .chat-group-label { display: none; }

/* ===========================================================================
 * Search highlights / chat match counts
 * ========================================================================= */

.search-highlight {
    background-color: var(--highlight-bg);
    color: var(--text-primary);
    border-radius: 2px;
    padding: 0 2px;
}

.search-highlight.current {
    background-color: var(--highlight-bg-current);
    color: var(--highlight-fg-current);
}

.chat-match-count {
    margin-left: auto;
    background: var(--accent);
    color: #fff;
    border-radius: 999px;
    padding: 1px 8px;
    font-size: 10px;
    font-weight: 600;
    font-family: var(--font-mono);
}

/* In-chat "find on this page" bar. Pinned to the top-right of .tab-nav-zone
 * (which is position:relative) so it floats over the transcript while the chat
 * scrolls underneath it. Reuses .search-toggle for the match-case control and
 * .search-highlight for the hits themselves. */
.in-chat-find-bar {
    position: absolute;
    top: 10px;
    right: 18px;
    z-index: 40;
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 5px 8px;
    background: var(--bg-elevated);
    border: 1px solid var(--border-subtle);
    border-radius: 8px;
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.25);
}

.in-chat-find-bar > .bi-search {
    color: var(--text-tertiary);
    font-size: 13px;
}

#in-chat-find-input {
    width: 180px;
    border: 0;
    outline: none;
    background: transparent;
    color: var(--text-primary);
    font-size: 13px;
    padding: 2px 2px;
}

#in-chat-find-input::placeholder { color: var(--text-tertiary); }

.in-chat-find-bar:focus-within {
    border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--accent-ring), 0 4px 16px rgba(0, 0, 0, 0.25);
}

.in-chat-find-counter {
    min-width: 54px;
    text-align: right;
    font-family: var(--font-mono);
    font-size: 11px;
    color: var(--text-tertiary);
    white-space: nowrap;
}

.in-chat-find-counter.no-results { color: var(--danger, #e5534b); }

.in-chat-find-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 26px;
    height: 26px;
    padding: 0;
    border: 0;
    border-radius: 6px;
    background: transparent;
    color: var(--text-tertiary);
    cursor: pointer;
    font-size: 13px;
    transition: color .15s, background-color .15s;
}

.in-chat-find-btn:hover { color: var(--text-secondary); background: var(--bg-base, var(--bg-elevated)); }

/* ===========================================================================
 * Modals (Bootstrap)
 * ========================================================================= */

.modal-content {
    background: var(--bg-elevated);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-lg);
    color: var(--text-primary);
    box-shadow: var(--shadow-soft);
}

.modal-header {
    border-bottom: 1px solid var(--border-subtle);
    padding: 16px 20px;
}

.modal-title { font-weight: 600; font-size: 16px; }

.modal-body { padding: 20px; }

.modal-footer {
    border-top: 1px solid var(--border-subtle);
    padding: 14px 20px;
    gap: 8px;
}

.btn-close {
    --bs-btn-close-color: var(--text-primary);
    filter: invert(85%);
    opacity: 0.7;
}

.btn-close:hover { opacity: 1; }

.btn-close:focus { box-shadow: 0 0 0 3px var(--accent-ring); }

/* Buttons inside Bootstrap modal */
.btn {
    font-family: var(--font-sans);
    border-radius: var(--radius-sm);
    font-size: 13px;
    font-weight: 500;
    padding: 6px 14px;
    transition: background-color .12s, border-color .12s, color .12s;
}

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

.btn-primary:hover,
.btn-accent:hover {
    background: var(--accent-hover);
    border-color: var(--accent-hover);
    color: #fff;
}

.btn-primary:focus-visible,
.btn-accent:focus-visible {
    box-shadow: 0 0 0 3px var(--accent-ring);
}

.btn-secondary {
    background: transparent;
    border-color: var(--border-strong);
    color: var(--text-primary);
}

.btn-secondary:hover {
    background: var(--bg-base);
    border-color: var(--border-strong);
    color: var(--text-primary);
}

.btn-outline-accent {
    background: transparent;
    border: 1px solid var(--accent);
    color: var(--accent);
}

.btn-outline-accent:hover {
    background: var(--accent-soft);
    color: var(--accent);
}

.btn-outline-danger {
    border-color: rgba(229, 72, 77, 0.4);
    color: var(--danger);
}

.btn-outline-danger:hover {
    background: var(--danger-soft);
    border-color: var(--danger);
    color: var(--danger);
}

/* Forms inside modal */
.form-control,
.form-select {
    background: var(--bg-input);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-sm);
    color: var(--text-primary);
    font-family: var(--font-sans);
    font-size: 13px;
    padding: 8px 12px;
    transition: border-color .12s, box-shadow .12s;
}

.form-control:focus,
.form-select:focus {
    background: var(--bg-input);
    border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--accent-ring);
    color: var(--text-primary);
}

.form-control::placeholder { color: var(--text-tertiary); }

.form-label {
    color: var(--text-secondary);
    font-size: 12px;
    font-weight: 500;
    margin-bottom: 6px;
    text-transform: uppercase;
    letter-spacing: 0.04em;
}

.form-text {
    color: var(--text-tertiary);
    font-size: 11px;
    margin-top: 4px;
}

.form-select option {
    background: var(--bg-elevated);
    color: var(--text-primary);
}

/* ===========================================================================
 * Manage Profiles modal
 * ========================================================================= */

/* The two-pane studio fills the modal body and owns its own scrolling, so the
   modal body itself never scrolls — that keeps the left footer and the right
   form-action bar pinned while the list / form bodies scroll underneath.
   `minmax(0, 1fr)` lets the single grid row shrink below its content so the
   inner overflow-y panes engage. */
#profiles-modal .modal-body,
#snippets-modal .modal-body {
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

/* Comfortable floor for sparse panes (packs / empty states) without
   re-introducing clipping: capped to the viewport so on short windows the
   dialog stays fully on-screen and the inner form pane owns the scrolling. */
#profiles-modal .modal-content,
#snippets-modal .modal-content {
    min-height: min(460px, 85vh);
}

.profiles-pane {
    display: grid;
    grid-template-columns: 240px 1fr;
    grid-template-rows: minmax(0, 1fr);
    flex: 1 1 auto;
    /* Shrink to the modal body so the inner form pane (overflow-y: auto) always
       engages and the sticky action bar stays reachable at every window height.
       The comfortable floor now lives on .modal-content (capped to the
       viewport) so short windows never clip. */
    min-height: 0;
}

.profiles-list-pane {
    border-right: 1px solid var(--border-subtle);
    display: flex;
    flex-direction: column;
    background: var(--bg-surface);
    min-height: 0;
}

.profile-list {
    list-style: none;
    margin: 0;
    padding: 8px;
    flex: 1;
    overflow-y: auto;
}

.profile-list li {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 10px;
    margin-bottom: 2px;
    border-radius: var(--radius-sm);
    color: var(--text-secondary);
    cursor: pointer;
    font-size: 13px;
    transition: background-color .12s, color .12s;
}

.profile-list li:hover { background: var(--bg-elevated); color: var(--text-primary); }

.profile-list li.active {
    background: var(--accent-soft);
    color: var(--text-primary);
}

.profile-list li.is-multi-selected {
    background: var(--accent-soft);
    color: var(--text-primary);
    box-shadow: inset 0 0 0 1px var(--accent);
}

.profile-list-add.profile-list-delete:hover {
    color: var(--danger);
    border-color: var(--danger);
    background: color-mix(in srgb, var(--danger) 12%, transparent);
}

.profile-list li .profile-list-active-marker {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--accent);
    visibility: hidden;
}

.profile-list li.is-active-profile .profile-list-active-marker { visibility: visible; }

.profile-list-default-badge {
    display: inline-flex;
    align-items: center;
    padding: 2px 8px;
    border-radius: 999px;
    font-size: 11px;
    font-weight: 500;
    line-height: 1.4;
    border: 1px solid transparent;
    background: var(--bg-elevated, rgba(0, 0, 0, 0.04));
    color: var(--text-secondary);
    cursor: pointer;
    transition: background-color .12s, border-color .12s, color .12s;
}
.profile-list-default-badge:hover {
    background: var(--accent-soft, rgba(13, 110, 253, 0.08));
    border-color: var(--accent, #0d6efd);
    color: var(--accent, #0d6efd);
}
.profile-list-default-badge.is-default {
    background: var(--bs-secondary, #6c757d);
    color: #fff;
    border-color: var(--bs-secondary, #6c757d);
    cursor: default;
}
.profile-list-default-badge.is-default:hover {
    background: var(--bs-secondary, #6c757d);
    border-color: var(--bs-secondary, #6c757d);
    color: #fff;
}

.profile-list-add {
    margin: 6px 8px 8px;
    height: 34px;
    border: 1px dashed var(--border-strong);
    background: transparent;
    color: var(--text-secondary);
    border-radius: var(--radius-sm);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    font-size: 12px;
    transition: color .12s, border-color .12s, background-color .12s;
}

.profile-list-add:hover {
    color: var(--accent);
    border-color: var(--accent);
    background: var(--accent-soft);
}

.profile-import-list {
    list-style: none;
    padding: 0;
    margin: 0;
}
.profile-import-list li {
    padding: 4px 0;
    border-bottom: 1px solid var(--border-strong, rgba(255,255,255,0.08));
    display: flex;
    align-items: center;
}
.profile-import-list li:last-child { border-bottom: none; }

/* Compose-package checkbox lists: scroll within a bounded height so a large
   agent/team roster keeps the modal compact. */
.compose-pick-list {
    max-height: 260px;
    overflow-y: auto;
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-sm);
    padding: 4px 8px;
}
.compose-pick-list li { gap: 8px; }
.compose-pick-list .form-check { margin: 0; width: 100%; }
.compose-pick-list:empty::after {
    content: "None available";
    color: var(--text-muted, var(--text-secondary));
    font-size: 12px;
}

.profile-packs-list {
    display: flex;
    flex-direction: column;
    gap: 8px;
    margin-top: 8px;
}
.profile-pack-row {
    border: 1px solid var(--border-strong, rgba(255,255,255,0.1));
    border-radius: var(--radius-sm, 4px);
    padding: 10px 12px;
    display: grid;
    grid-template-columns: 1fr auto;
    grid-template-rows: auto auto;
    column-gap: 12px;
    row-gap: 4px;
    align-items: center;
}
.profile-pack-head {
    grid-column: 1;
    grid-row: 1;
    display: flex;
    align-items: center;
    gap: 8px;
}
.profile-pack-title {
    font-weight: 600;
}
.profile-pack-status {
    font-size: 11px;
}
.profile-pack-desc {
    grid-column: 1;
    grid-row: 2;
    font-size: 12px;
    color: var(--text-secondary);
}
.profile-pack-count {
    margin-left: 8px;
    opacity: 0.7;
}
.profile-pack-actions {
    grid-column: 2;
    grid-row: 1 / span 2;
    align-self: center;
}

.profiles-form-pane {
    padding: 20px;
    overflow-y: auto;
    min-height: 0;
}

/* Action row pinned to the bottom of the scrolling form pane, so Save / Delete
   / Export stay visible no matter how tall the form grows. */
.profile-form-actions {
    display: flex;
    align-items: center;
    gap: 8px;
    padding-top: 12px;
    padding-bottom: 4px;
    border-top: 1px solid var(--border-subtle);
    margin-top: 16px;
    position: sticky;
    bottom: 0;
    background: var(--bg-elevated);
    z-index: 1;
}

/* Parallel-response slot rows in the profile editor.
   Grid: [letter | model | reasoning | temperature | remove], collapsing to
   a stacked layout below ~720px. */
.profile-slots {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.profile-slots:empty {
    display: none;
}

/* ---------------------------------------------------------------------------
 * Agents & Teams — merged studio modal.
 * A segmented toggle shows ONE left-pane list at a time (Agents or Teams); the
 * right pane swaps between the agent form and the team composer. Action buttons
 * live in pinned footers (left) / a sticky bar (right) so they never scroll off.
 * ------------------------------------------------------------------------- */

/* Left-pane segmented toggle (Agents | Teams), flush at the top of the pane. */
.studio-kind-toggle {
    flex: 0 0 auto;
    margin: 8px;
}
.studio-kind-toggle .segmented-option { flex: 1 1 0; }

/* One list at a time: only the .is-active section is shown, and it flexes to
   fill the space between the toggle and the pinned footer. The inner
   .profile-list scrolls; the footer never does. */
.studio-list-section { display: none; min-height: 0; }
.studio-list-section.is-active {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
}

/* Pinned action footer: New / Import / Compose stay put while the list above
   scrolls underneath. */
.studio-list-footer {
    flex: 0 0 auto;
    display: flex;
    flex-direction: column;
    border-top: 1px solid var(--border-subtle);
    padding-top: 4px;
}

/* A TEAMS-list row briefly flashes after a quick-add drop persists. */
.profile-list li.team-flash {
    background: var(--accent-soft);
    transition: background-color .2s;
}
/* A TEAMS-list row is a live dropzone for agent quick-add. */
.profile-list li.drag-over {
    outline: 2px dashed var(--accent);
    outline-offset: -2px;
    background: var(--accent-soft);
}

/* Team member roster — a vertical stack of draggable chips. */
.team-members {
    display: flex;
    flex-direction: column;
    gap: 6px;
    min-height: 52px;
    padding: 6px;
    border: 1px dashed var(--border-strong);
    border-radius: var(--radius-md);
    transition: background-color .12s, border-color .12s;
}
.team-members.is-empty::before {
    content: "Drag agents here, or use “Add agent…” below.";
    color: var(--text-muted, var(--text-secondary));
    font-size: 12px;
    padding: 10px 8px;
    text-align: center;
}
.team-members.drag-over {
    border-color: var(--accent);
    background: var(--accent-soft);
}

.team-member-chip {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 7px 10px;
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-md);
    background: var(--surface-soft, var(--bg-surface));
    cursor: grab;
}
.team-member-chip.is-dragging { opacity: 0.4; cursor: grabbing; }
.team-member-chip.tm-drop-before { box-shadow: inset 0 2px 0 var(--accent); }
.team-member-chip.tm-drop-after { box-shadow: inset 0 -2px 0 var(--accent); }
.team-member-chip.tm-missing { opacity: 0.6; }
.team-member-chip .tm-handle {
    color: var(--text-muted, var(--text-secondary));
    cursor: grab;
    display: inline-flex;
}
.team-member-chip .tm-letter {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    border-radius: 50%;
    font-weight: 600;
    font-size: 0.78rem;
    background: var(--accent-soft);
    color: var(--accent);
    flex: 0 0 auto;
}
.team-member-chip .tm-avatar { flex: 0 0 auto; }
.team-member-chip .tm-name {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: 13px;
}
.team-member-chip .tm-remove {
    flex: 0 0 auto;
    margin-left: auto;
    border: 0;
    background: transparent;
    color: var(--text-secondary);
    border-radius: var(--radius-sm);
    padding: 4px 6px;
    cursor: pointer;
}
.team-member-chip .tm-remove:hover { color: var(--bs-danger, #dc3545); background: var(--border-subtle); }

/* Trash affordance shown only while a chip is being dragged. */
.team-members-trash {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    margin-top: 8px;
    padding: 12px;
    border: 1px dashed var(--bs-danger, #dc3545);
    border-radius: var(--radius-md);
    color: var(--bs-danger, #dc3545);
    font-size: 12px;
    transition: background-color .12s;
}
.team-members-trash.drag-over { background: var(--danger-soft, rgba(220, 53, 69, 0.12)); }

.team-add-agent { max-width: 100%; }

.profile-slot-row {
    display: grid;
    grid-template-columns: 28px minmax(0, 1.4fr) minmax(0, 1fr) minmax(0, 1.2fr) 32px;
    gap: 8px;
    align-items: center;
    padding: 8px 10px;
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-md);
    background: var(--surface-soft, transparent);
    cursor: grab;
}

.profile-slot-row.is-dragging { opacity: 0.4; cursor: grabbing; }
.profile-slot-row.is-drop-above { box-shadow: inset 0 2px 0 var(--bs-primary); }
.profile-slot-row.is-drop-below { box-shadow: inset 0 -2px 0 var(--bs-primary); }
.discussion-participant-row.is-dragging { opacity: 0.4; cursor: grabbing; }
.discussion-participant-row.is-drop-above { box-shadow: inset 0 2px 0 var(--bs-primary); }
.discussion-participant-row.is-drop-below { box-shadow: inset 0 -2px 0 var(--bs-primary); }
.profile-slot-row select,
.profile-slot-row input,
.profile-slot-row button { cursor: auto; }

.profile-slot-letter {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 26px;
    height: 26px;
    border-radius: 50%;
    font-weight: 600;
    background: var(--accent-soft);
    color: var(--accent);
    font-size: 0.85rem;
}

/* The slot temperature is a single <input type="number">; empty = inherit
   (placeholder shows the inherited value). The checkbox + slider + readout
   trio it replaced are gone. */
.profile-slot-temp {
    width: 100%;
    min-width: 0;
    font-variant-numeric: tabular-nums;
}

.profile-slot-temp:disabled {
    opacity: 0.4;
}

.profile-slot-remove {
    border: none;
    background: transparent;
    color: var(--text-muted, #888);
    width: 28px;
    height: 28px;
    border-radius: 6px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
}

.profile-slot-remove:hover {
    color: var(--danger);
    background: var(--danger-soft);
}

/* Agent selector row — spans all columns; only present on slot rows. */
.profile-slot-agent-row {
    grid-column: 1 / -1;
}
.profile-slot-agent-row .profile-slot-agent {
    width: 100%;
}
/* Dim inline model/reasoning/temp when an agent provides the base config. */
.profile-slot-row.is-agent-override .profile-slot-model,
.profile-slot-row.is-agent-override .profile-slot-reasoning,
.profile-slot-row.is-agent-override .profile-slot-temp {
    opacity: 0.6;
}

@media (max-width: 720px) {
    .profile-slot-row {
        grid-template-columns: 28px 1fr 32px;
        grid-template-areas:
            "letter model remove"
            "letter reasoning remove"
            "letter temp remove";
    }
    .profile-slot-row.has-agent-sel {
        grid-template-areas:
            "agent  agent  agent"
            "letter model  remove"
            "letter reasoning remove"
            "letter temp   remove";
    }
    .profile-slot-agent-row { grid-area: agent; }
    .profile-slot-letter { grid-area: letter; }
    .profile-slot-row .profile-slot-model { grid-area: model; }
    .profile-slot-row .profile-slot-reasoning { grid-area: reasoning; }
    .profile-slot-row .profile-slot-temp { grid-area: temp; }
    .profile-slot-remove { grid-area: remove; }
}

/* ===========================================================================
 * Misc
 * ========================================================================= */

.alert-danger {
    background: var(--danger-soft);
    border: 1px solid rgba(229, 72, 77, 0.35);
    color: var(--danger);
    border-radius: var(--radius-md);
    padding: 12px 16px;
    margin: 16px auto;
    max-width: calc(100% - 48px);
}

.chat-error-banner {
    display: flex;
    align-items: center;
    gap: 12px;
}

.chat-error-banner-msg {
    flex: 1 1 auto;
    min-width: 0;
    word-break: break-word;
}

.chat-error-banner .chat-error-retry {
    flex: 0 0 auto;
    margin-left: auto;
}

.compare-set > .chat-error-banner {
    margin: 12px 0 0;
    max-width: none;
}

/* Hide elements */
.d-none { display: none !important; }

/* ===========================================================================
 * Settings — General section + segmented controls
 * ========================================================================= */

.settings-section-title {
    margin: 0 0 12px;
    font-size: 12px;
    font-weight: 600;
    color: var(--text-tertiary);
    text-transform: uppercase;
    letter-spacing: 0.06em;
}

/* Coupon-code easter egg (disguised external-models unlock). */
.coupon-redeem {
    padding: 12px 0 4px;
}

.coupon-input-group {
    display: flex;
    align-items: center;
    gap: 8px;
}

.coupon-input-group .form-control {
    flex: 1 1 auto;
    min-width: 0;
}

.coupon-input-group .btn {
    flex: 0 0 auto;
    white-space: nowrap;
}

.coupon-feedback {
    min-height: 18px;
    margin-top: 6px;
    color: var(--text-tertiary);
}

.coupon-feedback.is-error { color: var(--danger); }
.coupon-feedback.is-success { color: var(--accent); }

/* One-shot nudge for an invalid coupon code. */
@keyframes shake {
    0%, 100% { transform: translateX(0); }
    20% { transform: translateX(-5px); }
    40% { transform: translateX(5px); }
    60% { transform: translateX(-3px); }
    80% { transform: translateX(3px); }
}

.shake {
    animation: shake 0.4s ease-in-out;
}

@media (prefers-reduced-motion: reduce) {
    .shake { animation: none; }
}

.settings-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    padding: 10px 0;
}

.settings-row + .settings-row {
    border-top: 1px solid var(--border-subtle);
}

.settings-row-label {
    font-size: 13px;
    color: var(--text-primary);
    font-weight: 500;
}

.model-registry-status {
    font-size: 12px;
    color: var(--text-secondary);
}
.model-registry-status.text-danger {
    color: var(--bs-danger, #dc3545) !important;
}

.model-test-results {
    margin-top: 8px;
    font-size: 12px;
    font-family: var(--font-mono);
    max-height: 280px;
    overflow-y: auto;
    border: 1px solid var(--border-subtle);
    border-radius: 6px;
    padding: 8px 10px;
}
.model-test-results .model-test-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    margin-bottom: 8px;
    padding-bottom: 8px;
    border-bottom: 1px solid var(--border-subtle);
}
.model-test-results .model-test-summary {
    display: flex;
    align-items: center;
    gap: 6px;
    flex-wrap: wrap;
}
.model-test-results .model-test-pill {
    font-family: var(--font-base, inherit);
    font-weight: 600;
    font-size: 11px;
    line-height: 1.5;
    padding: 1px 9px;
    border-radius: 999px;
    white-space: nowrap;
}
.model-test-results .model-test-pill.is-ok {
    color: var(--accent);
    background: color-mix(in srgb, var(--accent) 15%, transparent);
}
.model-test-results .model-test-pill.is-fail {
    color: var(--bs-danger, #dc3545);
    background: color-mix(in srgb, var(--bs-danger, #dc3545) 15%, transparent);
}
.model-test-results .model-test-time {
    font-family: var(--font-base, inherit);
    font-size: 11px;
    color: var(--text-secondary);
    white-space: nowrap;
}
.model-test-results .model-test-row {
    display: flex;
    align-items: baseline;
    gap: 8px;
    padding: 3px 0;
}
.model-test-results .model-test-row + .model-test-row {
    border-top: 1px solid color-mix(in srgb, var(--border-subtle) 50%, transparent);
}
.model-test-results .model-test-mark {
    flex: 0 0 auto;
    width: 1em;
    text-align: center;
}
.model-test-results .model-test-name {
    flex: 1 1 auto;
    display: flex;
    align-items: baseline;
    gap: 6px;
    min-width: 0;
    color: var(--text-primary);
}
.model-test-results .model-test-name-label {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.model-test-results .model-test-id {
    flex: 0 0 auto;
    font-size: 10px;
    color: var(--text-secondary);
    opacity: 0.7;
}
.model-test-results .model-test-detail {
    flex: 0 0 auto;
    color: var(--text-secondary);
}
.model-test-results .model-test-row.is-ok .model-test-mark {
    color: var(--accent);
}
.model-test-results .model-test-row.is-fail .model-test-mark,
.model-test-results .model-test-row.is-fail .model-test-detail {
    color: var(--bs-danger, #dc3545);
}
.model-test-results .model-test-row.is-unknown .model-test-mark {
    color: var(--text-secondary);
}
.model-test-results .model-test-detail {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: 45%;
}
.model-test-results .model-test-btn {
    flex: 0 0 auto;
    padding: 0 8px;
    font-size: 11px;
    line-height: 1.6;
}

.settings-divider {
    margin: 18px 0;
    border-top: 1px solid var(--border-subtle);
    opacity: 1;
}

/* ---------------------------------------------------------------------------
 * Settings layout — sidebar nav + scrolling content pane.
 * Modeled on .notebook-edit-body (a 2-column grid with independently
 * scrolling columns). The dialog gets a fixed tall height and the
 * .modal-content becomes a flex column so the body fills it.
 * ------------------------------------------------------------------------- */
.settings-modal-dialog {
    height: 80vh;
    max-height: 760px;
}
.settings-modal-dialog .modal-content {
    height: 100%;
    display: flex;
    flex-direction: column;
    min-height: 0;
    overflow: hidden;
}
.settings-modal-dialog .modal-body {
    flex: 1 1 0;
    min-height: 0;
    padding: 0;
    overflow: hidden;
}

.settings-layout {
    height: 100%;
    min-height: 0;
    display: grid;
    grid-template-columns: 220px 1fr;
    gap: 0;
}

.settings-nav {
    min-height: 0;
    overflow-y: auto;
    border-right: 1px solid var(--border-subtle);
    padding: 14px 12px;
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.settings-nav .settings-search {
    margin-bottom: 8px;
}

/* Reuses the look of .profile-menu-item — full-width, left-aligned pills. */
.settings-nav-item {
    width: 100%;
    padding: 8px 12px;
    border: 0;
    border-radius: var(--radius-sm);
    background: transparent;
    color: var(--text-secondary);
    font-size: 13px;
    font-weight: 500;
    text-align: left;
    cursor: pointer;
    transition: background-color .1s, color .1s;
}
.settings-nav-item:hover { background: var(--border-subtle); }
.settings-nav-item.active {
    background: var(--accent-soft);
    color: var(--text-primary);
}

/* "About"-style footer under the nav list — always visible, click to expand
 * the Electron/Chromium/Node/platform detail line. */
.settings-version-footer {
    margin-top: 8px;
    padding-top: 10px;
    border: 0;
    border-top: 1px solid var(--border-subtle);
    background: transparent;
    color: var(--text-tertiary, var(--text-secondary));
    font-size: 11px;
    text-align: left;
    cursor: pointer;
}
.settings-version-footer:hover { color: var(--text-secondary); }
.settings-version-detail {
    font-size: 11px;
    color: var(--text-tertiary, var(--text-secondary));
    white-space: pre-line;
    line-height: 1.5;
    padding: 0 12px;
}
.settings-version-detail[hidden] { display: none; }

.settings-content {
    min-height: 0;
    overflow-y: auto;
    padding: 18px 20px;
}

.settings-pane { display: block; }
.settings-pane[hidden] { display: none; }

/* Search mode hides non-matching rows, section titles, dividers, and whole
 * panes that have no match. Scoped to the settings modal so the class can't
 * affect anything else. */
#settings-modal .is-search-hidden { display: none !important; }

.segmented {
    display: inline-flex;
    background: var(--bg-input);
    border: 1px solid var(--border-subtle);
    border-radius: 999px;
    padding: 2px;
}

.segmented-option {
    appearance: none;
    border: 0;
    background: transparent;
    color: var(--text-secondary);
    font-family: var(--font-sans);
    font-size: 12px;
    font-weight: 500;
    padding: 6px 14px;
    border-radius: 999px;
    cursor: pointer;
    transition: background-color .12s, color .12s;
}

.segmented-option:hover { color: var(--text-primary); }

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

.segmented-option:focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px var(--accent-ring);
}

/* Disabled segmented control — used when "Auto" (backend-driven routing) owns
 * the search decision, so the search-mode / intranet-method pickers are locked.
 * Clicks are also swallowed in JS (searchControlsLockedForAuto). */
.segmented.disabled {
    opacity: .5;
    pointer-events: none;
}

/* Empty "ready to chat" state, rendered into #chat-container when a chat has
 * no messages yet. Carries the Copy/Link attachment-storage toggle. */
.chat-empty-state {
    max-width: 560px;
    margin: 12vh auto 0;
    padding: 0 24px;
    text-align: center;
    color: var(--text-secondary);
}

.chat-empty-title {
    font-size: 20px;
    font-weight: 600;
    color: var(--text-primary);
    margin-bottom: 6px;
}

.chat-empty-sub {
    font-size: 13px;
    margin-bottom: 18px;
}

.chat-empty-attach-row {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 10px;
}

.chat-empty-attach-label {
    font-size: 12px;
    font-weight: 500;
    color: var(--text-secondary);
}

.chat-empty-hint {
    font-size: 12px;
    line-height: 1.5;
    color: var(--text-secondary);
    opacity: .85;
}

/* Shared Copy/Link + Synced/Not-synced control pair (buildStorageSyncControls),
 * used on the new-chat empty state and the discussion setup footer. Stacks the
 * two labelled segmented rows with their explainer/caveat hints; labels share a
 * min-width so the two segmented controls line up vertically. */
.chat-storage-sync-controls {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 4px;
}
.chat-storage-sync-controls .chat-empty-attach-row {
    margin-bottom: 0;
}
.chat-storage-sync-controls .chat-empty-attach-label {
    min-width: 120px;
}
.chat-storage-sync-controls .chat-empty-hint {
    margin-bottom: 8px;
}
.chat-empty-sync-row {
    margin-top: 6px;
}
/* Project-cascade indicator: a static, non-interactive "Not synced (whole
 * project)" pill (the per-chat toggle can't override the project). */
.chat-empty-attach-seg.is-disabled .segmented-option {
    opacity: .65;
    cursor: default;
}

/* ===========================================================================
 * Light theme tweaks
 * ========================================================================= */

[data-bs-theme="light"] .btn-close {
    filter: none;
    opacity: 0.6;
}

[data-bs-theme="light"] .btn-close:hover { opacity: 1; }

[data-bs-theme="light"] .btn-secondary:hover {
    background: var(--bg-elevated);
}


/* ===========================================================================
 * User query collapsing (one-line preview, click to expand)
 * ========================================================================= */
.user-message.collapsible {
    cursor: pointer;
}

.user-message.collapsible.collapsed .message-content {
    display: -webkit-box;
    -webkit-line-clamp: 1;
    -webkit-box-orient: vertical;
    overflow: hidden;
    color: var(--text-secondary);
    opacity: 0.75;
}

.user-message.collapsible.collapsed:hover .message-content {
    opacity: 1;
}

/* ===========================================================================
 * Conversation-level "show recent, collapse older"
 * ---------------------------------------------------------------------------
 * The transcript keeps the last 3 exchanges fully visible (never clamped) and
 * folds everything older away behind a single centered "Show earlier messages"
 * pill at the top. Replaces the former per-message tall-answer clamp. The fold
 * itself is just display:none on the earlier top-level blocks; the renderer
 * (applyTranscriptCollapse) decides which blocks carry the class.
 * ========================================================================= */
.transcript-hidden {
    display: none !important;
}

/* Centered pill at the top of the transcript (reuses the look of the removed
   bot-clamp toggle: rounded, elevated, subtle border, accent on hover). */
.transcript-show-earlier {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    margin: 4px auto 14px;
    padding: 5px 14px;
    font-size: 12px;
    line-height: 1.4;
    color: var(--text-secondary);
    background: var(--bg-elevated);
    border: 1px solid var(--border-subtle);
    border-radius: 999px;
    cursor: pointer;
    box-shadow: 0 1px 5px rgba(0, 0, 0, 0.2);
    transition: color .12s ease, border-color .12s ease;
}
.transcript-show-earlier:hover {
    color: var(--text-primary);
    border-color: var(--accent);
}
.transcript-show-earlier .bi {
    font-size: 13px;
    line-height: 1;
}

/* ===========================================================================
 * Floating "jump to newest" button (appears when scrolled away from bottom)
 * ========================================================================= */
.chat-jump-bottom {
    position: absolute;
    right: 28px;
    bottom: 20px;
    z-index: 20;
    width: 40px;
    height: 40px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 18px;
    border-radius: 50%;
    color: var(--text-primary);
    background: var(--bg-elevated);
    border: 1px solid var(--border-subtle);
    box-shadow: 0 2px 12px rgba(0, 0, 0, 0.28);
    cursor: pointer;
    opacity: 0;
    transform: translateY(8px);
    pointer-events: none;
    transition: opacity .15s ease, transform .15s ease, color .12s ease, border-color .12s ease;
}
.chat-jump-bottom.is-visible {
    opacity: 1;
    transform: translateY(0);
    pointer-events: auto;
}
.chat-jump-bottom:hover {
    color: var(--text-primary);
    border-color: var(--accent);
}

/* ===========================================================================
 * Floating per-message navigation FABs (↑/↓), stacked above "jump to newest".
 * Shares the exact look of .chat-jump-bottom; only the vertical offset differs.
 * ========================================================================= */
.chat-nav-fab {
    position: absolute;
    right: 28px;
    z-index: 20;
    width: 40px;
    height: 40px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 18px;
    border-radius: 50%;
    color: var(--text-primary);
    background: var(--bg-elevated);
    border: 1px solid var(--border-subtle);
    box-shadow: 0 2px 12px rgba(0, 0, 0, 0.28);
    cursor: pointer;
    opacity: 0;
    transform: translateY(8px);
    pointer-events: none;
    transition: opacity .15s ease, transform .15s ease, color .12s ease, border-color .12s ease;
}
#chat-jump-prev { bottom: 112px; }
#chat-jump-next { bottom: 66px; }
.chat-nav-fab.is-visible {
    opacity: 1;
    transform: translateY(0);
    pointer-events: auto;
}
.chat-nav-fab:hover {
    color: var(--text-primary);
    border-color: var(--accent);
}

/* ===========================================================================
 * Live reasoning indicator (visible while <think> is streaming)
 * ========================================================================= */
details.reasoning-live {
    display: block;
    margin-bottom: 0.5rem;
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-sm);
    background: var(--bg-elevated);
    color: var(--text-secondary);
    font-size: 13px;
    overflow: hidden;
}

.reasoning-live-summary {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 6px 10px;
    cursor: pointer;
    user-select: none;
    font-size: 12px;
    font-style: italic;
    color: var(--text-secondary);
    list-style: none;
}

.reasoning-live-summary::-webkit-details-marker { display: none; }

.reasoning-live-body {
    max-height: 14rem;
    overflow-y: auto;
    padding: 2px 10px 8px;
    font-size: 13px;
    color: var(--text-secondary);
    border-top: 1px solid var(--border-subtle);
}

.reasoning-live-body > :first-child { margin-top: 0.4rem; }
.reasoning-live-body > :last-child { margin-bottom: 0; }

.reasoning-live-dot {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--accent);
    animation: reasoning-pulse 1.1s ease-in-out infinite;
}

@keyframes reasoning-pulse {
    0%, 100% { opacity: 0.35; transform: scale(0.85); }
    50%      { opacity: 1;    transform: scale(1.1); }
}

@media (prefers-reduced-motion: reduce) {
    .reasoning-live-dot { animation: none; opacity: 0.7; }
}

/* Offline auto-retry status line, shown in the pending assistant bubble while
   a single-chat send is waiting out a temporary outage. Styled like the live
   "Thinking…" indicator (pulsing dot + muted italic text). */
.retry-status {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 6px 10px;
    font-size: 12px;
    font-style: italic;
    color: var(--text-secondary);
}

.retry-status-dot {
    flex: 0 0 auto;
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--accent);
    animation: reasoning-pulse 1.1s ease-in-out infinite;
}

@media (prefers-reduced-motion: reduce) {
    .retry-status-dot { animation: none; opacity: 0.7; }
}

/* Post-drop restart: the shown partial answer is kept but dimmed while a
 * reconnect countdown overlays it; the appended .restart-status line stays at
 * full opacity so it reads clearly. On the retry's first token the bubble is
 * cleared and re-streamed cleanly. Covers both the single-chat bubble
 * (.bot-message) and a discussion participant card (.discussion-card), whose
 * per-turn auto-recovery reuses the same dim + countdown overlay. */
.bot-message.is-restarting > *:not(.restart-status),
.discussion-card.is-restarting > *:not(.restart-status) {
    opacity: 0.4;
    transition: opacity 0.2s ease;
}

.bot-message.is-streaming::after {
    content: '▍';
    color: var(--text-tertiary);
    margin-left: 2px;
    animation: caret-blink 1s steps(1) infinite;
}

/* While only a live "Thinking…" panel is showing (no answer text yet), the
 * caret would dangle off the panel — suppress it until the answer begins. */
.bot-message.is-streaming.reasoning-only::after { content: none; }

/* Same for the offline-retry status line: no answer text yet, so the blinking
 * caret would dangle off the status — suppress it until streaming resumes. */
.bot-message.is-streaming:has(.retry-status)::after { content: none; }

@keyframes caret-blink {
    50% { opacity: 0; }
}

.bot-typing {
    display: inline-flex;
    gap: 4px;
    align-items: center;
    padding: 4px 0;
}

.bot-typing span {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--text-tertiary);
    animation: pulse-dot 1.4s ease-in-out infinite;
}

.bot-typing span:nth-child(2) { animation-delay: 0.2s; }
.bot-typing span:nth-child(3) { animation-delay: 0.4s; }

.toggle-switch {
    position: relative;
    display: inline-block;
    width: 28px;
    height: 16px;
    flex: 0 0 auto;
}

.toggle-switch input {
    opacity: 0;
    width: 0;
    height: 0;
}

.toggle-slider {
    position: absolute;
    inset: 0;
    cursor: pointer;
    background: var(--bg-elevated);
    border: 1px solid var(--border-subtle);
    border-radius: 16px;
    transition: background 0.15s ease, border-color 0.15s ease;
}

.toggle-slider::before {
    content: '';
    position: absolute;
    height: 10px;
    width: 10px;
    left: 2px;
    top: 50%;
    transform: translateY(-50%);
    background: var(--text-tertiary);
    border-radius: 50%;
    transition: transform 0.15s ease, background 0.15s ease;
}

.toggle-switch input:checked + .toggle-slider {
    background: var(--accent-soft);
    border-color: var(--accent);
}

.toggle-switch input:checked + .toggle-slider::before {
    transform: translate(12px, -50%);
    background: var(--accent);
}

/* ===========================================================================
 * Tags — ribbon, chips, filter bar, popover, manage modal,
 * colorize + filter toggles. The whole subsystem is gated behind the
 * experimental-features flag (body[data-tags-disabled] hides every surface).
 * ========================================================================= */

body[data-tags-disabled] .chat-tag-chips,
body[data-tags-disabled] .chat-row-tag-btn,
body[data-tags-disabled] .tab-tag-dot,
body[data-tags-disabled] #tag-filter-bar { display: none !important; }

#chat-list .list-group-item .chat-tag-chips {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    flex: 0 0 auto;
    margin-right: 2px;
}

#chat-list .list-group-item .chat-tag-chips:empty { display: none; }

/* Base chip = a full pill with text. Used by the filter chips inside the
   Filter popover, where the tag name still reads alongside its glyph. Chat
   rows override this to a bare compact glyph below. */
.chat-tag-chip {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 1px 7px;
    border-radius: 999px;
    font-size: 10.5px;
    font-weight: 600;
    letter-spacing: 0.02em;
    line-height: 1.4;
    background: color-mix(in srgb, var(--chip-color) 22%, transparent);
    color: color-mix(in srgb, var(--chip-color) 80%, var(--text-primary));
    border: 1px solid color-mix(in srgb, var(--chip-color) 40%, transparent);
    transition: transform .12s, background-color .12s, padding .12s;
    cursor: default;
    white-space: nowrap;
    max-width: 120px;
    overflow: hidden;
    text-overflow: ellipsis;
}

.chat-tag-chip-dot {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    flex: 0 0 auto;
}

.chat-tag-chip-name { display: inline; }

.chat-tag-chip-glyph {
    font-size: 12px;
    line-height: 1;
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

/* Chat-row tags are always compact glyphs: an emoji on a small swatch tinted
   in the tag color, or a plain colored dot for legacy tags with no emoji. No
   row tint, no ribbon, no text. */
#chat-list .list-group-item .chat-tag-chip {
    padding: 0;
    gap: 0;
    border: 0;
    background: transparent;
    max-width: none;
    overflow: visible;
}
#chat-list .list-group-item .chat-tag-chip .chat-tag-chip-name { display: none; }
#chat-list .list-group-item .chat-tag-chip.has-glyph {
    width: 17px;
    height: 17px;
    border-radius: 5px;
    background: color-mix(in srgb, var(--chip-color) 26%, transparent);
    border: 1px solid color-mix(in srgb, var(--chip-color) 45%, transparent);
}
#chat-list .list-group-item .chat-tag-chip-glyph {
    font-size: 10px;
    width: 100%;
    height: 100%;
}

.chat-tag-chip:hover { transform: translateY(-1px); }

#chat-list .list-group-item .chat-row-tag-btn {
    color: var(--text-tertiary);
    opacity: 0;
    transition: opacity .15s, color .12s, background-color .12s;
}
#chat-list .list-group-item:hover .chat-row-tag-btn,
#chat-list .list-group-item.has-tags .chat-row-tag-btn {
    opacity: 1;
}

/* Favorite star — hover-reveal on non-favorites; always shown + filled gold on
   favorited rows. Mirrors the tag-button reveal pattern above. */
#chat-list .list-group-item .chat-row-fav-btn {
    color: var(--text-tertiary);
    opacity: 0;
    transition: opacity .15s, color .12s, background-color .12s;
}
#chat-list .list-group-item:hover .chat-row-fav-btn {
    opacity: 1;
}
#chat-list .list-group-item .chat-row-fav-btn:hover { color: #FFCA28; }
#chat-list .list-group-item.is-favorite .chat-row-fav-btn {
    opacity: 1;
    color: #FFCA28;
}

/* "Do not sync" sidebar glyph (20260637) — a small, always-shown muted cloud-
   slash before the title; the row title is slightly dimmed so a local-only chat
   reads as "kept on this device". */
#chat-list .list-group-item .chat-row-localonly-glyph {
    color: var(--text-tertiary);
    font-size: 0.82em;
    margin-right: 4px;
    flex: 0 0 auto;
    opacity: 0.9;
}
#chat-list .list-group-item.is-local-only > a {
    opacity: 0.82;
}

/* Tag filter bar */
.tag-filter-bar {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 0 16px 12px;
}

.tag-filter-bar[hidden] { display: none; }

.tag-filter-chips {
    flex: 1;
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
    overflow: hidden;
}

.tag-filter-chip {
    cursor: pointer;
    padding: 2px 9px;
    font-size: 11px;
    border-style: solid;
    background: color-mix(in srgb, var(--chip-color) 14%, transparent);
}
.tag-filter-chip.active {
    background: var(--chip-color);
    color: #0F1311;
    border-color: var(--chip-color);
}

.tag-filter-empty {
    color: var(--text-tertiary);
    font-size: 11.5px;
    padding: 2px 0;
}
.tag-filter-empty-manage {
    background: transparent;
    border: 0;
    padding: 0;
    color: var(--accent);
    font-size: 11.5px;
    cursor: pointer;
}
.tag-filter-empty-manage:hover { text-decoration: underline; }

.tag-filter-clear,
.tag-filter-manage {
    flex: 0 0 auto;
    background: transparent;
    border: 0;
    color: var(--text-tertiary);
    padding: 4px 6px;
    border-radius: 6px;
    cursor: pointer;
    transition: color .12s, background-color .12s;
}
.tag-filter-clear:hover,
.tag-filter-manage:hover {
    color: var(--text-primary);
    background: var(--bg-elevated);
}

/* ===========================================================================
 * Consolidated chat-filter control (funnel button + popover)
 * Favorites / Discussions / Unread / Tags — independent AND toggles.
 * ======================================================================== */
.chat-filter-wrap { position: relative; flex: 0 0 auto; }

/* Funnel button mirrors .sidebar-manage-chats-btn; accent fill when any
   filter is on, matching the old favorites pill's active look. */
#chat-filter-toggle { position: relative; }
#chat-filter-toggle.active {
    background: var(--accent-soft);
    color: var(--accent);
    border-color: transparent;
}
.chat-filter-count {
    position: absolute;
    top: -5px;
    right: -5px;
    min-width: 15px;
    height: 15px;
    padding: 0 4px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 9.5px;
    font-weight: 600;
    line-height: 1;
    color: #fff;
    background: var(--accent);
    border-radius: 999px;
}
.chat-filter-count[hidden] { display: none; }

/* Shared inbox badge on #shared-btn — mirrors .chat-filter-count placement. */
#shared-btn { position: relative; }
.shared-inbox-badge {
    position: absolute;
    top: -5px;
    right: -5px;
    min-width: 15px;
    height: 15px;
    padding: 0 4px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 9.5px;
    font-weight: 600;
    line-height: 1;
    color: #fff;
    background: var(--accent);
    border-radius: 999px;
}
.shared-inbox-badge[hidden] { display: none; }

/* Shared hub grouped sections (Shared with you / everyone / by you). */
.shared-section { margin-bottom: 20px; }
.shared-section:last-child { margin-bottom: 0; }
.shared-section[hidden] { display: none; }
.shared-section-title {
    font-size: 12px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--text-muted, #888);
    padding-bottom: 6px;
    margin-bottom: 10px;
    border-bottom: 1px solid var(--border-color, rgba(0,0,0,.1));
}

/* Shared hub rows (all three sections). */
.shared-row {
    border: 1px solid var(--border-color, rgba(0,0,0,.1));
    border-radius: 8px;
    padding: 10px 12px;
    margin-bottom: 10px;
}
.shared-row-head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.shared-row-name { font-weight: 600; }
.shared-row-kind {
    font-size: 11px;
    padding: 1px 8px;
    border-radius: 999px;
    background: var(--accent-soft, rgba(0,0,0,.06));
    color: var(--accent, inherit);
}
.shared-row-desc { color: var(--text-muted, #888); font-size: 13px; margin: 4px 0; }
.shared-row-by { color: var(--text-muted, #888); font-size: 12px; }
/* Direct/inbox shares get a distinct accent so "shared with you by a person"
   reads differently from the muted public "shared with everyone" line. */
.shared-row-by-inbox { color: var(--accent, #4a90d9); font-weight: 500; }
.shared-row-controls { display: flex; align-items: center; gap: 8px; margin-top: 8px; flex-wrap: wrap; }
.shared-row-controls select { max-width: 140px; }

.chat-filter-popover {
    position: absolute;
    top: calc(100% + 6px);
    right: 0;
    z-index: 1100;
    min-width: 220px;
    max-width: 280px;
    padding: 5px;
    background: var(--bg-surface);
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-soft);
    display: flex;
    flex-direction: column;
    gap: 1px;
}
.chat-filter-popover[hidden] { display: none; }

.chat-filter-item {
    display: flex;
    align-items: center;
    gap: 9px;
    padding: 7px 9px;
    border-radius: var(--radius-sm);
    color: var(--text-primary);
    cursor: pointer;
    user-select: none;
}
.chat-filter-item:hover,
.chat-filter-item:focus-visible {
    background: var(--bg-elevated);
    outline: none;
}
.chat-filter-item .chat-filter-item-icon {
    font-size: 14px;
    width: 16px;
    text-align: center;
    color: var(--text-secondary);
    flex: 0 0 auto;
}
.chat-filter-item-label { flex: 1; min-width: 0; font-size: 13px; }
.chat-filter-item .chat-filter-item-check {
    font-size: 14px;
    color: var(--accent);
    flex: 0 0 auto;
    visibility: hidden;
}
.chat-filter-item.active .chat-filter-item-check { visibility: visible; }
.chat-filter-item.active .chat-filter-item-icon { color: var(--accent); }
.chat-filter-item[data-filter="unread"] .chat-filter-item-icon { font-size: 9px; }

.chat-filter-sep {
    height: 1px;
    margin: 4px 2px;
    background: var(--border-subtle);
}

.chat-filter-clear-all { color: var(--text-secondary); }
.chat-filter-clear-all .chat-filter-item-icon { font-size: 12px; }

/* Tags section inside the popover (relocated from the old #tag-filter-bar). */
.chat-filter-tags {
    display: flex;
    flex-direction: column;
    gap: 6px;
    padding: 6px 9px 8px;
}
.chat-filter-tags[hidden] { display: none; }
.chat-filter-section-label {
    font-size: 10.5px;
    font-weight: 600;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--text-tertiary);
}
.chat-filter-tags-actions {
    display: flex;
    gap: 4px;
}

/* Tag edit popover */
.tag-edit-popover {
    position: absolute;
    z-index: 1100;
    min-width: 240px;
    max-width: 300px;
    background: var(--bg-elevated);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-soft);
    padding: 6px;
}
.tag-edit-popover[hidden] { display: none; }

.tag-edit-popover-list {
    max-height: 240px;
    overflow-y: auto;
    margin-bottom: 4px;
}

.tag-edit-popover-empty {
    padding: 10px 8px;
    color: var(--text-tertiary);
    font-size: 12px;
    text-align: center;
}

.tag-edit-popover-item {
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
    padding: 6px 8px;
    border: 0;
    border-radius: var(--radius-sm);
    background: transparent;
    color: var(--text-primary);
    font-size: 13px;
    text-align: left;
    cursor: pointer;
    transition: background-color .1s;
}
.tag-edit-popover-item:hover { background: var(--border-subtle); }
.tag-edit-popover-item .tag-edit-popover-check {
    margin-left: auto;
    color: var(--accent);
    opacity: 0;
}
.tag-edit-popover-item.active .tag-edit-popover-check { opacity: 1; }
.tag-edit-popover-item.active {
    background: color-mix(in srgb, var(--chip-color) 14%, transparent);
}

.tag-edit-popover-swatch {
    width: 12px;
    height: 12px;
    border-radius: 4px;
    flex: 0 0 auto;
}

.tag-edit-popover-name {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.tag-edit-popover-divider {
    height: 1px;
    background: var(--border-subtle);
    margin: 4px 0;
}

.tag-edit-popover-newrow {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 4px;
}

.tag-edit-popover-newname {
    flex: 1;
    min-width: 0;
    height: 28px;
    padding: 0 8px;
    border-radius: var(--radius-sm);
    border: 1px solid var(--border-subtle);
    background: var(--bg-input);
    color: var(--text-primary);
    font-size: 12px;
    outline: none;
}
.tag-edit-popover-newname:focus {
    border-color: var(--accent);
    box-shadow: 0 0 0 2px var(--accent-ring);
}

.tag-edit-popover-add {
    flex: 0 0 auto;
    height: 28px;
    width: 28px;
    border-radius: var(--radius-sm);
    border: 1px solid var(--border-subtle);
    background: var(--bg-elevated);
    color: var(--text-primary);
    cursor: pointer;
    transition: background-color .12s;
}
.tag-edit-popover-add:hover { background: var(--accent-soft); border-color: var(--accent); }

.tag-edit-popover-swatches {
    display: flex;
    flex-wrap: wrap;
    gap: 3px;
    align-items: center;
    flex: 0 1 auto;
}

.tag-swatch {
    width: 16px;
    height: 16px;
    border-radius: 4px;
    border: 2px solid transparent;
    cursor: pointer;
    padding: 0;
    transition: transform .12s, border-color .12s;
}
.tag-swatch:hover { transform: scale(1.15); }
.tag-swatch.active {
    border-color: var(--text-primary);
    transform: scale(1.05);
}

/* Emoji picker — grid of curated emoji, mirrors the color swatches. */
.tag-edit-popover-icons {
    display: flex;
    flex-wrap: wrap;
    gap: 3px;
    align-items: center;
    padding: 4px;
}

.tag-icon-swatch {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    font-size: 13px;
    line-height: 1;
    border-radius: 5px;
    border: 1px solid var(--border-subtle);
    background: var(--bg-elevated);
    cursor: pointer;
    padding: 0;
    transition: transform .12s, border-color .12s, background-color .12s;
}
.tag-icon-swatch:hover { transform: scale(1.12); background: var(--accent-soft); }
.tag-icon-swatch.active {
    border-color: var(--accent);
    background: var(--accent-soft);
}

.tag-edit-popover-glyph {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 14px;
    height: 14px;
    font-size: 12px;
    line-height: 1;
    flex: 0 0 auto;
}

.tag-edit-popover-manage {
    display: flex;
    align-items: center;
    gap: 6px;
    width: 100%;
    margin-top: 4px;
    padding: 6px 8px;
    border: 0;
    border-radius: var(--radius-sm);
    background: transparent;
    color: var(--text-secondary);
    font-size: 12px;
    cursor: pointer;
    transition: background-color .12s, color .12s;
}
.tag-edit-popover-manage:hover {
    background: var(--border-subtle);
    color: var(--text-primary);
}

/* Manage tags modal */
.tag-manage-list {
    display: flex;
    flex-direction: column;
    gap: 6px;
    margin-bottom: 12px;
}

.tag-manage-empty {
    padding: 16px;
    color: var(--text-tertiary);
    text-align: center;
}

.tag-manage-row {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 6px 8px;
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-sm);
    background: var(--bg-surface);
    flex-wrap: wrap;
}

.tag-manage-swatch {
    width: 22px;
    height: 22px;
    border-radius: 6px;
    border: 1px solid var(--border-strong);
    cursor: pointer;
    flex: 0 0 auto;
    padding: 0;
}

.tag-manage-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 26px;
    height: 26px;
    font-size: 15px;
    line-height: 1;
    border-radius: 6px;
    border: 1px solid var(--border-strong);
    background: var(--bg-elevated);
    cursor: pointer;
    flex: 0 0 auto;
    padding: 0;
    transition: background-color .12s, border-color .12s;
}
.tag-manage-icon:hover { background: var(--accent-soft); border-color: var(--accent); }
.tag-manage-icon.is-empty { color: var(--text-tertiary); }

.tag-manage-name {
    flex: 1;
    min-width: 0;
    height: 30px;
    padding: 0 8px;
    border-radius: var(--radius-sm);
    border: 1px solid var(--border-subtle);
    background: var(--bg-input);
    color: var(--text-primary);
    font-size: 13px;
    outline: none;
}
.tag-manage-name:focus {
    border-color: var(--accent);
    box-shadow: 0 0 0 2px var(--accent-ring);
}

.tag-manage-count {
    font-size: 11px;
    color: var(--text-tertiary);
    flex: 0 0 auto;
    padding-right: 4px;
}

.tag-manage-save,
.tag-manage-delete {
    border: 0;
    background: transparent;
    color: var(--text-tertiary);
    width: 28px;
    height: 28px;
    border-radius: var(--radius-sm);
    cursor: pointer;
    flex: 0 0 auto;
    transition: color .12s, background-color .12s;
}
.tag-manage-save:hover { color: var(--accent); background: var(--accent-soft); }
.tag-manage-delete:hover { color: var(--danger); background: var(--danger-soft); }

.tag-manage-palette,
.tag-manage-iconpalette {
    width: 100%;
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
    padding: 6px 0 2px;
}

.tag-manage-newrow {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 0 0;
    border-top: 1px dashed var(--border-subtle);
    flex-wrap: wrap;
}
.tag-manage-newrow input { flex: 1; min-width: 140px; }


/* ---------- Conversation branching ---------------------------------- */

.composer-n-picker {
    display: inline-flex;
    align-items: center;
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-sm);
    overflow: hidden;
    margin: 0 6px 0 2px;
    align-self: center;
    height: 28px;
}
.composer-n-picker .n-pick {
    border: 0;
    background: transparent;
    color: var(--text-tertiary);
    width: 26px;
    height: 26px;
    font-size: 12px;
    font-weight: 600;
    cursor: pointer;
    transition: background-color .12s, color .12s;
}
.composer-n-picker .n-pick:hover { color: var(--text-primary); background: var(--border-subtle); }
.composer-n-picker .n-pick.active {
    background: var(--accent-soft);
    color: var(--accent);
}
.composer-n-picker .n-pick + .n-pick { border-left: 1px solid var(--border-subtle); }
.ui-chat-busy .composer-n-picker .n-pick { opacity: 0.5; pointer-events: none; }

/* ===========================================================================
 * Compare-set surface for N>1 responses. All N cards render simultaneously
 * under a prominent banner — the parallelism is the visual. After the user
 * picks one with "Use this answer", the surface flips to selected mode: the
 * eyebrow names the chosen slot, a pill row replaces the title, and the grid
 * collapses to a single column with the chosen card visible.
 * ========================================================================= */

.compare-set {
    container-type: inline-size;
    margin: var(--card-margin-block) auto;
    max-width: min(var(--card-max-width), calc(100% - 2 * var(--card-gutter-inline)));
    transition: max-width .15s ease;
    padding: 0;
}

.compare-set-header {
    display: flex;
    flex-direction: column;
    gap: 2px;
    margin-bottom: 10px;
}

.compare-set-eyebrow {
    font-family: var(--font-mono);
    font-size: 11px;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--text-tertiary);
    font-feature-settings: 'tnum' 1;
}

.compare-set-title {
    margin: 0;
    font-size: 16px;
    font-weight: 500;
    color: var(--text-secondary);
    line-height: 1.4;
}

.compare-set-pills {
    display: inline-flex;
    gap: 6px;
    margin-top: 6px;
}

.compare-pill {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    height: 28px;
    padding: 0 10px;
    border: 1px solid var(--border-subtle);
    border-radius: 999px;
    background: transparent;
    color: var(--text-secondary);
    font-family: var(--font-mono);
    font-size: 12px;
    cursor: pointer;
    transition: color .12s ease, border-color .12s ease, background-color .12s ease;
}

.compare-pill[data-tint="accent"]      { --tint: var(--tab-tint-accent); }
.compare-pill[data-tint="blue"]        { --tint: var(--tab-tint-blue); }
.compare-pill[data-tint="violet"]      { --tint: var(--tab-tint-violet); }
.compare-pill[data-tint="terracotta"]  { --tint: var(--tab-tint-terracotta); }
.compare-pill[data-tint="amber"]       { --tint: var(--tab-tint-amber); }
.compare-pill[data-tint="teal"]        { --tint: var(--tab-tint-teal); }

.compare-pill-dot {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--tint, var(--accent));
    flex: 0 0 auto;
}

.compare-pill-letter {
    font-weight: 600;
    letter-spacing: 0;
}

.compare-pill .compare-pill-check {
    display: none;
    font-size: 11px;
}

.compare-pill:hover {
    color: var(--text-primary);
    border-color: var(--border-strong);
}

.compare-pill.is-active {
    color: var(--text-primary);
    border-color: var(--tint, var(--accent));
    background: color-mix(in srgb, var(--tint, var(--accent)) 12%, var(--bg-elevated));
}

.compare-pill.is-active .compare-pill-check { display: inline; }

.compare-pill.is-error {
    --tint: var(--danger);
    color: var(--danger);
}

.compare-set-grid {
    display: grid;
    gap: 12px;
    transition: grid-template-columns 320ms cubic-bezier(0.32, 0.72, 0, 1);
}

/* Pair-and-swap compare mode: default (narrow) — exactly two cards visible. */
.compare-set[data-mode="compare"] .compare-set-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
}
.compare-set[data-mode="compare"] .compare-card { display: none; }
.compare-set[data-mode="compare"] .compare-card.is-pair-left,
.compare-set[data-mode="compare"] .compare-card.is-pair-right { display: flex; }

/* When n=1, only the left slot is set; show it full-width. */
.compare-set[data-mode="compare"][data-n="1"] .compare-set-grid {
    grid-template-columns: 1fr;
}

/* Wide container: show all N cards with auto-fit columns; hide swap strips. */
@container (min-width: 840px) {
    .compare-set[data-mode="compare"] .compare-set-grid {
        grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
    }
    .compare-set[data-mode="compare"] .compare-card { display: flex; }
    .compare-set[data-mode="compare"] .compare-card-swap { display: none; }
}

/* Narrow container: force single column. */
@container (max-width: 599px) {
    .compare-set[data-mode="compare"] .compare-set-grid { grid-template-columns: 1fr; }
}

.compare-set[data-mode="selected"] .compare-set-grid { grid-template-columns: 1fr; }
.compare-set[data-mode="selected"] .compare-card { display: none; }
.compare-set[data-mode="selected"] .compare-card.is-active { display: flex; }

/* Tabs view: pre-selection, single visible card with a pill row. */
.compare-set[data-mode="tabs"] .compare-set-grid { grid-template-columns: 1fr; }
.compare-set[data-mode="tabs"] .compare-card { display: none; }
.compare-set[data-mode="tabs"] .compare-card.is-active { display: flex; }

/* Pick button is the commit action only in side-by-side compare mode.
   In tabs mode the pill row already commits via setActiveSibling; in
   selected mode the pick is final. Hide pick + fork in both — but
   keep the footer itself visible so the per-message action bar
   (+ Another answer / Copy) stays available. */
.compare-set[data-mode="tabs"] .compare-card-foot > .compare-card-pick,
.compare-set[data-mode="tabs"] .compare-card-foot > .compare-card-fork,
.compare-set[data-mode="selected"] .compare-card-foot > .compare-card-pick,
.compare-set[data-mode="selected"] .compare-card-foot > .compare-card-fork { display: none; }

/* Hide the compare/tabs toggle on small viewports (keep as media query — UI chrome). */
@media (max-width: 900px) {
    .compare-view-toggle { display: none; }
}

/* Header view toggle — small segmented control pinned to the right. */
.compare-set-header { position: relative; }
.compare-view-toggle {
    position: absolute;
    top: 0;
    right: 0;
    display: inline-flex;
    border: 1px solid var(--border-subtle);
    border-radius: 999px;
    overflow: hidden;
    background: var(--bg-elevated);
}
.compare-view-toggle[hidden] { display: none; }
.compare-view-seg {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    border: 0;
    background: transparent;
    color: var(--text-tertiary);
    font-family: var(--font-mono);
    font-size: 11px;
    padding: 4px 10px;
    cursor: pointer;
    transition: color .12s ease, background-color .12s ease;
}
.compare-view-seg i { font-size: 12px; }
.compare-view-seg:hover { color: var(--text-primary); }
.compare-view-seg.is-active {
    color: var(--text-primary);
    background: color-mix(in srgb, var(--accent) 14%, var(--bg-elevated));
}

/* "Show N alternatives" link — minimal text-button under the eyebrow. */
.compare-set-alts-toggle {
    align-self: flex-start;
    margin-top: 6px;
    border: 0;
    background: transparent;
    padding: 0;
    color: var(--text-tertiary);
    font-family: var(--font-mono);
    font-size: 12px;
    cursor: pointer;
    transition: color .12s ease;
}
.compare-set-alts-toggle:hover { color: var(--text-primary); }
.compare-set-alts-toggle[hidden] { display: none; }

/* One-shot pulse to confirm a pick. */
@keyframes compare-just-picked {
    0%   { border-color: var(--border-subtle); box-shadow: none; }
    40%  { border-color: var(--accent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 22%, transparent); }
    100% { border-color: var(--border-subtle); box-shadow: none; }
}
.compare-card.is-just-picked {
    animation: compare-just-picked 240ms cubic-bezier(0.32, 0.72, 0, 1);
}
@media (prefers-reduced-motion: reduce) {
    .compare-card.is-just-picked { animation: none; }
}

/* Block affordance: the user tried to continue without committing a card.
   Pulse the whole set and ring its "Use this answer" buttons twice. */
@keyframes compare-needs-pick {
    0%, 100% { box-shadow: none; }
    50%      { box-shadow: 0 0 0 3px color-mix(in srgb, var(--danger) 32%, transparent); }
}
@keyframes compare-pick-btn-ring {
    0%, 100% { box-shadow: none; }
    50%      { box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 40%, transparent); }
}
.compare-set--needs-pick {
    border-radius: var(--radius-lg, 14px);
    animation: compare-needs-pick 700ms ease-in-out 2;
}
.compare-set--needs-pick .compare-card-pick {
    animation: compare-pick-btn-ring 700ms ease-in-out 2;
}
@media (prefers-reduced-motion: reduce) {
    .compare-set--needs-pick,
    .compare-set--needs-pick .compare-card-pick { animation: none; }
}

.compare-card {
    position: relative;
    display: flex;
    flex-direction: column;
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-md);
    background: var(--bg-elevated);
    min-width: 0;
    transition: border-color 160ms ease, box-shadow 160ms ease, transform 160ms ease;
}

/* Body is programmatically focusable so click-to-focus works for the
   ArrowLeft/Right shortcut. Suppress the default focus ring — the active
   card already provides ample visual context. */
.compare-card-body:focus { outline: none; }

.compare-card[data-tint="accent"]      { --tint: var(--tab-tint-accent); }
.compare-card[data-tint="blue"]        { --tint: var(--tab-tint-blue); }
.compare-card[data-tint="violet"]      { --tint: var(--tab-tint-violet); }
.compare-card[data-tint="terracotta"]  { --tint: var(--tab-tint-terracotta); }
.compare-card[data-tint="amber"]       { --tint: var(--tab-tint-amber); }
.compare-card[data-tint="teal"]        { --tint: var(--tab-tint-teal); }

.compare-card::before {
    content: '';
    display: block;
    height: 3px;
    background: var(--tint, var(--accent));
    border-top-left-radius: inherit;
    border-top-right-radius: inherit;
}

.compare-card:hover {
    border-color: var(--border-strong);
    box-shadow: var(--shadow-soft);
}

/* While a compare card is actively streaming, drop the 24px-blur shadow
   layer — it would otherwise be a continuously-recomposited blurred layer
   on a per-token-updating element. The cheap 1px shadow keeps depth; the
   full --shadow-soft returns the moment .is-streaming is removed at
   finalize. Scoped tightly so it also beats the :hover shadow above. */
.compare-set[data-streaming] .compare-card.is-streaming {
    box-shadow: 0 1px 2px rgba(0, 0, 0, .4);
}

.compare-card.is-error::before { background: var(--danger); }
.compare-card.is-error {
    border-color: color-mix(in srgb, var(--danger) 50%, var(--border-subtle));
}

.compare-card.is-error .compare-card-letter {
    background: color-mix(in srgb, var(--danger) 18%, var(--bg-base));
}

.compare-card-head {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: var(--card-padding-block-start) var(--card-padding-inline) 6px;
}

/* Agent avatar (image or Bootstrap icon) sits inline before the letter. The
 * slot is empty (and collapses) for plain regenerate cards with no agent, so
 * the colored letter alone keeps carrying identity there. */
.compare-card-avatar-slot {
    display: inline-flex;
    align-items: center;
    flex: 0 0 auto;
}
.compare-card-avatar-slot:empty { display: none; }
.compare-card-avatar { margin-right: 2px; }

.compare-card-letter {
    font-family: var(--font-mono);
    font-weight: 600;
    font-size: 13px;
    width: 24px;
    height: 24px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 6px;
    background: color-mix(in srgb, var(--tint, var(--accent)) 18%, var(--bg-base));
    color: var(--text-primary);
}

.compare-card-label {
    color: var(--text-secondary);
    font-size: 12px;
    letter-spacing: 0.02em;
}

.compare-card-meta {
    color: var(--text-tertiary);
    font-size: 12px;
    font-family: var(--font-mono);
    letter-spacing: 0.01em;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    min-width: 0;
}
.compare-card-meta:empty { display: none; }

.bot-message-meta {
    display: flex;
    align-items: center;
    gap: 6px;
    font-family: var(--font-mono);
    font-size: 12px;
    color: var(--text-tertiary);
    margin: 0 0 6px;
    letter-spacing: 0.01em;
}
.bot-message-meta:empty { display: none; }
/* The inline agent avatar leads the meta strip; keep it from inheriting the
 * monospace meta colour so the letter-circle tint stays legible. */
.bot-message-avatar { color: var(--text-primary); }

/* Byline segments (single chat, compare cards, discussion cards): the vendor
 * brand logo hugs the model name, and 🧠 hugs the reasoning level. Sized for
 * the mono 12px byline. */
.meta-model, .meta-reasoning { display: inline-flex; align-items: center; gap: 4px; vertical-align: middle; }
.meta-model .vendor-logo, .meta-model .vendor-logo .vendor-logo-svg { width: 14px; height: 14px; }
.meta-model .vendor-logo-fallback .bi { font-size: 13px; }
.meta-think { font-size: 12px; line-height: 1; }
.meta-sep { color: var(--text-tertiary); }  /* keep the · muted */

.compare-card.is-abandoned {
    opacity: 0.55;
    transition: opacity 140ms ease;
}
.compare-card.is-abandoned:hover { opacity: 1; }
.compare-card-abandoned-badge {
    display: inline-block;
    font-size: 0.72em;
    padding: 1px 6px;
    border-radius: 8px;
    background: var(--bs-secondary-bg, #e9ecef);
    color: var(--bs-secondary-color, #6c757d);
    margin-left: 6px;
    text-transform: uppercase;
    letter-spacing: 0.04em;
}

.compare-card-stream {
    margin-left: auto;
    width: 64px;
    height: 2px;
    border-radius: 2px;
    background: linear-gradient(90deg, transparent, var(--tint, var(--accent)), transparent) 0/200% 100%;
    opacity: 0;
    transition: opacity 160ms ease;
}

.compare-set[data-streaming] .compare-card.is-streaming .compare-card-stream {
    opacity: 1;
    animation: compare-stream 1.4s linear infinite;
}

@keyframes compare-stream {
    from { background-position: 200% 0; }
    to   { background-position: -200% 0; }
}

/* Per-card swap pill strip (pair-and-swap compare view, n>=3). Only
   meaningful in `compare` mode — hidden in tabs/selected to avoid the
   strip lingering on the visible card after a view toggle. */
.compare-card-swap {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    margin-left: 4px;
}
.compare-card-swap:empty { display: none; }
.compare-set:not([data-mode="compare"]) .compare-card-swap { display: none; }
.compare-card-swap-pill {
    font-family: var(--font-mono);
    font-weight: 600;
    font-size: 11px;
    line-height: 1;
    width: 22px;
    height: 22px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 999px;
    border: 1px solid var(--border-subtle);
    background: var(--bg-elevated);
    color: var(--text-tertiary);
    cursor: pointer;
    padding: 0;
    transition: color .12s ease, background-color .12s ease, border-color .12s ease, opacity .12s ease;
}
.compare-card-swap-pill[data-tint="accent"]      { --tint: var(--tab-tint-accent); }
.compare-card-swap-pill[data-tint="blue"]        { --tint: var(--tab-tint-blue); }
.compare-card-swap-pill[data-tint="violet"]      { --tint: var(--tab-tint-violet); }
.compare-card-swap-pill[data-tint="terracotta"]  { --tint: var(--tab-tint-terracotta); }
.compare-card-swap-pill[data-tint="amber"]       { --tint: var(--tab-tint-amber); }
.compare-card-swap-pill[data-tint="teal"]        { --tint: var(--tab-tint-teal); }
.compare-card-swap-pill:hover:not(:disabled) {
    color: var(--text-primary);
    border-color: var(--border-strong);
}
.compare-card-swap-pill.is-active {
    color: var(--text-primary);
    border-color: var(--tint, var(--accent));
    background: color-mix(in srgb, var(--tint, var(--accent)) 14%, var(--bg-elevated));
}
.compare-card-swap-pill:disabled {
    opacity: 0.3;
    cursor: not-allowed;
}

.compare-card-body {
    padding: 4px var(--card-padding-inline) var(--card-padding-block-end);
    overflow: auto;
    flex: 1 1 auto;
    min-width: 0;
}
.compare-card-body > *:first-child { margin-top: 0; }
.compare-card-body > *:last-child { margin-bottom: 0; }

.compare-card-foot {
    padding: 0 var(--card-padding-inline) var(--card-padding-block-end);
    display: flex;
    align-items: stretch;
    gap: 8px;
}

.compare-card-pick {
    flex: 1 1 auto;
    padding: 8px 14px;
    border: 0;
    border-radius: var(--radius-sm);
    background: var(--accent);
    color: #fff;
    font-weight: 500;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    transition: background-color .12s, transform .12s;
}
.compare-card-pick:hover { background: var(--accent-hover); }
.compare-card-pick i { transition: transform .12s; }
.compare-card-pick:hover i { transform: translateX(2px); }
.compare-card-pick:disabled {
    background: var(--border-subtle);
    color: var(--text-tertiary);
    cursor: not-allowed;
}

/* Secondary "fork to new chat" icon button. Lives next to the pick button in
   compare mode only (the foot is hidden in tabs/selected). */
.compare-card-fork {
    flex: 0 0 auto;
    width: 36px;
    padding: 0;
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-sm);
    background: transparent;
    color: var(--text-secondary);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: background-color .12s, color .12s, border-color .12s;
}
.compare-card-fork:hover {
    background: var(--bg-hover, rgba(127, 127, 127, 0.08));
    color: var(--text-primary);
    border-color: var(--border-strong, var(--border-subtle));
}
.compare-card-fork:disabled {
    color: var(--text-tertiary);
    cursor: not-allowed;
}

@media (prefers-reduced-motion: reduce) {
    .compare-set-grid,
    .compare-card,
    .compare-card-pick,
    .compare-card-pick i,
    .compare-card-fork,
    .compare-pill,
    .compare-card-stream { transition: none; }
    .compare-set[data-streaming] .compare-card.is-streaming .compare-card-stream {
        animation: none;
        opacity: 0.5;
    }
    .compare-set-pills--floating { transition: none; }
    .compare-card-nav { transition: none; }
}

/* Hover-revealed side chevrons just outside the active card. Quiet
   accelerator that complements the pill rows; keyboard ←/→ provides the
   same effect.

   The rail is a full-height track positioned slightly outside the card's
   left/right edge (negative offset); the chevron inside uses
   `position: sticky` so it tracks the viewport center while any part of
   the card is on screen, and rides off with the card edges as the rail
   scrolls past. A single element can't be both absolute (for edge
   alignment) and sticky (for viewport tracking) — hence the wrapper.
   The card itself uses no `overflow` so the rails can render outside
   its border; the 3px tint bar (`::before`) carries its own
   `border-top-*-radius: inherit` to keep the rounded-corner clip. */
.compare-card-nav-rail {
    position: absolute;
    top: 0;
    bottom: 0;
    width: 36px;
    pointer-events: none;
    z-index: 2;
}
.compare-card-nav-rail--left  { left: -44px; }
.compare-card-nav-rail--right { right: -44px; }

.compare-card-nav {
    position: sticky;
    top: calc(50vh - 18px);
    width: 36px;
    height: 36px;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: color-mix(in srgb, var(--tint, var(--accent)) 14%, var(--bg-elevated));
    color: var(--text-secondary);
    box-shadow: var(--shadow-soft);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    opacity: 0;
    pointer-events: auto;
    transition: opacity 160ms ease-out, transform 200ms cubic-bezier(0.32, 0.72, 0, 1), color .12s ease, background-color .12s ease;
}
.compare-card-nav i { font-size: 14px; line-height: 1; }
.compare-card-nav-rail--left  .compare-card-nav { transform: translateX(-4px) scale(.92); }
.compare-card-nav-rail--right .compare-card-nav { transform: translateX( 4px) scale(.92); }

.compare-set[data-mode="tabs"] .compare-card.is-active:hover .compare-card-nav,
.compare-set[data-mode="tabs"] .compare-card.is-active:focus-within .compare-card-nav {
    opacity: 1;
    pointer-events: auto;
    transform: translateX(0) scale(1);
}

.compare-card-nav:hover {
    color: var(--text-primary);
    background: color-mix(in srgb, var(--tint, var(--accent)) 22%, var(--bg-elevated));
}

/* Hide chevrons when there's nothing to cycle, and outside tabs mode. */
.compare-set[data-n="1"] .compare-card-nav,
.compare-set[data-mode="compare"] .compare-card-nav,
.compare-set[data-mode="selected"] .compare-card-nav,
.compare-set[data-n="1"] .compare-card-nav-rail,
.compare-set[data-mode="compare"] .compare-card-nav-rail,
.compare-set[data-mode="selected"] .compare-card-nav-rail { display: none; }

/* Touch devices have no hover — keep the affordance dimly visible. */
@media (hover: none) {
    .compare-set[data-mode="tabs"] .compare-card.is-active .compare-card-nav {
        opacity: .9;
        pointer-events: auto;
        transform: translateX(0) scale(1);
    }
}

/* Floating bottom pill bar — sticky to the chat viewport bottom, hugging
   the right edge of the compare-set's content column. Only revealed when
   the header pill row has scrolled out of view (the IntersectionObserver
   sets data-floating-pills="visible" on the host .compare-set). */
.compare-set-pills--floating {
    display: flex;
    width: 100%;
    position: sticky;
    bottom: 16px;
    margin-top: 8px;
    margin-bottom: 0;
    justify-content: flex-end;
    pointer-events: none;
    background: transparent;
    /* Hidden by default; opacity + slight rise on reveal. */
    opacity: 0;
    transform: translateY(4px);
    transition: opacity 180ms cubic-bezier(0.165, 0.84, 0.44, 1), transform 180ms cubic-bezier(0.165, 0.84, 0.44, 1);
    z-index: 3;
}

/* Inner cluster — the visual chip that holds the pills. Carries the
   tinted-neutral surface, border, shadow, and pad/gap so the pills read as
   a cohesive group. Restores pointer-events for interaction. */
.compare-set-pills--floating .compare-set-pills-cluster {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 4px 6px;
    border: 1px solid var(--border-subtle);
    border-radius: 999px;
    background: var(--bg-elevated);
    box-shadow: var(--shadow-soft);
    pointer-events: auto;
}

/* Show the bar only when in tabs mode AND the observer reports the header
   row out of view. */
.compare-set[data-mode="tabs"][data-floating-pills="visible"] .compare-set-pills--floating {
    opacity: 1;
    transform: translateY(0);
}

/* Always hide outside tabs mode regardless of the observer state. */
.compare-set:not([data-mode="tabs"]) .compare-set-pills--floating,
.compare-set[data-n="1"] .compare-set-pills--floating { display: none; }

/* ◀ N of M ▶ branch switcher inline on a message with siblings. */
.branch-switcher {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    margin-top: 8px;
    font-size: 11px;
    color: var(--text-tertiary);
    user-select: none;
}
.branch-switcher button {
    border: 0;
    background: transparent;
    color: var(--text-tertiary);
    width: 22px;
    height: 22px;
    border-radius: var(--radius-sm);
    cursor: pointer;
    line-height: 1;
    padding: 0;
    transition: background-color .12s, color .12s;
}
.branch-switcher button:hover { background: var(--border-subtle); color: var(--text-primary); }
.branch-switcher button:disabled { opacity: 0.3; pointer-events: none; }
.branch-switcher .switcher-count {
    font-variant-numeric: tabular-nums;
    min-width: 36px;
    text-align: center;
}

/* ===========================================================================
 * Context menu (chat-row right-click)
 * ========================================================================= */

.ctx-menu {
    position: fixed;
    z-index: 2000;
    min-width: 200px;
    padding: 4px;
    background: var(--bg-surface);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-soft);
    font-size: 13px;
    color: var(--text-primary);
}

.ctx-menu .ctx-menu-panel {
    display: flex;
    flex-direction: column;
    gap: 1px;
}

.ctx-menu .ctx-menu-item {
    position: relative;
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
    padding: 6px 10px;
    border: 0;
    background: transparent;
    color: var(--text-primary);
    border-radius: var(--radius-sm);
    text-align: left;
    cursor: pointer;
    font: inherit;
    line-height: 1.3;
}

/* Disabled informational item (e.g. "Not synced (whole project)") — muted and
   non-interactive; the project toggle owns that state. */
.ctx-menu .ctx-menu-item.is-disabled {
    color: var(--text-tertiary);
    cursor: default;
    opacity: 0.75;
}
.ctx-menu .ctx-menu-item.is-disabled:hover {
    background: transparent;
}

.ctx-menu .ctx-menu-item:not(.is-disabled):hover,
.ctx-menu .ctx-menu-item:not(.is-disabled):focus-visible {
    background: var(--bg-elevated);
    outline: none;
}

.ctx-menu .ctx-menu-item.danger { color: var(--danger); }
.ctx-menu .ctx-menu-item.danger:hover { background: var(--danger-soft); }

.ctx-menu .ctx-menu-item i.bi {
    font-size: 14px;
    width: 16px;
    text-align: center;
    color: var(--text-secondary);
    flex: 0 0 auto;
}
.ctx-menu .ctx-menu-item.danger i.bi { color: var(--danger); }

.ctx-menu .ctx-menu-item .ctx-menu-icon-spacer {
    width: 16px;
    flex: 0 0 auto;
}

.ctx-menu .ctx-menu-item > span:not(.ctx-menu-icon-spacer) {
    flex: 1;
    min-width: 0;
}

.ctx-menu .ctx-menu-chev {
    margin-left: auto;
    font-size: 11px !important;
    color: var(--text-tertiary) !important;
    width: auto !important;
}

.ctx-menu .ctx-menu-sep {
    height: 1px;
    background: var(--border-subtle);
    margin: 4px 2px;
}

.ctx-menu .ctx-menu-sub {
    position: absolute;
    top: -4px;
    left: calc(100% + 2px);
    min-width: 200px;
    padding: 4px;
    background: var(--bg-surface);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-soft);
    z-index: 1;
}

/* Inline rename hook on chat row title link. */
.list-group-item a.is-editing {
    cursor: text;
    background: var(--bg-base);
    border-radius: var(--radius-sm);
    box-shadow: 0 0 0 2px var(--accent-ring);
    padding: 0 4px;
    outline: none;
}

/* Chat-row duplicate icon — sit between tag and trash, mirror trash hover. */
.list-group-item .chat-row-duplicate {
    cursor: pointer;
    opacity: 0.7;
    transition: color .12s, opacity .12s;
}
.list-group-item .chat-row-duplicate:hover {
    opacity: 1;
    color: var(--accent);
}

/* ===========================================================================
 * Chat overview — right-hand TOC sibling of #chat-container.
 * ========================================================================= */
.chat-overview {
    flex: 0 0 240px;
    width: 240px;
    align-self: stretch;
    background: var(--bg-surface);
    border-left: 1px solid var(--border-subtle);
    display: flex;
    flex-direction: column;
    min-height: 0;
    overflow: hidden;
}
.chat-overview[hidden] { display: none; }

.chat-overview-header {
    flex: 0 0 auto;
    padding: 10px 12px;
    border-bottom: 1px solid var(--border-subtle);
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: .08em;
    color: var(--text-tertiary);
    font-weight: 600;
}

.chat-overview-list {
    flex: 1 1 auto;
    overflow-y: auto;
    padding: 6px 0;
}

.chat-overview-empty {
    padding: 16px 12px;
    color: var(--text-tertiary);
    font-size: 12px;
    line-height: 1.4;
}

.chat-overview-entry {
    position: relative;
    padding: 6px 10px 6px 14px;
    cursor: pointer;
    transition: background-color .12s ease;
}
.chat-overview-entry:hover {
    background: var(--accent-soft);
}
.chat-overview-entry.is-active {
    background: var(--accent-soft);
}

/* Two-tone left bar: top half = request hue (accent), bottom half = response
   hue (muted). On the active entry the bar flips to a solid accent so the
   highlight is unmistakable across themes. */
.chat-overview-entry-bar {
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    width: 3px;
    background: linear-gradient(
        to bottom,
        var(--accent) 0%,
        var(--accent) 50%,
        color-mix(in srgb, var(--text-tertiary) 35%, transparent) 50%,
        color-mix(in srgb, var(--text-tertiary) 35%, transparent) 100%
    );
    pointer-events: none;
    transition: background .12s ease;
}
.chat-overview-entry.is-active .chat-overview-entry-bar {
    background: var(--accent);
}

.chat-overview-entry-row {
    display: flex;
    align-items: center;
    gap: 6px;
}

.chat-overview-entry-num {
    flex: 0 0 28px;
    width: 28px;
    text-align: right;
    font-size: 12px;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    color: var(--text-tertiary);
    transition: color .12s ease;
}
.chat-overview-entry.is-active .chat-overview-entry-num {
    color: var(--accent);
}

.chat-overview-entry-chevron {
    flex: 0 0 16px;
    width: 16px;
    height: 18px;
    margin: 0;
    padding: 0;
    border: 0;
    background: transparent;
    color: var(--text-tertiary);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: transform .18s ease, color .12s ease;
}
.chat-overview-entry-chevron:hover { color: var(--accent); }
.chat-overview-entry-chevron[disabled] { visibility: hidden; cursor: default; }
.chat-overview-entry.expanded > .chat-overview-entry-row > .chat-overview-entry-chevron {
    transform: rotate(90deg);
}

.chat-overview-entry-headings {
    list-style: none;
    margin: 4px 0 2px 0;
    padding: 0;
    display: none;
}
.chat-overview-entry.expanded .chat-overview-entry-headings {
    display: block;
}

.chat-overview-entry-heading {
    padding: 3px 8px 3px 24px;
    margin: 0;
    font-size: 12px;
    line-height: 1.3;
    color: var(--text-secondary);
    cursor: pointer;
    border-radius: 4px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    transition: color .12s ease, background-color .12s ease;
}
.chat-overview-entry-heading.h2 { padding-left: 36px; }
.chat-overview-entry-heading:hover {
    color: var(--accent);
    background: var(--accent-soft);
}

/* =====================================================================
   Discussion-aware outline — replaces the H1/H2 heading list when a
   pair's answer is a .discussion-set. Rounds → participant turns →
   synthesis. Reuses the .chat-overview-entry-headings expand mechanism;
   per-agent tints mirror the transcript's data-tint → --tab-tint-* map.
   ===================================================================== */

/* Round sub-header: small uppercase label + trailing consensus marker,
   with a hairline separator between successive rounds. */
.chat-overview-disc-round {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 4px 8px 3px 24px;
    margin: 0;
    font-size: 10.5px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--text-muted);
    cursor: pointer;
    border-radius: 4px;
    transition: color .12s ease, background-color .12s ease;
}
.chat-overview-disc-round + .chat-overview-disc-round,
.chat-overview-disc-turn + .chat-overview-disc-round {
    margin-top: 4px;
    border-top: 1px solid var(--border-subtle);
    padding-top: 6px;
}
.chat-overview-disc-round:hover,
.chat-overview-disc-round.is-active {
    color: var(--accent);
    background: var(--accent-soft);
}
.chat-overview-disc-round-label {
    flex: 1 1 auto;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.chat-overview-disc-consensus {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    gap: 2px;
    font-size: 9.5px;
    font-weight: 700;
    letter-spacing: 0;
    font-variant-numeric: tabular-nums;
    color: var(--text-tertiary);
}
.chat-overview-disc-round.is-converged .chat-overview-disc-consensus {
    color: var(--accent);
}
.chat-overview-disc-consensus.is-pending::before {
    content: "";
    width: 5px;
    height: 5px;
    border-radius: 50%;
    background: color-mix(in srgb, var(--text-tertiary) 55%, transparent);
}

/* Participant turn: tinted left bar + tinted letter, then "A · Name". */
.chat-overview-disc-turn {
    position: relative;
    display: flex;
    align-items: center;
    gap: 5px;
    padding: 3px 8px 3px 36px;
    margin: 0;
    font-size: 12px;
    line-height: 1.3;
    color: var(--text-secondary);
    cursor: pointer;
    border-radius: 4px;
    overflow: hidden;
    transition: color .12s ease, background-color .12s ease;
}
.chat-overview-disc-turn::before {
    content: "";
    position: absolute;
    left: 24px;
    top: 4px;
    bottom: 4px;
    width: 2px;
    border-radius: 1px;
    background: var(--tint, var(--border-subtle));
}
.chat-overview-disc-turn[data-tint="accent"]      { --tint: var(--tab-tint-accent); }
.chat-overview-disc-turn[data-tint="blue"]        { --tint: var(--tab-tint-blue); }
.chat-overview-disc-turn[data-tint="violet"]      { --tint: var(--tab-tint-violet); }
.chat-overview-disc-turn[data-tint="terracotta"]  { --tint: var(--tab-tint-terracotta); }
.chat-overview-disc-turn[data-tint="amber"]       { --tint: var(--tab-tint-amber); }
.chat-overview-disc-turn[data-tint="teal"]        { --tint: var(--tab-tint-teal); }
.chat-overview-disc-letter {
    flex: 0 0 auto;
    font-weight: 700;
    color: var(--tint, var(--text-secondary));
}
.chat-overview-disc-sep {
    flex: 0 0 auto;
    color: var(--text-tertiary);
}
.chat-overview-disc-name {
    flex: 1 1 auto;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.chat-overview-disc-turn:hover {
    color: var(--accent);
    background: var(--accent-soft);
}

/* Synthesis: accent-styled row mirroring the transcript's synthesis head. */
.chat-overview-disc-synth {
    padding: 5px 8px 4px 24px;
    margin: 2px 0 0 0;
    font-size: 12px;
    font-weight: 600;
    color: var(--accent);
    cursor: pointer;
    border-radius: 4px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    transition: background-color .12s ease;
}
.chat-overview-disc-synth:hover,
.chat-overview-disc-synth.is-active {
    background: var(--accent-soft);
}

#chat-overview-toggle.is-active {
    color: var(--accent);
    background: var(--accent-soft);
}

/* Inset ring (not an outset box-shadow): the chat rows now use
   content-visibility:auto, whose paint containment clips anything drawn
   outside the border box. An inset ring renders inside the box so the
   jump-to-message / heading flash stays visible on virtualized rows. */
@keyframes chat-overview-flash {
    0%   { box-shadow: inset 0 0 0 0 var(--accent-ring); }
    20%  { box-shadow: inset 0 0 0 3px var(--accent-ring); }
    100% { box-shadow: inset 0 0 0 0 transparent; }
}
.flash-target {
    animation: chat-overview-flash 900ms ease-out 1;
    border-radius: 12px;
}

/* =====================================================================
   Per-message action bar — "Another answer" + model picker + Copy
   ===================================================================== */

.bot-msg-actions {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-top: 10px;
    padding-top: 6px;
    opacity: 0.65;
    transition: opacity 120ms ease;
}
.bot-message:hover .bot-msg-actions,
.bot-message:focus-within .bot-msg-actions,
.compare-card:hover .bot-msg-actions,
.compare-card:focus-within .bot-msg-actions { opacity: 1; }

/* In the compare-card footer the bar sits next to the pick/fork cluster.
   Reset the top margin since the foot already has its own padding. */
.compare-card-foot .bot-msg-actions {
    margin-top: 0;
    padding-top: 0;
    flex: 1 1 auto;
    min-width: 0;
}

.bot-msg-actions-split {
    display: inline-flex;
    align-items: stretch;
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-sm, 8px);
    background: transparent;
    overflow: hidden;
}

.bot-msg-actions-btn,
.bot-msg-actions-caret {
    border: 0;
    background: transparent;
    color: var(--text-secondary);
    cursor: pointer;
    padding: 4px 10px;
    font-size: 12px;
    line-height: 1.4;
    display: inline-flex;
    align-items: center;
    gap: 4px;
    transition: background-color .12s, color .12s;
}
.bot-msg-actions-btn:hover,
.bot-msg-actions-caret:hover {
    background: var(--bg-hover, rgba(127, 127, 127, 0.08));
    color: var(--text-primary);
}
.bot-msg-actions-caret {
    padding: 4px 8px;
    border-left: 1px solid var(--border-subtle);
}
.bot-msg-actions-btn i { font-size: 11px; }
.bot-msg-actions-caret i { font-size: 11px; }

.bot-msg-actions-btn:disabled,
.bot-msg-actions-caret:disabled,
.ui-chat-busy .bot-msg-actions-btn,
.ui-chat-busy .bot-msg-actions-caret {
    opacity: 0.45;
    cursor: not-allowed;
    pointer-events: none;
}

.bot-msg-actions-copy {
    border: 1px solid var(--border-subtle);
    background: transparent;
    color: var(--text-secondary);
    border-radius: var(--radius-sm, 8px);
    width: 28px;
    height: 28px;
    padding: 0;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: background-color .12s, color .12s, border-color .12s;
}
.bot-msg-actions-copy:hover {
    background: var(--bg-hover, rgba(127, 127, 127, 0.08));
    color: var(--text-primary);
    border-color: var(--border-strong, var(--border-subtle));
}
.bot-msg-actions-copy i { font-size: 13px; }
.bot-msg-actions-copy .bi-clipboard-check { color: var(--accent, #4f46e5); }

/* "Fork from here" (experimental conversation tree). Same chrome as the copy
   button; hidden unless the feature flag is on (a body attribute set in JS). */
.bot-msg-actions-fork {
    border: 1px solid var(--border-subtle);
    background: transparent;
    color: var(--text-secondary);
    border-radius: var(--radius-sm, 8px);
    width: 28px;
    height: 28px;
    padding: 0;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: background-color .12s, color .12s, border-color .12s;
}
.bot-msg-actions-fork:hover {
    background: var(--bg-hover, rgba(127, 127, 127, 0.08));
    color: var(--text-primary);
    border-color: var(--border-strong, var(--border-subtle));
}
.bot-msg-actions-fork i { font-size: 13px; }
.bot-msg-actions-fork:disabled { opacity: 0.45; cursor: not-allowed; pointer-events: none; }
body:not([data-conversation-tree-on]) .bot-msg-actions-fork { display: none; }

/* Transient toast (used by conversation-tree fork/rename feedback). */
.app-toast {
    position: fixed;
    left: 50%;
    bottom: 28px;
    transform: translateX(-50%) translateY(8px);
    z-index: 3000;
    max-width: 80vw;
    padding: 10px 16px;
    background: var(--bg-elevated);
    color: var(--text-primary);
    border: 1px solid var(--border-subtle);
    border-radius: 10px;
    box-shadow: var(--shadow-soft);
    font-size: 13px;
    opacity: 0;
    pointer-events: none;
    transition: opacity .18s, transform .18s;
}
.app-toast.is-visible { opacity: 1; transform: translateX(-50%) translateY(0); }

/* Model picker popover — body-attached, fixed positioning. */
.model-picker-pop {
    position: fixed;
    z-index: 2000;
    min-width: 240px;
    max-width: 360px;
    max-height: 360px;
    overflow-y: auto;
    background: var(--bg-elevated, var(--bg-primary, #fff));
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-sm, 8px);
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.18), 0 2px 6px rgba(0, 0, 0, 0.08);
    padding: 6px;
    font-size: 13px;
    color: var(--text-primary);
}

.model-picker-row {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 4px;
    padding: 8px 10px;
    border-radius: var(--radius-sm, 6px);
    cursor: pointer;
    transition: background-color 80ms ease;
}
.model-picker-row + .model-picker-row { margin-top: 2px; }
.model-picker-row:hover,
.model-picker-row:focus { background: var(--bg-hover, rgba(127, 127, 127, 0.08)); outline: 0; }
.model-picker-row-label {
    font-weight: 500;
    color: var(--text-primary);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.model-picker-list {
    display: flex;
    flex-direction: column;
}

/* Composer model trigger — a logo-capable button standing in for the (hidden)
   native #model-select. Shares .control-select sizing but lays out as a flex
   row (leading brand logo · label · caret) and drops the native caret bg. */
.model-select-trigger {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    background-image: none;
    padding: 0 8px;
    max-width: 220px;
    text-align: left;
}
.model-select-trigger:disabled {
    opacity: 0.55;
    cursor: default;
}
.model-select-trigger-label {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.model-select-trigger-caret {
    flex: 0 0 auto;
    font-size: 10px;
    color: var(--text-tertiary);
}
.model-select-trigger-logo {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
}
.model-select-trigger-logo .bi {
    font-size: 14px;
    color: var(--text-secondary);
}

/* Vendor logos in the trigger + popover rows. Tinted via currentColor (the
   inline color style carries the brand colour); sized to sit with the text. */
.vendor-logo {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 16px;
    height: 16px;
}
.vendor-logo-svg { width: 16px; height: 16px; display: block; }
.vendor-logo-fallback { color: var(--text-tertiary); }
.vendor-logo-fallback .bi { font-size: 14px; line-height: 1; }

/* Author-grouped model popover: section headers + logo rows. Extends the base
   .model-picker-pop / .model-picker-row used by the regenerate picker. */
.model-picker-pop--models { min-width: 240px; }
.model-picker-section-header {
    padding: 8px 10px 4px;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.02em;
    text-transform: uppercase;
    color: var(--text-tertiary);
}
.model-picker-list > .model-picker-section-header:first-child { padding-top: 4px; }
.model-picker-logo-row {
    flex-direction: row;
    align-items: center;
    gap: 8px;
}
.model-picker-row-logo {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
}
.model-picker-row-logo .bi {
    font-size: 15px;
    color: var(--text-secondary);
}
.model-picker-logo-row .model-picker-row-label { flex: 1 1 auto; }
.model-picker-row.is-selected {
    background: var(--bg-hover, rgba(127, 127, 127, 0.08));
}
.model-picker-row.is-selected .model-picker-row-label { font-weight: 600; }

.model-picker-empty {
    padding: 10px 10px 4px;
    color: var(--text-tertiary);
    font-size: 12px;
}
.model-picker-edit-link {
    margin-top: 2px;
    padding: 6px 10px;
    background: transparent;
    border: 0;
    color: var(--accent, #4f46e5);
    text-align: left;
    font-size: 12px;
    cursor: pointer;
    border-radius: var(--radius-sm, 6px);
}
.model-picker-edit-link:hover,
.model-picker-edit-link:focus {
    background: var(--bg-hover, rgba(127, 127, 127, 0.08));
    outline: 0;
}

/* Transient "+1" card while the new answer is streaming in. Soft accent
   border reads as "added now, others were pre-existing". The class is
   stripped on reload (which rebuilds the grid canonically). */
.compare-card.is-pending-grow {
    border-color: var(--accent, #4f46e5);
    box-shadow: 0 0 0 1px var(--accent-ring, rgba(79, 70, 229, 0.25));
}

/* ─── Per-profile icons ─── */

/* Pill icon sits between the dot and the name. Matches body font size so it
   doesn't shoulder the text up; the dot already carries the size cue. */
.profile-pill-icon {
    display: inline-flex;
    align-items: center;
    font-size: 13px;
    color: var(--text-primary);
}
.profile-pill-icon[hidden] { display: none; }

.profile-menu-item-label {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    min-width: 0;
}
.profile-menu-item-icon {
    font-size: 14px;
    color: var(--text-secondary);
    flex-shrink: 0;
}
.profile-menu-item.active .profile-menu-item-icon { color: var(--accent); }

.profile-list-name {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    min-width: 0;
}
.profile-list-icon {
    font-size: 14px;
    color: var(--text-secondary);
    flex-shrink: 0;
}
.profile-list li.active .profile-list-icon,
.profile-list li.is-active-profile .profile-list-icon { color: var(--accent); }

/* Pack rows: icon left of the title text. Falls back to bi-collection when
   the pack has no icon, so every row gets the same horizontal alignment. */
.profile-pack-title {
    display: inline-flex;
    align-items: center;
    gap: 8px;
}
.profile-pack-icon {
    font-size: 14px;
    color: var(--text-secondary);
    flex-shrink: 0;
}

/* ─── Icon picker in the profile editor ─── */

.profile-name-row {
    display: flex;
    align-items: stretch;
    gap: 8px;
    position: relative;
}
.profile-name-row .form-control { flex: 1; }

.profile-icon-btn {
    flex: 0 0 auto;
    width: 38px;
    border: 1px solid var(--border-strong, rgba(255,255,255,0.12));
    background: var(--bg-elevated, transparent);
    color: var(--text-secondary);
    border-radius: var(--radius-sm, 4px);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 16px;
    transition: border-color .12s, color .12s, background-color .12s;
}
.profile-icon-btn:hover {
    border-color: var(--accent, #0d6efd);
    color: var(--accent, #0d6efd);
}
.profile-icon-btn[aria-expanded="true"] {
    border-color: var(--accent, #0d6efd);
    color: var(--accent, #0d6efd);
    box-shadow: 0 0 0 3px var(--accent-ring, rgba(13, 110, 253, 0.2));
}
.profile-icon-btn.has-icon { color: var(--accent, #0d6efd); }

/* Avatar/icon picker — a centered overlay modal (mirrors `.crop-overlay`) so it
 * is always fully visible and layered above the Bootstrap modal it lives in,
 * rather than an anchored popover that the modal body clipped. */
.profile-icon-popover {
    position: fixed;
    inset: 0;
    z-index: 2000;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(0, 0, 0, 0.5);
}
.profile-icon-popover[hidden] { display: none; }

/* The dialog card holds the picker chrome (mirrors `.crop-dialog`). Capped so a
 * tall gallery scrolls inside the card instead of overflowing the viewport. */
.profile-icon-dialog {
    background: var(--bg-elevated);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-lg, 14px);
    box-shadow: var(--shadow-soft);
    padding: 20px;
    width: 420px;
    max-width: 92vw;
    max-height: 85vh;
    overflow: auto;
}
.profile-icon-dialog-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    margin-bottom: 10px;
}
.profile-icon-dialog-title {
    font-size: 14px;
    font-weight: 600;
    color: var(--text-primary);
}
.profile-icon-dialog-close {
    border: 0;
    background: transparent;
    color: var(--text-secondary);
    font-size: 14px;
    line-height: 1;
    padding: 4px;
    border-radius: var(--radius-sm, 4px);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: color .12s, background-color .12s;
}
.profile-icon-dialog-close:hover {
    color: var(--text-primary);
    background: var(--accent-soft, rgba(13, 110, 253, 0.08));
}

.profile-icon-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(46px, 1fr));
    gap: 6px;
}

.profile-icon-tile {
    width: 100%;
    aspect-ratio: 1 / 1;
    border: 1px solid transparent;
    border-radius: var(--radius-sm, 4px);
    background: transparent;
    color: var(--text-secondary);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 22px;
    cursor: pointer;
    transition: border-color .1s, color .1s, background-color .1s;
}
.profile-icon-tile:hover {
    border-color: var(--accent, #0d6efd);
    color: var(--accent, #0d6efd);
    background: var(--accent-soft, rgba(13, 110, 253, 0.08));
}
.profile-icon-tile.is-selected {
    border-color: var(--accent, #0d6efd);
    color: var(--accent, #0d6efd);
    background: var(--accent-soft, rgba(13, 110, 253, 0.12));
}

/* Picker tab strip: switches the popover body between the preset Images gallery
 * and the Icons glyph grid. Shared by the agent + team avatar pickers. */
.profile-icon-tabs {
    display: flex;
    gap: 4px;
    margin-bottom: 8px;
    border-bottom: 1px solid var(--border-subtle);
    padding-bottom: 6px;
}
.profile-icon-tab {
    flex: 1 1 auto;
    padding: 5px 8px;
    border: 1px solid transparent;
    border-radius: var(--radius-sm, 4px);
    background: transparent;
    color: var(--text-secondary);
    font-size: 12px;
    font-weight: 500;
    cursor: pointer;
    transition: border-color .12s, color .12s, background-color .12s;
}
.profile-icon-tab:hover {
    color: var(--accent, #0d6efd);
    background: var(--accent-soft, rgba(13, 110, 253, 0.08));
}
.profile-icon-tab.active {
    border-color: var(--accent, #0d6efd);
    color: var(--accent, #0d6efd);
    background: var(--accent-soft, rgba(13, 110, 253, 0.12));
}

/* Preset image gallery (the "Images" tab): square <img> thumbnails. Grid width
 * tracks the glyph grid so the popover doesn't jump between tabs. */
.profile-preset-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(72px, 1fr));
    gap: 10px;
}
.profile-preset-tile {
    width: 100%;
    aspect-ratio: 1 / 1;
    padding: 0;
    border: 2px solid transparent;
    border-radius: var(--radius-sm, 6px);
    background: transparent;
    cursor: pointer;
    overflow: hidden;
    transition: border-color .1s, transform .1s;
}
.profile-preset-tile img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
    border-radius: 4px;
}
.profile-preset-tile:hover {
    border-color: var(--accent, #0d6efd);
    transform: scale(1.04);
}
.profile-preset-tile.is-selected {
    border-color: var(--accent, #0d6efd);
    box-shadow: 0 0 0 2px var(--accent-ring, rgba(13, 110, 253, 0.25));
}
.profile-preset-empty {
    grid-column: 1 / -1;
    padding: 12px 4px;
    text-align: center;
    color: var(--text-secondary);
    font-size: 12px;
}

/* "Generate" tab: prompt textarea + Generate button + inline status line. */
.profile-generate-panel {
    display: flex;
    flex-direction: column;
    gap: 10px;
    width: 100%;
}
.profile-generate-prompt {
    width: 100%;
    resize: vertical;
    min-height: 120px;
    padding: 8px 10px;
    background: var(--bg-input);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-sm, 6px);
    color: var(--text-primary);
    font: inherit;
    font-size: 13px;
}
.profile-generate-row { display: flex; justify-content: flex-end; }
.profile-generate-status {
    min-height: 16px;
    font-size: 12px;
    color: var(--text-secondary);
    display: flex;
    align-items: center;
    gap: 6px;
}
.profile-generate-status.is-error { color: var(--danger, #dc3545); }
.profile-generate-spin {
    display: inline-block;
    animation: profile-generate-spin 0.8s linear infinite;
}
@keyframes profile-generate-spin { to { transform: rotate(360deg); } }

/* ---------------------------------------------------------------------------
 * Agent avatars — custom uploaded image (circular) or Bootstrap-icon fallback.
 * Display precedence everywhere: image > icon > nothing. A single helper in the
 * renderer (`agentVisualEl`) emits `.agent-avatar` (an <img>) or
 * `.agent-avatar-icon` (an <i class="bi …">) with a per-site `agent-avatar--*`
 * size modifier so all render sites stay visually consistent.
 * ------------------------------------------------------------------------- */
.agent-avatar {
    border-radius: 50%;
    object-fit: cover;
    flex: 0 0 auto;
    display: block;
    background: var(--bg-elevated, rgba(0, 0, 0, 0.04));
}
/* Icon fallback gets a fixed box equal to the matching <img> size so the glyph
 * occupies the same footprint as an image avatar and sits vertically centred in
 * its row (the discussion/roster heads are already `align-items: center`),
 * instead of a bare font-size that rode high against the name. */
.agent-avatar-icon {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

/* Letter fallback (opt-in): a tinted circle reusing the compare-card-letter
 * recipe so agents with neither image nor icon are never avatar-less. */
.agent-avatar-letter {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
    font-weight: 600;
    line-height: 1;
    background: color-mix(in srgb, var(--tint, var(--accent, #0d6efd)) 18%, var(--bg-base, #fff));
    color: var(--text-primary);
}

/* Per-site sizes. Image sizes drive the circle box; the icon and letter
 * fallbacks share that box so all three avatar kinds match per site. */
img.agent-avatar.agent-avatar--list   { width: 18px; height: 18px; }
img.agent-avatar.agent-avatar--pill   { width: 18px; height: 18px; }
img.agent-avatar.agent-avatar--menu   { width: 16px; height: 16px; }
img.agent-avatar.agent-avatar--roster { width: 20px; height: 20px; }
img.agent-avatar.agent-avatar--card   { width: 24px; height: 24px; }
img.agent-avatar.agent-avatar--meta   { width: 18px; height: 18px; }
i.agent-avatar-icon.agent-avatar--list   { width: 18px; height: 18px; font-size: 13px; }
i.agent-avatar-icon.agent-avatar--pill   { width: 18px; height: 18px; font-size: 13px; }
i.agent-avatar-icon.agent-avatar--menu   { width: 16px; height: 16px; font-size: 12px; }
i.agent-avatar-icon.agent-avatar--roster { width: 20px; height: 20px; font-size: 15px; }
i.agent-avatar-icon.agent-avatar--card   { width: 24px; height: 24px; font-size: 17px; }
i.agent-avatar-icon.agent-avatar--meta   { width: 18px; height: 18px; font-size: 13px; }
.agent-avatar-letter.agent-avatar--list   { width: 18px; height: 18px; font-size: 11px; }
.agent-avatar-letter.agent-avatar--pill   { width: 18px; height: 18px; font-size: 11px; }
.agent-avatar-letter.agent-avatar--menu   { width: 16px; height: 16px; font-size: 10px; }
.agent-avatar-letter.agent-avatar--roster { width: 20px; height: 20px; font-size: 12px; }
.agent-avatar-letter.agent-avatar--card   { width: 24px; height: 24px; font-size: 14px; }
.agent-avatar-letter.agent-avatar--meta   { width: 18px; height: 18px; font-size: 11px; }

/* Edit-form icon button: a square preview of the custom image fills the button
 * (which sizes itself to the adjacent name input). */
.profile-icon-btn-img {
    width: 28px;
    height: 28px;
    border-radius: 50%;
    object-fit: cover;
    display: block;
}

/* Icon popover: image actions row above the glyph grid. */
.profile-icon-actions {
    display: flex;
    flex-direction: column;
    gap: 4px;
    margin-bottom: 8px;
}
.profile-icon-action {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    width: 100%;
    padding: 6px 8px;
    border: 1px solid transparent;
    border-radius: var(--radius-sm, 4px);
    background: transparent;
    color: var(--text-secondary);
    font-size: 13px;
    cursor: pointer;
    transition: border-color .12s, color .12s, background-color .12s;
}
.profile-icon-action:hover {
    border-color: var(--accent, #0d6efd);
    color: var(--accent, #0d6efd);
    background: var(--accent-soft, rgba(13, 110, 253, 0.08));
}

/* Roster + transcript-card avatars share `.agent-avatar`; tiny tweaks so they
 * sit cleanly against the colored letter idiom. */
.discussion-roster-card-avatar { margin-right: 2px; }
.discussion-card-avatar { margin-right: 2px; }

/* ---------------------------------------------------------------------------
 * Avatar crop dialog — lightweight overlay (no library). Square viewport with
 * a <canvas>, drag-to-pan + zoom slider, export to a 256² WebP data URL.
 * ------------------------------------------------------------------------- */
.crop-overlay {
    position: fixed;
    inset: 0;
    z-index: 2000;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(0, 0, 0, 0.5);
}
.crop-dialog {
    background: var(--bg-elevated);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-lg, 14px);
    box-shadow: var(--shadow-soft);
    padding: 18px;
    display: flex;
    flex-direction: column;
    gap: 14px;
    align-items: stretch;
}
.crop-dialog-title {
    font-size: 14px;
    font-weight: 600;
    color: var(--text-primary);
}
.crop-viewport {
    position: relative;
    overflow: hidden;
    border-radius: 50%;
    border: 1px solid var(--border-strong, rgba(255, 255, 255, 0.12));
    align-self: center;
    background: var(--bg-base, rgba(0, 0, 0, 0.2));
}
.crop-canvas {
    display: block;
    cursor: grab;
    touch-action: none;
}
.crop-canvas:active { cursor: grabbing; }
.crop-zoom-row {
    display: flex;
    align-items: center;
    gap: 10px;
    color: var(--text-secondary);
}
.crop-zoom { flex: 1; }
.crop-actions {
    display: flex;
    justify-content: flex-end;
    gap: 8px;
}

/* ===========================================================================
 * Snippet library
 * ========================================================================= */

.snippet-list li {
    flex-direction: column;
    align-items: flex-start;
    gap: 4px;
}

.snippet-list-row-head {
    display: flex;
    align-items: center;
    gap: 6px;
    width: 100%;
}

.snippet-list-name {
    flex: 1;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.snippet-scope-chip {
    display: inline-flex;
    align-items: center;
    padding: 1px 7px;
    border-radius: 999px;
    font-size: 10px;
    font-weight: 500;
    line-height: 1.5;
    background: var(--bg-elevated);
    color: var(--text-secondary);
    border: 1px solid var(--border-subtle);
    flex-shrink: 0;
}

.snippet-scope-chip.is-project {
    background: var(--accent-soft);
    color: var(--accent);
    border-color: var(--accent-soft);
}

.snippet-scope-chip.is-chat {
    background: rgba(210, 140, 40, 0.12);
    color: rgb(220, 160, 60);
    border-color: rgba(210, 140, 40, 0.28);
}

.snippet-kind-chip {
    display: inline-flex;
    align-items: center;
    padding: 1px 7px;
    border-radius: 999px;
    font-size: 10px;
    font-weight: 500;
    line-height: 1.5;
    background: var(--bg-elevated);
    color: var(--text-secondary);
    border: 1px solid var(--border-subtle);
    flex-shrink: 0;
    text-transform: lowercase;
}

.snippet-kind-chip.is-template {
    background: rgba(120, 100, 220, 0.12);
    color: rgb(140, 120, 240);
    border-color: rgba(120, 100, 220, 0.28);
}

.snippet-kind-chip.is-snippet {
    background: rgba(40, 160, 120, 0.10);
    color: rgb(70, 170, 130);
    border-color: rgba(40, 160, 120, 0.24);
}

/* Manage Library: nav-tabs strip between header and two-pane body. */
.library-kind-tabs.nav-tabs {
    border-bottom: 1px solid var(--border-subtle);
    padding: 0 12px;
    gap: 2px;
    background: var(--bg-surface);
}
.library-kind-tabs .nav-link {
    color: var(--text-secondary);
    border: 1px solid transparent;
    border-bottom: none;
    border-top-left-radius: var(--radius-sm);
    border-top-right-radius: var(--radius-sm);
    padding: 6px 14px;
    font-size: 13px;
    background: transparent;
}
.library-kind-tabs .nav-link:hover {
    color: var(--text-primary);
    background: var(--bg-elevated);
}
.library-kind-tabs .nav-link.active {
    color: var(--text-primary);
    background: var(--bg-base, var(--bg-surface));
    border-color: var(--border-subtle);
    border-bottom-color: var(--bg-base, var(--bg-surface));
    margin-bottom: -1px;
}

.snippet-list-desc {
    font-size: 11px;
    color: var(--text-secondary);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: 100%;
}

.snippet-body-input {
    font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
    font-size: 12px;
}

/* Insert-snippet picker: two-pane layout (list + preview). */
.snippet-pick-pane {
    display: grid;
    grid-template-columns: 260px 1fr;
    min-height: 360px;
}
.snippet-pick-list-pane {
    border-right: 1px solid var(--border-subtle);
    display: flex;
    flex-direction: column;
    background: var(--bg-surface);
    padding: 8px;
    gap: 6px;
}
.snippet-pick-search {
    margin-bottom: 4px;
}
.snippet-pick-list {
    list-style: none;
    padding: 0;
    margin: 0;
    flex: 1;
    overflow-y: auto;
}
.snippet-pick-list li {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: 8px 10px;
    border-radius: var(--radius-sm);
    color: var(--text-secondary);
    cursor: pointer;
    font-size: 13px;
    margin-bottom: 2px;
}
.snippet-pick-list li:hover {
    background: var(--bg-elevated);
    color: var(--text-primary);
}
.snippet-pick-list li.active {
    background: var(--accent-soft);
    color: var(--text-primary);
}
.snippet-pick-list li.has-template::after {
    content: 'template';
    align-self: flex-start;
    font-size: 10px;
    color: var(--accent);
    text-transform: uppercase;
    letter-spacing: 0.04em;
}
.snippet-pick-empty {
    padding: 12px 10px;
    font-size: 12px;
    color: var(--text-secondary);
}
.snippet-pick-preview-pane {
    display: flex;
    flex-direction: column;
    gap: 6px;
    padding: 14px 16px;
    overflow: hidden;
}
.snippet-pick-preview-name {
    font-weight: 600;
    font-size: 14px;
}
.snippet-pick-preview-meta {
    font-size: 11px;
    color: var(--text-secondary);
}
.snippet-pick-preview-body {
    flex: 1;
    margin: 0;
    padding: 10px;
    border-radius: var(--radius-sm);
    background: var(--bg-elevated);
    font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
    font-size: 12px;
    white-space: pre-wrap;
    overflow: auto;
    max-height: 320px;
}

/* Fill wizard */
.snippet-fill-breadcrumb {
    font-size: 11px;
    color: var(--text-secondary);
    margin-bottom: 8px;
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
    align-items: center;
}
.snippet-fill-breadcrumb-sep::before {
    content: ' ▸ ';
    color: var(--text-secondary);
}
.snippet-fill-breadcrumb-name {
    font-weight: 600;
    color: var(--text-primary);
}
.snippet-fill-preview-wrap {
    margin-bottom: 10px;
}
.snippet-fill-preview-label {
    font-size: 11px;
    color: var(--text-secondary);
    margin-bottom: 4px;
}
.snippet-fill-preview {
    margin: 0;
    padding: 10px;
    border-radius: var(--radius-sm);
    background: var(--bg-elevated);
    font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
    font-size: 12px;
    white-space: pre-wrap;
    max-height: 140px;
    overflow: auto;
}
.snippet-fill-preview .snippet-fill-current {
    background: var(--accent-soft);
    color: var(--accent);
    border-radius: 3px;
    padding: 0 2px;
    font-weight: 600;
}
.snippet-fill-preview .snippet-fill-resolved {
    background: var(--bg-surface);
    color: var(--text-secondary);
    border-radius: 3px;
    padding: 0 2px;
}
.snippet-fill-progress {
    font-size: 11px;
    color: var(--text-secondary);
    margin-bottom: 8px;
}
.snippet-fill-current-label code {
    font-size: 12px;
    background: var(--accent-soft);
    color: var(--accent);
    padding: 1px 6px;
    border-radius: 4px;
}
.snippet-fill-error {
    margin-top: 8px;
    padding: 8px 10px;
    border-radius: var(--radius-sm);
    background: rgba(220, 53, 69, 0.12);
    color: var(--text-danger, #dc3545);
    font-size: 12px;
}

/* Picker filter strip — kind toggle + project select above the search input. */
.snippet-pick-filters {
    display: flex;
    align-items: center;
    gap: 6px;
    margin-bottom: 4px;
}
.snippet-pick-kind-toggle {
    display: inline-flex;
    border-radius: var(--radius-sm);
    overflow: hidden;
    border: 1px solid var(--border-subtle);
    background: var(--bg-elevated);
}
.snippet-pick-kind-toggle button {
    border: 0;
    background: transparent;
    color: var(--text-secondary);
    font-size: 11px;
    padding: 4px 10px;
    cursor: pointer;
}
.snippet-pick-kind-toggle button:hover {
    color: var(--text-primary);
}
.snippet-pick-kind-toggle button.active {
    background: var(--accent-soft);
    color: var(--accent);
}
.snippet-pick-project-filter {
    flex: 1;
    min-width: 0;
    font-size: 11px;
}

/* Recents pinned section above the main list. */
.snippet-pick-recents {
    display: flex;
    flex-direction: column;
    gap: 2px;
}
.snippet-pick-recents-label {
    font-size: 10px;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--text-secondary);
    margin: 6px 2px 2px;
}
.snippet-pick-recents-divider {
    border-bottom: 1px solid var(--border-subtle);
    margin: 4px 0;
}

/* Multi-fill form — one row per placeholder, optional nested rows. */
.snippet-fill-rows {
    display: flex;
    flex-direction: column;
    gap: 10px;
}
.snippet-fill-row {
    padding: 10px 12px;
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-sm);
    background: var(--bg-surface);
    display: flex;
    flex-direction: column;
    gap: 6px;
}
.snippet-fill-row-nested {
    margin-left: 18px;
    border-left: 2px solid var(--accent-soft);
    background: var(--bg-elevated);
}
.snippet-fill-row-head {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
}
.snippet-fill-row-name {
    font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
    font-size: 12px;
    background: var(--accent-soft);
    color: var(--accent);
    padding: 1px 6px;
    border-radius: 4px;
}
.snippet-fill-mode-toggle {
    display: inline-flex;
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-sm);
    overflow: hidden;
    background: var(--bg-elevated);
}
.snippet-fill-mode-toggle button {
    border: 0;
    background: transparent;
    color: var(--text-secondary);
    font-size: 11px;
    padding: 3px 9px;
    cursor: pointer;
}
.snippet-fill-mode-toggle button:hover {
    color: var(--text-primary);
}
.snippet-fill-mode-toggle button.active {
    background: var(--accent-soft);
    color: var(--accent);
}
.snippet-fill-row-body { display: flex; flex-direction: column; gap: 6px; }
.snippet-fill-row-pick {
    display: flex;
    gap: 6px;
    align-items: center;
}
.snippet-fill-row-pick .picked-name {
    font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
    font-size: 12px;
    color: var(--text-primary);
    background: var(--bg-elevated);
    padding: 2px 6px;
    border-radius: 4px;
    border: 1px solid var(--border-subtle);
}
.snippet-fill-row-pick .picked-clear {
    border: 0;
    background: transparent;
    color: var(--text-secondary);
    cursor: pointer;
    padding: 2px 6px;
    font-size: 12px;
}
.snippet-fill-row-pick .picked-clear:hover { color: var(--text-primary); }
.snippet-fill-row-cap-notice {
    font-size: 11px;
    color: var(--text-secondary);
    font-style: italic;
}
.snippet-fill-row-nested-toggle {
    border: 0;
    background: transparent;
    color: var(--text-secondary);
    cursor: pointer;
    font-size: 11px;
    padding: 0;
    text-align: left;
}
.snippet-fill-row-nested-toggle:hover { color: var(--text-primary); }
.snippet-fill-preview .snippet-fill-unfilled {
    background: rgba(220, 53, 69, 0.12);
    color: var(--text-danger, #dc3545);
    border-radius: 3px;
    padding: 0 2px;
}

/* Compare-responses modal — chip strip + warning. Click a chip to drop a
   response from the composed prompt; toggling regenerates the textarea. */
.compare-modal-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}

.compare-modal-chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    height: 26px;
    padding: 0 10px;
    border: 1px solid color-mix(in srgb, var(--accent) 40%, var(--border-subtle));
    border-radius: 999px;
    background: color-mix(in srgb, var(--accent) 14%, transparent);
    color: var(--text-primary);
    font-family: var(--font-mono);
    font-size: 12px;
    cursor: pointer;
    transition: color .12s, border-color .12s, background-color .12s, opacity .12s;
}
.compare-modal-chip:hover { border-color: var(--accent); }
.compare-modal-chip .compare-modal-chip-x { font-size: 10px; opacity: 0.75; }

.compare-modal-chip.is-off {
    background: transparent;
    border-color: var(--border-subtle);
    color: var(--text-tertiary);
    opacity: 0.7;
    text-decoration: line-through;
}
.compare-modal-chip.is-off:hover { color: var(--text-secondary); opacity: 1; }

.compare-modal-warning {
    margin-top: 6px;
    color: var(--text-danger, #dc3545);
    font-size: 12px;
}

/* ---------------------------------------------------------------------------
   Experimental: LaTeX paper workspace.
   A Paper tab is a normal chat tab with an attached workspace; in paper mode
   the main area becomes  Regions rail | Source (Monaco) | Chat , reusing the
   existing #chat-container as the chat column and the shared composer below.
--------------------------------------------------------------------------- */
#paper-workspace[hidden] { display: none; }
#paper-workspace {
    display: flex;
    flex: 1 1 0;
    min-width: 0;
    min-height: 0;
}
body.paper-mode #paper-right-pane {
    flex: 0 1 38%;
    min-width: 280px;
    border-left: 1px solid var(--border-subtle);
    display: flex;
    flex-direction: column;
    min-height: 0;
}
body.paper-mode #paper-right-pane #chat-container {
    flex: 1 1 auto;
    min-height: 0;
    min-width: 0;
    border-left: none;
}
body.paper-mode #paper-right-pane .composer-wrap {
    width: 100%;
    padding: 8px;
}
.paper-right-head {
    display: flex;
    padding: 6px 8px;
    border-bottom: 1px solid var(--border-subtle);
    flex: 0 0 auto;
    justify-content: space-between;
    align-items: center;
    gap: 8px;
}
.paper-right-head .paper-layout-seg .segmented-option {
    padding: 4px 8px;
    font-size: 13px;
    line-height: 1;
}
.paper-right-head .paper-layout-seg .segmented-option i { vertical-align: -1px; }
.paper-files-pane {
    display: flex;
    flex-direction: column;
    overflow: hidden;
    flex: 1 1 auto;
    min-height: 0;
}
body.paper-right-files #paper-files-pane[hidden] { display: flex !important; }
body.paper-right-files #paper-right-pane > #chat-container { display: none !important; }
body.paper-right-files #paper-right-pane .composer-wrap { display: none !important; }
body.paper-right-chat  #paper-files-pane { display: none !important; }

.paper-files-section {
    padding: 10px 12px;
    border-bottom: 1px solid var(--border-subtle);
}
.paper-files-section h6 {
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--text-tertiary);
    margin: 0 0 8px;
}
.paper-files-list {
    max-height: 30vh;
    overflow-y: auto;
}
.paper-files-list .file {
    padding: 4px 6px;
    cursor: pointer;
    border-radius: 4px;
    font-family: var(--font-mono);
    font-size: 12px;
    color: var(--text-primary);
}
.paper-files-list .file:hover { background: var(--bg-elevated); }
.paper-files-list .file.is-active { background: var(--accent-soft); color: var(--accent); }
.paper-files-sync-row {
    display: flex;
    gap: 8px;
    align-items: center;
}
.paper-files-sync-row .btn { flex: 1 1 auto; }
.paper-files-sync-row .paper-sync-indicator { flex: 0 0 auto; }
.paper-files-history-list {
    max-height: 28vh;
    overflow-y: auto;
}
.paper-files-history-list .paper-history-item {
    display: grid;
    grid-template-columns: 60px 1fr auto;
    gap: 8px;
    padding: 4px 6px;
    cursor: pointer;
    border-radius: 4px;
    font-size: 12px;
}
.paper-files-history-list .paper-history-item:hover { background: var(--bg-elevated); }
.paper-files-history-list .paper-history-sha {
    font-family: var(--font-mono);
    color: var(--text-tertiary);
}
.paper-files-history-list .paper-history-msg {
    color: var(--text-primary);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.paper-files-history-list .paper-history-date {
    color: var(--text-tertiary);
    font-size: 11px;
}
.paper-files-log {
    font: 11px/1.4 var(--font-mono);
    max-height: 24vh;
    overflow: auto;
    background: var(--bg-elevated);
    border-radius: 4px;
    padding: 6px 8px;
    white-space: pre-wrap;
    color: var(--text-secondary);
    margin: 0;
}
.paper-files-empty {
    color: var(--text-tertiary);
    font-size: 11px;
    font-style: italic;
}

/* Layout mode: editor only — right pane and its splitter hidden. */
body.paper-mode.paper-layout-editor #paper-right-pane,
body.paper-mode.paper-layout-editor #paper-chat-resize { display: none !important; }
body.paper-mode.paper-layout-editor #paper-workspace { flex: 1 1 100%; }

/* Layout mode: right pane only — editor + rail hidden. The !important on the
   width rule is needed to beat the persisted-from-split `has-paper-chat-width`
   rule lower in the file. The user picked "right pane only", so the stored
   split width must not leak in. */
body.paper-mode.paper-layout-right #paper-workspace,
body.paper-mode.paper-layout-right #paper-chat-resize { display: none !important; }
body.paper-mode.paper-layout-right #paper-right-pane,
body.paper-mode.paper-layout-right.has-paper-chat-width #paper-right-pane {
    flex: 1 1 100% !important;
    min-width: 0 !important;
}

body.paper-mode .tab-strip,
body.paper-mode .tab-nav-strip { display: none !important; }
body.paper-mode .chat-overview { display: none !important; }

.paper-file-error {
    padding: 4px 8px;
    border-radius: var(--radius-sm);
    background: var(--danger-soft);
    color: var(--danger);
    font-size: 11px;
}
.paper-source-head .paper-file-select {
    flex: 0 1 320px;
    min-width: 0;
    max-width: 50%;
    font-family: var(--font-mono);
    font-size: 12px;
}

/* Paper-mode chat picker — slim row above the chat messages inside
   #paper-right-pane. Only visible when paper mode is on AND the Chat
   sub-tab is active; hidden in Files & Sync mode and outside paper mode. */
.paper-chat-picker {
    display: none;
    align-items: center;
    gap: 6px;
    padding: 6px 10px;
    border-bottom: 1px solid var(--border-subtle);
}
body.paper-mode.paper-right-chat #paper-chat-picker { display: flex; }
.paper-chat-picker .paper-chat-select {
    flex: 1 1 auto;
    min-width: 0;
    font-family: var(--font-mono);
    font-size: 12px;
}
.paper-chat-picker .btn {
    flex: 0 0 auto;
    padding: 2px 8px;
    font-size: 12px;
}
.paper-source-head .paper-file-error {
    flex: 1 1 auto;
    margin: 0 0 0 8px;
}

.paper-source {
    flex: 1 1 0;
    min-width: 0;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}
.paper-source-head {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 12px;
    border-bottom: 1px solid var(--border-subtle);
}
.paper-monaco-wrap {
    flex: 1 1 auto;
    min-height: 0;
    min-width: 0;
    position: relative;
    display: flex;
    overflow: hidden;
}
.paper-monaco { flex: 1 1 auto; min-height: 0; min-width: 0; }
.paper-source-head #paper-view-segmented { margin-left: auto; }
.paper-source-head .segmented + .btn { margin-left: 8px; }
.paper-source-head .paper-layout-seg .segmented-option {
    padding: 4px 8px;
    font-size: 13px;
    line-height: 1;
}
.paper-source-head .paper-layout-seg .segmented-option i { vertical-align: -1px; }

/* Sync indicator + per-state push/pull icon buttons in the source header. */
.paper-sync-indicator {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    font-size: 14px;
    color: var(--text-secondary);
    border-radius: 4px;
}
.paper-sync-indicator.is-sync     { color: var(--success, #4caf50); }
.paper-sync-indicator.is-ahead    { color: var(--accent, #6cb0ff); }
.paper-sync-indicator.is-behind   { color: var(--accent, #6cb0ff); }
.paper-sync-indicator.is-diverged { color: var(--danger, #e06c75); }
.paper-sync-indicator.is-dirty    { color: var(--text-tertiary); }
.paper-sync-btn { padding: 2px 8px; font-size: 11px; flex: 0 0 auto; }
.paper-sync-btn i { vertical-align: -1px; }

/* Hide branched-response UI in paper mode — paper chat is single-answer. */
body.paper-mode .compare-set-pills,
body.paper-mode .branch-switcher { display: none !important; }

/* (Old focus-mode block removed — replaced by paper-layout-{editor,right} rules above.) */

/* Floating toolbar that appears in the paper editor when at least one
   AI-proposed ghost edit is pending. */
.paper-edit-actions {
    position: absolute;
    bottom: 10px;
    right: 16px;
    z-index: 4;
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 6px 10px;
    background: var(--bg-elevated, var(--bg-surface, #1d1f24));
    color: var(--text-primary);
    border: 1px solid var(--border-subtle);
    border-radius: 999px;
    box-shadow: var(--shadow-soft);
    font-size: 12px;
}
.paper-edit-actions-count {
    font-weight: 600;
}
.paper-edit-actions-hint {
    color: var(--text-tertiary);
    font-size: 11px;
}
.paper-edit-actions .btn { padding: 2px 10px; font-size: 11px; }
.paper-edit-actions-sep {
    opacity: 0.5;
    margin: 0 4px;
    color: var(--text-tertiary);
}
.paper-edit-actions .paper-edit-nav {
    padding: 2px 8px;
    font-size: 13px;
    line-height: 1;
}
.paper-edit-actions .paper-edit-nav:disabled {
    opacity: 0.35;
    cursor: not-allowed;
}
/* One-shot attention pulse when ghosts first arrive — JS sets
   data-just-arrived and clears it after the animation runs. */
@keyframes paper-edit-actions-pulse {
    0%   { box-shadow: var(--shadow-soft), 0 0 0 0 rgba(108, 176, 255, 0.55); }
    60%  { box-shadow: var(--shadow-soft), 0 0 0 8px rgba(108, 176, 255, 0); }
    100% { box-shadow: var(--shadow-soft), 0 0 0 0 rgba(108, 176, 255, 0); }
}
.paper-edit-actions[data-just-arrived] {
    animation: paper-edit-actions-pulse 600ms ease-out 1;
    border-color: var(--accent, #6cb0ff);
}

/* Inline ghost-text decorations live on the Monaco surface itself; these
   classes are attached via deltaDecorations.afterContentClassName. */
.paper-ghost-after::after {
    content: attr(data-ghost);
    color: var(--accent, #6cb0ff);
    opacity: 0.75;
    font-style: italic;
    margin-left: 2px;
    white-space: pre;
}
.paper-ghost-focus::after { opacity: 1; text-decoration: underline; }
.paper-ghost-search {
    background: rgba(108, 176, 255, 0.18);
    box-shadow: inset 2px 0 0 var(--accent, #6cb0ff);
}
.paper-ghost-search-focus {
    background: rgba(108, 176, 255, 0.34);
    box-shadow: inset 2px 0 0 var(--accent, #6cb0ff);
}
/* Gutter glyph next to every line the AI proposes to edit. The ::before
   carries the mark; the class is attached via linesDecorationsClassName so
   Monaco sizes the gutter slot for us. */
.paper-ghost-gutter {
    width: 4px !important;
    background: var(--accent, #6cb0ff);
    margin-left: 2px;
}
.paper-ghost-gutter::before {
    content: "✎";
    position: absolute;
    left: 8px;
    color: var(--accent, #6cb0ff);
    font-size: 11px;
    line-height: 1;
}
.paper-ghost-zone {
    background: rgba(108, 176, 255, 0.07);
    border-left: 2px solid var(--accent, #6cb0ff);
    padding: 4px 8px;
    color: var(--text-secondary);
    font-family: var(--font-mono);
    font-size: 12px;
    white-space: pre-wrap;
}
.paper-ghost-zone-focus {
    background: rgba(108, 176, 255, 0.16);
    color: var(--text-primary);
}

/* Composer context chip — only shown when a paper workspace is active. */
.paper-context-chip {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px;
    margin: 0 0 6px 0;
    padding: 4px 6px;
    border: 1px solid var(--border-subtle);
    border-radius: 999px;
    background: var(--bg-subtle, rgba(255,255,255,0.04));
    font-size: 11px;
}
.paper-context-toggle {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 2px 8px;
    border: none;
    background: transparent;
    color: var(--text-primary);
    border-radius: 999px;
    cursor: pointer;
    font-size: 11px;
}
.paper-context-toggle[aria-pressed="false"] {
    color: var(--text-tertiary);
}
.paper-context-name {
    font-family: var(--font-mono);
    min-width: 0;
    max-width: 22ch;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.paper-context-scope { color: var(--text-tertiary); min-width: 0; }
.paper-context-mode { font-size: 11px; flex: 0 0 auto; white-space: nowrap; }
.paper-context-mode .segmented-option { padding: 2px 8px; font-size: 11px; }

@media (max-width: 720px) {
    .paper-context-mode .segmented-option { padding: 2px 6px; }
    .paper-context-name { max-width: 14ch; }
}

/* Engaged state vs off state. When off, the whole chip dims and the
   segmented mode picker is greyed out + click-guarded by JS. The scope
   label text itself ("(off — not attached)") carries the primary signal. */
.paper-context-chip.is-off {
    opacity: 0.45;
}
.paper-context-chip.is-off .paper-context-mode .segmented-option {
    cursor: not-allowed;
    color: var(--text-tertiary);
}
.paper-context-chip.is-off .paper-context-scope {
    font-style: italic;
}

/* Soft warning state for all-files mode when the bundled byte count crosses
   the warn threshold (~200 KB). Amber border nudges the user without
   blocking the send. */
.paper-context-chip.is-warn {
    border-color: rgba(255, 176, 64, 0.7);
    box-shadow: inset 0 0 0 1px rgba(255, 176, 64, 0.2);
}

/* Section picker popover — anchored under the chip. Positioned relative
   to .paper-context-chip (its parent). Reuses the same elevated-surface
   chrome as the history dropdown. */
.paper-context-chip { position: relative; }
.paper-section-picker {
    position: absolute;
    bottom: calc(100% + 6px);
    left: 0;
    z-index: 70;
    min-width: 340px;
    max-width: 520px;
    max-height: 60vh;
    display: flex;
    flex-direction: column;
    background: var(--bg-surface);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-sm);
    box-shadow: var(--shadow-soft);
    overflow: hidden;
}
.paper-section-picker-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 6px 10px;
    border-bottom: 1px solid var(--border-subtle);
    background: var(--bg-elevated, transparent);
    font-size: 11px;
    color: var(--text-tertiary);
}
.paper-section-picker-title { font-weight: 600; color: var(--text-primary); }
.paper-section-picker-bulk { display: inline-flex; gap: 8px; }
.paper-section-picker-bulk .link-btn,
.paper-section-picker-bulk button {
    background: none;
    border: none;
    color: var(--text-link, #6cb0ff);
    cursor: pointer;
    font-size: 11px;
    padding: 0;
}
.paper-section-picker-bulk button:hover { text-decoration: underline; }
.paper-section-picker-list {
    flex: 1 1 auto;
    overflow: auto;
    padding: 4px 0;
}
.paper-section-picker-row {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 4px 10px;
    font-size: 12px;
    color: var(--text-primary);
    cursor: pointer;
}
.paper-section-picker-row:hover { background: var(--bg-elevated); }
.paper-section-picker-row[data-level="1"],
.paper-section-picker-row[data-level="2"] { padding-left: 10px; }
.paper-section-picker-row[data-level="3"] { padding-left: 10px; }
.paper-section-picker-row[data-level="4"] { padding-left: 28px; }
.paper-section-picker-row[data-level="5"] { padding-left: 46px; }
.paper-section-picker-row[data-level="6"] { padding-left: 64px; }
.paper-section-picker-title-row {
    flex: 1 1 auto;
    font-family: var(--font-mono);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.paper-section-picker-line {
    flex: 0 0 auto;
    color: var(--text-tertiary);
    font-size: 11px;
    font-family: var(--font-mono);
}
.paper-section-picker-empty {
    padding: 14px 12px;
    color: var(--text-tertiary);
    font-size: 12px;
    text-align: center;
}
.paper-section-picker-foot {
    display: flex;
    justify-content: flex-end;
    gap: 8px;
    padding: 6px 10px;
    border-top: 1px solid var(--border-subtle);
    background: var(--bg-elevated, transparent);
}
.paper-section-picker-foot .btn { padding: 4px 12px; font-size: 12px; }
.paper-section-picker-foot .btn:disabled { opacity: 0.5; cursor: not-allowed; }

/* Inline pill substituted in the chat assistant message when ≥1 edit
   block was extracted. Keeps the raw fenced bytes out of the visible
   chat while still letting the user know edits are pending. */
.paper-edit-pill {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    margin: 4px 0;
    padding: 4px 10px;
    border: 1px solid var(--border-subtle);
    border-radius: 999px;
    background: var(--bg-subtle, rgba(108,176,255,0.08));
    color: var(--text-primary);
    font-size: 12px;
    font-family: inherit;
    cursor: pointer;
    transition: transform 80ms ease-out, filter 80ms ease-out;
}
.paper-edit-pill:hover { filter: brightness(1.1); }
.paper-edit-pill:active { transform: scale(0.97); }
.paper-edit-pill:focus-visible {
    outline: 2px solid var(--accent, #6cb0ff);
    outline-offset: 1px;
}
.paper-edit-pill[disabled] {
    cursor: default;
    opacity: 0.55;
}
.paper-edit-warning {
    margin: 4px 0;
    padding: 4px 10px;
    border-left: 2px solid var(--danger, #e06c75);
    color: var(--text-secondary);
    font-size: 12px;
    background: var(--bg-subtle, rgba(224,108,117,0.08));
}
.paper-edit-warning-jump {
    margin-left: 8px;
    padding: 1px 8px;
    font-size: 11px;
    border: 1px solid var(--border-subtle);
    border-radius: 999px;
    background: transparent;
    color: var(--text-link, #6cb0ff);
    cursor: pointer;
}
.paper-edit-warning-jump:hover { filter: brightness(1.1); }

/* "Discuss this change" popover anchored to the focused ghost. */
.paper-ghost-discuss-btn {
    position: absolute;
    top: 4px;
    right: 8px;
    padding: 1px 8px;
    font-size: 11px;
    border: 1px solid var(--border-subtle);
    border-radius: 999px;
    background: var(--bg-elevated, var(--bg-surface, #1d1f24));
    color: var(--text-primary);
    cursor: pointer;
    line-height: 1.4;
    opacity: 0.85;
    z-index: 2;
}
.paper-ghost-zone { position: relative; }
.paper-ghost-discuss-btn:hover { opacity: 1; filter: brightness(1.1); }

.paper-ghost-discuss {
    position: absolute;
    z-index: 6;
    width: 340px;
    max-width: 92vw;
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding: 10px;
    background: var(--bg-elevated, var(--bg-surface, #1d1f24));
    color: var(--text-primary);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-sm);
    box-shadow: var(--shadow-soft);
    font-size: 12px;
}
.paper-ghost-discuss[hidden] { display: none; }
.paper-ghost-discuss-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
}
.paper-ghost-discuss-title { font-weight: 600; }
.paper-ghost-discuss-head .btn-close {
    background: transparent;
    border: none;
    color: var(--text-tertiary);
    font-size: 16px;
    line-height: 1;
    cursor: pointer;
    padding: 0 4px;
}
.paper-ghost-discuss-head .btn-close::before { content: "×"; }
.paper-ghost-discuss-head .btn-close:hover { color: var(--text-primary); }
.paper-ghost-discuss-thread {
    max-height: 220px;
    overflow: auto;
    display: flex;
    flex-direction: column;
    gap: 8px;
}
.paper-ghost-discuss-row {
    display: flex;
    flex-direction: column;
    gap: 2px;
}
.paper-ghost-discuss-role {
    font-size: 10px;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--text-tertiary);
}
.paper-ghost-discuss-body {
    white-space: pre-wrap;
    word-break: break-word;
    font-size: 12px;
}
.paper-ghost-discuss-row.assistant .paper-ghost-discuss-body {
    font-family: var(--font-mono);
    background: rgba(108,176,255,0.07);
    padding: 4px 6px;
    border-radius: 4px;
}
.paper-ghost-discuss-form {
    display: flex;
    gap: 6px;
    align-items: flex-end;
}
.paper-ghost-discuss-form textarea {
    flex: 1 1 auto;
    min-height: 38px;
    resize: vertical;
    background: var(--bg-base, #15171b);
    color: var(--text-primary);
    border: 1px solid var(--border-subtle);
    border-radius: 6px;
    padding: 6px 8px;
    font-family: inherit;
    font-size: 12px;
}
.paper-ghost-discuss-form .btn { padding: 4px 10px; font-size: 11px; }
.paper-ghost-discuss-status {
    font-size: 11px;
    color: var(--text-tertiary);
    min-height: 14px;
}

.paper-pdf {
    flex: 1 1 auto;
    min-height: 0;
    overflow: auto;
    background: var(--bg-base);
}
.paper-pdf-msg {
    color: var(--text-secondary);
    font-size: 13px;
    padding: 24px;
}
.paper-pdf-spinner {
    display: inline-block;
    width: 14px;
    height: 14px;
    border: 2px solid var(--border-subtle);
    border-top-color: var(--accent);
    border-radius: 999px;
    animation: paper-spin 0.8s linear infinite;
    vertical-align: -2px;
    margin-right: 8px;
}
@keyframes paper-spin { to { transform: rotate(360deg); } }
.paper-pdf-progress {
    padding: 24px;
    color: var(--text-secondary);
    font-size: 13px;
    text-align: left;
}
.paper-pdf-progress .paper-pdf-hint {
    display: block;
    color: var(--text-tertiary);
    font-size: 12px;
    margin-top: 8px;
    max-width: 540px;
}
#paper-compile.is-loading {
    position: relative;
    padding-left: 24px;
    color: var(--text-secondary);
}
#paper-compile.is-loading::before {
    content: '';
    position: absolute;
    left: 8px;
    top: 50%;
    width: 10px;
    height: 10px;
    margin-top: -5px;
    border: 2px solid var(--border-subtle);
    border-top-color: var(--accent);
    border-radius: 999px;
    animation: paper-spin 0.8s linear infinite;
}
.paper-pdf-log {
    text-align: left;
    font-family: var(--font-mono);
    font-size: 11px;
    color: var(--text-secondary);
    white-space: pre-wrap;
    background: var(--bg-elevated);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-sm);
    padding: 10px;
    margin-top: 12px;
    max-height: 50%;
    overflow: auto;
}

body.paper-mode.has-paper-chat-width #paper-right-pane {
    flex: 0 1 var(--paper-chat-width, 38%);
}

/* Vertical splitter handle — same affordance as #sidebar-resize-handle. */
.paper-chat-resize {
    flex: 0 0 6px;
    cursor: col-resize;
    z-index: 5;
    background: transparent;
    transition: background-color .12s;
}
.paper-chat-resize:hover,
.paper-chat-resize.is-dragging { background: var(--accent-soft); }
body.is-resizing-paper { cursor: col-resize; user-select: none; }
body.is-resizing-paper iframe { pointer-events: none; }
body:not(.paper-mode) #paper-chat-resize { display: none; }

/* Sidebar Papers list */
.sidebar-papers-section {
    border-top: 1px solid var(--border-subtle);
    padding: 8px 6px 10px;
    flex: 0 0 auto;
    display: flex;
    flex-direction: column;
    gap: 4px;
}
.sidebar-papers-header-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 2px 6px;
}
.sidebar-papers-title {
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--text-tertiary);
    font-weight: 600;
}
.sidebar-papers-action,
.sidebar-papers-add {
    background: none;
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
    color: var(--text-secondary);
    font-size: 12px;
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 3px 8px;
    cursor: pointer;
}
.sidebar-papers-action:hover,
.sidebar-papers-add:hover {
    background: var(--accent-soft);
    color: var(--accent);
}
.paper-list { display: flex; flex-direction: column; gap: 2px; }
.paper-list-item {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 6px 8px;
    border-radius: var(--radius-sm);
    cursor: pointer;
    color: var(--text-primary);
    font-size: 13px;
}
.paper-list-item:hover { background: var(--bg-elevated); }
.paper-list-item.is-active {
    background: var(--accent-soft);
    color: var(--accent);
}
.paper-list-item .paper-list-name {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.paper-list-item .paper-list-dot {
    flex: 0 0 6px;
    width: 6px;
    height: 6px;
    border-radius: 999px;
    background: transparent;
}
.paper-list-item.is-active .paper-list-dot { background: var(--accent); }
.paper-list-item .paper-list-menu {
    flex: 0 0 auto;
    opacity: 0;
    background: none;
    border: 0;
    color: var(--text-tertiary);
    padding: 0 4px;
    cursor: pointer;
}
.paper-list-item:hover .paper-list-menu,
.paper-list-item.is-active .paper-list-menu { opacity: 1; }
.paper-list-empty {
    padding: 6px 8px;
    color: var(--text-tertiary);
    font-size: 12px;
}

/* Settings: multi-repo manager */
.tex-repos-list {
    display: flex;
    flex-direction: column;
    gap: 6px;
    margin-bottom: 8px;
}
.tex-repo-row {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 6px 8px;
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-sm);
    background: var(--bg-elevated);
}
.tex-repo-row .tex-repo-name {
    flex: 0 0 160px;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-weight: 600;
    color: var(--text-primary);
    font-size: 13px;
}
.tex-repo-row .tex-repo-url {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-family: var(--font-mono);
    font-size: 11px;
    color: var(--text-secondary);
}
.tex-repo-row .tex-repo-token-badge {
    flex: 0 0 auto;
    font-size: 10px;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    padding: 1px 6px;
    border-radius: 999px;
    background: var(--accent-soft);
    color: var(--accent);
}
.tex-repo-row .tex-repo-token-badge.is-missing {
    background: var(--danger-soft);
    color: var(--danger);
}
.tex-repo-row .btn { padding: 2px 8px; font-size: 11px; }
.tex-repo-add-row {
    display: flex;
    gap: 6px;
    align-items: center;
    flex-wrap: wrap;
    margin-bottom: 8px;
}
.tex-repos-empty {
    padding: 8px;
    color: var(--text-tertiary);
    font-size: 12px;
    text-align: center;
}
.tex-engine-log {
    font-family: var(--font-mono);
    font-size: 11px;
    color: var(--text-secondary);
    background: var(--bg-elevated);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-sm);
    padding: 8px 10px;
    margin-top: 8px;
    max-height: 160px;
    overflow: auto;
    white-space: pre-wrap;
}

/* Paper source-head extras: history dropdown + autosave indicator */
.paper-history-wrap { position: relative; flex: 0 0 auto; }
.paper-history-wrap .btn { padding: 2px 8px; font-size: 11px; }
.paper-history-menu {
    position: absolute;
    top: calc(100% + 4px);
    right: 0;
    z-index: 60;
    min-width: 280px;
    max-height: 320px;
    overflow: auto;
    background: var(--bg-surface);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-sm);
    box-shadow: var(--shadow-soft);
    padding: 4px 0;
}
.paper-history-item {
    padding: 6px 10px;
    cursor: pointer;
    font-size: 12px;
    color: var(--text-primary);
    display: flex;
    gap: 8px;
    align-items: baseline;
}
.paper-history-item:hover { background: var(--bg-elevated); }
.paper-history-item .paper-history-sha {
    font-family: var(--font-mono);
    color: var(--text-tertiary);
    flex: 0 0 auto;
}
.paper-history-item .paper-history-msg {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.paper-history-item .paper-history-date {
    flex: 0 0 auto;
    color: var(--text-tertiary);
    font-size: 11px;
}
.paper-history-empty,
.paper-history-error {
    padding: 8px 10px;
    color: var(--text-tertiary);
    font-size: 12px;
}
.paper-autosave-status {
    font-size: 11px;
    color: var(--text-tertiary);
    margin-left: 6px;
    flex: 0 0 auto;
}
.paper-autosave-status.is-dirty { color: var(--accent); }
.paper-autosave-status.is-error { color: var(--danger); }

/* Engine-missing inline notice (shown when Compile is attempted with no engine) */
.paper-engine-notice {
    margin: 10px 12px 0;
    padding: 10px 12px;
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-sm);
    background: var(--bg-elevated);
    color: var(--text-secondary);
    font-size: 12px;
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
}
.paper-engine-notice .btn { padding: 2px 10px; font-size: 11px; }

/* PDF iframe — Electron's built-in PDF viewer renders the bytes directly */
.paper-pdf iframe {
    display: block;
    width: 100%;
    height: 100%;
    border: 0;
    background: #fff;
}

/* Read-only history viewer overlay */
.paper-history-viewer {
    position: absolute;
    inset: 0;
    background: var(--bg-base);
    z-index: 10;
    display: flex;
    flex-direction: column;
}
.paper-history-viewer-head {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 6px 12px;
    border-bottom: 1px solid var(--border-subtle);
    font-size: 12px;
    color: var(--text-secondary);
}
.paper-history-viewer-head .btn { padding: 2px 8px; font-size: 11px; }
.paper-history-viewer-body { flex: 1 1 auto; min-height: 0; }

/* --- Zotero picker --- */

.zotero-modal-content {
    min-height: min(78vh, 720px);
}

.zotero-picker {
    display: grid;
    grid-template-columns: minmax(280px, 360px) 1fr;
    gap: 0;
    min-height: 60vh;
}

.zotero-picker-left {
    display: flex;
    flex-direction: column;
    min-height: 0;
    border-right: 1px solid var(--border-subtle);
}

.zotero-search-bar {
    padding: 10px 12px;
    border-bottom: 1px solid var(--border-subtle);
    flex: 0 0 auto;
}

.zotero-results {
    list-style: none;
    margin: 0;
    padding: 0;
    overflow-y: auto;
    flex: 1 1 auto;
    min-height: 0;
}

.zotero-result {
    padding: 8px 12px 8px 10px;
    border-bottom: 1px solid var(--border-subtle);
    border-left: 2px solid transparent;
    cursor: pointer;
    transition: background-color .1s, border-color .1s;
}
.zotero-result:hover { background: var(--bg-elevated); }
.zotero-result.active {
    background: var(--bg-elevated);
    border-left-color: var(--accent);
}
.zotero-result.active .zotero-result-title { color: var(--accent); }
.zotero-result-title {
    font-weight: 600;
    font-size: 13px;
    line-height: 1.3;
    color: var(--text-primary);
    margin-bottom: 2px;
    /* Two-line clamp */
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.zotero-result-meta {
    font-size: 11px;
    color: var(--text-secondary);
    display: flex;
    gap: 6px;
    flex-wrap: wrap;
}
.zotero-result-meta .zotero-citekey {
    font-family: var(--font-mono, monospace);
}
.zotero-result-meta .zotero-pdf-pill {
    background: var(--bg-elevated);
    border: 1px solid var(--border-subtle);
    border-radius: 8px;
    padding: 0 6px;
    font-size: 10px;
}

.zotero-results-empty {
    flex: 1 1 auto;
    display: flex;
    align-items: center;
    justify-content: center;
    text-align: center;
}

/* Inline `@citekey` mention autocomplete in the composer. A fixed, elevated
 * dropdown modelled on .files-popover; rows reuse the .zotero-result* info
 * styling so they read like the modal's results. */
.zotero-mention-popover {
    position: fixed;
    z-index: 1200;
    min-width: 320px;
    max-width: 460px;
    background: var(--bg-elevated);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-soft);
    padding: 4px;
    overflow: hidden;
}
.zotero-mention-popover[hidden] { display: none; }
/* Explicit open state so visibility never depends on attribute removal alone. */
.zotero-mention-popover.is-open { display: block; }
.zotero-mention-list {
    list-style: none;
    margin: 0;
    padding: 0;
    max-height: 280px;
    overflow-y: auto;
}
.zotero-mention-item {
    padding: 7px 10px;
    border-radius: var(--radius-sm);
    border-left: 2px solid transparent;
    cursor: pointer;
    transition: background-color .1s, border-color .1s;
}
.zotero-mention-item:hover { background: var(--bg-base); }
.zotero-mention-item.active {
    background: var(--bg-base);
    border-left-color: var(--accent);
}
.zotero-mention-item.active .zotero-result-title { color: var(--accent); }
.zotero-mention-hint {
    padding: 9px 10px;
    color: var(--text-tertiary);
    font-size: 12px;
}
/* Section header separating the Files and Zotero groups in the unified
   `@` dropdown — modeled on .files-popover-section-label. */
.zotero-mention-section-label {
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--text-tertiary);
    padding: 6px 10px 2px;
}
/* File rows: icon + name + token count on a single line. */
.zotero-mention-item.zotero-mention-file {
    display: flex;
    align-items: center;
    gap: 8px;
}
.zotero-mention-file-icon {
    flex-shrink: 0;
    color: var(--text-secondary);
}
.zotero-mention-file-name {
    flex: 1;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.zotero-mention-file-tokens {
    flex-shrink: 0;
    color: var(--text-tertiary);
    font-family: var(--font-mono);
    font-size: 11px;
}

/* Slash-command autocomplete — a clone of the Zotero `@mention` popover above,
   reused as the composer's `/command` menu. */
.slash-cmd-popover {
    position: fixed;
    z-index: 1200;
    min-width: 280px;
    max-width: 420px;
    background: var(--bg-elevated);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-soft);
    padding: 4px;
    overflow: hidden;
}
.slash-cmd-popover[hidden] { display: none; }
.slash-cmd-popover.is-open { display: block; }
.slash-cmd-list {
    list-style: none;
    margin: 0;
    padding: 0;
    max-height: 280px;
    overflow-y: auto;
}
.slash-cmd-item {
    display: flex;
    align-items: baseline;
    gap: 10px;
    padding: 7px 10px;
    border-radius: var(--radius-sm);
    border-left: 2px solid transparent;
    cursor: pointer;
    transition: background-color .1s, border-color .1s;
}
.slash-cmd-item:hover { background: var(--bg-base); }
.slash-cmd-item.active {
    background: var(--bg-base);
    border-left-color: var(--accent);
}
.slash-cmd-name {
    font-family: var(--font-mono);
    font-size: 12px;
    font-weight: 600;
    color: var(--text-primary);
    white-space: nowrap;
}
.slash-cmd-item.active .slash-cmd-name { color: var(--accent); }
.slash-cmd-desc {
    font-size: 12px;
    color: var(--text-secondary);
    flex: 1 1 auto;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.slash-cmd-hint {
    padding: 9px 10px;
    color: var(--text-tertiary);
    font-size: 12px;
}

/* Ephemeral, non-persisted command-output notes appended to the transcript
   (compaction result, unknown-command warning, /help listing). */
.slash-note {
    display: flex;
    align-items: flex-start;
    gap: 8px;
    margin: 10px auto;
    max-width: 720px;
    padding: 9px 12px;
    border: 1px solid var(--border-subtle);
    border-left: 3px solid var(--text-tertiary);
    border-radius: var(--radius-sm);
    background: var(--bg-elevated);
    color: var(--text-secondary);
    font-size: 13px;
    line-height: 1.45;
}
.slash-note > i { margin-top: 1px; color: var(--text-tertiary); }
.slash-note-success { border-left-color: #4a9d6a; }
.slash-note-success > i { color: #4a9d6a; }
.slash-note-error { border-left-color: #d05656; }
.slash-note-error > i { color: #d05656; }
.slash-note-title { font-weight: 600; color: var(--text-primary); margin-bottom: 4px; }
.slash-note-cmds { list-style: none; margin: 0; padding: 0; }
.slash-note-cmds li { padding: 2px 0; }
.slash-note-cmds code {
    font-family: var(--font-mono);
    font-weight: 600;
    color: var(--text-primary);
}

/* Compaction boundary marker — placed after the last message the stored
   summary covers. Top: a toggle that reveals/hides the collapsed originals.
   Below: a highlighted summary card (visible by default). The verbatim recent
   turns continue below the card. */
.compaction-divider {
    margin: 16px auto;
    max-width: 820px;
}
/* Collapsed originals: hide the marker's preceding message siblings.
   !important so it wins over per-message content-visibility/display rules. */
.compaction-collapsed { display: none !important; }

.compaction-expand-row {
    display: flex;
    justify-content: center;
    margin-bottom: 10px;
}
.compaction-expand-btn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    background: transparent;
    border: 1px solid var(--border-subtle);
    border-radius: 999px;
    padding: 3px 12px;
    font-size: 11.5px;
    font-weight: 600;
    color: var(--text-secondary);
    cursor: pointer;
    transition: border-color .12s, color .12s, background .12s;
}
.compaction-expand-btn:hover {
    border-color: var(--border-strong);
    color: var(--text-primary);
}
.compaction-expand-btn .bi {
    font-size: 11px;
    transition: transform .12s;
}

.compaction-summary-card {
    max-width: 820px;
    padding: 12px 16px;
    border: 1px solid var(--accent);
    border-left: 3px solid var(--accent);
    border-radius: var(--radius-md);
    background: var(--accent-soft);
    max-height: 360px;
    overflow: auto;
}
.compaction-summary-head {
    display: flex;
    align-items: center;
    gap: 7px;
    margin-bottom: 8px;
    font-size: 11.5px;
    font-weight: 600;
    letter-spacing: .02em;
    color: var(--accent);
}
.compaction-summary-head .bi { font-size: 13px; }
.compaction-summary-body {
    color: var(--text-secondary);
    font-size: 12.5px;
    line-height: 1.55;
    white-space: pre-wrap;
}
.compaction-summary-body.compaction-summary-empty {
    color: var(--text-tertiary);
    font-style: italic;
}

/* Clear boundary marker (/clear + /clearfull). Reuses .compaction-divider for
   layout and the .compaction-expand-* toggle; here it's just a labelled rule
   + sub-note, no summary card. */
.clear-divider-line {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 7px;
    font-size: 11.5px;
    font-weight: 600;
    letter-spacing: .02em;
    color: var(--text-secondary);
}
.clear-divider-line::before,
.clear-divider-line::after {
    content: "";
    flex: 1 1 auto;
    height: 1px;
    background: var(--border-subtle);
}
.clear-divider-line .bi { font-size: 12px; }
.clear-divider-note {
    margin-top: 5px;
    text-align: center;
    font-size: 11px;
    color: var(--text-tertiary);
}

.zotero-picker-right {
    display: flex;
    flex-direction: column;
    min-height: 0;
}

.zotero-preview {
    padding: 14px 16px;
    overflow-y: auto;
    flex: 1 1 auto;
    min-height: 0;
    font-size: 13px;
    line-height: 1.45;
}
.zotero-preview h3 {
    font-size: 15px;
    margin: 0 0 6px;
    color: var(--text-primary);
}
.zotero-preview dl {
    display: grid;
    grid-template-columns: max-content 1fr;
    gap: 2px 12px;
    margin: 8px 0 12px;
}
.zotero-preview dt {
    color: var(--text-secondary);
    font-weight: 500;
    font-size: 12px;
}
.zotero-preview dd {
    margin: 0;
    font-size: 12px;
    word-break: break-word;
}
.zotero-preview .zotero-abstract {
    margin-top: 8px;
    padding: 8px 10px;
    background: var(--bg-elevated);
    border-radius: var(--radius-sm);
    font-size: 12px;
    color: var(--text-secondary);
}

.zotero-options {
    border-top: 1px solid var(--border-subtle);
    padding: 12px 16px;
    background: var(--bg-elevated);
    flex: 0 0 auto;
}
.zotero-options .form-check { margin-bottom: 6px; }
.zotero-options .form-check:last-child { margin-bottom: 0; }

.zotero-status {
    padding: 6px 16px 10px;
    min-height: 24px;
    flex: 0 0 auto;
}
.zotero-status.is-error { color: var(--danger); }
.zotero-status.is-success { color: var(--success, #198754); }

/* Badge on file rows whose kind === 'zotero' — picked up by the file list
   widget where it renders `data-file-kind` on each row. */
.file-row[data-file-kind="zotero"] .file-row-name::before,
.recent-file-row[data-file-kind="zotero"]::before {
    content: 'Z';
    display: inline-block;
    width: 16px;
    height: 16px;
    line-height: 16px;
    text-align: center;
    border-radius: 50%;
    background: #b91c1c;
    color: #fff;
    font-size: 10px;
    font-weight: 700;
    margin-right: 6px;
    vertical-align: middle;
}

/* "From Zotero…" entry inside the files-popover. Sits below the file lists,
   separated by a divider so it visually belongs to the popover but reads
   as a different category (external source). */
.files-popover-external {
    border-top: 1px solid var(--border-subtle);
    margin-top: 4px;
    padding-top: 4px;
}
.files-popover-zotero-btn { width: 100%; }
.files-popover-zotero-icon {
    color: #b91c1c; /* Zotero red */
    font-size: 14px;
    flex-shrink: 0;
}

/* =====================================================================
 * Multi-model discussion
 * =================================================================== */

/* Composer "people" toggle — armed state mirrors the accent treatment. */
.composer-discussion {
    width: 32px;
    height: 32px;
    flex-shrink: 0;
    border: 0;
    border-radius: 50%;
    background: var(--bg-elevated);
    color: var(--text-secondary);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 14px;
    transition: background-color .12s, color .12s;
}
.composer-discussion:hover { background: var(--border-subtle); color: var(--text-primary); }
.composer-discussion.active {
    background: var(--accent-soft);
    color: var(--accent);
    box-shadow: inset 0 0 0 1px var(--accent-ring);
}

/* Discussion transcript surface. Mirrors the compare-set card framing. */
#chat-container > .discussion-set {
    margin: var(--card-margin-block) auto;
    max-width: min(var(--card-max-width), calc(100% - 2 * var(--card-gutter-inline)));
}
.discussion-set {
    /* Frameless wrapper: keep margins for breathing room in the chat flow,
       but no border/background — per-turn cards and the accent synthesis box
       carry the visual framing. */
}
.discussion-eyebrow {
    font-size: 11px;
    letter-spacing: .08em;
    font-weight: 600;
    color: var(--text-muted, var(--text-secondary));
    margin-bottom: 8px;
}
.discussion-round + .discussion-round { margin-top: 10px; }
.discussion-round-divider {
    font-size: 11px;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--text-muted, var(--text-secondary));
    border-top: 1px dashed var(--border-subtle);
    padding-top: 8px;
    margin: 6px 0 8px;
}
.discussion-round-body {
    display: flex;
    flex-direction: column;
    gap: 10px;
}
.discussion-card {
    padding: 2px 0 2px 14px;
}
.discussion-card.is-streaming {
    background: color-mix(in srgb, var(--tint, var(--accent)) 6%, transparent);
}
.discussion-card.is-error { border-left-color: var(--danger); }
.discussion-card-head {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 2px;
}
.discussion-card-name {
    font-weight: 600;
    font-size: 13px;
    color: var(--text-primary);
}
.discussion-card-badge {
    font-size: 11px;
    color: var(--text-muted, var(--text-secondary));
    background: var(--accent-soft);
    border-radius: 6px;
    padding: 1px 6px;
}
.discussion-card-body { font-size: 14px; }

/* Discussion turn/synthesis bodies render via .bot-message for markdown prose,
   but the .bot-message:not(.compare-card-body) frame rules (border, accent bar,
   margins, padding) would wrap each one in a second box inside its card. Reset
   only those frame props here — placed after .discussion-card-body so it wins on
   source order — leaving the prose styling (p/h1–h3/ul/ol/blockquote/code) and
   word-wrap/position from rule 1536 intact. */
.discussion-card-body.bot-message,
.discussion-synthesis-body.bot-message {
    margin: 0;
    max-width: none;
    padding: 0;
    border: 0;
    border-radius: 0;
    background: transparent;
}
.discussion-card-body.bot-message::before,
.discussion-synthesis-body.bot-message::before { content: none; }

.discussion-consensus-chip {
    display: inline-block;
    margin-top: 8px;
    font-size: 11px;
    color: var(--text-secondary);
    border: 1px solid var(--border-subtle);
    border-radius: 999px;
    padding: 2px 10px;
}
.discussion-consensus-chip.is-converged {
    color: var(--accent);
    border-color: var(--accent-ring);
    background: var(--accent-soft);
}

.discussion-synthesis {
    margin-top: 14px;
    border: 1px solid var(--accent-ring);
    border-radius: 10px;
    padding: 10px 14px;
    background: var(--accent-soft);
}
.discussion-synthesis.is-streaming { box-shadow: inset 0 0 0 1px var(--accent-ring); }
.discussion-synthesis-head {
    font-weight: 600;
    font-size: 12px;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--accent);
    margin-bottom: 4px;
}
.discussion-synthesis-body { font-size: 14px; }

/* "Continue as a normal chat with <synthesizer>?" footer action — the explicit,
   user-driven conversion that replaced the old silent one-shot auto-revert. A
   quiet prompt below the synthesis, not a loud call-to-action. */
.discussion-convert {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 10px;
    margin-top: 10px;
    padding: 8px 12px;
    border: 1px dashed var(--border-subtle);
    border-radius: 10px;
}
.discussion-convert-msg {
    font-size: 13px;
    color: var(--text-secondary);
    flex: 1 1 220px;
}
.discussion-convert-btn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    white-space: nowrap;
    font-size: 12px;
    font-weight: 500;
    padding: 5px 12px;
    border-radius: 999px;
    border: 1px solid var(--accent-ring);
    color: var(--accent);
    background: var(--accent-soft);
    cursor: pointer;
}
.discussion-convert-btn:hover { filter: brightness(1.08); }
.discussion-convert-btn:disabled { opacity: .6; cursor: default; }

/* Setup modal — participant rows + section titles. */
.discussion-section-title {
    font-size: 13px;
    font-weight: 600;
    color: var(--text-primary);
    margin-bottom: 8px;
}
.discussion-participants {
    display: flex;
    flex-direction: column;
    gap: 10px;
}
.discussion-participant-row {
    border: 1px solid var(--border-subtle);
    border-radius: 10px;
    padding: 8px 10px;
}
.discussion-participant-head {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 6px;
}
.discussion-participant-letter {
    font-weight: 600;
    font-size: 12px;
    color: var(--text-muted, var(--text-secondary));
    width: 18px;
    text-align: center;
    flex-shrink: 0;
}
.discussion-participant-head .discussion-p-label { max-width: 160px; }
.discussion-participant-head .discussion-p-model { flex: 1; min-width: 140px; }
.discussion-participant-head .discussion-p-reasoning { max-width: 130px; }
.discussion-participant-head .discussion-p-temp { width: 70px; flex-shrink: 0; }
.discussion-p-remove { flex-shrink: 0; }

/* Team builder — custom-member extras on the shared participant editor row.
   Scoped to #team-form-members so the in-chat discussion roster is untouched
   (it passes none of the showIcon/showReorder/showPromote opts anyway). The
   head can carry more controls here, so let it wrap on narrow widths. */
#team-form-members .discussion-participant-head { flex-wrap: wrap; }
.discussion-p-custom-badge {
    font-size: 10px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--text-muted, var(--text-secondary));
    background: var(--border-subtle);
    border-radius: 6px;
    padding: 1px 6px;
    flex-shrink: 0;
}
.discussion-p-icon {
    flex-shrink: 0;
    width: 30px;
    padding: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
}
.discussion-p-icon-img {
    width: 22px;
    height: 22px;
    border-radius: 50%;
    object-fit: cover;
}
.discussion-p-drag-handle {
    display: inline-flex;
    align-items: center;
    flex-shrink: 0;
    padding: 0 4px;
    color: var(--bs-secondary-color, #888);
    cursor: grab;
}
.discussion-p-drag-handle:active { cursor: grabbing; }
.discussion-p-promote { flex-shrink: 0; white-space: nowrap; }

/* =====================================================================
 * Dedicated discussion surface — sidebar badge, roster strip, popover
 * editor, stacked transcript, and composer/topbar control hiding.
 * =================================================================== */

/* Sidebar: people-icon ribbon marking discussion rows in the chat list. */
.chat-kind-badge {
    display: none;
    flex-shrink: 0;
    font-size: 12px;
    color: var(--accent);
    margin-right: 2px;
}
#chat-list .list-group-item.is-discussion-chat .chat-kind-badge { display: inline-flex; }

/* On the discussion surface, the per-message model controls don't apply
 * (models are per-participant) — hide them along with the N-picker. */
body.discussion-surface #model-control-group,
body.discussion-surface #reasoning-container,
body.discussion-surface #temperature-container,
body.discussion-surface .composer-n-picker { display: none !important; }
/* Discuss is armed for this chat (per-chat toggle on, or an active discussion):
 * the parallel-response count is meaningless — the roster defines parallelism. */
body.discuss-armed .composer-n-picker { display: none !important; }
/* The single-model context meter (and its Compact button) targets the leftover
 * "active model" that isn't a discussion participant — misleading here. */
body.discussion-surface .context-meter-wrap { display: none !important; }

/* Image-generation mode: an image-gen model is selected. The chat-only
 * controls (reasoning / temperature) and the N-picker don't apply —
 * the per-model image-options row takes their place. The model picker stays. */
body[data-image-model] #reasoning-container,
body[data-image-model] #temperature-container,
body[data-image-model] .composer-n-picker { display: none !important; }

/* Search doesn't apply on the discussion or image-generation surfaces, so
 * hide the composer search button there (it lives in the message bar now). */
body.discussion-surface #composer-search-btn,
body[data-image-model] #composer-search-btn { display: none !important; }

/* ===================================================================
 * Unified search: composer 🔍 button + its popover. The button is a
 * .composer-attach variant that grows to fit an inline mode label when a
 * mode is active; the popover (mirroring .files-popover) hosts the relocated
 * segmented controls.
 * =================================================================== */
.composer-search-btn {
    width: auto;
    min-width: 32px;
    border-radius: 999px;
    gap: 5px;
    padding: 0 9px;
}
.composer-search-btn.active {
    background: var(--accent-soft);
    color: var(--accent);
}
.composer-search-btn.active:hover { background: var(--accent-soft); }
.composer-search-btn[aria-expanded="true"] {
    background: var(--accent-soft);
    color: var(--accent);
}
.composer-search-label {
    font-size: 12px;
    font-weight: 500;
    white-space: nowrap;
}
.composer-search-label[hidden] { display: none; }

/* Per-chat RAG (notebook retrieval) toggle — mirrors the search button's
 * pill shape + active highlight. Hidden unless the active chat is in a
 * RAG-enabled notebook (toggled from the renderer). */
.composer-rag-btn {
    width: auto;
    min-width: 32px;
    border-radius: 999px;
    gap: 5px;
    padding: 0 9px;
}
.composer-rag-btn[hidden] { display: none; }
.composer-rag-btn.active {
    background: var(--accent-soft);
    color: var(--accent);
}
.composer-rag-btn.active:hover { background: var(--accent-soft); }
.composer-rag-label {
    font-size: 12px;
    font-weight: 500;
    white-space: nowrap;
}
.composer-rag-label[hidden] { display: none; }
/* RAG retrieval, like search, is moot on the discussion/image surfaces. */
body.discussion-surface #composer-rag-btn,
body[data-image-model] #composer-rag-btn { display: none !important; }

/* Per-chat "run my messages as a discussion" toggle — mirrors the RAG button's
 * pill shape + active highlight. Shown in any chat when Discussions are enabled
 * (toggled from the renderer). Unlike RAG/search it must stay usable on the
 * discussion surface (so a discussion chat can be toggled back off), so it is
 * NOT hidden on body.discussion-surface — only on image models. */
.composer-discuss-btn {
    width: auto;
    min-width: 32px;
    border-radius: 999px;
    gap: 5px;
    padding: 0 9px;
}
.composer-discuss-btn[hidden] { display: none; }
.composer-discuss-btn.active {
    background: var(--accent-soft);
    color: var(--accent);
}
.composer-discuss-btn.active:hover { background: var(--accent-soft); }
/* Inside an active discussion the button is a status badge, but clicking (or
   right-clicking) it opens a menu — "Discussion settings…" + "Continue as
   normal chat" — so it must read as interactive. Keep the pointer cursor and
   add a caret to signal the menu. */
.composer-discuss-btn.discuss-status { cursor: pointer; }
.composer-discuss-btn.discuss-status::after {
    content: '';
    display: inline-block;
    width: 0;
    height: 0;
    margin-left: 1px;
    border-left: 3.5px solid transparent;
    border-right: 3.5px solid transparent;
    border-top: 4px solid currentColor;
    opacity: 0.7;
}
.composer-discuss-btn.discuss-status:hover { background: var(--accent-soft); }
.composer-discuss-label {
    font-size: 12px;
    font-weight: 500;
    white-space: nowrap;
}
.composer-discuss-label[hidden] { display: none; }
/* Discussions are single-send-incompatible with image generation only. */
body[data-image-model] #composer-discuss-btn { display: none !important; }

/* Director plan preview modal. */
.director-question {
    font-size: 13px;
    font-style: italic;
    margin-bottom: 12px;
    padding: 8px 12px;
    border-left: 3px solid var(--accent, #5B8DEF);
    background: var(--accent-soft, rgba(91, 141, 239, 0.08));
    border-radius: 4px;
}
.director-planning {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 28px 4px;
    color: var(--muted, #888);
    font-size: 14px;
}
.director-controls {
    display: flex;
    align-items: center;
    gap: 22px;
    flex-wrap: wrap;
    margin-bottom: 14px;
}
.director-mode-row {
    display: flex;
    align-items: center;
    gap: 10px;
}
.director-rounds-row {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 0;
}
.director-rounds-input { width: 72px; }
.director-roster {
    display: flex;
    flex-direction: column;
    gap: 12px;
    margin-bottom: 12px;
}

.search-popover {
    position: absolute;
    z-index: 1100;
    min-width: 220px;
    background: var(--bg-elevated);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-soft);
    padding: 10px;
    display: flex;
    flex-direction: column;
    gap: 10px;
}
.search-popover[hidden] { display: none; }
.search-popover-section {
    display: flex;
    flex-direction: column;
    gap: 6px;
}
.search-popover-section[hidden] { display: none; }
.search-popover-hint {
    font-size: 11px;
    line-height: 1.4;
    color: var(--text-tertiary);
}
.search-popover-hint[hidden] { display: none; }

/* "Quellen / Sources" list rendered beneath an assistant answer from a
 * search turn. Web sources show title + date; intranet sources add a
 * collapsible content snippet. */
.bot-sources {
    margin-top: 12px;
    padding-top: 10px;
    border-top: 1px solid var(--border-subtle);
}
.bot-sources-header {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--text-tertiary);
    margin-bottom: 6px;
}
.bot-sources-header .bi { font-size: 12px; color: var(--accent); }
.bot-sources-list {
    margin: 0;
    padding-left: 20px;
    display: flex;
    flex-direction: column;
    gap: 6px;
}
.bot-sources-item {
    font-size: 13px;
    line-height: 1.4;
    color: var(--text-secondary);
}
.bot-sources-link {
    color: var(--accent);
    text-decoration: none;
    word-break: break-word;
}
a.bot-sources-link:hover { text-decoration: underline; }
.bot-sources-date {
    margin-left: 8px;
    font-size: 11px;
    color: var(--text-tertiary);
    white-space: nowrap;
}
/* RAG chunk location appended after a source title ("— p.4 · §Methods"). */
.bot-sources-loc {
    color: var(--text-tertiary);
    font-variant-numeric: tabular-nums;
}
.bot-sources-snippet {
    margin-top: 3px;
    font-size: 12px;
}
.bot-sources-snippet > summary {
    cursor: pointer;
    color: var(--text-tertiary);
    font-size: 11px;
    user-select: none;
}
.bot-sources-snippet > summary:hover { color: var(--text-secondary); }
.bot-sources-snippet-body {
    margin-top: 4px;
    padding: 6px 8px;
    border-left: 2px solid var(--border-subtle);
    color: var(--text-secondary);
    background: var(--bg-elevated);
    border-radius: var(--radius-sm);
    white-space: pre-wrap;
}

/* Expandable "RAG steps" card — sits at the top of an assistant bubble (just
   under the meta strip) and walks the retrieval pipeline. Mirrors the
   .bot-sources look (subtle bordered card, uppercase tracked header) and the
   RAG-progress palette (accent / border-subtle / tabular-nums scores). */
.rag-trace-card {
    margin: 4px 0 12px;
    padding: 6px 10px;
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-sm);
    background: var(--bg-elevated);
    font-size: 12px;
}
.rag-trace-summary {
    display: flex;
    align-items: center;
    gap: 6px;
    cursor: pointer;
    user-select: none;
    list-style: none;
    color: var(--text-secondary);
}
.rag-trace-summary::-webkit-details-marker { display: none; }
.rag-trace-glyph { font-size: 12px; line-height: 1; }
.rag-trace-summary-label {
    font-size: 10px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--accent);
}
.rag-trace-summary-text { color: var(--text-secondary); }
.rag-trace-card.is-empty .rag-trace-summary-text { color: var(--text-tertiary); }
.rag-trace-body {
    margin-top: 8px;
    padding-top: 8px;
    border-top: 1px solid var(--border-subtle);
    display: flex;
    flex-direction: column;
    gap: 10px;
}
.rag-trace-steps {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 5px;
}
.rag-trace-step {
    display: grid;
    grid-template-columns: 10px auto 1fr;
    align-items: baseline;
    gap: 8px;
    line-height: 1.4;
}
.rag-trace-dot {
    width: 7px;
    height: 7px;
    border-radius: 50%;
    align-self: center;
    background: var(--text-tertiary);
}
.rag-trace-step.is-ok .rag-trace-dot { background: var(--accent); }
.rag-trace-step.is-empty .rag-trace-dot,
.rag-trace-step.is-skip .rag-trace-dot { background: var(--text-tertiary); }
.rag-trace-step.is-error .rag-trace-dot { background: var(--danger); }
.rag-trace-step-label {
    font-weight: 600;
    color: var(--text-secondary);
    white-space: nowrap;
}
.rag-trace-step-detail { color: var(--text-tertiary); }
.rag-trace-section-head {
    font-size: 10px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--text-tertiary);
    margin-bottom: 5px;
}
.rag-trace-chunks {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 4px;
}
.rag-trace-chunk {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 8px;
    color: var(--text-secondary);
}
.rag-trace-chunk-title {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.rag-trace-chunk-kind {
    font-size: 10px;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--text-tertiary);
}
/* Per-chunk source location (page / section), shown after the chunk title in
   the retrieval-steps card. Empty for legacy (loc = NULL) chunks. */
.rag-trace-chunk-loc {
    font-size: 11px;
    color: var(--text-tertiary);
    white-space: nowrap;
    flex: 0 0 auto;
}
.rag-trace-chunk-score {
    font-variant-numeric: tabular-nums;
    color: var(--accent);
    white-space: nowrap;
}
.rag-trace-chunk-tokens {
    font-variant-numeric: tabular-nums;
    color: var(--text-tertiary);
    white-space: nowrap;
}
/* Full included passage text under a chunk's metadata row — collapsed by
   default, full-width (flex-basis 100% forces a wrap onto its own line so it
   sits below the title/loc/score row). Styled like .bot-sources-snippet:
   small, indented, scrollable so a long passage doesn't crowd the card. */
.rag-trace-chunk-text {
    flex: 1 1 100%;
    margin-top: 2px;
    font-size: 12px;
}
.rag-trace-chunk-text > summary {
    cursor: pointer;
    color: var(--text-tertiary);
    font-size: 11px;
    user-select: none;
}
.rag-trace-chunk-text > summary:hover { color: var(--text-secondary); }
.rag-trace-chunk-text-body {
    margin-top: 4px;
    padding: 6px 8px;
    border-left: 2px solid var(--border-subtle);
    color: var(--text-secondary);
    background: var(--bg-elevated);
    border-radius: var(--radius-sm);
    white-space: pre-wrap;
    max-height: 280px;
    overflow: auto;
}
/* Card actions row (Download prompt). Quiet bordered button, accent on hover. */
.rag-trace-actions {
    display: flex;
    justify-content: flex-end;
}
.rag-trace-download-btn {
    display: inline-flex;
    align-items: center;
    gap: 2px;
    padding: 3px 8px;
    font-size: 11px;
    color: var(--text-secondary);
    background: transparent;
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-sm);
    cursor: pointer;
}
.rag-trace-download-btn:hover {
    color: var(--accent);
    border-color: var(--accent);
}
.rag-trace-download-btn:disabled {
    opacity: 0.5;
    cursor: default;
}
.rag-trace-meta {
    font-size: 11px;
    color: var(--text-tertiary);
    font-variant-numeric: tabular-nums;
}

/* Inline [docN] search-citation markers → small superscript chips linking
   back to the matching "Quellen / Sources" entry. */
.cite-ref {
    font-size: 0.7em;
    line-height: 0;
    vertical-align: super;
    margin: 0 1px;
}
.cite-ref a {
    color: var(--accent);
    text-decoration: none;
    padding: 0 1px;
}
.cite-ref a:hover { text-decoration: underline; }

.image-options-row {
    display: flex;
    align-items: center;
    gap: 14px;
    flex-wrap: wrap;
}
.image-options-row[hidden] { display: none; }
.image-options-row .image-option {
    display: flex;
    align-items: center;
    gap: 6px;
}
.image-options-row .image-option-number {
    width: 88px;
}
/* Reuse the chat controls' input chrome for the number field. */
.image-options-row .control-input {
    background: var(--bg-input, var(--bg-elevated));
    color: var(--text-primary);
    border: 1px solid var(--border-subtle);
    border-radius: 8px;
    padding: 4px 8px;
    font-size: 13px;
    line-height: 1.4;
}
.image-options-row .control-input:hover { border-color: var(--border-strong); }
.image-options-row .control-input:focus {
    outline: none;
    border-color: var(--accent, var(--border-strong));
}

/* Roster strip — editable participant cards pinned above the stacked
 * transcript. Lives inside the scrolling #chat-container as a sticky first
 * child so it stays visible while the transcript scrolls beneath it. */
.discussion-roster {
    position: sticky;
    top: 0;
    z-index: 5;
    border-bottom: 1px solid var(--border-subtle);
    background: var(--bg-elevated);
    padding: 10px 16px;
    display: flex;
    flex-direction: column;
    gap: 8px;
}
.discussion-roster[hidden] { display: none; }
.discussion-roster-eyebrow {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 11px;
    letter-spacing: .08em;
    font-weight: 600;
    text-transform: uppercase;
    color: var(--text-muted, var(--text-secondary));
}
.discussion-roster-cards {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}
.discussion-roster-card {
    --tint: var(--tab-tint-accent);
    display: flex;
    align-items: center;
    gap: 8px;
    border: 1px solid var(--border-subtle);
    border-left: 3px solid var(--tint);
    border-radius: 8px;
    background: var(--bg-base, transparent);
    padding: 6px 10px;
    min-width: 160px;
    cursor: pointer;
    text-align: left;
    transition: background-color .12s, box-shadow .12s;
}
.discussion-roster-card:hover { background: var(--border-subtle); }
.discussion-roster-card[data-tint="accent"]     { --tint: var(--tab-tint-accent); }
.discussion-roster-card[data-tint="blue"]       { --tint: var(--tab-tint-blue); }
.discussion-roster-card[data-tint="violet"]     { --tint: var(--tab-tint-violet); }
.discussion-roster-card[data-tint="terracotta"] { --tint: var(--tab-tint-terracotta); }
.discussion-roster-card[data-tint="amber"]      { --tint: var(--tab-tint-amber); }
.discussion-roster-card[data-tint="teal"]       { --tint: var(--tab-tint-teal); }
.discussion-roster-card-letter {
    font-weight: 700;
    font-size: 12px;
    color: var(--tint);
    width: 16px;
    text-align: center;
    flex-shrink: 0;
}
.discussion-roster-card-meta { display: flex; flex-direction: column; line-height: 1.2; }
.discussion-roster-card-name { font-size: 13px; font-weight: 600; color: var(--text-primary); }
.discussion-roster-card-model { font-size: 11px; color: var(--text-muted, var(--text-secondary)); }
.discussion-roster-actions { display: flex; gap: 8px; align-items: center; }
.discussion-roster-add,
.discussion-roster-settings {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    border: 1px dashed var(--border-subtle);
    border-radius: 8px;
    background: transparent;
    color: var(--text-secondary);
    padding: 5px 10px;
    font-size: 12px;
    cursor: pointer;
    transition: background-color .12s, color .12s;
}
.discussion-roster-add:hover:not(:disabled),
.discussion-roster-settings:hover { background: var(--border-subtle); color: var(--text-primary); }
.discussion-roster-add:disabled { opacity: .5; cursor: not-allowed; }
.discussion-roster-settings { border-style: solid; }

/* Chevron that collapses/expands the roster. Mirrors the overview chevron:
   transparent ghost button, rotates with state. The eyebrow row owns it, so
   push it to the right edge with margin-left:auto. */
.discussion-roster-toggle {
    margin-left: auto;
    flex: 0 0 18px;
    width: 18px;
    height: 18px;
    padding: 0;
    border: 0;
    background: transparent;
    color: var(--text-tertiary);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: color .12s ease;
}
.discussion-roster-toggle:hover { color: var(--accent); }

/* Collapsed state: a single compact row — eyebrow + letter-only cards + chevron.
   The markup is unchanged; we just hide the editor affordances and shrink the
   cards to their A/B/C letters. */
.discussion-roster.is-collapsed {
    flex-direction: row;
    align-items: center;
    flex-wrap: wrap;
    gap: 10px;
    padding-top: 6px;
    padding-bottom: 6px;
}
.discussion-roster.is-collapsed .discussion-roster-eyebrow { flex: 0 0 auto; }
.discussion-roster.is-collapsed .discussion-roster-toggle { margin-left: 0; }
.discussion-roster.is-collapsed .discussion-roster-cards { gap: 6px; }
.discussion-roster.is-collapsed .discussion-roster-card {
    min-width: 0;
    padding: 4px 8px;
    gap: 0;
}
.discussion-roster.is-collapsed .discussion-roster-card-meta { display: none; }
.discussion-roster.is-collapsed .discussion-roster-actions { display: none; }

/* Floating popover editor (participant fields / discussion settings). */
.discussion-popover {
    position: fixed;
    z-index: 1080;
    width: 340px;
    max-width: calc(100vw - 24px);
    max-height: calc(100vh - 80px);
    overflow-y: auto;
    background: var(--bg-elevated);
    border: 1px solid var(--border-subtle);
    border-radius: 12px;
    box-shadow: 0 12px 32px rgba(0, 0, 0, .28);
    padding: 0;
}
.discussion-popover-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 10px 12px;
    border-bottom: 1px solid var(--border-subtle);
}
.discussion-popover-title { font-size: 13px; font-weight: 600; color: var(--text-primary); }
.discussion-popover-close {
    border: 0;
    background: transparent;
    color: var(--text-secondary);
    cursor: pointer;
    font-size: 13px;
    padding: 2px 4px;
    border-radius: 6px;
}
.discussion-popover-close:hover { background: var(--border-subtle); color: var(--text-primary); }
.discussion-popover-body { padding: 12px; }
.discussion-popover-body .discussion-participant-row { border: 0; padding: 0; }
.discussion-popover-body .discussion-participant-head {
    flex-wrap: wrap;
    gap: 6px;
}
.discussion-popover-body .discussion-participant-head .discussion-p-label { max-width: none; flex: 1 1 100%; }
.discussion-popover-body .discussion-participant-head .discussion-p-model { flex: 1 1 100%; }
.discussion-settings-group { margin-bottom: 14px; }
.discussion-settings-group:last-child { margin-bottom: 0; }
.discussion-settings-label {
    font-size: 11px;
    letter-spacing: .04em;
    text-transform: uppercase;
    font-weight: 600;
    color: var(--text-muted, var(--text-secondary));
    margin-bottom: 6px;
}
.discussion-settings-field {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 6px;
}
.discussion-settings-field > span {
    flex: 0 0 110px;
    font-size: 12px;
    color: var(--text-secondary);
}
.discussion-settings-field > select,
.discussion-settings-field > input { flex: 1; }
.discussion-settings-field-wide { flex-direction: column; align-items: stretch; gap: 4px; }
.discussion-settings-field-wide > span { flex: none; }

/* ---- Guided discussion setup (empty-surface walk-through) ---- */
.discussion-setup {
    max-width: 760px;
    margin: 8px auto 24px;
    padding: 4px 8px;
    display: flex;
    flex-direction: column;
    gap: 22px;
}
.discussion-setup-section { display: flex; flex-direction: column; gap: 10px; }
.discussion-setup-section-title {
    font-size: 14px;
    font-weight: 600;
    color: var(--text-primary);
}
.discussion-setup-section-sub { font-size: 12px; color: var(--text-secondary); margin-top: -4px; }
.discussion-setup-empty {
    font-size: 13px;
    color: var(--text-secondary);
    padding: 16px;
    border: 1px dashed var(--border-subtle);
    border-radius: 10px;
}

/* Setup-mode segmented control (Use a team / Manual) */
.discussion-mode-toggle { display: flex; gap: 8px; }

/* Team mode: team picker + read-only locked summary */
.discussion-team-select { max-width: 320px; }
.discussion-team-locked {
    margin-top: 10px;
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding: 12px 14px;
    border: 1px solid var(--border-subtle);
    border-radius: 10px;
    background: color-mix(in srgb, var(--tab-tint-accent) 5%, transparent);
}
.discussion-team-locked-meta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px;
    font-size: 12px;
    color: var(--text-secondary);
}

/* Strategy radio cards */
.discussion-strategy-cards { display: flex; flex-direction: column; gap: 8px; }
.discussion-strategy-card {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    text-align: left;
    border: 1px solid var(--border-subtle);
    border-radius: 10px;
    background: var(--bg-base, transparent);
    padding: 12px 14px;
    cursor: pointer;
    transition: border-color .12s, background-color .12s;
}
.discussion-strategy-card:hover { background: var(--border-subtle); }
.discussion-strategy-card.is-selected {
    border-color: var(--tab-tint-accent);
    background: color-mix(in srgb, var(--tab-tint-accent) 8%, transparent);
}
.discussion-strategy-card-radio {
    flex-shrink: 0;
    width: 16px;
    height: 16px;
    margin-top: 2px;
    border-radius: 50%;
    border: 2px solid var(--border-strong, var(--text-muted, var(--text-secondary)));
    transition: border-color .12s;
}
.discussion-strategy-card.is-selected .discussion-strategy-card-radio {
    border-color: var(--tab-tint-accent);
    background:
        radial-gradient(circle, var(--tab-tint-accent) 0 4px, transparent 5px);
}
.discussion-strategy-card-text { display: flex; flex-direction: column; gap: 2px; }
.discussion-strategy-card-title { font-size: 13px; font-weight: 600; color: var(--text-primary); }
.discussion-strategy-card-sub { font-size: 12px; color: var(--text-secondary); }
.discussion-rounds-row { display: inline-flex; align-items: center; gap: 8px; font-size: 13px; }
.discussion-rounds-row > span { color: var(--text-secondary); }
.discussion-rounds-input { width: 72px; }

/* Slot-based agent picker (Manual mode) */
.discussion-slot-row {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 8px;
}
.discussion-slot-caption {
    flex-shrink: 0;
    width: 52px;
    font-size: 12px;
    font-weight: 600;
    color: var(--text-secondary);
}
.discussion-slot-select { flex: 1 1 auto; min-width: 0; }
.discussion-slot-remove {
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 30px;
    height: 30px;
    border: 1px solid var(--border-subtle);
    border-radius: 8px;
    background: var(--bg-base, transparent);
    color: var(--text-secondary);
    cursor: pointer;
    transition: background-color .12s, border-color .12s, color .12s;
}
.discussion-slot-remove:hover:not([disabled]) {
    background: var(--border-subtle);
    color: var(--text-primary);
}
.discussion-slot-remove[disabled] { opacity: .4; cursor: default; }
.discussion-slot-add {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    border: 1px dashed var(--border-subtle);
    border-radius: 8px;
    background: var(--bg-base, transparent);
    padding: 6px 12px;
    font-size: 13px;
    color: var(--text-secondary);
    cursor: pointer;
    transition: background-color .12s, border-color .12s, color .12s;
}
.discussion-slot-add:hover:not([disabled]) {
    background: var(--border-subtle);
    color: var(--text-primary);
}
.discussion-slot-add[disabled] { opacity: .4; cursor: default; }

/* The Advanced toggle inside Manual: a checkbox + label sitting just under the
   "Choose your agents/participants" section heading. */
.discussion-advanced-toggle {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 2px 0 10px;
    font-size: 13px;
    color: var(--text-secondary);
    cursor: pointer;
}
.discussion-advanced-toggle input { margin: 0; cursor: pointer; }

/* Advanced mode: the "Add participant / Add custom participant" buttons sit in
   a wrapping row beneath the editor rows. */
.discussion-advanced-add {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin-top: 8px;
}

/* Auto mode: a calm explanatory panel (no roster/strategy). */
.discussion-auto-explain {
    display: flex;
    gap: 12px;
    align-items: flex-start;
    padding: 14px 16px;
    border: 1px solid var(--border);
    border-radius: 10px;
    background: var(--accent-soft);
}
.discussion-auto-explain-icon {
    font-size: 22px;
    line-height: 1;
    color: var(--accent);
    flex: 0 0 auto;
    margin-top: 1px;
}
.discussion-auto-explain-text p { margin: 0 0 6px; font-size: 13px; }
.discussion-auto-explain-text p:last-child { margin-bottom: 0; color: var(--text-secondary); }
/* The full editor rows are taller than the simple slot rows; give them a little
   breathing room when stacked in the (narrower) guided setup panel. */
.discussion-setup .discussion-participant-row + .discussion-participant-row {
    margin-top: 8px;
}

/* Final-answer-by */
.discussion-synth-opts { display: flex; gap: 8px; }
.discussion-radio-pill {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    border: 1px solid var(--border-subtle);
    border-radius: 999px;
    background: var(--bg-base, transparent);
    padding: 6px 14px;
    font-size: 13px;
    color: var(--text-primary);
    cursor: pointer;
    transition: border-color .12s, background-color .12s;
}
.discussion-radio-pill:hover { background: var(--border-subtle); }
.discussion-radio-pill.is-selected {
    border-color: var(--tab-tint-accent);
    background: color-mix(in srgb, var(--tab-tint-accent) 8%, transparent);
}
.discussion-radio-pill-dot {
    width: 12px;
    height: 12px;
    border-radius: 50%;
    border: 2px solid var(--border-strong, var(--text-muted, var(--text-secondary)));
}
.discussion-radio-pill.is-selected .discussion-radio-pill-dot {
    border-color: var(--tab-tint-accent);
    background: radial-gradient(circle, var(--tab-tint-accent) 0 3px, transparent 4px);
}
.discussion-synth-select { max-width: 280px; margin-top: 4px; }

/* Status line / Start gating */
.discussion-setup-status {
    font-size: 13px;
    padding: 10px 12px;
    border-radius: 8px;
    border: 1px solid var(--border-subtle);
}
.discussion-setup-status.is-incomplete { color: var(--text-secondary); }
/* "Ready" uses --accent (not the teal identity tint) so it inherits the
   discussion-surface violet override — this panel only ever renders inside
   #chat-container, where --accent is violet. */
.discussion-setup-status.is-ready {
    color: var(--text-primary);
    border-color: color-mix(in srgb, var(--accent) 40%, var(--border-subtle));
    background: color-mix(in srgb, var(--accent) 8%, transparent);
}
/* "≈ 10 requests · about 2–4 min" under the status line / in the Director
   preview — runs are paced for fair use of the gateway, so set expectations. */
.discussion-setup-estimate,
.director-estimate {
    margin-top: 6px;
    font-size: 12px;
    color: var(--text-secondary);
}
.director-estimate { margin: -6px 0 12px; }
/* Live "Round 2/3 · ~1 min left · next speaker in 8s…" line at the bottom of
   a streaming discussion block; gone once the run stops streaming. */
.discussion-progress {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 8px 2px 2px;
    font-size: 12px;
    color: var(--text-secondary);
}
.discussion-progress[hidden],
.discussion-set:not([data-streaming]) .discussion-progress { display: none; }
.discussion-setup-status.is-flash {
    border-color: var(--tab-tint-terracotta);
    animation: discussion-status-flash .4s ease;
}
@keyframes discussion-status-flash {
    0%, 100% { transform: translateX(0); }
    25% { transform: translateX(-4px); }
    75% { transform: translateX(4px); }
}

/* ---- Compact read-only summary (running discussion top bar) ---- */
.discussion-summary-body {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 12px;
}
.discussion-summary-avatars { display: flex; flex-wrap: wrap; gap: 6px; }
.discussion-summary-chip {
    --tint: var(--tab-tint-accent);
    display: inline-flex;
    align-items: center;
    gap: 6px;
    border: 1px solid var(--border-subtle);
    border-left: 3px solid var(--tint);
    border-radius: 999px;
    padding: 3px 10px 3px 7px;
    font-size: 12px;
}
.discussion-summary-chip[data-tint="accent"]     { --tint: var(--tab-tint-accent); }
.discussion-summary-chip[data-tint="blue"]       { --tint: var(--tab-tint-blue); }
.discussion-summary-chip[data-tint="violet"]     { --tint: var(--tab-tint-violet); }
.discussion-summary-chip[data-tint="terracotta"] { --tint: var(--tab-tint-terracotta); }
.discussion-summary-chip[data-tint="amber"]      { --tint: var(--tab-tint-amber); }
.discussion-summary-chip[data-tint="teal"]       { --tint: var(--tab-tint-teal); }
.discussion-summary-letter { font-weight: 700; color: var(--tint); width: 14px; text-align: center; }
img.agent-avatar.discussion-summary-avatar,
.discussion-summary-avatar { width: 18px; height: 18px; }
.discussion-summary-name { font-weight: 600; color: var(--text-primary); }
.discussion-summary-model { color: var(--text-muted, var(--text-secondary)); font-size: 11px; }
.discussion-summary-meta {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 12px;
    color: var(--text-secondary);
}
.discussion-summary-sep { color: var(--text-muted, var(--text-secondary)); }

/* Stacked transcript — one chronological stream of turns grouped by round;
 * each card color-coded per agent (tinted left edge + colored letter/name).
 * Consensus chips sit under their round; synthesis + notices below. */
.discussion-stream {
    display: flex;
    flex-direction: column;
    gap: 14px;
}
.discussion-round-group {
    display: flex;
    flex-direction: column;
    gap: 10px;
}
.discussion-stacked .discussion-card {
    border-left: 3px solid var(--tint, var(--border-subtle));
}
.discussion-stacked .discussion-card[data-tint="accent"]     { --tint: var(--tab-tint-accent); }
.discussion-stacked .discussion-card[data-tint="blue"]       { --tint: var(--tab-tint-blue); }
.discussion-stacked .discussion-card[data-tint="violet"]     { --tint: var(--tab-tint-violet); }
.discussion-stacked .discussion-card[data-tint="terracotta"] { --tint: var(--tab-tint-terracotta); }
.discussion-stacked .discussion-card[data-tint="amber"]      { --tint: var(--tab-tint-amber); }
.discussion-stacked .discussion-card[data-tint="teal"]       { --tint: var(--tab-tint-teal); }
.discussion-card-letter {
    font-weight: 700;
    font-size: 12px;
    color: var(--tint, var(--text-secondary));
    width: 16px;
    text-align: center;
    flex-shrink: 0;
}
.discussion-below { margin-top: 12px; display: flex; flex-direction: column; gap: 8px; }
.discussion-below .discussion-consensus-chip { align-self: flex-start; margin-top: 0; }
.discussion-below .discussion-synthesis { margin-top: 2px; }

/* ============================================================
   Vote mode (Council): scoreboard headline + collapsed debate.
   Reuses the discussion card/tint vocabulary above.
   ============================================================ */
.discussion-headline { display: flex; flex-direction: column; gap: 12px; }
.discussion-vote .discussion-synthesis { margin-top: 0; }

/* The round-by-round debate collapses below the headline. */
.discussion-debate { margin-top: 14px; }
.discussion-debate-toggle {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 12px;
    font-weight: 600;
    color: var(--text-secondary);
    background: none;
    border: 0;
    padding: 4px 0;
    cursor: pointer;
}
.discussion-debate-toggle:hover { color: var(--text-primary); }
.discussion-debate-toggle i { font-size: 11px; }
.discussion-debate.is-collapsed .discussion-stream { display: none; }

/* Scoreboard: one group per ballot option; the winner is highlighted. */
.discussion-scoreboard {
    display: flex;
    flex-direction: column;
    gap: 10px;
}
.discussion-scoreboard-status {
    font-size: 12px;
    color: var(--text-muted, var(--text-secondary));
}
.scoreboard-option {
    border: 1px solid var(--border-subtle);
    border-radius: 10px;
    padding: 10px 12px;
}
.scoreboard-option.is-winner {
    border-color: var(--accent-ring);
    background: var(--accent-soft);
}
.scoreboard-option.scoreboard-abstained { opacity: .8; }
.scoreboard-option-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 10px;
    margin-bottom: 8px;
}
.scoreboard-option-label {
    font-weight: 600;
    font-size: 14px;
    color: var(--text-primary);
}
.scoreboard-option.is-winner .scoreboard-option-label { color: var(--accent); }
.scoreboard-option-count {
    flex-shrink: 0;
    font-weight: 700;
    font-size: 13px;
    color: var(--text-secondary);
    background: var(--bg-input);
    border-radius: 999px;
    min-width: 22px;
    text-align: center;
    padding: 1px 8px;
}
.scoreboard-option.is-winner .scoreboard-option-count {
    color: var(--accent);
    background: color-mix(in srgb, var(--accent) 14%, transparent);
}
.scoreboard-voters {
    display: flex;
    flex-direction: column;
    gap: 8px;
}
.scoreboard-voter {
    border-left: 3px solid var(--tint, var(--border-subtle));
    padding: 2px 0 2px 10px;
}
.scoreboard-voter[data-tint="accent"]     { --tint: var(--tab-tint-accent); }
.scoreboard-voter[data-tint="blue"]       { --tint: var(--tab-tint-blue); }
.scoreboard-voter[data-tint="violet"]     { --tint: var(--tab-tint-violet); }
.scoreboard-voter[data-tint="terracotta"] { --tint: var(--tab-tint-terracotta); }
.scoreboard-voter[data-tint="amber"]      { --tint: var(--tab-tint-amber); }
.scoreboard-voter[data-tint="teal"]       { --tint: var(--tab-tint-teal); }
.scoreboard-voter-head {
    display: flex;
    align-items: center;
    gap: 8px;
}
.scoreboard-voter-letter {
    font-weight: 700;
    font-size: 12px;
    color: var(--tint, var(--text-secondary));
    width: 16px;
    text-align: center;
    flex-shrink: 0;
}
.scoreboard-voter-name {
    font-weight: 600;
    font-size: 13px;
    color: var(--text-primary);
}
.scoreboard-voter-badge {
    font-size: 11px;
    color: var(--text-muted, var(--text-secondary));
    background: var(--accent-soft);
    border-radius: 6px;
    padding: 1px 6px;
}
.scoreboard-voter-rationale {
    font-size: 13px;
    color: var(--text-secondary);
    margin-top: 2px;
}

/* Vote ballot options editor in the guided setup. */
.discussion-ballot-options-row { align-items: flex-start; }
.discussion-ballot-options-row textarea { resize: vertical; }

/* ============================================================
   Chat navigation: sidebar Chats|Projects toggle + collapsed
   "Older" row + the full-screen All Chats management view.
   ============================================================ */

/* Sidebar segmented toggle (Chats | Projects) + Manage-chats button */
.sidebar-mode-row {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 8px 10px 4px;
}
.sidebar-mode-seg { flex: 1 1 auto; }
.sidebar-mode-seg .segmented-option { flex: 1 1 0; }
.sidebar-action-row {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 0 10px 6px;     /* sits directly under the toggle row */
}
/* Distribute the 5 actions evenly across the sidebar width */
.sidebar-action-row .sidebar-manage-chats-btn,
.sidebar-action-row .chat-filter-wrap { flex: 1 1 0; }
.sidebar-action-row .sidebar-manage-chats-btn { width: auto; }      /* override fixed 30px */
.sidebar-action-row .chat-filter-wrap > #chat-filter-toggle { width: 100%; }  /* funnel fills its wrap */
.sidebar-manage-chats-btn {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 30px;
    height: 30px;
    border: 1px solid var(--border-subtle);
    background: var(--bg-input);
    color: var(--text-secondary);
    border-radius: var(--radius-sm);
    cursor: pointer;
}
.sidebar-manage-chats-btn:hover { color: var(--text-primary); background: var(--bg-elevated); }

/* All Chats management view — overlays the tab content zone */
body.all-chats-mode #chat-container,
body.all-chats-mode #paper-workspace,
body.all-chats-mode .tab-nav-strip,
body.all-chats-mode #chat-overview,
body.all-chats-mode .topbar,
body.all-chats-mode #tab-strip,
body.all-chats-mode .composer-wrap { display: none !important; }

/* Generated-images gallery view — overlays the tab content zone, same as the
 * All Chats view (body.images-mode + its own [hidden]). */
body.images-mode #chat-container,
body.images-mode #paper-workspace,
body.images-mode .tab-nav-strip,
body.images-mode #chat-overview,
body.images-mode .topbar,
body.images-mode #tab-strip,
body.images-mode .composer-wrap { display: none !important; }

/* Manage-notebook full-screen view — overlays the tab content zone, same
 * mechanism as the All Chats / gallery views (body.notebook-edit-mode + its
 * own [hidden]). */
body.notebook-edit-mode #chat-container,
body.notebook-edit-mode #paper-workspace,
body.notebook-edit-mode .tab-nav-strip,
body.notebook-edit-mode #chat-overview,
body.notebook-edit-mode .topbar,
body.notebook-edit-mode #tab-strip,
body.notebook-edit-mode .composer-wrap { display: none !important; }

/* Library full-screen view — overlays the tab content zone, same mechanism as
 * the All Chats / gallery / notebook views (body.library-mode + its own
 * [hidden]). */
body.library-mode #chat-container,
body.library-mode #paper-workspace,
body.library-mode .tab-nav-strip,
body.library-mode #chat-overview,
body.library-mode .topbar,
body.library-mode #tab-strip,
body.library-mode .composer-wrap { display: none !important; }

.notebook-edit-view {
    flex: 1 1 0;
    min-width: 0;
    min-height: 0;
    display: flex;
    flex-direction: column;
    background: var(--bg-base);
    overflow: hidden;
}
.notebook-edit-view[hidden] { display: none; }
.notebook-edit-header {
    flex: 0 0 auto;
    padding: 14px 18px 10px;
    border-bottom: 1px solid var(--border-subtle);
}
.notebook-edit-title-row { display: flex; align-items: center; gap: 10px; }
.notebook-edit-title { font-size: 18px; font-weight: 650; margin: 0; color: var(--text-primary); }
/* Two-column body (Settings | Sources) + an optional third preview column that
 * appears only when a source is clicked. Each column scrolls independently. */
.notebook-edit-body {
    flex: 1 1 0;
    min-height: 0;
    display: grid;
    grid-template-columns: 360px 1fr;
    gap: 0;
}
.notebook-edit-body:has(.notebook-source-preview:not([hidden])) {
    grid-template-columns: 320px minmax(0, 1fr) minmax(0, 1fr);
}
.notebook-edit-settings,
.notebook-edit-sources {
    min-height: 0;
    overflow-y: auto;
    padding: 16px 18px;
    display: flex;
    flex-direction: column;
}
.notebook-edit-settings { border-right: 1px solid var(--border-subtle); }
.notebook-edit-sources { gap: 8px; }
.notebook-sources-toolbar {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    gap: 10px;
}
.notebook-sources-toolbar .settings-section-title { margin: 0; flex: 0 0 auto; }
.notebook-sources-search {
    flex: 1 1 auto;
    min-width: 120px;
    padding: 5px 10px;
    background: var(--bg-input);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-sm);
    color: var(--text-primary);
    font-size: 13px;
}
.notebook-edit-sources .notebook-modal-summary { flex: 0 0 auto; }
/* Preview pane — third column, slides in on source click. */
.notebook-source-preview {
    min-height: 0;
    overflow-y: auto;
    padding: 16px 18px;
    border-left: 1px solid var(--border-subtle);
    display: flex;
    flex-direction: column;
    gap: 10px;
}
.notebook-source-preview[hidden] { display: none; }
.notebook-preview-head {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    gap: 8px;
}
.notebook-preview-title {
    flex: 1 1 auto;
    min-width: 0;
    font-size: 14px;
    font-weight: 600;
    color: var(--text-primary);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.notebook-preview-close {
    flex: 0 0 auto;
    width: 26px;
    height: 26px;
    border: 1px solid var(--border-subtle);
    background: var(--bg-input);
    color: var(--text-secondary);
    border-radius: var(--radius-sm);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}
.notebook-preview-close:hover { color: var(--text-primary); background: var(--bg-elevated); }
.notebook-preview-section-title {
    flex: 0 0 auto;
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--text-tertiary);
    margin: 4px 0 0;
}
.notebook-preview-summary {
    flex: 0 0 auto;
    font-size: 13px;
    color: var(--text-secondary);
    background: var(--bg-elevated);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-sm);
    padding: 8px 10px;
}
.notebook-preview-body {
    flex: 1 1 auto;
    min-height: 0;
    font-size: 12px;
    font-family: var(--font-mono);
    color: var(--text-primary);
    white-space: pre-wrap;
    word-break: break-word;
}
/* Rendered markdown drops the monospace/pre-wrap source look and gets prose
   spacing. Body and summary both render markdown; the compact prose rules below
   are scoped to these containers (a trimmed mirror of the .bot-message rules). */
.notebook-preview-body.rendered {
    font-family: inherit;
    font-size: 13px;
    white-space: normal;
    line-height: 1.5;
}
.notebook-preview-toggle {
    flex: 0 0 auto;
    display: inline-flex;
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-sm);
    overflow: hidden;
}
.notebook-preview-toggle .seg {
    border: 0;
    background: var(--bg-input);
    color: var(--text-secondary);
    font-size: 11px;
    padding: 3px 9px;
    cursor: pointer;
}
.notebook-preview-toggle .seg + .seg { border-left: 1px solid var(--border-subtle); }
.notebook-preview-toggle .seg:hover { color: var(--text-primary); }
.notebook-preview-toggle .seg.active {
    background: var(--accent-soft, var(--bg-elevated));
    color: var(--accent);
}
.notebook-preview-edit {
    flex: 0 0 auto;
    width: 26px;
    height: 26px;
    border: 1px solid var(--border-subtle);
    background: var(--bg-input);
    color: var(--text-secondary);
    border-radius: var(--radius-sm);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}
.notebook-preview-edit:hover { color: var(--text-primary); background: var(--bg-elevated); }

/* Compact markdown prose for the rendered content/summary panes. */
.notebook-preview-body.rendered > *:first-child,
.notebook-preview-summary > *:first-child { margin-top: 0; }
.notebook-preview-body.rendered > *:last-child,
.notebook-preview-summary > *:last-child { margin-bottom: 0; }
.notebook-preview-body.rendered p,
.notebook-preview-summary p { margin: 0 0 0.6em; }
.notebook-preview-body.rendered h1,
.notebook-preview-body.rendered h2,
.notebook-preview-body.rendered h3,
.notebook-preview-summary h1,
.notebook-preview-summary h2,
.notebook-preview-summary h3 {
    margin: 0.8em 0 0.4em;
    line-height: 1.3;
    font-weight: 600;
}
.notebook-preview-body.rendered h1 { font-size: 1.35rem; }
.notebook-preview-body.rendered h2 { font-size: 1.15rem; }
.notebook-preview-body.rendered h3 { font-size: 1.02rem; }
.notebook-preview-body.rendered ul,
.notebook-preview-body.rendered ol,
.notebook-preview-summary ul,
.notebook-preview-summary ol { padding-left: 1.4rem; margin: 0 0 0.6em; }
.notebook-preview-body.rendered li,
.notebook-preview-summary li { margin: 0.15em 0; }
/* PDF page boundary: a centered `p. N` label flanked by rules. Built from the
   `--- p.N ---` extraction sentinels by decoratePageMarkers (Rendered mode only). */
.notebook-preview-body.rendered .page-sep {
    display: flex;
    align-items: center;
    gap: 0.75em;
    margin: 1.5em 0;
    font-size: 0.8em;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--text-tertiary);
}
.notebook-preview-body.rendered .page-sep::before,
.notebook-preview-body.rendered .page-sep::after {
    content: "";
    flex: 1 1 auto;
    border-top: 1px solid var(--border-subtle);
}
.notebook-preview-body.rendered blockquote,
.notebook-preview-summary blockquote {
    margin: 0 0 0.6em;
    padding-left: 0.8em;
    border-left: 3px solid var(--border-subtle);
    color: var(--text-secondary);
}
.notebook-preview-body.rendered a,
.notebook-preview-summary a { color: var(--accent); }
.notebook-preview-body.rendered code:not(.hljs),
.notebook-preview-summary code:not(.hljs) {
    font-family: var(--font-mono);
    font-size: 0.88em;
    background: var(--bg-elevated);
    border-radius: 4px;
    padding: 0.1em 0.3em;
}
.notebook-preview-body.rendered pre,
.notebook-preview-summary pre {
    background: var(--bg-elevated);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-sm);
    padding: 10px 12px;
    overflow-x: auto;
    margin: 0 0 0.6em;
}
.notebook-preview-body.rendered table,
.notebook-preview-summary table {
    border-collapse: collapse;
    margin: 0 0 0.6em;
    font-size: 0.92em;
}
.notebook-preview-body.rendered th,
.notebook-preview-body.rendered td,
.notebook-preview-summary th,
.notebook-preview-summary td {
    border: 1px solid var(--border-subtle);
    padding: 4px 8px;
    text-align: left;
}
.notebook-preview-body.rendered th,
.notebook-preview-summary th { background: var(--bg-elevated); font-weight: 600; }

/* Manual-note editor occupying the preview <aside>. */
.notebook-note-editor {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
    gap: 10px;
}
.notebook-note-editor .note-title {
    flex: 0 0 auto;
    font-size: 14px;
    padding: 6px 10px;
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-sm);
    background: var(--bg-input);
    color: var(--text-primary);
}
/* Monaco mount for the "New document" editor. Flexes to fill the pane; Monaco
   sizes itself within it (automaticLayout). */
.notebook-note-editor .note-editor-monaco {
    flex: 1 1 auto;
    min-height: 200px;
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-sm);
    overflow: hidden;
}
/* Type chooser row (new docs only): "Type:" + a <select> and, for Custom, a
   free-text extension input. Editing shows a static .ext-static label instead. */
.notebook-note-editor .note-editor-type {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 12px;
    color: var(--text-secondary);
}
.notebook-note-editor .note-editor-type select,
.notebook-note-editor .note-editor-type input {
    font-size: 12px;
    padding: 4px 8px;
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-sm);
    background: var(--bg-input);
    color: var(--text-primary);
}
.notebook-note-editor .note-editor-type .note-type-custom { width: 9ch; }
.notebook-note-editor .note-editor-type .ext-static {
    font-family: var(--font-mono);
    color: var(--text-primary);
}
.notebook-note-editor .note-editor-type input[hidden] { display: none; }
/* Inline notice shown when a RAG-enabled project gets a non-md/tex doc. */
.notebook-note-editor .note-editor-raghint {
    flex: 0 0 auto;
    font-size: 12px;
    color: var(--text-secondary);
    font-style: italic;
}
.notebook-note-editor .note-editor-raghint[hidden] { display: none; }
.notebook-note-editor .note-editor-error {
    flex: 0 0 auto;
    font-size: 12px;
    color: var(--danger);
}
.notebook-note-editor .note-editor-error[hidden] { display: none; }
.notebook-note-editor .note-editor-actions {
    flex: 0 0 auto;
    display: flex;
    justify-content: flex-end;
    gap: 8px;
}
.notebook-edit-footer {
    flex: 0 0 auto;
    display: flex;
    justify-content: flex-end;
    gap: 8px;
    padding: 10px 18px;
    border-top: 1px solid var(--border-subtle);
}

.gallery-view {
    flex: 1 1 0;
    min-width: 0;
    min-height: 0;
    display: flex;
    flex-direction: column;
    background: var(--bg-base);
    overflow: hidden;
}
.gallery-view[hidden] { display: none; }
.gallery-header {
    flex: 0 0 auto;
    padding: 14px 18px 10px;
    border-bottom: 1px solid var(--border-subtle);
}
.gallery-title-row { display: flex; align-items: center; gap: 10px; }
.gallery-title { font-size: 18px; font-weight: 650; margin: 0; color: var(--text-primary); }
.gallery-count { color: var(--text-tertiary); font-size: 13px; }
.gallery-body { flex: 1 1 0; min-height: 0; overflow-y: auto; padding: 16px 18px; }
.gallery-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
    gap: 14px;
}
.gallery-tile {
    margin: 0;
    display: flex;
    flex-direction: column;
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-sm, 6px);
    background: var(--bg-elevated);
    overflow: hidden;
}
.gallery-thumb {
    width: 100%;
    aspect-ratio: 1 / 1;
    object-fit: contain;
    display: block;
    background: var(--bg-input);
    padding: 6px;
    box-sizing: border-box;
}
.gallery-caption {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 10px;
    font-size: 12px;
    color: var(--text-secondary);
}
.gallery-prompt {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.gallery-open {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 3px 7px;
    border: 1px solid var(--border-subtle);
    background: var(--bg-input);
    color: var(--text-secondary);
    border-radius: var(--radius-sm, 6px);
    cursor: pointer;
    font-size: 11px;
}
.gallery-open:hover { color: var(--text-primary); background: var(--bg-base); }
.gallery-empty { padding: 40px; text-align: center; color: var(--text-tertiary); }

.all-chats-view {
    flex: 1 1 0;
    min-width: 0;
    min-height: 0;
    display: flex;
    flex-direction: column;
    background: var(--bg-base);
    overflow: hidden;
}
.all-chats-view[hidden] { display: none; }

.all-chats-header {
    flex: 0 0 auto;
    padding: 14px 18px 10px;
    border-bottom: 1px solid var(--border-subtle);
    display: flex;
    flex-direction: column;
    gap: 10px;
}
.all-chats-title-row { display: flex; align-items: center; gap: 10px; }
.all-chats-title { font-size: 18px; font-weight: 650; margin: 0; color: var(--text-primary); }
.all-chats-count { color: var(--text-tertiary); font-size: 13px; }
.all-chats-close {
    margin-left: auto;
    width: 30px;
    height: 30px;
    border: 1px solid var(--border-subtle);
    background: var(--bg-input);
    color: var(--text-secondary);
    border-radius: var(--radius-sm);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}
.all-chats-close:hover { color: var(--text-primary); background: var(--bg-elevated); }

.all-chats-toolbar { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.all-chats-search {
    flex: 1 1 220px;
    min-width: 160px;
    padding: 6px 10px;
    background: var(--bg-input);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-sm);
    color: var(--text-primary);
}
.all-chats-select {
    padding: 6px 8px;
    background: var(--bg-input);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-sm);
    color: var(--text-primary);
    font-size: 13px;
}
.all-chats-status-seg .segmented-option { padding: 4px 10px; font-size: 12px; }

.all-chats-tag-filter { display: flex; flex-wrap: wrap; gap: 6px; }
.all-chats-tagfilter-chip {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 3px 9px;
    border: 1px solid var(--border-subtle);
    border-radius: 999px;
    background: var(--bg-input);
    color: var(--text-secondary);
    font-size: 12px;
    cursor: pointer;
}
.all-chats-tagfilter-chip.active {
    border-color: var(--chip-color, var(--accent));
    background: var(--accent-soft);
    color: var(--text-primary);
}
.all-chats-tag-dot { width: 8px; height: 8px; border-radius: 50%; flex: 0 0 auto; }

.all-chats-action-bar {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 18px;
    border-bottom: 1px solid var(--border-subtle);
    background: var(--accent-soft);
}
.all-chats-selcount { font-size: 13px; font-weight: 600; color: var(--text-primary); margin-right: 4px; }
.all-chats-act {
    padding: 5px 12px;
    border: 1px solid var(--border-subtle);
    background: var(--bg-input);
    color: var(--text-primary);
    border-radius: var(--radius-sm);
    cursor: pointer;
    font-size: 13px;
}
.all-chats-act:hover { background: var(--bg-elevated); }
.all-chats-act-danger { color: #e5484d; border-color: rgba(229, 72, 77, .4); }
.all-chats-act-danger:hover { background: rgba(229, 72, 77, .12); }
.all-chats-act-ghost { color: var(--text-secondary); }

.all-chats-table-wrap { flex: 1 1 auto; min-height: 0; overflow: auto; position: relative; }
.all-chats-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.all-chats-table thead th {
    position: sticky;
    top: 0;
    z-index: 1;
    text-align: left;
    padding: 8px 10px;
    background: var(--bg-surface);
    border-bottom: 1px solid var(--border-strong);
    color: var(--text-secondary);
    font-weight: 600;
    white-space: nowrap;
}
.all-chats-table tbody td {
    padding: 7px 10px;
    border-bottom: 1px solid var(--border-subtle);
    color: var(--text-primary);
    vertical-align: middle;
}
.all-chats-row { cursor: pointer; }
.all-chats-row:hover td { background: var(--bg-elevated); }
.all-chats-row.is-multi-selected td { background: var(--accent-soft); }
.all-chats-row.is-archived td { color: var(--text-tertiary); }
.all-chats-row.is-archived .all-chats-row-title { font-style: italic; }
.all-chats-status-dot {
    display: inline-block; width: 8px; height: 8px; border-radius: 50%;
    margin-right: 8px; vertical-align: middle; flex: 0 0 auto;
}
.all-chats-status-dot.is-running { background: var(--accent); animation: pulse-dot 1.4s ease-in-out infinite; }
.all-chats-status-dot.is-unread  { background: var(--accent); }
.all-chats-row.is-unread .all-chats-row-title { font-weight: 600; }

.acc-check { width: 28px; text-align: center; }
.acc-title { min-width: 200px; max-width: 360px; }
.all-chats-row-title { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.acc-project, .acc-agent { max-width: 160px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.acc-date { white-space: nowrap; color: var(--text-secondary); }
.acc-models { max-width: 200px; }
.acc-images { width: 72px; white-space: nowrap; }
.acc-actions { width: 64px; white-space: nowrap; text-align: right; }

.all-chats-model-chip {
    display: inline-block;
    max-width: 160px;
    padding: 1px 7px;
    margin: 1px 3px 1px 0;
    border-radius: 999px;
    border: 1px solid var(--border-subtle);
    font-size: 11px;
    color: var(--text-secondary);
    vertical-align: middle;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.all-chats-images-btn {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 2px 8px;
    border: 1px solid var(--border-subtle);
    background: var(--bg-input);
    color: var(--text-secondary);
    border-radius: var(--radius-sm, 6px);
    cursor: pointer;
    font-size: 12px;
}
.all-chats-images-btn:hover { color: var(--text-primary); background: var(--bg-elevated); }

.all-chats-kind-badge {
    display: inline-block;
    padding: 1px 7px;
    border-radius: 999px;
    font-size: 11px;
    background: var(--bg-elevated);
    color: var(--text-secondary);
}
.all-chats-kind-badge.is-discussion { background: var(--accent-soft); color: var(--accent); }
.all-chats-tag-chip {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 1px 7px;
    margin: 1px 3px 1px 0;
    border-radius: 999px;
    border: 1px solid var(--chip-color, var(--border-subtle));
    font-size: 11px;
    color: var(--text-secondary);
}
.all-chats-arch-badge {
    display: inline-block;
    padding: 1px 7px;
    border-radius: 999px;
    font-size: 11px;
    background: var(--bg-elevated);
    color: var(--text-tertiary);
}
.all-chats-rowact {
    border: none;
    background: transparent;
    color: var(--text-tertiary);
    cursor: pointer;
    padding: 3px 5px;
    border-radius: var(--radius-sm);
    font-size: 14px;
}
.all-chats-rowact:hover { color: var(--text-primary); background: var(--border-subtle); }
.all-chats-rowact-danger:hover { color: #e5484d; background: rgba(229, 72, 77, .12); }
/* "Do not sync" toggle (20260637): muted when local-only; locked + dimmed when
   the owning project cascades the flag. */
.all-chats-rowact.is-local-only { color: var(--text-secondary); }
.all-chats-rowact.is-cascaded {
    cursor: default;
    opacity: 0.5;
}
.all-chats-rowact.is-cascaded:hover { color: var(--text-tertiary); background: transparent; }

.all-chats-empty { padding: 30px; text-align: center; color: var(--text-tertiary); }

/* ── Library view — reuses the All Chats shell; only the bits unique to the
 * unified files/notes/snippets/templates surface live here. ───────────── */

/* Body splits into the table (left) and an optional preview/editor aside
 * (right, the Monaco doc-editor host). The aside reuses .notebook-source-preview
 * for its chrome; when [hidden] it collapses and the table takes the full width. */
.library-body { flex: 1 1 auto; min-height: 0; display: flex; }
.library-table-wrap { flex: 1 1 auto; }
#library-source-preview { flex: 1 1 0; min-width: 0; max-width: 50%; }
#library-source-preview[hidden] { display: none; }

/* "New ▾" split button + its dropdown menu. */
.library-new-wrap { position: relative; flex: 0 0 auto; }
.library-new-btn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 6px 12px;
    border: 1px solid var(--border-subtle);
    background: var(--bg-input);
    color: var(--text-primary);
    border-radius: var(--radius-sm);
    cursor: pointer;
    font-size: 13px;
}
.library-new-btn:hover { background: var(--bg-elevated); }
.library-new-caret { font-size: 9px; opacity: .7; }
.library-new-menu {
    position: absolute;
    top: calc(100% + 4px);
    right: 0;
    z-index: 20;
    min-width: 190px;
    padding: 4px;
    background: var(--bg-surface);
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-sm);
    box-shadow: 0 8px 24px rgba(0, 0, 0, .28);
    display: flex;
    flex-direction: column;
    gap: 1px;
}
.library-new-menu[hidden] { display: none; }
.library-new-menu button {
    display: flex;
    align-items: center;
    gap: 9px;
    padding: 7px 10px;
    border: 0;
    background: transparent;
    color: var(--text-primary);
    border-radius: var(--radius-sm);
    cursor: pointer;
    font-size: 13px;
    text-align: left;
    white-space: nowrap;
}
.library-new-menu button:hover { background: var(--accent-soft); color: var(--accent); }
.library-new-menu button i { width: 16px; text-align: center; color: var(--text-tertiary); }
.library-new-menu button:hover i { color: var(--accent); }
.library-new-sep { height: 1px; margin: 3px 2px; background: var(--border-subtle); }

/* Library table columns. */
.library-table .acc-kind { width: 96px; white-space: nowrap; }
.library-table .acc-meta { width: 150px; white-space: nowrap; color: var(--text-secondary); }
.library-table .acc-title .all-chats-row-title i { margin-right: 7px; color: var(--text-tertiary); }

/* Type badge — one pill per kind, modeled on .all-chats-kind-badge with the
 * snippet/template colour cues from .snippet-kind-chip. */
.library-kind-badge {
    display: inline-block;
    padding: 1px 8px;
    border-radius: 999px;
    font-size: 11px;
    border: 1px solid transparent;
    background: var(--bg-elevated);
    color: var(--text-secondary);
}
.library-kind-badge.is-file {
    background: rgba(90, 130, 200, 0.12);
    color: rgb(110, 150, 220);
    border-color: rgba(90, 130, 200, 0.26);
}
.library-kind-badge.is-note {
    background: rgba(40, 160, 120, 0.10);
    color: rgb(70, 170, 130);
    border-color: rgba(40, 160, 120, 0.24);
}
.library-kind-badge.is-snippet {
    background: var(--bg-elevated);
    color: var(--text-secondary);
    border-color: var(--border-subtle);
}
.library-kind-badge.is-template {
    background: rgba(120, 100, 220, 0.12);
    color: rgb(140, 120, 240);
    border-color: rgba(120, 100, 220, 0.28);
}

/* Per-chat image lightbox — a modal over the All Chats table. */
.chat-images-lightbox {
    position: fixed;
    inset: 0;
    z-index: 1200;
    display: flex;
    align-items: center;
    justify-content: center;
}
.chat-images-lightbox[hidden] { display: none; }
.chat-images-backdrop {
    position: absolute;
    inset: 0;
    background: rgba(0, 0, 0, .5);
}
.chat-images-panel {
    position: relative;
    display: flex;
    flex-direction: column;
    width: min(90vw, 1000px);
    max-height: 85vh;
    background: var(--bg-base);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-md, 10px);
    box-shadow: 0 12px 40px rgba(0, 0, 0, .35);
    overflow: hidden;
}
.chat-images-header {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 14px 18px 10px;
    border-bottom: 1px solid var(--border-subtle);
}
.chat-images-title {
    font-size: 16px;
    font-weight: 650;
    margin: 0;
    color: var(--text-primary);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.chat-images-body { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: 16px 18px; }
.image-viewer-lightbox {
    position: fixed; inset: 0; z-index: 1300;
    display: flex; align-items: center; justify-content: center;
}
.image-viewer-lightbox[hidden] { display: none; }
.image-viewer-backdrop { position: absolute; inset: 0; background: rgba(0, 0, 0, .8); }
.image-viewer-img {
    position: relative;
    max-width: 95vw; max-height: 95vh;
    object-fit: contain;
    border-radius: var(--radius-sm, 6px);
    box-shadow: 0 12px 40px rgba(0, 0, 0, .5);
}
.image-viewer-close { position: absolute; top: 16px; right: 16px; z-index: 1; }
/* thumbnails are now clickable */
.gallery-thumb { cursor: zoom-in; }

/* ── Conversation map (experimental) ─────────────────────────────────────────
   Full-screen overlay with a pan/zoom SVG canvas. Built from db:chatGraph via
   libs/chat-graph-layout.js; nodes are coloured per chat lineage in JS, so the
   CSS here is mostly chrome + interaction affordances. */
.chat-map-modal {
    position: fixed;
    inset: 0;
    z-index: 2500;
    display: flex;
    flex-direction: column;
    background: var(--bg-base);
}
.chat-map-modal[hidden] { display: none; }
.chat-map-header {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 14px 18px;
    border-bottom: 1px solid var(--border-subtle);
    background: var(--bg-surface);
    flex: 0 0 auto;
}
.chat-map-title {
    margin: 0;
    font-size: 1.05rem;
    font-weight: 600;
    color: var(--text-primary);
}
.chat-map-count { color: var(--text-secondary); font-size: .85rem; }
.chat-map-header-spacer { flex: 1 1 auto; }
.chat-map-btn,
.chat-map-close {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 32px; height: 32px;
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-sm, 6px);
    background: var(--bg-elevated);
    color: var(--text-primary);
    cursor: pointer;
}
.chat-map-btn:hover,
.chat-map-close:hover { background: var(--bg-input); border-color: var(--border-strong); }
.chat-map-canvas-wrap {
    position: relative;
    flex: 1 1 0;
    min-height: 0;
    overflow: hidden;
    background:
        radial-gradient(circle at 1px 1px, var(--border-subtle) 1px, transparent 0) 0 0 / 24px 24px;
}
.chat-map-svg {
    width: 100%;
    height: 100%;
    display: block;
    cursor: grab;
    user-select: none;
}
.chat-map-svg.panning { cursor: grabbing; }
.chat-map-empty,
.chat-map-hint {
    position: absolute;
    color: var(--text-secondary);
    pointer-events: none;
}
.chat-map-empty {
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: .95rem;
}
.chat-map-hint {
    left: 50%;
    bottom: 12px;
    transform: translateX(-50%);
    font-size: .78rem;
    background: var(--bg-surface);
    border: 1px solid var(--border-subtle);
    border-radius: 999px;
    padding: 4px 12px;
    opacity: .85;
}
/* "No forks yet" hint sits at the top so a lone node doesn't read as a bug. */
.chat-map-noforks {
    bottom: auto;
    top: 12px;
}
/* SVG node/edge primitives (most colours set inline per lineage in JS). */
.cmap-edge { stroke: var(--border-strong); stroke-width: 1.6; fill: none; }
.cmap-node { cursor: pointer; }
.cmap-node-rect { stroke: var(--border-strong); stroke-width: 1.5; rx: 10; }
.cmap-node.current .cmap-node-rect { stroke: var(--accent); stroke-width: 3; }
/* The node we've drilled into (the new root of the scoped view). */
.cmap-node.focus-root .cmap-node-rect {
    stroke: var(--accent);
    stroke-width: 3;
    stroke-dasharray: 6 4;
    filter: brightness(1.06);
}
.cmap-node-label {
    fill: var(--text-primary);
    font-size: 13px;
    font-family: inherit;
    pointer-events: none;
    dominant-baseline: middle;
}
.cmap-node-sub {
    fill: var(--text-secondary);
    font-size: 10.5px;
    pointer-events: none;
}
.cmap-node:hover .cmap-node-rect { filter: brightness(1.12); }
/* Inline rename input overlaid on a node. */
.cmap-rename-input {
    position: absolute;
    z-index: 2;
    border: 1px solid var(--accent);
    border-radius: 6px;
    background: var(--bg-input);
    color: var(--text-primary);
    font-size: 13px;
    padding: 2px 6px;
    box-shadow: var(--shadow-soft);
}

/* ===================== Special Chats (chat presets) ===================== */
/* Gallery cards mirror the agent/team picker visual language. */
.preset-gallery-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
    gap: 12px;
}
.preset-card {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    text-align: left;
    padding: 12px;
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-md);
    background: var(--bg-surface);
    color: var(--text-primary);
    cursor: pointer;
    transition: border-color 120ms ease, background 120ms ease, transform 80ms ease;
}
.preset-card:hover { border-color: var(--accent); background: var(--bg-elevated); }
.preset-card:active { transform: translateY(1px); }
.preset-card-icon { flex-shrink: 0; }
.preset-card-body { min-width: 0; flex: 1; }
.preset-card-name { font-weight: 600; font-size: 14px; }
.preset-card-desc {
    font-size: 12px;
    color: var(--text-secondary);
    margin-top: 2px;
    overflow: hidden;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
}
.preset-card-meta {
    font-size: 11px;
    color: var(--text-secondary);
    margin-top: 6px;
    text-transform: uppercase;
    letter-spacing: 0.02em;
    opacity: 0.8;
}
.preset-gallery-empty {
    text-align: center;
    color: var(--text-secondary);
    padding: 32px 16px;
}
.preset-gallery-empty .bi { font-size: 32px; display: block; margin-bottom: 8px; opacity: 0.6; }

/* Input form */
.preset-input-description { color: var(--text-secondary); font-size: 13px; }
.preset-input-fields { display: flex; flex-direction: column; gap: 14px; }
.preset-input-row { display: flex; flex-direction: column; gap: 4px; }
.preset-input-file-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }
.preset-input-file-chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 3px 8px;
    border-radius: 12px;
    background: var(--accent-soft);
    font-size: 12px;
}
.preset-input-file-chip-x {
    border: 0;
    background: transparent;
    cursor: pointer;
    color: var(--text-secondary);
    font-size: 14px;
    line-height: 1;
    padding: 0;
}
.preset-input-preview-wrap { margin-top: 16px; }
.preset-input-preview {
    white-space: pre-wrap;
    font-size: 13px;
    line-height: 1.5;
    padding: 10px 12px;
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-sm);
    background: var(--bg-input);
    color: var(--text-primary);
    max-height: 200px;
    overflow-y: auto;
}

/* Editor: token helper + inputs builder */
.preset-token-helper { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-top: 6px; }
.preset-token-hint { font-size: 12px; color: var(--text-secondary); }
.preset-token-chip {
    border: 1px solid var(--border-subtle);
    border-radius: 12px;
    background: var(--bg-elevated);
    color: var(--text-primary);
    font-family: var(--font-mono);
    font-size: 11px;
    padding: 2px 8px;
    cursor: pointer;
}
.preset-token-chip:hover { border-color: var(--accent); }
.preset-inputs-builder { display: flex; flex-direction: column; gap: 8px; }
.preset-input-builder-row {
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-sm);
    padding: 8px;
    background: var(--bg-surface);
}
.preset-input-builder-head { display: flex; align-items: center; gap: 8px; }
.preset-input-builder-type {
    font-size: 10px;
    font-weight: 600;
    color: var(--text-secondary);
    background: var(--border-subtle);
    border-radius: 4px;
    padding: 2px 6px;
}
.preset-input-builder-opts { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; margin-top: 8px; }
.preset-input-builder-check { display: inline-flex; align-items: center; gap: 4px; font-size: 12px; margin: 0; }
.preset-input-builder-ph { max-width: 280px; }
.preset-inputs-add { display: flex; gap: 8px; margin-top: 8px; }
.preset-settings-details summary { cursor: pointer; font-size: 13px; color: var(--text-secondary); }
.form-label-sm { font-size: 12px; margin-bottom: 2px; }
.preset-form-empty { display: flex; align-items: center; justify-content: center; }
.preset-form-empty-inner { text-align: center; color: var(--text-secondary); }
.preset-form-empty-inner .bi { font-size: 32px; display: block; margin-bottom: 8px; opacity: 0.6; }

/* ==========================================================================
   The Genie — roaming pixel-art companion (gamification layer)
   ========================================================================== */

#genie-mount {
    position: relative;
    width: 58px;
    height: 30px;
    align-self: center;
    flex: 0 0 auto;
    margin-inline: 2px;
}
#genie-mount.genie-off { display: none; }

.genie-sprite {
    position: absolute;
    left: 6px;
    bottom: 0;
    width: 26px;
    height: 26px;
    display: flex;
    align-items: flex-end;
    justify-content: center;
    cursor: pointer;
    transition: left 2.4s cubic-bezier(.45,.05,.55,.95);
    outline: none;
    -webkit-user-select: none;
    user-select: none;
}
.genie-sprite:focus-visible { box-shadow: 0 0 0 2px var(--accent-ring); border-radius: 6px; }
.genie-sprite:hover { filter: brightness(1.08); }

.genie-img {
    width: 22px;
    height: auto;
    image-rendering: pixelated;
    image-rendering: crisp-edges;
    display: block;
    transform-origin: center bottom;
    pointer-events: none;
    -webkit-user-drag: none;
}
.genie-sprite.genie-face-left .genie-img { transform: scaleX(-1); }

.genie-flair {
    position: absolute;
    inset: 0;
    pointer-events: none;
    opacity: 0;
    transition: opacity .3s ease;
}

/* Growth tiers: bigger + glowier as the level rises */
.genie-sprite[data-tier="1"] .genie-img { width: 20px; }
.genie-sprite[data-tier="2"] .genie-img { width: 22px; }
.genie-sprite[data-tier="3"] .genie-img { width: 24px; filter: drop-shadow(0 0 2px rgba(124,92,255,.5)); }
.genie-sprite[data-tier="4"] .genie-img { width: 26px; filter: drop-shadow(0 0 3px rgba(124,92,255,.65)); }
.genie-sprite[data-tier="5"] .genie-img { width: 28px; filter: drop-shadow(0 0 5px rgba(255,207,71,.8)); }
.genie-sprite[data-tier="4"] .genie-flair,
.genie-sprite[data-tier="5"] .genie-flair {
    opacity: 1;
    background: radial-gradient(circle at 50% 40%, rgba(255,207,71,.28), transparent 60%);
    animation: genie-aura 3.2s ease-in-out infinite;
}

/* --- state animations --- */
.genie-idle .genie-img { animation: genie-float 3.4s ease-in-out infinite; }
.genie-walk { animation: genie-bob .44s steps(2, jump-none) infinite; }
.genie-think .genie-img { animation: genie-think-pulse 1.1s ease-in-out infinite; }
.genie-celebrate { animation: genie-hop .5s cubic-bezier(.3,1.4,.6,1) 2; }
.genie-celebrate .genie-img { filter: drop-shadow(0 0 4px rgba(255,207,71,.9)); }
.genie-nap .genie-img { animation: genie-breathe 3.6s ease-in-out infinite; opacity: .92; }
/* Duck state is no longer used to hide the Genie while typing (that made it
   vanish). Kept as a gentle nudge only — never fully transparent. */
.genie-duck { transform: translateY(6px); transition: transform .25s ease; }

@keyframes genie-float {
    0%, 100% { transform: translateY(0); }
    50% { transform: translateY(-2px); }
}
@keyframes genie-bob {
    0% { transform: translateY(0); }
    50% { transform: translateY(-2px); }
    100% { transform: translateY(0); }
}
@keyframes genie-think-pulse {
    0%, 100% { transform: translateY(0) scale(1); }
    50% { transform: translateY(-1px) scale(1.05); }
}
@keyframes genie-hop {
    0% { transform: translateY(0); }
    40% { transform: translateY(-9px); }
    100% { transform: translateY(0); }
}
@keyframes genie-breathe {
    0%, 100% { transform: translateY(2px) scale(1); }
    50% { transform: translateY(3px) scale(.97); }
}
@keyframes genie-aura {
    0%, 100% { opacity: .55; }
    50% { opacity: 1; }
}

/* --- stats / achievements panel (mirrors #context-popover shape) --- */
.genie-panel {
    position: absolute;
    top: calc(100% + 10px);
    right: 0;
    width: 300px;
    max-width: 88vw;
    max-height: 70vh;
    overflow-y: auto;
    background: var(--bg-elevated);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-soft);
    padding: 14px;
    z-index: 4000;
    display: none;
    color: var(--text-primary);
    font-size: 13px;
}
.genie-panel.genie-panel-open { display: block; }
.genie-panel-head { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; }
.genie-level-badge {
    flex: 0 0 auto;
    min-width: 40px;
    height: 40px;
    padding: 0 8px;
    border-radius: 10px;
    display: flex; align-items: center; justify-content: center;
    font-weight: 700;
    color: #fff;
    background: linear-gradient(135deg, #7c5cff, #5b3fd6);
    box-shadow: 0 2px 6px rgba(124,92,255,.4);
}
.genie-level-badge[data-tier="4"] { background: linear-gradient(135deg, #9a7bff, #6b4fe6); }
.genie-level-badge[data-tier="5"] { background: linear-gradient(135deg, #ffcf47, #e0a91e); color: #241634; }
.genie-title-main { font-weight: 600; }
.genie-title-sub { color: var(--text-secondary); font-size: 11.5px; margin-top: 1px; }
.genie-progress {
    height: 8px; border-radius: 6px; background: var(--bg-input);
    border: 1px solid var(--border-subtle); overflow: hidden; margin-top: 2px;
}
.genie-progress-fill {
    height: 100%;
    background: linear-gradient(90deg, #7c5cff, #ffcf47);
    transition: width .5s ease;
}
.genie-progress-label { color: var(--text-tertiary); font-size: 11px; margin: 4px 0 2px; }
.genie-section { margin-top: 12px; }
.genie-section-title {
    font-size: 11px; text-transform: uppercase; letter-spacing: .04em;
    color: var(--text-tertiary); margin-bottom: 6px; display: flex; justify-content: space-between;
}
.genie-count { color: var(--accent); font-weight: 600; }
.genie-row { display: flex; justify-content: space-between; gap: 8px; padding: 2px 0; }
.genie-row .genie-k { color: var(--text-secondary); }
.genie-row .genie-v { color: var(--text-primary); font-variant-numeric: tabular-nums; }
.genie-badges { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; }
.genie-badge {
    display: flex; align-items: center; gap: 6px;
    padding: 6px 8px; border-radius: 8px;
    background: var(--bg-surface); border: 1px solid var(--border-subtle);
    font-size: 11.5px;
}
.genie-badge-ico { font-size: 14px; line-height: 1; }
.genie-badge-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.genie-badge-on { border-color: var(--accent); }
.genie-badge-on .genie-badge-ico { color: var(--accent); }
.genie-badge-off { opacity: .45; filter: grayscale(1); }

/* --- toast --- */
.genie-toast {
    position: fixed;
    right: 18px;
    bottom: 18px;
    min-width: 200px;
    max-width: 320px;
    background: var(--bg-elevated);
    border: 1px solid var(--border-subtle);
    border-left: 3px solid #ffcf47;
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-soft);
    padding: 10px 14px;
    color: var(--text-primary);
    z-index: 5000;
    opacity: 0;
    transform: translateY(12px);
    pointer-events: none;
    transition: opacity .3s ease, transform .3s ease;
}
.genie-toast.genie-toast-show { opacity: 1; transform: translateY(0); }
.genie-toast-title { font-weight: 600; font-size: 13px; }
.genie-toast-body { color: var(--text-secondary); font-size: 12px; margin-top: 2px; }

/* --- caret / info affordance (opens stats; keeps left-click free for tricks) --- */
.genie-caret {
    position: absolute;
    right: -3px;
    top: -4px;
    font-size: 10px;
    line-height: 1;
    color: var(--text-tertiary);
    opacity: 0;
    cursor: pointer;
    transition: opacity .15s ease, color .15s ease;
    pointer-events: auto;
}
#genie-mount:hover .genie-caret,
.genie-sprite:focus-within .genie-caret,
.genie-caret:focus-visible { opacity: .85; }
.genie-caret:hover { color: var(--accent); opacity: 1; }
.genie-caret:focus-visible { outline: none; box-shadow: 0 0 0 2px var(--accent-ring); border-radius: 4px; }

.genie-panel-hint {
    margin-top: 10px;
    font-size: 10.5px;
    color: var(--text-tertiary);
    text-align: center;
}

/* While a WAAPI reaction plays, drop the ambient state animation so the two
   don't fight over transform. */
.genie-sprite.genie-reacting,
.genie-sprite.genie-reacting .genie-img { animation: none !important; }

/* --- floating overlay stage: zero layout cost, never blocks input --- */
#genie-stage {
    position: fixed;
    inset: 0;
    pointer-events: none;   /* input passes straight through */
    z-index: 4999;          /* under the toast (5000), over the panel (4000) */
    /* No containment/overflow clip: the performer is position:fixed and must be
       free to arc anywhere over the viewport (containment would re-anchor it). */
}
.genie-performer {
    position: fixed;
    left: 0;
    top: 0;
    width: 48px;
    height: 46px;
    display: none;
    pointer-events: none;
    will-change: transform;
    transform-origin: center bottom;
}
.genie-performer .genie-performer-img {
    width: 48px;
    height: auto;
    image-rendering: pixelated;
    image-rendering: crisp-edges;
    display: block;
    transform-origin: center bottom;
    pointer-events: none;
    filter: drop-shadow(0 3px 4px rgba(0, 0, 0, .3));
}
.genie-performer[data-tier="4"] .genie-performer-img { filter: drop-shadow(0 0 4px rgba(124,92,255,.7)) drop-shadow(0 3px 4px rgba(0,0,0,.3)); }
.genie-performer[data-tier="5"] .genie-performer-img { filter: drop-shadow(0 0 6px rgba(255,207,71,.85)) drop-shadow(0 3px 4px rgba(0,0,0,.3)); }

/* --- perched: dragged out of the top bar to live in the chat ---
   Positioned by left/top and sized by the img width (transform stays free for
   reaction keyframes), mirroring the home sprite's model. The stage stays
   pointer-events:none; only the perched performer opts back in. */
.genie-performer.genie-perched {
    display: block;
    pointer-events: auto;
    cursor: grab;
}
.genie-performer.genie-dragging { cursor: grabbing; opacity: .9; }
.genie-performer.genie-perched .genie-performer-img { width: 28px; }
.genie-performer.genie-perched[data-tier="1"] .genie-performer-img { width: 24px; }
.genie-performer.genie-perched[data-tier="2"] .genie-performer-img { width: 26px; }
.genie-performer.genie-perched[data-tier="3"] .genie-performer-img { width: 28px; }
.genie-performer.genie-perched[data-tier="4"] .genie-performer-img { width: 30px; }
.genie-performer.genie-perched[data-tier="5"] .genie-performer-img { width: 32px; }
.genie-performer.genie-face-left .genie-performer-img { transform: scaleX(-1); }

/* --- respect reduced motion: static Genie, no roaming/animation, no stage --- */
#genie-mount.genie-reduced .genie-sprite { transition: none; left: 16px; }
@media (prefers-reduced-motion: reduce) {
    .genie-sprite, .genie-img, .genie-flair,
    .genie-idle .genie-img, .genie-walk, .genie-think .genie-img,
    .genie-celebrate, .genie-nap .genie-img {
        animation: none !important;
        transition: none !important;
    }
    .genie-duck { transform: none; }
    /* The stage stays available so a perched pet can render — but statically:
       no lift/opacity flourish. A non-perched performer (the idle stroll) stays
       fully suppressed. Dragging to perch/re-dock is still allowed. */
    .genie-performer { animation: none !important; }
    .genie-performer:not(.genie-perched) { display: none !important; }
}

/* ---- Web build (body.fhg-web, set by the web shell + fhgenie-pro.js) ----
   Entry points for features with no web equivalent. Pure hiding with
   !important so renderer code that later un-hides an element (feature flags,
   d-none toggles, settings search) can't bring it back. Desktop never has the
   class, so none of this applies there. */
body.fhg-web .fhg-web-hidden,
body.fhg-web .settings-nav-item[data-pane="tools"],
body.fhg-web .settings-nav-item[data-pane="experimental"],
body.fhg-web .settings-pane[data-pane="tools"],
body.fhg-web .settings-pane[data-pane="experimental"],
body.fhg-web #chat-map-btn,
body.fhg-web #chat-settings-btn,
body.fhg-web #sidebar-papers-section,
body.fhg-web #paper-context-chip,
body.fhg-web #composer-rag-btn,
body.fhg-web .files-popover-external,
body.fhg-web #project-new-notebook-btn,
body.fhg-web .project-section-files,
body.fhg-web .project-section-files-count,
body.fhg-web .sidebar-inproject-files,
body.fhg-web .notebook-edit-sources,
body.fhg-web label[for="notebook-modal-attachment-mode"],
body.fhg-web #notebook-modal-attachment-mode,
body.fhg-web #notebook-modal-attachment-mode + .project-edit-hint,
body.fhg-web #notebook-modal-rag-row,
body.fhg-web #notebook-modal-summarize-row {
    display: none !important;
}
