/* ============================================================
   CHAT PANEL
   ============================================================ */


#chat-panel {
    --chat-pad: 6px;
    width: var(--chat-w);
    min-width: 280px;
    /* Canonical glass — same recipe as landing's .pricing-card and the
     * account modal. Translucent layered gradient + blur lets the lapis
     * sky behind the app glow through, so the chat reads as luminous
     * material instead of a solid slate plate. */
    background: var(--surface-glass-bg);
    backdrop-filter: var(--surface-glass-blur);
    -webkit-backdrop-filter: var(--surface-glass-blur);
    border-left: var(--surface-glass-border);
    display: flex;
    flex-direction: column;
    flex-shrink: 0;
    min-height: 0;
    overflow: hidden;
}

#chat-header {
    display: flex;
    align-items: center;
    gap: 4px;
    padding: 10px calc(var(--chat-pad) + 7px) 6px calc(var(--chat-pad) + 4px);
    flex-shrink: 0;
    border-bottom: 1px solid rgba(255,255,255,0.04);
}

/* Running pulse — appears in the header when the agent is mid-flight.
   Toggled via .is-streaming on #chat-panel by chat-core.js _updateUI. */
#chat-panel.is-streaming #thread-switcher::after {
    content: '';
    flex-shrink: 0;
    width: 6px; height: 6px;
    border-radius: 50%;
    background: var(--accent);
    margin: 0 4px 0 6px;
    animation: chat-pulse 1.4s ease-in-out infinite;
}
@keyframes chat-pulse {
    0%, 100% { opacity: 0.35; transform: scale(0.85); }
    50%      { opacity: 1;    transform: scale(1); }
}

#thread-switcher {
    position: relative;
    display: flex;
    align-items: center;
    gap: 4px;
    flex: 1;
    min-width: 0;
}

#thread-label {
    font: 600 14px var(--sans);
    color: var(--t1);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    flex: 1;
    min-width: 0;
}

/* ---- Messages ---- */
#chat-messages {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    padding: 8px 6px;
    display: flex;
    flex-direction: column;
    gap: 10px;
    /* Zero-width scrollbar — still scrolls (touch/wheel/keyboard) but
       doesn't reserve a column. Cards get the full panel width. */
    scrollbar-width: none;            /* Firefox */
    -ms-overflow-style: none;         /* legacy Edge / IE */
}
#chat-messages::-webkit-scrollbar { width: 0; height: 0; }   /* WebKit/Blink */

/* Chat empty extends the shared .empty-state primitive — fills available height. */
.chat-empty {
    flex: 1;
    justify-content: center;
    padding: 32px 20px;
}

.chat-empty-icon { opacity: 0.3; }

/* Right-aligned chat bubble, "soft sheen" treatment — visually distinct from
   the gold-underline input below. Borderless lapis fill with a subtle
   top-lighter gradient + an inset top highlight (lit from above) + a faint
   drop shadow. No gold: the message reads as "you said this" while gold stays
   reserved for agent actions and the send button. Small bottom-right tail. */
.msg.user {
    align-self: flex-end;
    max-width: 84%;
    margin-left: 32px;
}
.msg.user .msg-body {
    background: linear-gradient(180deg, var(--chrome-active) 0%, var(--chrome-surface) 100%);
    border: none;
    padding: 9px 13px;
    border-radius: 14px 14px 5px 14px;
    font-size: var(--fs-base);
    color: var(--t1);
    line-height: 1.5;
    box-shadow:
        inset 0 1px 0 rgba(255,255,255,0.07),
        0 1px 4px rgba(0,0,0,0.35);
}
.msg.assistant .msg-body {
    font-size: var(--fs-base);
    color: var(--t1);
    line-height: 1.7;
}
.msg.assistant .msg-body p { margin-bottom: 10px; }
.msg.assistant .msg-body p:last-child { margin-bottom: 0; }
.msg.assistant .msg-body strong { color: var(--t1); font-weight: 600; }
.msg.assistant .msg-body em { color: var(--t2); font-style: italic; }
.msg.system .msg-body {
    font-size: var(--fs-sm);
    color: var(--red);
    padding: 6px 0;
}
.msg.system.chat-msg-warning .msg-body {
    color: var(--warning);
}

