/* ═══════════════════════════════════════════════════════════════
   Tanngrisnir — App Styles
   ═══════════════════════════════════════════════════════════════ */

/* ── Layer B: Shared semantic tokens ──────────────────────────────── */
:root {
    --t-topbar-height: 48px;
    --t-surface:          #ffffff;
    --t-surface-elevated: #f5f5f7;
    --t-surface-sunken:   #eeeef0;
    --t-border:           rgba(0, 0, 0, 0.10);
    --t-text-muted:       #6c757d;
    --t-accent:           rgb(108, 142, 191); /* midday default; overridden by time-of-day JS */
    --t-accent-rgb:       108, 142, 191;
    --t-font-ui:          'Inter', system-ui, sans-serif;
    --t-font-serif:       'Source Serif 4', Georgia, serif;
}

[data-bs-theme="dark"] {
    --t-surface:          #181c24;
    --t-surface-elevated: #111318;
    --t-surface-sunken:   #0e1016;
    --t-border:           rgba(255, 255, 255, 0.08);
    --t-text-muted:       #8892a0;
}

/* ── App-specific variables (legacy; aliases point to Layer B) ── */
:root {
    --sidebar-width: 260px;
    --artifact-panel-width: 300px;
    --composer-height: auto;
    --header-height: 52px;
    --message-assistant-bg: transparent;
    /* chat-specific values that have no Layer B equivalent */
    --message-user-bg: #1e2433;
    /* Legacy aliases → Layer B */
    --sidebar-bg:   var(--t-surface-elevated);
    --chat-bg:      var(--t-surface);
    --border-color: var(--t-border);
    --accent:       var(--t-accent);
    --text-muted:   var(--t-text-muted);
}

[data-bs-theme="light"] {
    --message-user-bg: #f0f2f5;
}

/* ── Sitewide font ── */
body { font-family: var(--t-font-ui); }

/* ── Serif / reading context ── */
.prose {
    font-family: var(--t-font-serif);
    font-size: 1.0625rem;
    line-height: 1.78;
    font-optical-sizing: auto;
}

/* ── Reset / Globals ── */
*, *::before, *::after { box-sizing: border-box; }
html, body { height: 100%; }
/* Prevent document-level scroll only on the chat page; other pages scroll normally */
/* overflow:clip (not hidden) so position:sticky on the topbar still works */
body.chat-page { overflow: clip; }

/* ══════════════════════════════════════════ SHARED TOPBAR ════ */