/* ---- Tool steps ---- */
/* Narrow chat panel (~280px) — every pixel of horizontal indent costs.
   No rail, no left padding on the group, minimal head padding. Adjacent
   rows form a visual group via shared bg-tint on hover and tight spacing;
   inter-group separation comes from the chat-messages gap. */
.tool-group {
    margin: 2px 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 3px;
}

.tool-step { display: block; }
.tool-step-head {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 3px 4px;
    font-size: var(--fs-sm);
    cursor: pointer;
    color: var(--t3);
    border-radius: var(--radius-sm);
    transition: background var(--dur), color var(--dur);
}
.tool-step-head:hover { background: var(--chrome-hover); color: var(--t2); }

/* Status icon only — ✓ done, spinner running, × failed.
   The tool-type icon was dropped: the verb in the label ("Searched",
   "Read", "Registered") already conveys the kind of action, so a second
   icon doubled the chrome for no extra signal. */
.tool-step-status {
    flex-shrink: 0;
    display: flex;
    align-items: center;
}
.tool-step-status svg { width: 12px; height: 12px; }
.tool-step-icon { display: none; }
.tool-step.done .tool-check { color: var(--accent); opacity: 0.85; }
.tool-step.done .tool-step-head:hover .tool-check { opacity: 1; }
.tool-spinner { color: var(--accent); animation: spin 1.2s linear infinite; }
.tool-step.failed .tool-fail { color: var(--red); }

/* Label — single line with ellipsis. ALL tool rows now use the same dim
   weight regardless of tool kind (action vs info). Visual hierarchy lives
   in the change cards (gold-bordered glass panels); tool rows are a calm
   ambient ticker of "what the agent did". Click any row to expand details. */
.tool-step-label {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-weight: 450;
    color: var(--t2);
}

/* Info vs action: identical at rest. The whole tool-row column is one
   ambient layer below the gold change cards. No hover color shift —
   row click expands the detail panel, that's the affordance. */

/* Affordance slot — tiny chevron on the right that rotates 90° when open.
   Dim by default, brightens on hover. The only signal of clickability.
   No row bg flash, no chrome shift — keep the stream calm. */
.tool-step-affordance {
    flex-shrink: 0;
    display: flex;
    align-items: center;
    color: var(--t4);
    opacity: 0.55;
    transition: opacity var(--dur), color var(--dur), transform var(--dur);
}
.tool-step-head:hover .tool-step-affordance { opacity: 1; color: var(--t2); }
.tool-step-affordance.expand { transform: rotate(0deg); }
.tool-step:not(.collapsed) .tool-step-affordance.expand { transform: rotate(90deg); }

/* Right-side hint + duration — quiet facts that sit by the chevron, never a
   status colour. Hint carries a write's magnitude or a fold's total; dur is how
   long the call took (live runs only, shown only when it's worth a second). The
   label flex-grows and pushes both to the right edge; each hides when empty. */
.tool-step-hint {
    flex-shrink: 0;
    font: 450 11px var(--sans);
    color: var(--t3);
}
.tool-step-dur {
    flex-shrink: 0;
    font: 500 10px var(--mono);
    color: var(--t4);
}
.tool-step-hint:empty, .tool-step-dur:empty { display: none; }

/* Second-line metadata (action rows only) — sits right under the row,
   indented to align with the label (4px head pad + 13px icon + 6px gap = 23px).
   Sized to read comfortably, not as a tiny footnote. */