.t-topbar-right {
    display: flex; align-items: center; gap: 0.25rem;
    flex-shrink: 0; position: relative;
}
.t-topbar-breadcrumb {
    font-size: 0.825rem; color: var(--t-text-muted);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.t-topbar-breadcrumb:not(:empty)::before { content: '/'; margin-right: 0.4rem; opacity: 0.4; }
.t-topbar-breadcrumb a { color: inherit; text-decoration: none; }
.t-topbar-breadcrumb a:hover { color: var(--bs-body-color); }

/* Rolling-budget sidebar-footer meter — a dual-ring donut icon (outer =
   weekly, inner = 6-hour) replacing the old bars, compact enough to survive
   the collapsed icon rail without overflowing (#777 follow-up). Shares
   .sidebar-footer-link's icon+label layout/coloring; only the blocked-state
   override lives here. */
.t-budget-meter.is-blocked { color: var(--bs-danger); }
.t-budget-ring-track { stroke: rgba(var(--t-accent-rgb), 0.18); }
.t-budget-ring-fill {
    stroke: var(--t-accent);
    transform: rotate(-90deg); transform-origin: 12px 12px;
    transition: stroke-dashoffset 0.3s ease;
}
.t-budget-ring-six { opacity: 0.85; }
.t-budget-meter.is-blocked .t-budget-ring-fill { stroke: var(--bs-danger); }
.budget-fill-accent { background-color: var(--accent); }

.nav-group-link { padding-left: 1.9rem; }
.nav-chevron { transition: transform 0.18s; flex-shrink: 0; }
.nav-chevron.rotated { transform: rotate(180deg); }

.btn-reset {
    background: none; border: none; padding: 0; cursor: pointer;
    color: inherit; font: inherit;
}
.btn-ghost {
    background: none; border: none; padding: 4px 8px; cursor: pointer;
    color: var(--bs-body-color); border-radius: 6px; line-height: 1;
    opacity: 0.6; transition: opacity 0.15s;
}
.btn-ghost:hover { opacity: 1; background: var(--border-color); }

/* ── Accent buttons — wired to the time-of-day --t-accent token ──
   Bootstrap has no class for the app accent, so these fill the gap that
   bright `btn-info` used to. Color/border/hover only — Bootstrap sizing
   (.btn, .btn-sm) still applies. */
.btn-accent {
    background: var(--t-accent);
    border: 1px solid var(--t-accent);
    color: #fff;
    transition: background 0.15s, border-color 0.15s;
}
.btn-accent:hover,
.btn-accent:focus-visible {
    background: color-mix(in srgb, var(--t-accent) 84%, #000);
    border-color: color-mix(in srgb, var(--t-accent) 84%, #000);
    color: #fff;
}
.btn-outline-accent {
    background: none;
    border: 1px solid var(--t-accent);
    color: var(--t-accent);
    transition: background 0.15s, color 0.15s;
}
.btn-outline-accent:hover,
.btn-outline-accent:focus-visible {
    background: rgba(var(--t-accent-rgb), 0.10);
    color: var(--t-accent);
}
/* Ghost: no border until hover — the quiet "Revise with AI" treatment */
.btn-accent-ghost {
    background: none;
    border: 1px solid transparent;
    color: var(--t-accent);
    transition: background 0.15s, border-color 0.15s;
}
.btn-accent-ghost:hover,
.btn-accent-ghost:focus-visible {
    background: rgba(var(--t-accent-rgb), 0.10);
    color: var(--t-accent);
}

[x-cloak] { display: none !important; }

/* ══════════════════════════════════════ UNIFIED SIDEBAR NAV ════
   #777 — replaces the old hamburger-drawer topbar nav. .t-shell is the
   page-level flex row (sidebar + main column); .t-sidenav is the persistent
   left column, collapsing to an icon rail on desktop and a full-height
   overlay on mobile. See _docs/PLAN_issue777_unified_sidebar_nav.md. */

:root {
    --t-sidenav-width: 240px;
    --t-sidenav-collapsed-width: 56px;
}

.t-shell {
    display: flex;
    min-height: 100vh;
    min-height: 100dvh;
    align-items: stretch;
}

.t-shell-main {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
}

/* FOUC guard: apply the persisted collapsed width immediately (before Alpine
   hydrates), mirroring the data-bs-theme FOUC script. The :not(.is-collapsed)
   override is load-bearing, not cosmetic: html[data-sidebar-collapsed] is only
   ever set once (page load) and never cleared on expand, so without a rule
   that outranks it once Alpine removes .is-collapsed, a session that has
   collapsed at least once can never expand again — this attribute-selector
   rule's specificity otherwise beats the plain two-class .is-collapsed rule. */
html[data-sidebar-collapsed="true"] .t-sidenav { width: var(--t-sidenav-collapsed-width); }
html[data-sidebar-collapsed="true"] .t-sidenav:not(.is-collapsed) { width: var(--t-sidenav-width); }

.t-sidenav {
    width: var(--t-sidenav-width);
    flex-shrink: 0;
    display: flex;
    flex-direction: column;
    background: var(--t-surface-elevated);
    border-right: 1px solid var(--t-border);
    transition: width 0.18s ease;
    overflow: hidden;
    /* Pin to the viewport instead of stretching to the page's (possibly
       taller-than-viewport) content height — the sidebar scrolls its own
       nav-links/recents internally, it never grows the whole-page scroll. */
    position: sticky;
    top: 0;
    height: 100vh;
    height: 100dvh;
}
.t-sidenav.is-collapsed { width: var(--t-sidenav-collapsed-width); }
.t-sidenav.is-collapsed .t-sidenav-label { display: none; }
.t-sidenav.is-collapsed .t-sidenav-recents { display: none; }
.t-sidenav.is-collapsed .t-sidenav-header { justify-content: center; }

.t-sidenav-header {
    display: flex; align-items: center; justify-content: space-between;
    height: var(--t-topbar-height); flex-shrink: 0;
    padding: 0 0.75rem;
    border-bottom: 1px solid var(--t-border);
}
.t-sidenav-brand {
    font-weight: 700; font-size: 0.95rem; letter-spacing: -0.02em;
    text-decoration: none; color: var(--bs-body-color); white-space: nowrap;
}
.t-sidenav-collapse-btn {
    display: flex; align-items: center; justify-content: center;
    width: 28px; height: 28px; border-radius: 6px; flex-shrink: 0;
    color: var(--t-text-muted); transition: color 0.15s, background 0.15s;
}
.t-sidenav-collapse-btn:hover { color: var(--bs-body-color); background: rgba(var(--t-accent-rgb), 0.10); }

.t-sidenav-links {
    /* Capped so that expanding every collapsible group (Library/Jobs/Account)
       can't push Recent Conversations fully out of view below — it scrolls
       internally past this instead. */
    max-height: 45vh;
    overflow-y: auto; overflow-x: hidden;
    padding: 0.5rem 0.4rem;
    scrollbar-width: thin;
    scrollbar-color: var(--t-border) transparent;
}
.t-sidenav-link {
    display: flex; align-items: center; gap: 0.65rem;
    padding: 0.4rem 0.55rem; border-radius: 8px;
    color: var(--bs-body-color); text-decoration: none; font-size: 0.85rem;
    transition: background 0.12s; white-space: nowrap;
}
.t-sidenav-link:hover { background: rgba(var(--t-accent-rgb), 0.08); color: var(--bs-body-color); }
.t-sidenav-link.active { color: var(--t-accent); font-weight: 500; background: rgba(var(--t-accent-rgb), 0.08); }
.t-sidenav-link.nav-group-link { padding-left: 1.85rem; font-size: 0.82rem; }
.t-sidenav.is-collapsed .t-sidenav-link { justify-content: center; padding-left: 0.55rem; padding-right: 0.55rem; }
.t-sidenav.is-collapsed .t-sidenav-link.nav-group-link { display: none; }
.t-sidenav-section {
    background: none; border: none; width: 100%; cursor: pointer; font-family: inherit;
    color: var(--t-text-muted); margin-top: 0.35rem;
}
.t-sidenav-section:hover { color: var(--bs-body-color); background: rgba(var(--t-accent-rgb), 0.08); }
.t-sidenav-group-icon { display: none; }
.t-sidenav.is-collapsed .t-sidenav-group-icon { display: flex; }
.t-sidenav.is-collapsed .t-sidenav-section svg.nav-chevron { display: none; }

.t-sidenav-divider { height: 1px; background: var(--t-border); margin: 0.3rem 0.75rem; flex-shrink: 0; }

.t-sidenav-new-convo {
    margin: 0 0.4rem 0.4rem; flex-shrink: 0;
    color: var(--t-text-muted); border: 1px dashed var(--t-border);
}
.t-sidenav-new-convo:hover { color: var(--t-accent); border-color: var(--t-accent); background: rgba(var(--t-accent-rgb), 0.06); }

.t-sidenav-recents {
    flex: 1; min-height: 0;
    display: flex; flex-direction: column;
    overflow: hidden;
}
.t-sidenav-recents-label {
    padding: 0.4rem 1rem 0.2rem;
    font-size: 0.7rem; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase;
    color: var(--t-text-muted); flex-shrink: 0;
}
.t-sidenav-recents .sidebar-convos { flex: 1; }
.t-sidenav-view-all {
    display: block; padding: 0.4rem 1rem; font-size: 0.78rem;
    color: var(--t-text-muted); text-decoration: none; flex-shrink: 0;
}
.t-sidenav-view-all:hover { color: var(--bs-body-color); }

.t-sidenav-footer {
    display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap;
    flex-shrink: 0;
}
.t-sidenav-footer-btn {
    display: flex; align-items: center; justify-content: center;
    width: 30px; height: 30px; border-radius: 6px;
    color: var(--t-text-muted); transition: color 0.15s, background 0.15s;
}
.t-sidenav-footer-btn:hover { color: var(--bs-body-color); background: rgba(var(--t-accent-rgb), 0.10); }
/* Show sun (→ switch to light) in dark mode; moon (→ switch to dark) in light mode */
[data-bs-theme="light"] .t-icon-sun  { display: none; }
[data-bs-theme="dark"]  .t-icon-moon { display: none; }
.t-sidenav.is-collapsed .t-sidenav-footer { flex-direction: column; }

/* ── Slim top strip (per-page title/actions only — nav lives in the sidebar) ── */
.t-topstrip {
    position: sticky; top: 0; z-index: 1010;
    height: var(--t-topbar-height); flex-shrink: 0;
    display: flex; align-items: center; justify-content: space-between;
    padding: 0 1rem;
    background: var(--t-surface-elevated);
    border-bottom: 1px solid var(--t-border);
    gap: 0.75rem;
}
.t-topstrip-left { display: flex; align-items: center; gap: 0.5rem; min-width: 0; flex: 1; }
.t-mobile-nav-toggle {
    display: flex; align-items: center; justify-content: center;
    width: 32px; height: 32px; border-radius: 6px; flex-shrink: 0;
    color: var(--t-text-muted); transition: color 0.15s, background 0.15s;
}
.t-mobile-nav-toggle:hover { color: var(--bs-body-color); background: rgba(var(--t-accent-rgb), 0.10); }

/* Newsfeed hides the topstrip entirely for its full-bleed hero, so its
   mobile nav toggle floats standalone instead of living in a topstrip row. */
.nf-mobile-nav-toggle {
    position: fixed; top: 0.75rem; left: 0.75rem; z-index: 1030;
    background: rgba(0, 0, 0, 0.25); color: #fff;
}

@media (max-width: 767.98px) {
    .t-sidenav {
        position: fixed; inset: 0 auto 0 0; height: 100%;
        width: var(--t-sidenav-width) !important;
        transform: translateX(-100%);
        z-index: 1040;
        transition: transform 0.25s ease;
    }
    .t-sidenav.is-mobile-open { transform: translateX(0); }
    .t-sidenav.is-collapsed .t-sidenav-label,
    .t-sidenav.is-collapsed .t-sidenav-recents { display: revert; }
    .t-sidenav.is-collapsed .t-sidenav-link { justify-content: flex-start; }
    .t-sidenav.is-collapsed .t-sidenav-link.nav-group-link { display: flex; }
}

/* ═══════════════════════════════════════════ CHAT LAYOUT ════ */

.chat-layout {
    display: flex;
    height: calc(100vh - var(--t-topbar-height));
    height: calc(100dvh - var(--t-topbar-height)); /* dynamic viewport — shrinks when mobile keyboard opens */
    overflow: hidden;
    position: relative;
}

/* Conversation list */
.sidebar-convos {
    flex: 1;
    overflow-y: auto;
    padding: 6px 0;
    scrollbar-width: thin;
    scrollbar-color: var(--border-color) transparent;
}

.convo-group { margin-bottom: 4px; }
.convo-group-label {
    padding: 8px 14px 3px;
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--text-muted);
    font-weight: 600;
}

.convo-item {
    position: relative;
    display: flex;
    align-items: center;
    padding: 2px 8px 2px 12px;
    border-radius: 6px;
    margin: 0 4px;
    transition: background 0.1s;
}
.convo-item:hover { background: var(--border-color); }
.convo-item.active { background: rgba(108, 142, 191, 0.12); }

.convo-link {
    flex: 1;
    text-decoration: none;
    color: var(--bs-body-color);
    font-size: 0.82rem;
    padding: 5px 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    line-height: 1.3;
}

.convo-actions { display: flex; align-items: center; }
.convo-menu-btn {
    background: none; border: none; padding: 2px 6px;
    color: var(--text-muted); cursor: pointer; font-size: 1rem;
    opacity: 0; transition: opacity 0.1s; border-radius: 4px;
}
.convo-item:hover .convo-menu-btn { opacity: 1; }
.convo-menu-btn:hover { background: var(--border-color); color: var(--bs-body-color); }

.convo-menu {
    position: absolute; right: 8px; top: 100%; z-index: 200;
    background: var(--bs-body-bg);
    border: 1px solid var(--border-color);
    border-radius: 8px; padding: 4px;
    min-width: 120px; box-shadow: 0 4px 16px rgba(0,0,0,0.3);
}
.convo-menu-item {
    display: block; width: 100%; text-align: left;
    background: none; border: none; padding: 6px 10px;
    font-size: 0.82rem; cursor: pointer; border-radius: 4px;
    color: var(--bs-body-color);
}
.convo-menu-item:hover { background: var(--border-color); }

/* Branch conversations — indented under parent */
.convo-branch {
    padding-left: 4px;
    margin-left: 8px;
    border-left: 2px solid var(--border-color);
}
.convo-branch-indicator {
    font-size: 0.75rem;
    color: var(--text-muted);
    margin-right: 3px;
    flex-shrink: 0;
    line-height: 1;
}
.convo-branch-deeper {
    font-size: 0.7rem; color: var(--text-muted); margin-left: 2px;
}

/* Sidebar footer — rows share .t-sidenav-link's inset/hover language so they
   read as a continuation of the nav list above, not a separately-centered block. */
.sidebar-footer {
    padding: 10px 0.4rem;
    border-top: 1px solid var(--border-color);
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 4px;
    min-width: 0;
}
.sidebar-footer-row {
    display: flex;
    align-items: center;
    gap: 0.65rem;
    padding: 0.2rem 0.55rem;
    min-width: 0;
}
.sidebar-footer-actions {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
}
.sidebar-footer-actions form { min-width: 0; }
.sidebar-footer-link {
    font-size: 0.85rem;
    color: var(--text-muted);
    text-decoration: none;
    display: flex; align-items: center; gap: 0.65rem;
    padding: 0.4rem 0.55rem; border-radius: 8px;
    transition: background 0.12s, color 0.15s;
    white-space: nowrap;
    min-width: 0;
}
.sidebar-footer-link:hover { color: var(--bs-body-color); background: rgba(var(--t-accent-rgb), 0.08); }
.sidebar-footer-actions .sidebar-footer-link { width: 100%; }
/* Collapsed rail: theme toggle + budget meter stack into their own full-width
   rows (same shape as .sidebar-footer-actions) instead of sitting side by
   side — two icons can't both center at the nav-icon column position, and
   the pair was overflowing the 56px rail (min-width:auto flex overflow),
   clipping the budget ring off the right edge entirely. Every one of the
   four controls ends up centered at the same inset as the collapsed nav
   icons above (.t-sidenav.is-collapsed .t-sidenav-link) and the same size. */
.t-sidenav.is-collapsed .sidebar-footer-row {
    flex-direction: column;
    align-items: stretch;
    gap: 2px;
    padding: 0;
}
.t-sidenav.is-collapsed #themeToggle {
    width: 100%; height: auto;
    justify-content: center;
    padding: 0.4rem 0.55rem; border-radius: 8px;
}
.t-sidenav.is-collapsed .t-budget-meter { justify-content: center; padding-left: 0.55rem; padding-right: 0.55rem; }
.t-sidenav.is-collapsed .sidebar-footer-link { justify-content: center; padding-left: 0.55rem; padding-right: 0.55rem; }

/* ── Chat Main ── */
.chat-main {
    flex: 1;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    background: var(--chat-bg);
}


.chat-title {
    font-size: 0.9rem;
    font-weight: 600;
    margin: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    cursor: pointer;
    border-bottom: 1px solid transparent;
    transition: border-color 0.15s;
}
.chat-title:hover { border-bottom-color: var(--border-color); }

.loop-status { display: flex; align-items: center; gap: 6px; }

.conv-cost-badge {
    background: transparent;
    border: 1px solid var(--border-color);
    color: var(--bs-secondary-color);
    font-size: 0.7rem;
    font-variant-numeric: tabular-nums;
    letter-spacing: 0.01em;
    padding: 2px 7px;
    border-radius: 10px;
    transition: color 0.2s, border-color 0.2s;
}
.conv-cost-badge:hover {
    color: var(--bs-body-color);
    border-color: var(--bs-secondary-color);
}

/* Messages area */
.chat-messages {
    flex: 1;
    overflow-y: auto;
    padding: 16px 0 8px;
    scroll-behavior: smooth;
    scrollbar-width: thin;
    scrollbar-color: var(--border-color) transparent;
}

.chat-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    height: 100%;
    text-align: center;
    padding: 40px 20px;
    color: var(--text-muted);
}
.chat-empty-icon { font-size: 2.5rem; margin-bottom: 12px; opacity: 0.5; }