.tool-step-meta {
    color: var(--t3);
    font: 12px/1.45 var(--sans);
    margin: 1px 0 3px 23px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.tool-step-meta:empty { display: none; }

/* No-detail / no-affordance state — cursor stays default */
.tool-step.no-affordance .tool-step-head { cursor: default; }
.tool-step.running .tool-step-head { cursor: default; }
.tool-step.no-affordance .tool-step-head:hover { background: none; }
.tool-step.no-affordance .tool-step-affordance { display: none; }

/* Detail panel — minimal indent. The detail is its own block beneath the
   row, not aligned-under-the-label; in a narrow column we can't afford
   the 36px tax. 8px is enough to read as nested without crushing width. */
.tool-step-detail {
    padding: 4px 0 6px 8px;
    font: var(--fs-xs)/1.55 var(--sans);
    color: var(--t3);
    overflow-y: auto;
}
.tool-step.collapsed .tool-step-detail { display: none; }
.tool-step-detail:empty { display: none; }

/* Fold-merge — multiple same-tool info rows collapse into one summary row.
   The root row shows the count; the absorbed children render inside a
   nested container that expands alongside the root's detail panel. */
.tool-fold-children {
    margin-left: 16px;
    padding-left: 8px;
    border-left: 1px solid var(--chrome-border);
}
.tool-fold-children.collapsed { display: none; }
.tool-fold-children > .tool-step.fold-child { margin-top: 1px; }

/* Detail rows — inline label + value flow rather than a 56px label column.
   In a narrow panel, the fixed column wasted ~20% of horizontal space; with
   inline flow the label is a small-caps prefix and the value flows beside. */
.td-row {
    padding: 1px 0;
    font-size: var(--fs-xs); line-height: 1.5;
    color: var(--t2);
}
.td-label {
    color: var(--t3);
    font: 600 10px var(--sans);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    margin-right: 5px;
}
.td-label::after { content: ':'; }
.td-value {
    color: var(--t2); word-break: break-word;
}
.td-divider {
    height: 1px; background: var(--chrome-border);
    margin: 5px 0;
}
/* batch_cite detail — one row per cited source + the section it landed in. */
.td-cite-row {
    display: flex;
    align-items: baseline;
    gap: 8px;
    padding: 3px 0;
    font-size: var(--fs-xs);
    line-height: 1.5;
    border-top: 1px solid var(--chrome-border-subtle);
}
.td-cite-row:first-child { border-top: none; }
.td-cite-row[data-action] { cursor: pointer; }
.td-cite-row[data-action]:hover .td-cite-src { color: var(--t1); }
.td-cite-src { color: var(--t2); flex: 1; min-width: 0; }
.td-cite-sec { color: var(--t3); flex-shrink: 0; }
.td-block { padding: 2px 0; }
.td-block .td-label { display: block; margin-bottom: 2px; }
.td-blockval {
    color: var(--t2); font-size: var(--fs-xs); line-height: 1.5;
    white-space: pre-wrap; word-break: break-word;
    overflow-y: auto;
    padding: 4px 8px;
    background: var(--chrome-surface);
    border-radius: var(--radius-sm);
    border: 1px solid var(--chrome-border);
}
/* Plain block — no card chrome, just text. Used for free-form gloss like
   propose_edit's full summary where the surrounding box is just noise. */
.td-blockval-plain {
    background: none;
    border: none;
    padding: 0;
    font: italic 12px/1.5 var(--serif);
    color: var(--t3);
}

/* Search results in detail */
.td-result {
    padding: 4px 0;
    border-bottom: 1px solid var(--chrome-border);
}
.td-result:last-child { border-bottom: none; }
.td-result-title {
    font-size: var(--fs-xs); color: var(--t2);
    font-weight: 500;
}
.td-result-snippet {
    font-size: var(--fs-xs); color: var(--t3);
    margin-top: 1px; line-height: 1.4;
}
/* Plan tasks in detail */
.td-task {
    display: flex; align-items: center; gap: 6px;
    padding: 2px 0; font-size: var(--fs-xs); color: var(--t2);
}
.td-task-icon { width: 12px; text-align: center; flex-shrink: 0; }
.td-task.done { color: var(--t3); }
.td-task.done .td-task-icon { color: var(--t2); }
.td-task.running .td-task-icon { color: var(--accent); }

/* Section list in read_sections tool detail */
.td-sec-list { padding: 2px 0; }
.td-sec {
    padding: 1px 0;
    font-size: var(--fs-xs);
    color: var(--t2);
}

.td-error .td-value { color: var(--red); }
.td-error .td-label { color: var(--red); }

/* Warning row — amber/ochre, distinct from red error */
.td-warn .td-label { color: var(--warning); }
.td-warn .td-value { color: var(--warning); }

/* Search/academic result enhancements */
.td-result-link {
    color: var(--t1);
    text-decoration: none;
    border-bottom: 1px dashed var(--chrome-border);
}
.td-result-link:hover { color: var(--accent-text); border-bottom-color: var(--accent-text); }
.td-result-meta {
    font-size: 11px; color: var(--t3);
    margin-top: 1px;
}
.td-result-quote {
    margin: 4px 0 0; padding: 3px 8px;
    border-left: 2px solid var(--chrome-border);
    color: var(--t2); font-style: italic;
    font-size: var(--fs-xs); line-height: 1.5;
}

/* Source cards — register_source / batch_register_sources / read_source detail.
   A compact bibliographic record (what you'd put in a bibliography): title,
   authors, venue · year, DOI. One card per source. */
.td-src-card { padding: 5px 0; }
.td-src-card + .td-src-card {
    margin-top: 5px;
    border-top: 1px solid var(--chrome-border-subtle);
}
.td-src-title { font: 500 var(--fs-xs)/1.4 var(--sans); color: var(--t2); }
.td-src-tag {
    margin-left: 6px;
    font: 500 10px var(--sans);
    color: var(--t3);
    text-transform: uppercase; letter-spacing: 0.04em;
}
.td-src-authors { font: 400 var(--fs-xs)/1.4 var(--sans); color: var(--t3); margin-top: 1px; }
.td-src-venue   { font: italic var(--fs-xs)/1.4 var(--serif); color: var(--t3); margin-top: 1px; }
.td-src-doi     { font: 400 11px var(--mono); color: var(--accent-text); margin-top: 2px; }

/* A duplicate source recedes so the freshly added ones read first; the small
   "already saved" tag says why it's dimmed. */
.td-src-card--dup { opacity: 0.5; }
.td-src-card--dup .td-src-title { font-weight: 450; }

/* validate_citations — one plainly-named problem per row, with its citation
   number + section for context. Rows that have a section home are .chip-link
   (they get the → arrow and jump to that section on click); the rest are inert
   text. No red/amber — the row label already framed these as issues. */
.td-issue {
    padding: 3px 0;
    font-size: var(--fs-xs); line-height: 1.45;
    color: var(--t2);
    border-top: 1px solid var(--chrome-border-subtle);
}
.td-issue:first-child { border-top: none; }
.td-issue-label { color: var(--t2); font-weight: 500; }
.td-issue-ctx { color: var(--t3); }
.td-issue.chip-link { cursor: pointer; }
.td-issue.chip-link:hover .td-issue-label { color: var(--accent-text); }

/* Passage quotes — search_source detail. Italic pull-quotes with a dim rule. */
.td-passage {
    font: italic var(--fs-xs)/1.5 var(--serif);
    color: var(--t2);
    padding: 3px 0 3px 8px;
    border-left: 1px solid var(--chrome-border);
    margin: 3px 0;
}

/* Tool action area in card head (right of label, left of chevron) */
.tool-step-actions {
    display: flex; align-items: center; gap: 4px;
    flex-shrink: 0; margin-left: auto;
}
.tool-step-actions:empty { display: none; }

/* Image thumbnail preview in figure tool details */
.td-thumb {
    max-width: 80px; max-height: 80px;
    border-radius: var(--radius-sm);
    border: 1px solid var(--chrome-border);
    object-fit: cover;
}
.td-eq-preview { font-size: var(--fs-sm); color: var(--t1); padding: 4px 0; }
.td-table-preview { font-size: var(--fs-xs); color: var(--t2); overflow-x: auto; }
.td-table-preview table { border-collapse: collapse; }
.td-table-preview th, .td-table-preview td {
    border: 1px solid var(--chrome-border); padding: 2px 6px;
}

/* Truncated text "Show more" */
.td-truncate { position: relative; }
.td-trunc-toggle, .td-more-btn {
    display: inline-block; margin-top: 4px;
    background: none; border: none; padding: 0;
    color: var(--accent-text); cursor: pointer;
    font: var(--font-meta);
}
.td-trunc-toggle:hover, .td-more-btn:hover {
    text-decoration: underline;
}

/* grep_document match chip */
.td-grep { padding: 3px 0; }
.td-grep-label {
    display: block; font-size: var(--fs-xs); color: var(--t2); font-weight: 500;
}
.td-grep-label.chip-link { cursor: pointer; }
.td-grep-label.chip-link:hover { color: var(--accent-text); }

/* Inline links inside tool detail panels — render with a small leading arrow
   so the vocabulary matches the row-level ↗ navigate affordance. */
.tool-step-detail .chip-link::before {
    content: '→ ';
    color: var(--t3);
    margin-right: 2px;
}
.tool-step-detail .chip-link:hover::before { color: var(--accent); }
.td-grep-snippet {
    font-size: var(--fs-xs); color: var(--t3);
    margin-top: 1px; line-height: 1.4;
    font-style: italic;
}

/* "+N more" expander wrapper */
.td-more-wrap { padding: 2px 0; }
.td-more.hidden { display: none; }

/* Highlight flash on history sidebar entry — used by Undo cue */
.rev-flash {
    animation: rev-flash 1.6s ease-out;
}
@keyframes rev-flash {
    0%, 100% { background: transparent; }
    20%, 60% { background: var(--accent-dim); }
}

/* ============================================================
   TWO-TIER VISUAL HIERARCHY

   Tier 1 — Change cards (gold-bordered glass panels). The "what changed
            in the document" surface. Click navigates to the section.
   Tier 2 — Tool rows (all dim, uniform). Ambient activity log: the AI's
            reading, searching, registering, citing. Click any row to
            expand its detail panel.
   ============================================================ */

/* ============================================================
   CHANGE CARD — soft gold frame (v4 design).
   Lighter chrome than the landing pricing-card: no blur/saturate,
   no halo shadow, no hover lift. A clean frame that sits in the
   thread rather than floating above it. Title + type chip + italic
   serif summary. Click navigates to the change in the doc.
   ============================================================ */
/* A change reads as a calm transcript line, not a boxy card: a coloured left
   rule (add/remove/edit) + a verb sentence. Click jumps to it in the document,
   where the per-section bar is the decision surface. */
.change-step {
    position: relative;
    margin: 3px 0;
    padding: 5px 10px;
    border-left: 2px solid var(--accent);
    border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
    font: 400 13px/1.45 var(--sans);
    cursor: pointer;
    transition: background var(--dur);
}
.change-step:hover { background: rgba(255,255,255,0.03); }
.change-step--add    { border-left-color: var(--green); }
.change-step--remove { border-left-color: var(--red); }
.change-step--edit   { border-left-color: var(--accent); }
.change-verb   { color: var(--t2); }
.change-target { color: var(--t1); font-weight: 600; }

/* Manual (user) edits get a small inline tag; agent edits don't —
   the chat panel is already the agent's context. */
.change-origin {
    margin-left: 6px;
    font: 600 10px/1 var(--sans);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--green);
    vertical-align: 1px;
}