/* Messages */
.message {
    display: flex;
    gap: 12px;
    padding: 10px 20px;
    max-width: 100%;
    animation: messageIn 0.2s ease;
}
@keyframes messageIn {
    from { opacity: 0; transform: translateY(6px); }
    to   { opacity: 1; transform: translateY(0); }
}

.message-user {
    flex-direction: row-reverse;
}
.message-user-col {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    max-width: 72%;
}
.message-user .message-body {
    background: var(--message-user-bg);
    border-radius: 14px 14px 4px 14px;
    padding: 10px 14px;
}

.message-assistant .message-body {
    /* width (not just max-width): an assistant bubble is a shrink-to-fit
       flex child by default, so its box sizes to whichever content line is
       currently widest. A tool card's collapsed header is much narrower
       than its expanded panels, so expand/collapse used to reflow the
       whole column — pinning width stops the bubble itself from moving;
       only the card's internal panels grow/shrink. */
    width: 85%;
}

.message-avatar {
    width: 28px;
    height: 28px;
    border-radius: 50%;
    background: var(--accent);
    color: white;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 0.7rem;
    font-weight: 700;
    flex-shrink: 0;
    margin-top: 2px;
}
.message-user .message-avatar { background: #4a7fbf; }

.message-content {
    font-size: 0.9rem;
    line-height: 1.6;
}

/* Markdown body styles */
.markdown-body h1, .markdown-body h2, .markdown-body h3 { margin-top: 1em; margin-bottom: 0.5em; }
.markdown-body h1 { font-size: 1.4em; }
.markdown-body h2 { font-size: 1.2em; }
.markdown-body h3 { font-size: 1.05em; }
.markdown-body p { margin-bottom: 0.7em; }
.markdown-body ul, .markdown-body ol { padding-left: 1.5em; margin-bottom: 0.7em; }
.markdown-body li { margin-bottom: 0.2em; }
.markdown-body code {
    background: rgba(255,255,255,0.08);
    padding: 0.15em 0.4em; border-radius: 4px;
    font-size: 0.85em; font-family: 'SF Mono', 'Cascadia Code', 'Fira Code', monospace;
}
[data-bs-theme="light"] .markdown-body code { background: rgba(0,0,0,0.06); }
.markdown-body pre {
    background: #0d1117; border-radius: 8px; padding: 14px;
    overflow-x: auto; white-space: pre-wrap; word-break: break-word; margin: 0.8em 0;
}
.markdown-body pre code { background: none; padding: 0; font-size: 0.875em; }
[data-bs-theme="light"] .markdown-body pre { background: #f6f8fa; }
.markdown-body blockquote {
    border-left: 3px solid var(--accent); margin: 0.7em 0;
    padding: 4px 12px; color: var(--text-muted);
}
.markdown-body table { width: 100%; border-collapse: collapse; margin: 0.8em 0; font-size: 0.85em; }
.markdown-body th, .markdown-body td { border: 1px solid var(--border-color); padding: 6px 10px; }
.markdown-body th { background: var(--message-user-bg); }
.markdown-body a { color: var(--accent); }
.markdown-body hr { border-color: var(--border-color); margin: 1em 0; }

/* Tool call blocks.
   width: 100% (rather than the default shrink-to-fit) keeps the card's
   footprint stable across expand/collapse — without it, a collapsed card
   (header row only) sizes to its narrow content, then jumps wide the moment
   a details/result panel with longer lines opens, reflowing the whole
   message column. max-width caps it so it never outgrows the 85%-wide
   assistant bubble it sits in (see .message-assistant .message-body). */
.tool-call-block {
    width: 100%;
    max-width: 100%;
    box-sizing: border-box;
    margin: 8px 0;
    border: 1px solid var(--border-color);
    border-radius: 8px;
    overflow: hidden;
    font-size: 0.82rem;
}
.tool-call-header {
    display: flex; align-items: center; gap: 8px;
    padding: 7px 12px;
    background: rgba(255,255,255,0.04);
    border-bottom: 1px solid var(--border-color);
}
[data-bs-theme="light"] .tool-call-header { background: rgba(0,0,0,0.03); }
.tool-call-icon { font-size: 0.8rem; color: var(--accent); }
.tool-call-name { font-weight: 600; }

/* Details/Result toggles: pressed state must read clearly at a glance,
   since both panels can be open at once and are otherwise easy to conflate
   — the labeled panel headers below carry the rest of that disambiguation. */
.tool-toggle-btn.active {
    opacity: 1;
    background: rgba(var(--t-accent-rgb), 0.16);
    color: var(--accent);
    font-weight: 600;
}

/* Expanded details/result panels each open with their own small label so
   which-is-which stays legible even with both panels open together. Both
   panels always exist in the DOM (x-show toggles display, not presence), so
   the details panel — always immediately after the header — omits its own
   top border (the header's border-bottom already draws that line); the
   result panel keeps its top border to separate it from an open details
   panel above it, and reads as the sole separator from the header when
   details is collapsed. Without this split, an open panel doubled up with
   the header's border-bottom into a stray-looking double line. */
.tool-call-header + .tool-call-panel { border-top: none; }
.tool-call-panel ~ .tool-call-panel { border-top: 1px solid var(--border-color); }
.tool-call-panel-label {
    padding: 6px 12px 0;
    font-size: 0.7rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--text-muted);
}

/* Result panel's label + raw/pretty toggle share one row (moved up from the
   panel's bottom, #684 follow-up) so the toggle reads as acting on "Result"
   rather than floating unattached below the chrome line. */
.tool-call-panel-label-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    padding: 6px 12px 0;
}
.tool-call-panel-label-row .tool-call-panel-label { padding: 0; }