/* Resolved cards recede — left rule + text go secondary. Rejected adds
   strikethrough to differentiate from accepted at a glance. */
.change-step.change-accepted,
.change-step.change-rejected { border-left-color: var(--t4); }
.change-step.change-accepted .change-verb,
.change-step.change-accepted .change-target,
.change-step.change-rejected .change-verb,
.change-step.change-rejected .change-target { color: var(--t3); font-weight: 400; }
.change-step.change-rejected .change-target { text-decoration: line-through; }

/* ---- Chips ---- */
.chip-section {
    display: inline-flex; align-items: center; gap: 4px;
    color: var(--t3);
    font: 450 11px var(--sans);
    padding: 2px 4px;
    cursor: pointer; transition: color var(--dur);
}
.chip-section:hover { color: var(--t2); }
.chip-source {
    display: inline-flex; align-items: center; gap: 4px;
    color: var(--t3);
    font: 450 11px var(--sans);
    padding: 2px 4px; cursor: pointer;
}

/* ---- Chat input ---- */
#chat-input-area {
    padding: 8px var(--chat-pad) 10px;
    border-top: 1px solid var(--chrome-border);
    flex-shrink: 0;
}

/* Same input vocabulary as .acct-field-input (profile/login/register):
   borderless, gold underline that brightens on hover and goes full gold
   when typing. Underline is on the textarea only so it stops at the send
   button (instead of extending across the whole row). */
#chat-input-wrap {
    display: flex;
    align-items: flex-end;
    gap: 6px;
    background: none;
    border: none;
    padding: 6px 4px 8px 4px;
}

#chat-input {
    flex: 1;
    background: none;
    border: none;
    border-bottom: 1px solid rgba(212,168,68,0.30);
    color: var(--t1);
    font: 13px/1.55 var(--sans);
    padding: 6px 0 8px;
    resize: none;
    outline: none;
    max-height: 140px;
    transition: border-color var(--dur);
}
#chat-input:hover { border-bottom-color: rgba(212,168,68,0.55); }
#chat-input:focus { border-bottom-color: var(--accent); }
#chat-input::placeholder { color: var(--t3); }

/* Chat send — uses the canonical gold gradient from .landing-btn-primary
 * so it matches the rest of the app's primary CTAs. Scaled to a 32×32
 * icon square with a tighter halo since it sits in a high-frequency spot. */
.btn-send {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 32px; height: 32px;
    border-radius: var(--radius);
    border: none;
    background: var(--grad-gold-pill);
    color: var(--on-gold);
    cursor: pointer;
    flex-shrink: 0;
    box-shadow:
        inset 0 1px 0 rgba(255,255,255,0.45),
        inset 0 -1px 0 rgba(0,0,0,0.18),
        0 2px 8px -2px rgba(212,168,68,0.55);
    transition: box-shadow var(--dur) var(--ease),
                transform var(--dur) var(--ease),
                filter var(--dur) var(--ease);
}
.btn-send:hover {
    transform: translateY(-0.5px);
    filter: brightness(1.06);
    box-shadow:
        inset 0 1px 0 rgba(255,255,255,0.55),
        inset 0 -1px 0 rgba(0,0,0,0.18),
        0 6px 16px -4px rgba(212,168,68,0.65);
}
.btn-send:active { transform: translateY(0); filter: brightness(0.98); }
.btn-send:disabled {
    opacity: 0.35;
    cursor: not-allowed;
    filter: saturate(0.6);
}
.btn-send.is-stopping {
    background: var(--red);
    color: var(--btn-text);
    box-shadow:
        inset 0 1px 0 rgba(255,255,255,0.30),
        inset 0 -1px 0 rgba(0,0,0,0.22),
        0 2px 6px -2px rgba(212,88,64,0.55);
}
.btn-send.is-stopping:hover { background: var(--red-hover); }
.btn-send.is-stopping-pending { opacity: 0.5; pointer-events: none; }