.raw-toggle-btn {
    font-size: 0.68rem;
    font-weight: 600;
    padding: 2px 9px;
    border: 1px solid var(--border-color);
    border-radius: 999px;
    background: none;
    color: var(--text-muted);
    line-height: 1.5;
    transition: color 0.15s, border-color 0.15s, background 0.15s;
}
.raw-toggle-btn:hover {
    color: var(--accent);
    border-color: var(--accent);
    background: rgba(var(--t-accent-rgb), 0.1);
}

.tool-call-input {
    padding: 8px 12px;
    overflow-x: auto;
    max-height: 200px;
    white-space: pre-wrap;
    word-break: break-word;
}

/* Tool result content */
.tool-result-content {
    padding: 8px 12px;
    white-space: pre-wrap;
    word-break: break-word;
    overflow-wrap: break-word;
    font-size: 0.78rem;
    line-height: 1.5;
    margin: 0;
    font-family: 'SF Mono', 'Cascadia Code', 'Fira Code', monospace;
}

/* "External content — treated as untrusted" badge (#536 envelope framing).
   A dedicated class rather than bare Bootstrap .badge + *-subtle utilities:
   the subtle warning tokens are low-contrast enough against the card's own
   dark background to read as unstyled text. Equal top/bottom margin (not
   top-only) gives it breathing room from the payload that follows. */