/* Markdown rendering in chat */
.msg-body pre.md-pre {
    background: var(--chrome-surface);
    border: 1px solid var(--chrome-border);
    border-radius: var(--radius-sm);
    padding: 10px 12px;
    overflow-x: auto;
    font-size: var(--fs-sm);
    line-height: 1.55;
    margin: 8px 0;
}
.msg-body pre.md-pre code { background: none; padding: 0; font-size: inherit; }
.msg-body code.md-code {
    background: var(--chrome-surface);
    border: 1px solid var(--chrome-border);
    padding: 1px 5px;
    border-radius: var(--radius-xs);
    font-size: var(--fs-xs);
}
.msg-body ul, .msg-body ol {
    margin: 8px 0;
    padding-left: 18px;
}
.msg-body ul { list-style: none; }
.msg-body ul > li { position: relative; padding-left: 4px; }
.msg-body ul > li::before {
    content: '';
    position: absolute;
    left: -12px;
    top: 8px;
    width: 4px;
    height: 4px;
    border-radius: 50%;
    background: var(--t3);
}
.msg-body ol { padding-left: 22px; }
.msg-body ol > li::marker { color: var(--t3); font-size: var(--fs-sm); font-weight: 500; }
.msg-body li {
    margin: 4px 0;
    line-height: 1.6;
    padding-left: 2px;
}
.msg-body li + li { margin-top: 6px; }
.msg-body h3 {
    margin: 14px 0 6px;
    font-size: var(--fs-md);
    font-weight: 600;
    color: var(--t1);
    letter-spacing: -0.01em;
}
.msg-body h4 {
    margin: 12px 0 4px;
    font-size: var(--fs-base);
    font-weight: 600;
    color: var(--t1);
}
.msg-body h5 {
    margin: 10px 0 4px;
    font-size: var(--fs-sm);
    font-weight: 600;
    color: var(--t2);
    text-transform: uppercase;
    letter-spacing: 0.04em;
}
.msg-body h3:first-child, .msg-body h4:first-child, .msg-body h5:first-child { margin-top: 2px; }
.msg-body a {
    color: var(--accent-text);
    text-decoration: none;
    border-bottom: 1px solid var(--accent-border);
    transition: border-color var(--dur);
}
.msg-body a:hover { border-bottom-color: var(--accent-text); }