.tool-untrusted-badge {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 4px 10px;
    margin: 8px 12px;
    border-radius: 6px;
    border: 1px solid rgba(var(--bs-warning-rgb, 255, 193, 7), 0.35);
    background: rgba(var(--bs-warning-rgb, 255, 193, 7), 0.14);
    color: var(--bs-warning-text-emphasis, #ffca2c);
    font-size: 0.72rem;
    font-weight: 600;
}

/* Result "chrome" — harness-authored suffixes (budget/checklist/goal
   metadata) appended below the payload. Previously bare text-utility
   classes with no box at all, so it read as stray, unpadded text
   floating under the result; now a distinct muted footer strip. The dashed
   top border stays as the divider from the payload above, but the text
   itself stays in the ordinary UI font rather than picking up the result
   payload's monospace stack. */
.tool-chrome {
    padding: 6px 12px;
    margin: 0;
    background: rgba(0,0,0,0.08);
    border-top: 1px dashed var(--border-color);
    color: var(--text-muted);
    font-family: inherit;
    font-size: 0.72rem;
    line-height: 1.5;
    white-space: pre-wrap;
}
[data-bs-theme="light"] .tool-chrome { background: rgba(0,0,0,0.03); }

/* Flex layout for the reasoning toggle and the tokens-only static line.
   Deliberately NOT Bootstrap's .d-flex: that utility is `display:flex
   !important`, which outranks the inline `display:none` Alpine's x-show sets
   to hide an element — so a `.d-flex` + `x-show` element can never hide (the
   "Reasoning: 0 tokens" ghost line, #219 / follow-up). These plain (non-
   !important) rules let x-show's inline display:none win when the guard is
   false. A static guard (chat/test_stream_items_display_toggle.py) keeps
   `.d-flex` from creeping back onto an x-show element. */
.reasoning-toggle,
.reasoning-stat {
    display: flex;
}

/* Reasoning rendered as markdown — wraps .markdown-body, overrides heading sizes */
.reasoning-markdown {
    font-size: 0.75rem;
    color: var(--text-muted);
    background: rgba(0,0,0,0.12);
    border-radius: 6px;
    padding: 8px 10px;
    line-height: 1.5;
}
[data-bs-theme="light"] .reasoning-markdown { background: rgba(0,0,0,0.04); }
.reasoning-markdown h1,
.reasoning-markdown h2,
.reasoning-markdown h3,
.reasoning-markdown h4,
.reasoning-markdown h5,
.reasoning-markdown h6 {
    font-size: inherit;
    font-weight: 600;
    margin: 0.3em 0;
}
.reasoning-markdown p { margin-bottom: 0.5em; }
.reasoning-markdown p:last-child { margin-bottom: 0; }

/* Reasoning / thinking content (legacy pre-wrap fallback) */
.reasoning-content {
    font-size: 0.75rem;
    white-space: pre-wrap;
    word-break: break-word;
    overflow-wrap: break-word;
    line-height: 1.5;
    color: var(--text-muted);
    background: rgba(0,0,0,0.12);
    border-radius: 6px;
    padding: 8px 10px;
    font-family: inherit;
    margin: 0;
}
[data-bs-theme="light"] .reasoning-content { background: rgba(0,0,0,0.04); }

/* Compaction notice */
.compaction-notice {
    margin: 8px 0;
    padding: 7px 12px;
    border: 1px dashed var(--border-color);
    border-radius: 8px;
    font-size: 0.82rem;
    color: var(--text-muted);
}
.compaction-notice summary {
    cursor: pointer;
    list-style: none;
    user-select: none;
}
.compaction-notice summary::-webkit-details-marker { display: none; }

/* Scroll-to-bottom button */
.scroll-to-bottom-wrap {
    position: relative;
    display: flex;
    justify-content: center;
    flex-shrink: 0;
    pointer-events: none;
    margin-top: -32px;
    margin-bottom: 8px;
    z-index: 40;
}
.scroll-to-bottom-btn {
    pointer-events: all;
    display: flex; align-items: center; gap: 6px;
    padding: 6px 14px;
    background: var(--accent);
    color: #fff;
    border: none; border-radius: 20px;
    font-size: 0.8rem; font-weight: 500;
    cursor: pointer;
    box-shadow: 0 2px 8px rgba(0,0,0,0.4);
    transition: background 0.15s, transform 0.1s;
}
.scroll-to-bottom-btn:hover { background: #5a7aab; transform: translateY(-1px); }

/* Typing indicator */
.typing-indicator {
    display: flex; align-items: center; gap: 4px;
    padding: 8px 0;
}
.typing-indicator span {
    width: 6px; height: 6px; border-radius: 50%;
    background: var(--text-muted);
    animation: typingBounce 1.2s infinite ease-in-out;
}
.typing-indicator span:nth-child(2) { animation-delay: 0.2s; }
.typing-indicator span:nth-child(3) { animation-delay: 0.4s; }
@keyframes typingBounce {
    0%, 60%, 100% { transform: translateY(0); opacity: 0.4; }
    30% { transform: translateY(-5px); opacity: 1; }
}

/* Message actions */
.message-actions {
    display: flex; gap: 4px; margin-top: 6px; opacity: 0;
    transition: opacity 0.15s;
}
.message-assistant:hover .message-actions,
.message-user:hover .message-actions { opacity: 1; }
.msg-action-btn {
    background: none; border: none; padding: 3px 6px;
    color: var(--text-muted); cursor: pointer;
    border-radius: 4px; font-size: 0.75rem;
    transition: background 0.1s, color 0.1s;
}
.msg-action-btn:hover { background: var(--border-color); color: var(--bs-body-color); }
.msg-action-btn:disabled { opacity: 0.4; cursor: default; }

/* #71 edit-and-resend / regenerate */
.msg-edit-box { margin-top: 4px; }
.regenerate-model-menu { margin-top: 2px; }

/* ask_user sticky zone */
.uiq-wrap {
    flex-shrink: 0;
    border-top: 1px solid var(--border-color);
    padding: 14px 20px 16px;
    background: rgba(255,255,255,.02);
    display: flex;
    flex-direction: column;
    gap: 10px;
    max-height: 55vh;
    overflow-y: auto;
}
[data-bs-theme="light"] .uiq-wrap { background: rgba(0,0,0,.02); }
.uiq-question { font-size: .95rem; font-weight: 600; margin: 0; color: var(--bs-body-color); }
.uiq-options { display: flex; flex-direction: column; gap: 6px; }
.uiq-option-row {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 9px 12px;
    border: 1px solid var(--border-color);
    border-radius: 8px;
    cursor: pointer;
    transition: background .12s, border-color .12s;
    user-select: none;
}
.uiq-option-row:hover { background: rgba(255,255,255,.06); border-color: rgba(255,255,255,.22); }
.uiq-option-row--selected { background: rgba(var(--bs-primary-rgb),.1); border-color: var(--bs-primary); }
[data-bs-theme="light"] .uiq-option-row:hover { background: rgba(0,0,0,.04); border-color: rgba(0,0,0,.18); }
[data-bs-theme="light"] .uiq-option-row--selected { background: rgba(var(--bs-primary-rgb),.08); }
.uiq-checkbox,
.uiq-radio {
    flex-shrink: 0;
    width: 16px;
    height: 16px;
    margin-top: 2px;
    border: 1.5px solid rgba(255,255,255,.3);
    background: transparent;
    transition: border-color .12s, background .12s;
}
.uiq-checkbox { border-radius: 4px; }
.uiq-radio    { border-radius: 50%; }
.uiq-checkbox--checked {
    background: var(--bs-primary);
    border-color: var(--bs-primary);
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill='white' d='M13.854 3.646a.5.5 0 0 1 0 .708l-7 7a.5.5 0 0 1-.708 0l-3.5-3.5a.5.5 0 1 1 .708-.708L6.5 10.293l6.646-6.647a.5.5 0 0 1 .708 0z'/%3E%3C/svg%3E");
    background-size: 12px;
    background-repeat: no-repeat;
    background-position: center;
}
.uiq-radio--checked {
    border-color: var(--bs-primary);
    background: radial-gradient(circle, var(--bs-primary) 45%, transparent 46%);
}
[data-bs-theme="light"] .uiq-checkbox,
[data-bs-theme="light"] .uiq-radio { border-color: rgba(0,0,0,.3); }
.uiq-option-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.uiq-option-label { font-size: .9rem; color: var(--bs-body-color); line-height: 1.3; }
.uiq-option-description { font-size: .78rem; color: var(--text-muted); line-height: 1.3; }
.uiq-other-input {
    display: flex;
    flex-direction: column;
    gap: 4px;
    padding-left: 26px;
    max-width: 380px;
}
.uiq-submit-btn {
    align-self: flex-start;
    background: var(--bs-primary);
    border: none;
    border-radius: 7px;
    color: #fff;
    padding: 7px 18px;
    font-size: .875rem;
    font-weight: 500;
    cursor: pointer;
    transition: opacity .15s;
}
.uiq-submit-btn:disabled { opacity: .4; cursor: not-allowed; }
.uiq-submit-btn:not(:disabled):hover { opacity: .88; }

/* HITL approval */
.hitl-approval { padding: 0 20px; }
.hitl-card {
    border: 1px solid #ffc107;
    border-radius: 10px;
    padding: 14px 16px;
    background: rgba(255, 193, 7, 0.06);
}
.hitl-card pre { background: rgba(0,0,0,0.2); border-radius: 6px; padding: 8px; font-size: 0.75rem; }

/* Inbound security-hold preview: collapsible excerpt of the flagged content. */
.security-hold-preview {
    max-height: 16rem;
    overflow: auto;
    word-break: break-word;
    font-family: var(--bs-font-monospace);
    font-size: 0.75rem;
    line-height: 1.6;
}
.security-hold-hl {
    background: rgba(220, 53, 69, 0.30);
    color: inherit;
    padding: 0 2px;
    border-radius: 3px;
}

/* ── Composer ── */
/* Tasks strip (#987 PR3) — background tool jobs, directly above the composer.
   Plain (non-!important) display rules on purpose: the root and its rows are
   x-show'd, and a Bootstrap d-flex there would pin them open. */
.async-tasks-strip {
    margin: 0 0 8px;
    padding: 6px 10px;
    border: 1px solid var(--bs-border-color);
    border-radius: 8px;
    background: var(--bs-tertiary-bg);
    font-size: 0.8rem;
}
.async-tasks-strip-title {
    display: flex;
    align-items: center;
    gap: 6px;
    font-weight: 600;
    margin-bottom: 4px;
}
.async-tasks-strip-title .spinner-border { width: 0.8rem; height: 0.8rem; border-width: 0.12em; }
.async-task-row {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 2px 0;
    min-width: 0;
}
.async-task-id { font-size: 0.72rem; }
.async-task-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.async-tasks-strip-note { font-size: 0.72rem; margin-top: 4px; }

.chat-composer {
    flex-shrink: 0;
    border-top: 1px solid var(--border-color);
    padding: 10px 16px 14px;
    position: relative;
}

.composer-config {
    padding: 12px 4px;
    border-bottom: 1px solid var(--border-color);
    margin-bottom: 10px;
}
.composer-config-inner { max-width: 100%; }

.composer-bar {
    display: flex;
    align-items: flex-end;
    gap: 8px;
    background: var(--message-user-bg);
    border: 1px solid var(--border-color);
    border-radius: 14px;
    padding: 8px 10px;
    transition: border-color 0.15s;
}
.composer-bar:focus-within { border-color: var(--accent); }

.composer-textarea {
    flex: 1;
    background: none;
    border: none;
    outline: none;
    resize: none;
    font-size: 0.9rem;
    line-height: 1.5;
    color: var(--bs-body-color);
    max-height: 200px;
    overflow-y: auto;
    padding: 2px 0;
    scrollbar-width: thin;
}
.composer-textarea::placeholder { color: var(--text-muted); }

.composer-btn {
    background: none; border: none;
    color: var(--text-muted); cursor: pointer;
    padding: 4px; border-radius: 6px;
    display: flex; align-items: center; justify-content: center;
    flex-shrink: 0; transition: color 0.15s, background 0.15s;
    align-self: flex-end; margin-bottom: 1px;
}
.composer-btn:hover { color: var(--bs-body-color); background: var(--border-color); }

.composer-send {
    background: var(--accent);
    border: none; color: white; cursor: pointer;
    width: 34px; height: 34px; border-radius: 8px;
    display: flex; align-items: center; justify-content: center;
    flex-shrink: 0; transition: background 0.15s, opacity 0.15s;
    align-self: flex-end;
}
.composer-send:hover:not(:disabled) { background: #5a7aab; }
.composer-send:disabled { opacity: 0.4; cursor: not-allowed; }

.composer-footer {
    padding: 4px 2px 0;
    font-size: 0.75rem;
    color: var(--text-muted);
    display: flex; align-items: center;
}

/* ── Composer tool-count badge + hover popover ── */
.tool-count-badge {
    position: relative;
    outline: none;
}
.tool-count-badge .badge { cursor: default; }
.tool-count-popover {
    display: none;
    position: absolute;
    bottom: calc(100% + 6px);
    left: 0;
    z-index: 20;
    min-width: 220px;
    max-width: 340px;
    max-height: 260px;
    overflow-y: auto;
    background: var(--bs-body-bg);
    border: 1px solid var(--border-color);
    border-radius: 8px;
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.25);
    padding: 8px 10px;
}
.tool-count-badge:hover .tool-count-popover,
.tool-count-badge:focus-within .tool-count-popover,
.tool-count-badge:focus .tool-count-popover {
    display: block;
}
.tool-count-popover-group + .tool-count-popover-group { margin-top: 6px; }
.tool-count-popover-heading {
    font-size: 0.7rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    color: var(--text-muted);
    margin-bottom: 2px;
}
.tool-count-popover-list {
    font-size: 0.78rem;
    color: var(--bs-body-color);
    line-height: 1.4;
}

/* ── Skill chip on sent user messages ── */
.skill-chip {
    display: inline-flex; align-items: center; gap: 4px;
    font-size: 0.72rem; font-weight: 500;
    color: var(--accent); opacity: 0.85;
}

/* ── Composer skill selection UI ── */
.skill-chip-selected {
    display: flex; align-items: center; gap: 5px;
    font-size: 0.75rem; font-weight: 500;
    color: var(--accent);
    padding: 2px 6px 4px;
}
.skill-chip-clear {
    background: none; border: none; cursor: pointer;
    color: var(--text-muted); font-size: 0.9rem;
    padding: 0 2px; line-height: 1;
}
.skill-chip-clear:hover { color: var(--bs-body-color); }
.composer-btn.active { color: var(--accent); }

/* ── Vision attachments (#67) ── */
.composer-attachments {
    display: flex; flex-wrap: wrap; gap: 8px;
    padding: 6px 4px; margin-bottom: 4px;
}
.attach-chip {
    display: inline-flex; align-items: center; gap: 6px;
    max-width: 220px; padding: 3px 6px 3px 3px;
    border: 1px solid var(--border-color); border-radius: 8px;
    background: var(--bs-tertiary-bg); cursor: pointer;
}
.attach-chip:hover { border-color: var(--accent); }
.attach-chip-thumb {
    width: 32px; height: 32px; object-fit: cover; border-radius: 5px; flex-shrink: 0;
}
.attach-chip-icon {
    display: inline-flex; align-items: center; justify-content: center;
    width: 32px; height: 32px; border-radius: 5px; flex-shrink: 0;
    background: var(--accent); color: #fff;
    font-size: 0.6rem; font-weight: 700; letter-spacing: 0.04em;
}
.attach-chip-name {
    font-size: 0.75rem; color: var(--bs-body-color);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.attach-chip-remove {
    background: none; border: none; cursor: pointer; padding: 0 2px;
    color: var(--text-muted); font-size: 1rem; line-height: 1; flex-shrink: 0;
}
.attach-chip-remove:hover { color: var(--bs-danger); }
.attach-chip-warn { border-color: var(--bs-warning); }
.attach-chip-warn-badge { color: var(--bs-warning); font-size: 0.8rem; flex-shrink: 0; }

/* Flagged uploads awaiting an "attach anyway" confirm (#442 Slice 2) */
.composer-flagged-attachments {
    display: flex; flex-direction: column; gap: 6px;
    padding: 6px 4px; margin-bottom: 4px;
}
.flagged-attach-card {
    border: 1px solid var(--bs-warning); border-radius: 8px;
    background: var(--bs-tertiary-bg); padding: 8px 10px;
}
.flagged-attach-header {
    display: flex; align-items: center; gap: 6px;
    font-size: 0.8rem; font-weight: 600; color: var(--bs-warning);
}
.flagged-attach-detail {
    margin: 4px 0 8px; white-space: pre-wrap; word-break: break-word;
}
.flagged-attach-actions { display: flex; gap: 8px; }

/* Attachments shown inside a committed user bubble */
.msg-attachments { display: flex; flex-wrap: wrap; gap: 8px; }
.msg-attachment { cursor: pointer; }
.msg-attachment-thumb {
    max-width: 180px; max-height: 180px; border-radius: 8px;
    border: 1px solid var(--border-color); display: block;
}
.msg-attachment-thumb:hover { border-color: var(--accent); }
.msg-attachment-pdf {
    display: inline-flex; align-items: center; gap: 8px;
    padding: 8px 12px; border-radius: 8px;
    border: 1px solid var(--border-color); background: var(--bs-tertiary-bg);
}
.msg-attachment-pdf:hover { border-color: var(--accent); }
.msg-attachment-name { font-size: 0.8rem; color: var(--bs-body-color); }

/* Drawer / lightbox */
.attachment-drawer-overlay {
    position: fixed; inset: 0; z-index: 1080;
    display: flex; align-items: center; justify-content: center;
    background: rgba(0, 0, 0, 0.7); padding: 24px;
}
.attachment-drawer {
    display: flex; flex-direction: column;
    width: min(1000px, 96vw); height: min(88vh, 1000px);
    background: var(--bs-body-bg); border: 1px solid var(--border-color);
    border-radius: 12px; overflow: hidden;
}
.attachment-drawer-head {
    display: flex; align-items: center; justify-content: space-between; gap: 12px;
    padding: 10px 14px; border-bottom: 1px solid var(--border-color);
}
.attachment-drawer-title { font-size: 0.85rem; color: var(--bs-body-color); min-width: 0; }
.attachment-drawer-actions { display: flex; gap: 8px; flex-shrink: 0; }
.attachment-drawer-body {
    flex: 1; min-height: 0; display: flex; align-items: center; justify-content: center;
    background: var(--bs-tertiary-bg); overflow: auto;
}
.attachment-drawer-image { max-width: 100%; max-height: 100%; object-fit: contain; }
.attachment-drawer-pdf { width: 100%; height: 100%; border: 0; }

.skill-menu {
    position: absolute; bottom: calc(100% + 6px); left: 0; right: 0;
    background: var(--sidebar-bg);
    border: 1px solid var(--border-color);
    border-radius: 10px;
    box-shadow: 0 4px 16px rgba(0,0,0,0.18);
    z-index: 200;
    max-height: 260px;
    display: flex; flex-direction: column;
    overflow: hidden;
}
.skill-menu-search { padding: 8px 10px 4px; }
.skill-menu-input {
    width: 100%; background: var(--bs-body-bg);
    border: 1px solid var(--border-color); border-radius: 6px;
    padding: 5px 9px; font-size: 0.85rem;
    color: var(--bs-body-color); outline: none;
}
.skill-menu-input:focus { border-color: var(--accent); }
.skill-menu-list { overflow-y: auto; flex: 1; padding: 4px 4px 6px; }
.skill-menu-item {
    display: flex; flex-direction: column; align-items: flex-start;
    width: 100%; background: none; border: none; text-align: left;
    padding: 7px 10px; border-radius: 6px; cursor: pointer;
    color: var(--bs-body-color); transition: background 0.1s;
}
.skill-menu-item:hover,
.skill-menu-item.active { background: var(--border-color); }
.skill-menu-item-name { font-size: 0.85rem; font-weight: 500; }
.skill-menu-item-desc { font-size: 0.75rem; line-height: 1.3; margin-top: 1px; }
.skill-menu-empty { font-size: 0.8rem; }

/* ── Artifact Panel ── */
.artifact-panel {
    width: var(--artifact-panel-width);
    flex-shrink: 0;
    border-left: 1px solid var(--border-color);
    background: var(--sidebar-bg);
    display: flex;
    flex-direction: column;
    overflow: hidden;
    transform: translateX(100%);
    transition: transform 0.25s ease;
    position: absolute; right: 0; top: 0; height: 100%;
    z-index: 90;
}
.artifact-panel.open { transform: translateX(0); }

@media (min-width: 1200px) {
    .artifact-panel {
        position: relative;
        transform: none;
        display: none;
    }
    .artifact-panel.open { display: flex; }
}

.artifact-panel-header {
    display: flex; align-items: center; justify-content: space-between;
    padding: 14px 14px 12px;
    border-bottom: 1px solid var(--border-color);
    font-size: 0.85rem;
}
.artifact-panel-body { flex: 1; overflow-y: auto; padding: 10px; }
.artifact-card-link { text-decoration: none; display: block; margin-bottom: 8px; }
.artifact-card {
    border: 1px solid var(--border-color);
    border-radius: 8px; padding: 10px 12px;
    transition: background 0.1s; color: var(--bs-body-color);
}
.artifact-card:hover { background: var(--border-color); }
.artifact-card-title { font-size: 0.82rem; font-weight: 500; margin-bottom: 2px; }
.artifact-card-date { font-size: 0.72rem; }

/* Branch tree panel */
.branch-tree-panel {
    width: 320px;
    flex-shrink: 0;
    border-left: 1px solid var(--border-color);
    background: var(--sidebar-bg);
    display: flex;
    flex-direction: column;
    overflow: hidden;
    transform: translateX(100%);
    transition: transform 0.25s ease;
    position: absolute; right: 0; top: 0; height: 100%;
    z-index: 89;
}
.branch-tree-panel.open { transform: translateX(0); }
@media (min-width: 1200px) {
    .branch-tree-panel { position: relative; transform: none; display: none; }
    .branch-tree-panel.open { display: flex; }
}
.branch-tree-panel-header {
    display: flex; align-items: center; justify-content: space-between;
    padding: 14px 14px 12px;
    border-bottom: 1px solid var(--border-color);
    font-size: 0.85rem;
    flex-shrink: 0;
}
.branch-tree-panel-body { flex: 1; overflow-y: auto; padding: 8px 0; }

.branch-tree-entry {
    display: flex; align-items: flex-start; gap: 6px;
    padding: 8px 12px;
    text-decoration: none;
    color: var(--bs-body-color);
    border-radius: 6px;
    margin: 2px 6px;
    transition: background 0.12s;
    border-left: 2px solid transparent;
}
.branch-tree-entry:hover { background: var(--border-color); color: var(--bs-body-color); }
.branch-tree-entry--current {
    border-left-color: var(--bs-primary);
    background: color-mix(in srgb, var(--bs-primary) 10%, transparent);
}
.branch-tree-connector {
    font-family: monospace; font-size: 0.75rem;
    color: var(--text-muted); flex-shrink: 0;
    width: 12px; padding-top: 1px;
}
.branch-tree-info { flex: 1; min-width: 0; }
.branch-tree-title { font-size: 0.82rem; font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.branch-tree-preview { font-size: 0.72rem; color: var(--text-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; margin-top: 1px; }
.branch-tree-meta { font-size: 0.7rem; color: var(--text-muted); margin-top: 3px; }
.branch-tree-current-badge { font-size: 0.6rem; color: var(--bs-primary); flex-shrink: 0; margin-top: 2px; }

/* Branch ancestor breadcrumb */
.branch-breadcrumb {
    display: flex; align-items: center; flex-wrap: wrap; gap: 2px;
    padding: 6px 16px 4px;
    font-size: 0.75rem;
    color: var(--text-muted);
    border-bottom: 1px solid var(--border-color);
    flex-shrink: 0;
}
.branch-breadcrumb-item {
    color: var(--text-muted); text-decoration: none;
    padding: 1px 4px; border-radius: 3px;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 180px;
    transition: color 0.1s;
}
a.branch-breadcrumb-item:hover { color: var(--bs-body-color); }
.branch-breadcrumb-current { color: var(--bs-body-color); font-weight: 500; }
.branch-breadcrumb-sep { color: var(--text-muted); }

/* Inline branch indicator below messages */
.branch-indicator {
    display: flex; flex-wrap: wrap; gap: 6px;
    margin-left: 44px; margin-top: -4px; margin-bottom: 8px;
    padding: 0 16px 0 0;
}
.branch-indicator-link {
    display: inline-flex; align-items: center; gap: 4px;
    font-size: 0.72rem; color: var(--text-muted);
    text-decoration: none; padding: 2px 8px;
    border: 1px solid var(--border-color); border-radius: 99px;
    transition: color 0.12s, border-color 0.12s;
}
.branch-indicator-link:hover { color: var(--bs-body-color); border-color: var(--bs-body-color); }

/* Sidebar backdrop (mobile) */
.sidebar-backdrop {
    position: fixed; inset: 0;
    background: rgba(0,0,0,0.5);
    z-index: 99;
    opacity: 0; pointer-events: none;
    transition: opacity 0.25s;
}
.sidebar-backdrop.show { opacity: 1; pointer-events: all; }

/* ═══════════════════════════════════════ MOBILE ════ */
@media (max-width: 767.98px) {
    .chat-main { width: 100%; }
    .message-user-col { max-width: 88%; }
    .message-assistant .message-body { max-width: 95%; }

    /* Prevent iOS Safari from zooming in when the composer is focused.
       iOS zooms on inputs with font-size < 16px; setting it to 16px avoids that. */
    .composer-textarea { font-size: 16px; }
}

/* ── Chat topbar overflow menu (mobile) ── */
.t-chat-actions-menu {
    min-width: 220px;
}
.t-chat-actions-menu .dropdown-item {
    display: flex; align-items: center; gap: 8px;
}
.t-chat-actions-menu .dropdown-item svg { flex-shrink: 0; opacity: 0.75; }

/* ═══════════════════════════════════════ ARTIFACT LIBRARY ════ */
.artifact-card-grid {
    transition: box-shadow 0.15s;
    color: var(--bs-body-color);
}
.artifact-card-grid:hover { box-shadow: 0 0 0 2px var(--accent); }


/* Model-slug picker (#876) — `templates/partials/_model_slug_picker.html`.
   The row highlight is its own rule rather than a Bootstrap utility because the
   panel's rows are plain buttons, not list-group items. */
.tg-model-picker-item.active,
.tg-model-picker-item:hover { background-color: var(--bs-secondary-bg); }