/* Clickable section/figure/table/equation links from [sec:ID], [fig:ID], etc. */
.sec-link, .fig-link {
    color: var(--accent-text);
    cursor: pointer;
    font-weight: 500;
    border-bottom: 1px dotted var(--accent-border);
    transition: border-color var(--dur), color var(--dur);
}
.sec-link:hover, .fig-link:hover { border-bottom-style: solid; border-bottom-color: var(--accent-text); }

/* Horizontal rule in chat messages */
.msg-body hr {
    border: none;
    height: 1px;
    background: var(--chrome-border);
    margin: 12px 0;
}

/* Nested lists */
.msg-body li > ul, .msg-body li > ol { margin: 4px 0 2px; }

.streaming-dot {
    display: inline-block;
    width: 6px; height: 6px;
    background: var(--accent);
    border-radius: 50%;
    animation: blink 1s ease-in-out infinite;
    margin-left: 3px;
    vertical-align: middle;
}
@keyframes blink { 0%,100% { opacity: 0.2; } 50% { opacity: 1; } }

.thinking-indicator {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 12px;
    color: var(--t3);
    font: 12px/1.4 var(--sans);
}
.thinking-indicator .thinking-dots {
    display: flex;
    gap: 3px;
}
.thinking-indicator .thinking-dots span {
    width: 4px; height: 4px;
    background: var(--accent);
    border-radius: 50%;
    animation: thinking-bounce 1.4s ease-in-out infinite;
}
.thinking-indicator .thinking-dots span:nth-child(2) { animation-delay: 0.16s; }
.thinking-indicator .thinking-dots span:nth-child(3) { animation-delay: 0.32s; }
@keyframes thinking-bounce {
    0%, 80%, 100% { opacity: 0.2; transform: scale(0.8); }
    40% { opacity: 1; transform: scale(1); }
}

/* ---- Status trail (frozen thinking steps) ---- */
.status-trail {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 2px 12px;
    color: var(--t3);
    font: var(--fs-xs)/1.4 var(--sans);
}
.status-trail svg { flex-shrink: 0; opacity: 0.5; }

/* ============================================================
   CHAT ACCENT MESSAGE (stop indicator, not a real message)
   ============================================================ */

.chat-accent {
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 6px 0;
    margin: 4px 0;
}
.chat-accent span {
    font: var(--font-meta);
    color: var(--t3);
    letter-spacing: 0.01em;
}

/* ============================================================
   END-OF-RUN FOOTER
   A faint hairline that closes a run and shows how long it took; the token
   detail is one click behind it (no model, no credits). Replaces the old
   centered "Run complete" line and the near-invisible raw-token line.
   ============================================================ */
.run-foot { margin: 9px 2px 2px; }
.run-foot-head {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 5px 4px 4px;
    cursor: pointer;
    color: var(--t4);
    transition: color var(--dur);
}
.run-foot:not(.no-expand) .run-foot-head:hover { color: var(--t3); }
.run-foot.no-expand .run-foot-head { cursor: default; }
.run-foot-line { flex: 1; height: 1px; background: var(--chrome-border-subtle); }
.run-foot-time { font: 400 10px var(--mono); flex-shrink: 0; }
.run-foot-chev { display: flex; align-items: center; opacity: 0.6; transition: transform var(--dur); }
.run-foot:not(.collapsed) .run-foot-chev { transform: rotate(90deg); }
.run-foot.collapsed .run-foot-detail { display: none; }
.run-foot-detail {
    display: flex;
    justify-content: flex-end;
    align-items: baseline;
    gap: 8px;
    padding: 0 4px 4px;
}
.run-foot-tok { font: 400 10px var(--mono); color: var(--t3); }
.run-foot-bk  { font: 400 10px var(--mono); color: var(--t4); }

