/* Clean Ask AI Assistant Styles */

/* AI Button in navbar */
.ai-button {
    position: relative;
    transition: all 0.3s ease;
}

.ai-button:hover {
    transform: scale(1.05);
}

/* Ask AI toggle button styling */
#ask-ai-toggle {
    color: inherit;
    text-decoration: none;
    background: transparent;
}

#ask-ai-toggle:hover {
    color: inherit;
    text-decoration: none;
    background: transparent;
    transform: scale(1.05);
}

#ask-ai-toggle:focus {
    color: inherit;
    text-decoration: none;
    background: transparent;
    box-shadow: none;
}

.ai-indicator {
    position: absolute;
    top: 0;
    right: 0;
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background-color: #10b981;
    box-shadow: 0 0 0 2px #ffffff;
    animation: pulse 2s infinite;
}

@keyframes pulse {
    0% {
        box-shadow: 0 0 0 0 rgba(16, 185, 129, 0.7);
    }

    70% {
        box-shadow: 0 0 0 6px rgba(16, 185, 129, 0);
    }

    100% {
        box-shadow: 0 0 0 0 rgba(16, 185, 129, 0);
    }
}

/* Sidebar Container */
.ask-ai-sidebar {
    position: fixed;
    top: 0;
    right: 0;
    width: var(--ask-ai-width, 420px);
    min-width: 360px;
    max-width: 80vw;
    height: 100vh;
    background: white;
    box-shadow: -2px 0 20px rgba(0, 0, 0, 0.15);
    z-index: 1050;
    transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
    display: flex;
    flex-direction: column;
    will-change: transform;
}

/* Resize handle on left edge */
.ask-ai-resize-handle {
    position: absolute;
    left: 0;
    top: 0;
    width: 5px;
    height: 100%;
    cursor: col-resize;
    z-index: 2;
    background: transparent;
    transition: background 0.2s;
}

.ask-ai-resize-handle:hover {
    background: rgba(var(--bs-primary-rgb, 59, 125, 221), 0.4);
}

.ask-ai-sidebar.resizing .ask-ai-resize-handle {
    background: rgba(var(--bs-primary-rgb, 59, 125, 221), 0.6);
}

.ask-ai-sidebar.resizing {
    transition: none;
    user-select: none;
}

.ask-ai-sidebar.visible {
    right: 0;
}

.ask-ai-sidebar-inner {
    display: flex;
    flex-direction: column;
    height: 100%;
}

/* Header */
.chat-header {
    padding: 1rem;
    border-bottom: 1px solid #e9ecef;
    background: #f8f9fa;
    flex-shrink: 0;
}

.chat-header h5 {
    color: #343a40;
    font-weight: 600;
}

/* Messages Area */
.chat-messages-container {
    flex: 1;
    overflow-y: auto;
    padding: 1rem;
    scroll-behavior: smooth;
}

.chat-messages {
    display: flex;
    flex-direction: column;
    gap: 1rem;
    min-height: 200px;
    position: relative;
}

/* Welcome Message */
.chat-welcome {
    /* 1.5rem, not 2rem: the block is the ENTIRE empty state of a 450px rail,
       so its padding reads as dead air rather than breathing room. */
    padding: 1.5rem 1.25rem;
    color: #6c757d;
    text-align: center;
}

.chat-welcome i {
    color: var(--bs-primary, #007bff);
}

/* margin-bottom lived on `.chat-welcome i` and hit EVERY icon in the block,
   which is two of them, and was wrong for both:

     - the hero wand already sits in a `.mb-3` wrapper (see
       AiAssistantHelper#render_ai_assistant_welcome_html), so the two stacked
       into a 35px gap under a 40px icon;
     - the taught-line's inline fa-user-check is a 12px glyph sitting in a line
       of text, where 1rem of bottom margin shoved it above its own baseline.

   The wrapper's own .mb-3 is now the single source of the hero's gap; inline
   icons get none. */

/* Composer — one bordered shell holding the textarea with its tools BELOW it,
   rather than a flex row with the field wedged between three 40px circles.
   Measured on the 450px rail, that row gave the textarea 238px of 385px (62%);
   moving the buttons onto their own line hands it the full width.

   The shell (not the textarea) draws the border and owns the focus ring, so the
   whole thing reads as one control. */
.ask-ai-composer {
    border: 1px solid #ced4da;
    border-radius: 16px;
    /* transparent, NOT var(--bs-body-bg): this tenant resolves that to
       aliceblue (#f0f8ff) while .chat-input-container around it is white, so
       the shell rendered as a tinted panel floating on white. The shell is
       chrome — a border and a radius — not its own surface, so it takes
       whatever the composer container is, in either theme. */
    background: transparent;
    padding: 8px 10px 6px;
}

.ask-ai-composer:focus-within {
    border-color: var(--bs-primary, #007bff);
    box-shadow: 0 0 0 0.2rem rgba(13, 110, 253, 0.15);
}

/* The textarea is now a bare text surface — the shell above draws the chrome.
   !important is unavoidable on the three .form-control properties: Bootstrap's
   own .form-control rules land later in the cascade at equal specificity. */
.ask-ai-composer .form-control {
    border: 0 !important;
    box-shadow: none !important;
    background: transparent !important;
    padding: 0;
    resize: none;
    max-height: 160px;
}

/* Tools row: + and mic left, Enter hint and send right. 32px targets — smaller
   than the old 40px because they no longer compete with the field for width,
   but still well clear of the 24px minimum. The mic could shrink safely only
   because it no longer sits flush against Send: starting a voice session is
   billed, and the two being neighbours was what made a mis-tap expensive. */
.ask-ai-composer-tools {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    margin-top: 4px;
}

.ask-ai-composer-tools .btn {
    width: 32px;
    height: 32px;
    min-width: 32px;
    min-height: 32px;
    padding: 0;
    font-size: 0.8rem;
    line-height: 1;
}

/* The "+" is QUIET. It shipped as a btn-light solid circle, which in dark mode
   stayed white and burned a hole in the panel.

   This mirrors .aichat-tool in ask_ai_page.css — the same composer's treatment
   on the full-page chat: no fill, no border, muted ink, faint hover.

   The MIC deliberately keeps its btn-outline-primary ring rather than joining
   this rule. It is the one control here that starts a BILLED voice session, and
   the ring is the only thing distinguishing it from the innocuous "+" beside it
   — the same concern that originally sized it at 40px. (It is also the harder
   one to quiet: --bs-btn-border-color has no effect on it, because the theme
   sets border-color on .btn-outline-primary directly rather than through the
   variable. Not worth an !important to reach an outcome we don't want.)

   Set as Bootstrap's --bs-btn-* variables rather than plain background/
   border-color. .btn reads every one of those through var(), so overriding the
   property directly wins the cascade but loses the hover and :active states
   back to the originals — the "+" kept flashing its grey fill on hover. Driving
   the variables restyles all three states from one place, and reverts cleanly
   the moment the class swaps. */
.ask-ai-composer-tools .btn-light {
    --bs-btn-bg: transparent;
    --bs-btn-border-color: transparent;
    --bs-btn-color: #6c757d;
    --bs-btn-hover-bg: rgba(15, 23, 42, 0.06);
    --bs-btn-hover-border-color: transparent;
    --bs-btn-hover-color: #212529;
    --bs-btn-active-bg: rgba(15, 23, 42, 0.09);
    --bs-btn-active-border-color: transparent;
    --bs-btn-active-color: #212529;
}

.ask-ai-composer-tools .btn-light[aria-expanded="true"] {
    background: rgba(15, 23, 42, 0.09);
}

/* Removing the fill removed the only thing marking keyboard focus on these
   two, so restore an explicit ring rather than leaving them silently focusable. */
.ask-ai-composer-tools .btn:focus-visible {
    outline: 2px solid var(--bs-primary, #007bff);
    outline-offset: 1px;
    box-shadow: none;
}

/* Sized off the button so the row height never depends on this hint. */
.ask-ai-composer-hint {
    font-size: 0.7rem;
    color: #adb5bd;
    white-space: nowrap;
}

/* Quick Suggestions */
.quick-suggestions {
    max-width: 300px;
    margin: 0 auto;
}

.quick-suggestions .btn {
    font-size: 0.75rem;
    padding: 0.25rem 0.5rem;
    margin: 0.1rem;
    border-radius: 12px;
    transition: all 0.2s ease;
}

.quick-suggestions .btn:hover {
    transform: translateY(-1px);
    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}

/* Date Separator */
.date-separator {
    text-align: center;
    margin: 1rem 0;
    position: relative;
}

.date-separator span {
    background: #f8f9fa;
    padding: 0.25rem 0.75rem;
    font-size: 0.75rem;
    color: #6c757d;
    border-radius: 12px;
    border: 1px solid #e9ecef;
    font-weight: 500;
}

/* System Message Styles */
.system-message {
    margin: 0.5rem 0;
    padding: 0.75rem;
    border-radius: 8px;
    font-size: 0.9rem;
    text-align: center;
}

.system-message.info {
    background: #e3f2fd;
    color: #1976d2;
    border-left: 3px solid #2196f3;
}

.system-message.primary {
    background: #f3e5f5;
    color: #7b1fa2;
    border-left: 3px solid #9c27b0;
}

.system-message.warning {
    background: #fff3e0;
    color: #f57c00;
    border-left: 3px solid #ff9800;
}

/* Message Bubbles */
.message {
    max-width: 85%;
    margin-bottom: 1rem;
    opacity: 1;
    visibility: visible;
    position: relative;
    z-index: 1;
}

.user-message {
    align-self: flex-end;
    margin-left: auto;
}

.assistant-message {
    align-self: flex-start;
    margin-right: auto;
}

/* Live streaming sidebar bubbles are built in JS with the `chat-message` class
   (ask_ai_form_controller.js), NOT `.message`, so the `max-width: 85%` cap above
   never applied to them. Without a definite-width containing block, a wide
   markdown/HTML table inside the bubble (e.g. Ask AI's Digital Signage
   "which screens are offline?" answer) resolves its own `max-width: 100%`
   against an indefinite width and expands to full intrinsic width — overflowing
   and distorting the narrow sidebar. Mirror the `.message` cap and give
   `.message-content` `min-width: 0` so the table's `overflow-x: auto` (rule
   below) can scroll inside the bubble instead. Scoped to `.ask-ai-sidebar` so
   the full-page chat (capped separately by ask_ai.css) stays untouched. */
.ask-ai-sidebar .chat-message.assistant-message,
.ask-ai-sidebar .chat-message.user-message {
    max-width: 85%;
}

.ask-ai-sidebar .chat-message.assistant-message .message-content,
.ask-ai-sidebar .chat-message.user-message .message-content {
    max-width: 100%;
    min-width: 0;
}

.message-content {
    padding: 12px 16px;
    border-radius: 18px;
    line-height: 1.4;
    word-wrap: break-word;
}

.user-message .message-content {
    background: var(--bs-primary, #007bff);
    color: var(--bs-on-primary, #fff);
    border-bottom-right-radius: 4px;
}

.assistant-message .message-content {
    background: #f8f9fa;
    color: #333;
    border: 1px solid #e9ecef;
    border-bottom-left-radius: 4px;
}

/* Markdown Content Styling */
.markdown-content {
    line-height: 1.6;
    color: inherit;
}

.markdown-content p {
    margin: 0 0 1rem 0;
}

.markdown-content p:last-child {
    margin-bottom: 0;
}

.markdown-content ol,
.markdown-content ul {
    margin: 0.5rem 0;
    padding-left: 1.5rem;
}

.markdown-content li {
    margin-bottom: 0.25rem;
}

.markdown-content a {
    color: var(--bs-primary, #007bff);
    text-decoration: none;
}

.markdown-content a:hover {
    text-decoration: underline;
}

.markdown-content strong {
    font-weight: 600;
}

/* Scale down LLM-emitted markdown headings inside chat bubbles. Default
   browser sizes (h1 ≈ 2rem, h2 ≈ 1.5rem) overwhelm a narrow sidebar.
   Applied to both `.message-content` and `.markdown-content` so it works
   for tenant Ask AI and the MangoApps Console sidebar uniformly. */
.message-content h1,
.markdown-content h1 {
    font-size: 1.15rem;
    font-weight: 600;
    line-height: 1.3;
    margin: 0.6rem 0 0.4rem;
}

.message-content h2,
.markdown-content h2 {
    font-size: 1.05rem;
    font-weight: 600;
    line-height: 1.3;
    margin: 0.6rem 0 0.4rem;
}

.message-content h3,
.markdown-content h3 {
    font-size: 1rem;
    font-weight: 600;
    line-height: 1.3;
    margin: 0.5rem 0 0.3rem;
}

.message-content h4,
.markdown-content h4 {
    font-size: 0.95rem;
    font-weight: 600;
    line-height: 1.3;
    margin: 0.4rem 0 0.3rem;
}

.message-content h5,
.message-content h6,
.markdown-content h5,
.markdown-content h6 {
    font-size: 0.9rem;
    font-weight: 600;
    line-height: 1.3;
    margin: 0.4rem 0 0.25rem;
}

/* First heading in a message has no top margin (the bubble padding
   already provides the gap). */
.message-content > :is(h1,h2,h3,h4,h5,h6):first-child,
.markdown-content > :is(h1,h2,h3,h4,h5,h6):first-child {
    margin-top: 0;
}

/* Markdown tables (e.g. Ask AI tabular answers like "Which screens are
   offline?" Digital Signage status) must not push the narrow sidebar out of
   shape. Render the table as a block capped at the bubble width with its own
   horizontal scroll so wide, multi-column tables stay contained instead of
   overflowing and distorting the panel. */
.message-content table,
.markdown-content table {
    display: block;
    width: max-content;
    max-width: 100%;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    border-collapse: collapse;
    margin: 0.5rem 0;
    font-size: 0.85rem;
}

.message-content th,
.message-content td,
.markdown-content th,
.markdown-content td {
    border: 1px solid #e9ecef;
    padding: 0.35rem 0.5rem;
    text-align: left;
    vertical-align: top;
}

.message-content th,
.markdown-content th {
    background-color: #f2f2f2;
    font-weight: 600;
    white-space: nowrap;
}

/* ── Readable wide tables (ISS-20260617-117) ───────────────────────────────
   ask_ai_form_controller.js#enhanceChatTables tags AI-answer tables
   `.ai-md-table` (+ `.ai-md-table--multicol` for >=3 columns) and stamps each
   <td> with a `data-label` taken from its column header; when the bubble is too
   narrow to give the columns a comfortable width it also adds
   `.ai-md-table--stack`. The earlier fix kept the panel from distorting, but a
   wide table still rendered at full intrinsic width with horizontal scroll only,
   so most columns — including the Status column that actually answers "which
   screens are offline?" — stayed off-screen ("still hard to read"). These rules
   (a) let columns wrap to fit the bubble instead of forcing a horizontal scroll,
   and (b) reflow cramped tables into labeled "Header / value" cards so every
   field is visible without scrolling. report-preview tables are skipped by the
   JS and keep their own .table-responsive treatment. The two-class selectors
   out-specify the base `.message-content table` rule above. */
.message-content table.ai-md-table,
.markdown-content table.ai-md-table {
    display: table;
    width: 100%;
    max-width: 100%;
    table-layout: fixed;
    overflow-x: visible;
}

.message-content table.ai-md-table th,
.message-content table.ai-md-table td,
.markdown-content table.ai-md-table th,
.markdown-content table.ai-md-table td {
    white-space: normal;
    overflow-wrap: anywhere;
    word-break: break-word;
    vertical-align: top;
}

.message-content table.ai-md-table--stack,
.markdown-content table.ai-md-table--stack {
    display: block;
    width: 100%;
    border: 0;
}

.message-content table.ai-md-table--stack thead,
.markdown-content table.ai-md-table--stack thead {
    display: none;
}

.message-content table.ai-md-table--stack tbody,
.message-content table.ai-md-table--stack tr,
.message-content table.ai-md-table--stack td,
.markdown-content table.ai-md-table--stack tbody,
.markdown-content table.ai-md-table--stack tr,
.markdown-content table.ai-md-table--stack td {
    display: block;
    width: 100%;
}

.message-content table.ai-md-table--stack tr,
.markdown-content table.ai-md-table--stack tr {
    border: 1px solid #e9ecef;
    border-radius: 8px;
    margin: 0 0 0.5rem;
    padding: 0.15rem 0;
    background: #fff;
}

.message-content table.ai-md-table--stack td,
.markdown-content table.ai-md-table--stack td {
    border: 0;
    border-bottom: 1px solid #f1f3f5;
    padding: 0.3rem 0.6rem;
}

.message-content table.ai-md-table--stack td:last-child,
.markdown-content table.ai-md-table--stack td:last-child {
    border-bottom: 0;
}

.message-content table.ai-md-table--stack td::before,
.markdown-content table.ai-md-table--stack td::before {
    content: attr(data-label);
    display: block;
    font-weight: 600;
    font-size: 0.78rem;
    color: #6c757d;
    margin-bottom: 1px;
}

.message-content table.ai-md-table--stack td:not([data-label])::before,
.markdown-content table.ai-md-table--stack td:not([data-label])::before {
    content: none;
}

/* ── Ask AI diff-preview card (ISS-20260904-168) ───────────────────────────
   The action-capable-agent confirmation card
   (ask_ai/ui_components/_diff_confirmation_prompt.html.erb) is PLATFORM-authored
   markup that happens to live inside `.message-content`, so every rule above —
   written for LLM-authored markdown tables — was reshaping it. Two of them broke
   it in the ~293px sidebar bubble:

     * `.message-content table { display: block; width: max-content }` turned the
       field-diff table into its own horizontal scroller.
     * enhanceChatTables() stamped it `.ai-md-table`, adding `table-layout: fixed`
       + `word-break: break-word`; against the partial's old `width: 30%` label
       column (~76px here) that rendered "Remediation owner notification
       preference" one to two characters per line, and split values mid-token
       ("2026-10-" / "19 00:00:00 UTC").

   ask_ai_form_controller.js#enhanceChatTables now skips this component the same
   way it already skips `.report-preview`.

   SPECIFICITY: the base `.message-content table` pair above is NOT the only rule
   these have to beat — the same partial renders on four Ask AI surfaces, and
   three other sheets style the same element:
     * ask_ai_page.css   `.aichat .assistant-message .message-content table`  (0,3,1)
     * ask_ai.css        `.message-content table`                             (0,1,1)
     * custom.css        `.ask-ai-container .message-content table`           (0,2,1)
   ask_ai_page.css also LOADS AFTER this file (layouts/application yields
   :stylesheets below its own ask_ai_clean link), so a tie loses there. Anchoring
   on the component's two wrapper classes plus `.card-body` puts these at (0,4,1)
   / (0,4,2), which wins on every one of those surfaces regardless of load order —
   measured: `getComputedStyle(table).display` is `table` in BOTH the sidebar and
   the full-page `.aichat` transcript. All three class hooks are literals in the
   partial itself, so they move together with the markup. */
.ask-ai-ui-component.ask-ai-diff-confirmation .card-body table.ask-ai-diff-table {
    display: table;
    table-layout: auto;
    width: 100%;
    max-width: 100%;
    overflow-x: visible;
    margin: 0;
}

/* `anywhere` rather than `break-word`: it also lowers the cell's MIN-CONTENT
   width, which is what stops a URL or an underscored slug from widening the
   table past the card. Words still break at spaces first. */
.ask-ai-ui-component.ask-ai-diff-confirmation .card-body table.ask-ai-diff-table th,
.ask-ai-ui-component.ask-ai-diff-confirmation .card-body table.ask-ai-diff-table td {
    white-space: normal;
    overflow-wrap: anywhere;
    vertical-align: top;
    padding: 0.3rem 0.5rem;
}

/* Same `break-word` reasoning as the label cell below — the bulk table's
   headers are short words ("Record", "Changes", "Valid?") and `anywhere` broke
   them mid-word in the narrow third column. */
.ask-ai-ui-component.ask-ai-diff-confirmation .card-body table.ask-ai-diff-table th {
    overflow-wrap: break-word;
}

/* The label column. A percentage under `table-layout: auto` is a hint the
   browser may exceed, so a long humanized column name wraps at a readable width
   instead of being crushed into the fixed 30% it used to get. `text-align`
   is set here because `.message-content td { text-align: left }` above — and its
   (0,3,1) twin in ask_ai_page.css — was already overriding the partial's
   `.text-end` utility. */
.ask-ai-ui-component.ask-ai-diff-confirmation .card-body table.ask-ai-diff-table td.ask-ai-diff-field {
    width: 38%;
    text-align: right;
    /* `break-word`, NOT the `anywhere` above: `anywhere` also drops this cell's
       min-content width to one character, so `table-layout: auto` handed the
       label column less room than its longest word and "Remediation" broke as
       "Remediatio / n". `break-word` leaves min-content at the longest word — so
       a humanized column name wraps at its spaces — and still breaks a word that
       genuinely cannot fit rather than letting it paint outside the cell. The
       value column keeps `anywhere`, which is what URLs and emails need. */
    overflow-wrap: break-word;
}

/* Same `min-width: auto` trap as the table: this span is a flex item in the
   card's header row, so without these it refuses to shrink below its longest
   unbreakable token and pushes the text out through the card's right border. */
.ask-ai-ui-component.ask-ai-diff-confirmation .ask-ai-diff-summary {
    min-width: 0;
    overflow-wrap: anywhere;
}

.message-time {
    font-size: 0.75rem;
    color: #6c757d;
    margin-top: 4px;
    text-align: right;
}

.assistant-message .message-time {
    text-align: left;
}

/* Enhanced Thinking Indicator */
.typing-indicator {
    align-self: flex-start;
}

.thinking-container {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 12px 16px;
    background: #f8f9fa;
    border-radius: 18px;
    border: 1px solid #e9ecef;
    min-width: 200px;
}

.thinking-icon {
    flex-shrink: 0;
    animation: pulse-brain 2s infinite ease-in-out;
}

.thinking-content {
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.thinking-text {
    font-size: 0.85rem;
    color: #495057;
    font-weight: 500;
    min-height: 1.2em;
    transition: opacity 0.3s ease;
}

.thinking-dots {
    display: flex;
    gap: 4px;
    justify-content: center;
}

.thinking-dots span {
    width: 4px;
    height: 4px;
    background: #6c757d;
    border-radius: 50%;
    animation: typing-dots 1.4s infinite ease-in-out;
}

.thinking-dots span:nth-child(1) {
    animation-delay: -0.32s;
}

.thinking-dots span:nth-child(2) {
    animation-delay: -0.16s;
}

@keyframes typing-dots {

    0%,
    80%,
    100% {
        transform: scale(0.8);
        opacity: 0.5;
    }

    40% {
        transform: scale(1);
        opacity: 1;
    }
}

@keyframes pulse-brain {

    0%,
    100% {
        transform: scale(1);
        opacity: 1;
    }

    50% {
        transform: scale(1.1);
        opacity: 0.8;
    }
}

/* Typewriter Effect */
.typewriting .message-content::after {
    content: '|';
    display: inline;
    opacity: 1;
    animation: cursor-blink 0.7s infinite;
    margin-left: 2px;
    color: var(--bs-primary, #007bff);
    font-weight: bold;
}

@keyframes cursor-blink {

    0%,
    100% {
        opacity: 1;
    }

    50% {
        opacity: 0;
    }
}

/* Smooth message appearance */
.message {
    animation: message-appear 0.3s ease-out;
}

@keyframes message-appear {
    from {
        opacity: 0;
        transform: translateY(10px);
    }

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

/* Input Area */
.chat-input-container {
    padding: 1rem;
    border-top: 1px solid #e9ecef;
    flex-shrink: 0;
    background: white;
}

.chat-input-container textarea {
    resize: none;
    border: 1px solid #ced4da;
    border-radius: 20px 0 0 20px;
}

.chat-input-container textarea:focus {
    border-color: var(--bs-primary, #007bff);
    box-shadow: 0 0 0 0.2rem rgba(var(--bs-primary-rgb, 0, 123, 255), 0.25);
}

.chat-input-container .btn {
    border-radius: 0 20px 20px 0;
}

/* Overlay */
.ask-ai-overlay {
    display: none;
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: rgba(0, 0, 0, 0.5);
    z-index: 1040;
    opacity: 0;
    transition: opacity 0.3s cubic-bezier(0.4, 0, 0.2, 1);
    backdrop-filter: blur(2px);
    will-change: opacity;
}

.ask-ai-overlay.visible {
    display: block;
    opacity: 1;
}

/* Code blocks in messages */
.message-content pre {
    background: #2d3748;
    color: #e2e8f0;
    padding: 12px;
    border-radius: 8px;
    overflow-x: auto;
    font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
    font-size: 0.85rem;
    margin: 8px 0;
}

.message-content code {
    background: rgba(0, 0, 0, 0.1);
    padding: 2px 6px;
    border-radius: 4px;
    font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
    font-size: 0.9em;
}

.user-message code {
    background: rgba(255, 255, 255, 0.2);
}

/* Entity Previews */
.entity-preview {
    margin-top: 8px;
    padding: 8px;
    background: #f1f3f4;
    border-radius: 8px;
    border-left: 3px solid var(--bs-primary, #007bff);
    font-size: 0.9rem;
}

/* Mobile Responsive */
@media (max-width: 576px) {
    .ask-ai-sidebar {
        --ask-ai-width: 100% !important;
        width: 100% !important;
        min-width: 100%;
        max-width: 100%;
    }

    .message {
        max-width: 95%;
    }

    .chat-header {
        padding: 0.75rem;
    }

    .chat-messages-container {
        padding: 0.75rem;
    }

    .chat-input-container {
        padding: 0.75rem;
    }
}

/* Animations */
.ask-ai-sidebar {
    transform: translateX(100%);
    transition: transform 0.3s ease;
}

.ask-ai-sidebar.visible {
    transform: translateX(0);
}

/* AI Response formatting */
.ai-response {
    margin: 0;
}

.ai-response p {
    margin: 0 0 8px 0;
}

.ai-response p:last-child {
    margin-bottom: 0;
}

/* Focus styles for accessibility */
.chat-input-container textarea:focus,
.chat-header button:focus {
    outline: 2px solid var(--bs-primary, #007bff);
    outline-offset: 2px;
}

/* Load Conversation History Button */
.load-history-container {
    border-bottom: 1px solid #e9ecef;
    padding-bottom: 15px;
    margin-bottom: 15px !important;
}

#load_history_btn {
    border-radius: 20px;
    transition: all 0.3s ease;
    position: relative;
    overflow: hidden;
    text-decoration: none;
}

#load_history_btn:hover {
    transform: translateY(-1px);
    box-shadow: 0 2px 8px rgba(var(--bs-primary-rgb, 0, 123, 255), 0.2);
    text-decoration: none;
}

#load_history_btn small {
    font-size: 0.7rem;
    margin-top: 2px;
}

/* Load More Messages Button */
.load-more-container {
    border-bottom: 1px solid #e9ecef;
    padding-bottom: 15px;
    margin-bottom: 15px !important;
}

#load_more_btn {
    border-radius: 20px;
    transition: all 0.3s ease;
    position: relative;
    overflow: hidden;
}

#load_more_btn:hover {
    transform: translateY(-1px);
    box-shadow: 0 2px 8px rgba(108, 117, 125, 0.2);
}

#load_more_btn:disabled {
    cursor: not-allowed;
    opacity: 0.6;
}

#load_more_btn small {
    font-size: 0.7rem;
    margin-top: 2px;
}

/* Messages container top alignment */
/* Class, not id: the page and the sidebar carry different transcript ids now. */
.ask-ai-transcript {
    display: flex;
    flex-direction: column;
    align-items: stretch;
}

/* Ensure date separators are properly aligned */
.date-separator {
    text-align: center;
    margin: 15px 0 10px 0;
    position: relative;
}

.date-separator span {
    background: #f8f9fa;
    padding: 4px 12px;
    border-radius: 12px;
    font-size: 0.8rem;
    color: #6c757d;
    border: 1px solid #e9ecef;
}

/* Report Preview in Chat - Special Styling */
/* When a report preview is inside a message, reset the bubble styling */
/* Using :has() selector for modern browsers */
.assistant-message .message-content:has(.report-preview) {
    background: transparent !important;
    border: none !important;
    padding: 0 !important;
    border-radius: 0 !important;
}

/* Ensure report preview takes full width of message area */
.message:has(.report-preview) {
    max-width: 100% !important;
    width: 100% !important;
}

/* Fallback for browsers without :has() support - use .has-report-preview class */
.assistant-message.has-report-preview .message-content,
.message-content.has-report-preview {
    background: transparent !important;
    border: none !important;
    padding: 0 !important;
    border-radius: 0 !important;
}

.message.has-report-preview {
    max-width: 100% !important;
    width: 100% !important;
}

.message-content .report-preview {
    margin: 0;
    border-radius: 12px;
    overflow: hidden;
}

/* Report preview card styling in chat */
.message-content .report-preview .card-header {
    padding: 0.5rem 0.75rem;
    font-size: 0.9rem;
}

.message-content .report-preview .card-header h6 {
    font-size: 0.85rem;
    margin: 0;
}

/* Table in report preview */
.message-content .report-preview .table-responsive {
    max-height: 250px;
    font-size: 0.8rem;
    overflow: auto !important;
}

/* Ensure report preview card contains all content */
.report-preview {
    overflow: hidden;
}

.report-preview .card-body {
    overflow: hidden;
}

.message-content .report-preview table {
    /* Report-preview tables already scroll via their .table-responsive
       wrapper — keep them as normal full-width tables, not the block-scroll
       treatment applied to plain markdown tables above. */
    display: table;
    width: 100%;
    margin-bottom: 0;
}

.message-content .report-preview th,
.message-content .report-preview td {
    padding: 0.4rem 0.6rem;
    font-size: 0.8rem;
    vertical-align: middle;
}

.message-content .report-preview th {
    background-color: #f8f9fa;
    font-weight: 600;
    border-bottom: 2px solid #dee2e6;
}

/* Action buttons in report preview */
.message-content .report-preview .card-footer {
    padding: 0.5rem 0.75rem;
    background-color: #f8f9fa;
}

.message-content .report-preview .card-footer .btn {
    font-size: 0.75rem;
    padding: 0.25rem 0.5rem;
}

/* Badge styling in report preview header */
.message-content .report-preview .badge {
    font-size: 0.7rem;
    font-weight: 500;
}

/* Ensure proper contrast for text in cards */
.message-content .report-preview .card-body {
    background-color: #fff;
}

/* Chart container in report preview */
.message-content .report-preview .card-body.border-top {
    padding: 0.75rem;
}

/* Ensure message timestamp appears correctly after report preview */
.assistant-message:has(.report-preview) .message-time {
    margin-top: 0.5rem;
}

/* ═══════════════════════════════════════════════════════
   Shared turn chrome (sidebar + console)
   ───────────────────────────────────────────────────────
   views/ask_ai/_message.html.erb is rendered by THREE surfaces: the full-page
   chat, this slide-out sidebar, and the sysadmin console. The attribution row
   and the answer-action row it emits used to carry Bootstrap utility classes
   inline, which made them impossible to restyle per surface — utilities are
   !important, so no scoped rule could win. The markup now carries semantic
   classes only, and each surface owns its own presentation: the full page in
   ask_ai_page.css (scoped under .aichat), the sidebar and console here.

   Every selector below is anchored to .message / .chat-message so these rules
   can never escape a chat transcript into the rest of the app.
   ═══════════════════════════════════════════════════════ */
/* Hide the streaming placeholder's content div until the first token lands —
   without this the user sees an empty bubble under the status line. Scoped to
   .streaming so ERB-rendered turns (whitespace text nodes defeat :empty)
   are unaffected. */
.assistant-message.streaming .message-content:empty {
    display: none;
}

/* One quiet meta row under the answer: attribution + trust badges always
   visible; time + actions fade in on hover/focus so the transcript reads as
   conversation, not toolbars. */
.message .ai-answer-footer,
.chat-message .ai-answer-footer {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    margin-top: 6px;
    min-height: 24px;
}

.message .aichat-attribution,
.chat-message .aichat-attribution {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    font-size: 11.5px;
    font-weight: 600;
    color: #495057;
}

.message .aichat-attribution i,
.chat-message .aichat-attribution i {
    color: #1a73e8;
    font-size: 10px;
}

.message .ai-answer-badges,
.chat-message .ai-answer-badges {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 4px;
}

.message .ai-answer-badges .badge,
.chat-message .ai-answer-badges .badge {
    font-size: 10px;
    font-weight: 500;
    padding: 2px 6px;
}

.message .aichat-actions,
.chat-message .aichat-actions {
    display: flex;
    align-items: center;
    gap: 2px;
    flex-wrap: wrap;
    margin-left: auto;
    opacity: 0.35;
    transition: opacity 0.15s ease;
}

.message:hover .aichat-actions,
.message:focus-within .aichat-actions,
.chat-message:hover .aichat-actions,
.chat-message:focus-within .aichat-actions {
    opacity: 1;
}

.message .aichat-actions .message-time,
.chat-message .aichat-actions .message-time {
    font-size: 11px;
    color: #adb5bd;
    margin: 0 4px 0 0;
}

.message .aichat-action,
.chat-message .aichat-action {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    background: none;
    border: 0;
    border-radius: 5px;
    padding: 3px 6px;
    font-size: 12px;
    color: #6c757d;
    cursor: pointer;
}

.message .aichat-action:hover,
.chat-message .aichat-action:hover {
    background: rgba(15, 23, 42, 0.06);
    color: #212529;
}

.message .aichat-action.is-done,
.chat-message .aichat-action.is-done {
    color: #1e7e34;
}

.message .aichat-actions .ai-escalated-note,
.chat-message .aichat-actions .ai-escalated-note {
    font-size: 12px;
    color: #1e7e34;
}

.message .aichat-actions .ai-feedback-btn,
.message .aichat-actions .ai-correct-btn,
.message .aichat-actions .ai-escalate-btn,
.chat-message .aichat-actions .ai-feedback-btn,
.chat-message .aichat-actions .ai-correct-btn,
.chat-message .aichat-actions .ai-escalate-btn {
    padding: 3px 6px;
    font-size: 12px;
    color: #6c757d;
    text-decoration: none;
}

/* ═══════════════════════════════════════════════════════
   Tool Progress Pills
   ═══════════════════════════════════════════════════════ */
.ai-tool-pills {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
    margin-bottom: 6px;
    min-height: 0;
}

.ai-tool-pill {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 3px 10px;
    border-radius: 12px;
    font-size: 11px;
    background: #e8f0fe;
    color: #1a73e8;
    transition: all 0.3s ease;
}

.ai-tool-pill.completed {
    background: #e6f4ea;
    color: #1e7e34;
}

.ai-tool-pill.error {
    background: #fce8e6;
    color: #d93025;
}

.ai-tool-pill .spinner-border {
    width: 10px;
    height: 10px;
    border-width: 1.5px;
}

/* ═══════════════════════════════════════════════════════
   Typing Dots Animation
   ═══════════════════════════════════════════════════════ */
.ai-typing-dots span {
    display: inline-block;
    width: 8px;
    height: 8px;
    background: #adb5bd;
    border-radius: 50%;
    margin: 0 2px;
    animation: ai-dot-bounce 1.4s infinite ease-in-out;
}

.ai-typing-dots span:nth-child(1) {
    animation-delay: 0s;
}

.ai-typing-dots span:nth-child(2) {
    animation-delay: 0.2s;
}

.ai-typing-dots span:nth-child(3) {
    animation-delay: 0.4s;
}

@keyframes ai-dot-bounce {

    0%,
    80%,
    100% {
        transform: scale(0.6);
        opacity: 0.5;
    }

    40% {
        transform: scale(1);
        opacity: 1;
    }
}

/* ═══════════════════════════════════════════════════════
   Streaming Cursor
   ═══════════════════════════════════════════════════════ */
.ai-streaming-cursor::after {
    content: '▊';
    animation: ai-blink 0.8s infinite;
    color: #6c757d;
    font-size: 0.9em;
}

@keyframes ai-blink {

    0%,
    100% {
        opacity: 1;
    }

    50% {
        opacity: 0;
    }
}
/* ═══════════════════════════════════════════════════════
   Global search panel chrome (⌘K badge, pinned See-all slot, idle panel)
   ───────────────────────────────────────────────────────
   Historically the Ask AI front door (a pinned Ask row above the results);
   that row was removed 2026-09-06 — asking lives on the header button and
   the results page. Everything here is scoped to #global-search-results.
   ═══════════════════════════════════════════════════════ */
/* The ⌘K badge. Anchored to the search wrapper, NOT to .input-group — the
   search button is an input-group child, so Bootstrap gives it
   position: relative + z-index: 2 and its opaque background paints over
   anything beneath it. The offset must therefore clear the button's full
   width (~55px: 1rem padding either side of a 20px icon); z-index is a
   backstop in case that width ever changes. */
.omnibox-kbd-hint {
    position: absolute;
    right: 58px;
    top: 50%;
    transform: translateY(-50%);
    z-index: 3;
    font-size: 10px;
    color: #8d939b;
    border: 1px solid #dcdfe5;
    border-radius: 4px;
    padding: 0 5px;
    background: #f4f5f8;
    pointer-events: none;
    white-space: nowrap; /* "Ctrl K" (non-Apple platforms) must not wrap */
}

/* Keep typed text from sliding under the badge. Matches the d-lg-inline
   breakpoint the badge is shown at, so narrower viewports keep the full field.
   Sized for the wider "Ctrl K" chip (~42px), not just ⌘K (~28px). */
@media (min-width: 992px) {
    #global-search-input {
        padding-right: 106px;
    }
}

/* Pill omnibox — a deliberate exception to --mgx-ctl-radius (0.2rem), which
   every other input and button keeps. This is the search-or-ask command bar,
   not an ordinary field, and the shape is what marks it as the front door.
   (AdminKit styled it this way originally; body.mgx-restyle flattened it.)
   Only the OUTER corners: Bootstrap's .input-group segment rules zero the
   inner pair so the field and button read as one capsule. Scoped by id to
   clear body.mgx-restyle (0,2,1) without depending on that class. 50rem
   always resolves to a true pill — border-radius caps at half the height. */
#global-search-input {
    border-top-left-radius: var(--bs-border-radius-pill, 50rem);
    border-bottom-left-radius: var(--bs-border-radius-pill, 50rem);
}

#global-search-button {
    border-top-right-radius: var(--bs-border-radius-pill, 50rem);
    border-bottom-right-radius: var(--bs-border-radius-pill, 50rem);
}

/* The pinned See-all slot stays visible at the bottom while long result lists
   scroll under it. It carries the panel's own opaque background: a sticky
   element paints over whatever scrolls beneath it, and the See-all anchor (a
   plain list-group-item) is transparent on its own. */
#global-search-see-all-row {
    position: sticky;
    bottom: 0;
    z-index: 2;
    background: var(--bs-dropdown-bg, #fff);
}

#global-search-see-all-row:not(:empty) {
    border-top: 1px solid #e8ecf1;
}

/* Idle panel (focused, empty field): recent searches */
#global-search-results .omnibox-idle-row {
    width: 100%;
    border: 0;
    cursor: pointer;
}

#global-search-results .omnibox-idle-icon {
    background: #f4f5f8;
    color: #8d939b;
}

#global-search-results .omnibox-idle-hints {
    display: flex;
    gap: 16px;
    padding: 8px 16px;
    border-top: 1px solid #eef0f3;
}

#global-search-results .omnibox-idle-hints kbd {
    font-size: 10px;
    padding: 1px 5px;
    margin-right: 2px;
    color: #5f6672;
    background: #f4f5f8;
    border: 1px solid #dcdfe5;
    border-radius: 4px;
    box-shadow: none;
}

/* ═══════════════════════════════════════════════════════
   Dark theme
   ───────────────────────────────────────────────────────
   Every colour above is a light-mode literal with no dark counterpart — white
   and #f8f9fa surfaces, #e9ecef borders, #6c757d/#495057/#333 text — so the
   whole slide-in panel kept painting itself light while the tenant theme forced
   LIGHT text on top of it. BusinessTheme#generate_dark_css_from_config emits
   `[data-theme="dark"] h5 { color: <light> !important }`, which out-ranks
   `.chat-header h5` above. Measured on officechat-dev with the panel open:
   the "Ask AI" title 1.15:1, "Showing last 10 of N messages" 2.29:1, source
   links 2.44:1, "Load older messages" 2.80:1 — i.e. blank, on every page in
   the product.

   Surfaces are re-pointed at the TENANT's own dark tokens (--bs-card-bg,
   --bs-body-bg, --bs-border-color, --bs-body-color, --bs-link-color) rather
   than at fixed dark literals, so the panel follows each tenant's branded dark
   palette exactly like the rest of the app chrome; the literal inside each
   var() is only the fallback for a tenant with no theme block. The light
   hierarchy is preserved rather than re-invented: the panel body takes the CARD
   surface and its chrome (header, composer, bubbles, separators) takes the
   one-step-darker PAGE surface — the dark mirror of white-panel/#f8f9fa-chrome.

   Keyed on `:root[data-theme="dark"]`, i.e. <html>: layouts/application sets
   the attribute on documentElement, so a `body[data-theme="dark"]` key would
   never match (custom.css carries 13 such rules that are dead for exactly this
   reason). The Console mount (layouts/system_admin) renders no data-theme at
   all, so none of this reaches it.

   EVERY rule in the PANEL block below is anchored to `.ask-ai-sidebar`, and
   that anchor is load-bearing rather than tidiness: this stylesheet is loaded
   on every page, and most of the selectors above (`.message-content`,
   `.date-separator span`, `.aichat-action`, `.ai-tool-pill`…) are shared
   verbatim with the FULL-PAGE chat at /apps/ask-ai/chat. An unanchored rule
   here out-specifies ask_ai_page.css and darkens that page's bubbles while its
   shell stays light. Measured while writing this: assistant bubble
   rgb(37,37,38) inside a rgb(247,248,250) shell, i.e. a half-themed page that
   reads worse than the all-light one it replaced. That page now carries its
   own dark block in ask_ai_page.css (ISS-20260812-567-7EAE54), which is what
   these anchors leave room for — keep them.

   The OMNIBOX block at the end of this file is the one exception, and is
   anchored to `#global-search-results` instead: those rows are not sidebar
   chrome. They were held back from this pass because their container is
   painted white by global_search.css, so darkening the Ask row alone would
   have put a dark row in a white panel. That file now has its own dark theme
   (same case), so the two move together.
   ═══════════════════════════════════════════════════════ */
:root[data-theme="dark"] {
    --ask-ai-surface: var(--bs-card-bg, #333333);
    --ask-ai-chrome: var(--bs-body-bg, #252526);
    --ask-ai-border: var(--bs-border-color, #4b4b4b);
    --ask-ai-text: var(--bs-body-color, #dededf);
    --ask-ai-muted: var(--text-muted, #a7acb1);
}

/* `.ai-indicator`'s white 2px ring (line 42) looks like it belongs in this
   block and does NOT: the element also runs `animation: pulse 2s infinite`,
   and those keyframes set box-shadow at 0/70/100%, so the animation — which
   outranks a normal author declaration — owns that property at every frame.
   Verified by injecting the element in dark mode: computed box-shadow came
   back as the keyframe value, never the white ring. A dark override there
   would be inert, so there isn't one. */

/* Panel container + chrome */
:root[data-theme="dark"] .ask-ai-sidebar {
    background: var(--ask-ai-surface);
    box-shadow: -2px 0 20px rgba(0, 0, 0, 0.5);
}

:root[data-theme="dark"] .ask-ai-sidebar .chat-header {
    background: var(--ask-ai-chrome);
    border-bottom-color: var(--ask-ai-border);
}

/* The theme's !important heading rule wins here; this is the answer for a
   tenant that has no theme block but still toggles dark. */
:root[data-theme="dark"] .ask-ai-sidebar .chat-header h5 {
    color: var(--bs-heading-color, #e9e9ea);
}

:root[data-theme="dark"] .ask-ai-sidebar .chat-input-container {
    background: var(--ask-ai-chrome);
    border-top-color: var(--ask-ai-border);
}

/* The border moved from the textarea to the .ask-ai-composer shell around it,
   so the dark override has to move with it — left on the textarea it styled a
   `border: 0` element and dark mode kept the light #ced4da shell. */
:root[data-theme="dark"] .ask-ai-sidebar .ask-ai-composer {
    border-color: var(--ask-ai-border);
}

/* Dark counterpart of the quiet-tools rule above. Without it btn-light kept
   Bootstrap's white fill and dark ink — the bright disc on the dark panel. */
:root[data-theme="dark"] .ask-ai-sidebar .ask-ai-composer-tools .btn-light {
    --bs-btn-bg: transparent;
    --bs-btn-border-color: transparent;
    --bs-btn-color: var(--ask-ai-muted);
    --bs-btn-hover-bg: rgba(255, 255, 255, 0.08);
    --bs-btn-hover-border-color: transparent;
    --bs-btn-hover-color: var(--ask-ai-text);
    --bs-btn-active-bg: rgba(255, 255, 255, 0.12);
    --bs-btn-active-border-color: transparent;
    --bs-btn-active-color: var(--ask-ai-text);
}

:root[data-theme="dark"] .ask-ai-sidebar .ask-ai-composer-tools .btn-light[aria-expanded="true"] {
    background: rgba(255, 255, 255, 0.12);
}

:root[data-theme="dark"] .ask-ai-sidebar .chat-welcome {
    color: var(--ask-ai-muted);
}

/* Covers both .date-separator span blocks above — they declare the same
   selector twice, so one override is enough. */
:root[data-theme="dark"] .ask-ai-sidebar .date-separator span {
    background: var(--ask-ai-chrome);
    color: var(--ask-ai-muted);
    border-color: var(--ask-ai-border);
}

:root[data-theme="dark"] .ask-ai-sidebar .load-history-container,
:root[data-theme="dark"] .ask-ai-sidebar .load-more-container {
    border-bottom-color: var(--ask-ai-border);
}

/* Assistant bubble. The user bubble is already a brand fill with
   --bs-on-primary ink, so it needs nothing. */
:root[data-theme="dark"] .ask-ai-sidebar .assistant-message .message-content {
    background: var(--ask-ai-chrome);
    color: var(--ask-ai-text);
    border-color: var(--ask-ai-border);
}

/* Source links in an answer. --bs-primary is the RAW brand fill (2.6:1 on the
   dark bubble); --bs-link-color is the same brand already clamped for
   readability by BusinessTheme#link_and_validation_tokens (5.3:1). */
:root[data-theme="dark"] .ask-ai-sidebar .markdown-content a {
    color: var(--bs-link-color, #8ba3c9);
}

/* The wash has to lift off the dark bubble, and AdminKit's --bs-code-color
   (#e83e8c) is identical in its dark bundle — 2.27:1 against that wash — so the
   ink moves up the same hue with it. */
:root[data-theme="dark"] .ask-ai-sidebar .message-content code {
    background: rgba(255, 255, 255, 0.12);
    color: #ffb0d6;
}

/* Re-stated after the rule above (equal specificity, later wins) so the chip on
   the brand-filled user bubble keeps its own stronger wash. */
:root[data-theme="dark"] .ask-ai-sidebar .user-message code {
    background: rgba(255, 255, 255, 0.2);
}

:root[data-theme="dark"] .ask-ai-sidebar .message-time {
    color: var(--ask-ai-muted);
}

:root[data-theme="dark"] .ask-ai-sidebar .entity-preview {
    background: var(--ask-ai-chrome);
}

/* Thinking / typing indicator */
:root[data-theme="dark"] .ask-ai-sidebar .thinking-container {
    background: var(--ask-ai-chrome);
    border-color: var(--ask-ai-border);
}

:root[data-theme="dark"] .ask-ai-sidebar .thinking-text {
    color: var(--ask-ai-text);
}

:root[data-theme="dark"] .ask-ai-sidebar .thinking-dots span {
    background: var(--ask-ai-muted);
}

/* The status line's colour is an inline style on the element (see
   ask_ai/_clean_sidebar), so !important is the only way to reach it. */
:root[data-theme="dark"] .ask-ai-sidebar #typing-indicator {
    color: var(--ask-ai-muted) !important;
}

/* Same shape: ask_ai_form_controller.js builds these three collapsed panels
   with an inline `color: #6c757d` on the <summary> — 2.69:1 on the dark
   bubble, measured live on "Informed by N business lessons". The inline style
   is why these carry !important; it stays untouched so light mode is
   unchanged. The ERB twin (ask_ai/_message) sets no colour and simply
   inherits, so this also lines the two render paths up. */
:root[data-theme="dark"] .ask-ai-sidebar .thinking-steps-collapsed > summary,
:root[data-theme="dark"] .ask-ai-sidebar .ai-provenance-panel > summary,
:root[data-theme="dark"] .ask-ai-sidebar .ai-business-lessons-panel > summary {
    color: var(--ask-ai-muted) !important;
}

:root[data-theme="dark"] .ask-ai-sidebar .ai-streaming-cursor::after {
    color: var(--ask-ai-muted);
}

/* Markdown tables, including the stacked "Header / value" card reflow */
:root[data-theme="dark"] .ask-ai-sidebar .message-content th,
:root[data-theme="dark"] .ask-ai-sidebar .message-content td,
:root[data-theme="dark"] .ask-ai-sidebar .markdown-content th,
:root[data-theme="dark"] .ask-ai-sidebar .markdown-content td {
    border-color: var(--ask-ai-border);
}

:root[data-theme="dark"] .ask-ai-sidebar .message-content th,
:root[data-theme="dark"] .ask-ai-sidebar .markdown-content th {
    background-color: var(--ask-ai-surface);
}

:root[data-theme="dark"] .ask-ai-sidebar .message-content table.ai-md-table--stack tr,
:root[data-theme="dark"] .ask-ai-sidebar .markdown-content table.ai-md-table--stack tr {
    background: var(--ask-ai-surface);
    border-color: var(--ask-ai-border);
}

:root[data-theme="dark"] .ask-ai-sidebar .message-content table.ai-md-table--stack td,
:root[data-theme="dark"] .ask-ai-sidebar .markdown-content table.ai-md-table--stack td {
    border-bottom-color: var(--ask-ai-border);
}

:root[data-theme="dark"] .ask-ai-sidebar .message-content table.ai-md-table--stack td::before,
:root[data-theme="dark"] .ask-ai-sidebar .markdown-content table.ai-md-table--stack td::before {
    color: var(--ask-ai-muted);
}

/* Report preview card rendered inside a bubble */
:root[data-theme="dark"] .ask-ai-sidebar .message-content .report-preview th {
    background-color: var(--ask-ai-chrome);
    border-bottom-color: var(--ask-ai-border);
}

:root[data-theme="dark"] .ask-ai-sidebar .message-content .report-preview .card-footer {
    background-color: var(--ask-ai-chrome);
}

:root[data-theme="dark"] .ask-ai-sidebar .message-content .report-preview .card-body {
    background-color: var(--ask-ai-surface);
}

/* Answer footer — attribution row and the action strip */
:root[data-theme="dark"] .ask-ai-sidebar .aichat-attribution {
    color: var(--ask-ai-muted);
}

:root[data-theme="dark"] .ask-ai-sidebar .aichat-attribution i {
    color: #8ab4f8;
}

:root[data-theme="dark"] .ask-ai-sidebar .aichat-action,
:root[data-theme="dark"] .ask-ai-sidebar .aichat-actions .ai-feedback-btn,
:root[data-theme="dark"] .ask-ai-sidebar .aichat-actions .ai-correct-btn,
:root[data-theme="dark"] .ask-ai-sidebar .aichat-actions .ai-escalate-btn {
    color: var(--ask-ai-muted);
}

:root[data-theme="dark"] .ask-ai-sidebar .aichat-action:hover {
    background: rgba(255, 255, 255, 0.1);
    color: var(--ask-ai-text);
}

/* #1e7e34 is 2.2:1 against the dark bubble. */
:root[data-theme="dark"] .ask-ai-sidebar .aichat-action.is-done,
:root[data-theme="dark"] .ask-ai-sidebar .aichat-actions .ai-escalated-note {
    color: #6fcf97;
}

/* Tool progress pills and system messages are light PASTELS with dark ink —
   internally readable, but bright slabs once the panel around them is dark.
   Same hue, re-expressed as a low-alpha wash with light ink, matching the
   *-bg-subtle treatment custom.css gives the rest of the app in dark mode. */
:root[data-theme="dark"] .ask-ai-sidebar .ai-tool-pill {
    background: rgba(138, 180, 248, 0.16);
    color: #a3c5fa;
}

:root[data-theme="dark"] .ask-ai-sidebar .ai-tool-pill.completed {
    background: rgba(111, 207, 151, 0.16);
    color: #6fcf97;
}

:root[data-theme="dark"] .ask-ai-sidebar .ai-tool-pill.error {
    background: rgba(242, 139, 130, 0.16);
    color: #f8a9a2;
}

:root[data-theme="dark"] .ask-ai-sidebar .system-message.info {
    background: rgba(33, 150, 243, 0.16);
    color: #8ab4f8;
}

:root[data-theme="dark"] .ask-ai-sidebar .system-message.primary {
    background: rgba(156, 39, 176, 0.2);
    color: #dba6ea;
}

:root[data-theme="dark"] .ask-ai-sidebar .system-message.warning {
    background: rgba(255, 152, 0, 0.16);
    color: #f6c177;
}

/* ═══════════════════════════════════════════════════════
   Dark theme — omnibox
   ───────────────────────────────────────────────────────
   Anchored to `#global-search-results` / `.omnibox-*`, NOT to
   `.ask-ai-sidebar`: this is the search panel's Ask row, not sidebar chrome,
   and none of these selectors is shared with the full-page chat.

   The light fills above were chosen to sit on a WHITE panel; global_search.css
   now themes that panel, so they move with it or the Ask row becomes a light
   slab in a dark dropdown. The blue accent is kept — it is what marks the row
   as the Ask AI front door — but re-expressed as a low-alpha wash with light
   ink, the same treatment the panel block above gives its pastels.
   ═══════════════════════════════════════════════════════ */

/* The ⌘K badge sits inside the navbar's search FIELD, which the theme already
   darkens — so this one is a light chip on a dark input even before the panel
   opens. */
:root[data-theme="dark"] .omnibox-kbd-hint {
    color: var(--text-muted, #a7acb1);
    background: var(--bs-body-bg, #252526);
    border-color: var(--bs-border-color, #4b4b4b);
}

/* Same surface as the dark panel itself (global_search.css: --bs-card-bg) so
   the sticky slot stays opaque over scrolling rows. */
:root[data-theme="dark"] #global-search-see-all-row {
    background: var(--bs-card-bg, #333333);
}

:root[data-theme="dark"] #global-search-see-all-row:not(:empty) {
    border-top-color: var(--bs-border-color, #4b4b4b);
}

:root[data-theme="dark"] #global-search-results .omnibox-idle-icon {
    background: rgba(255, 255, 255, 0.08);
    color: var(--text-muted, #a7acb1);
}

:root[data-theme="dark"] #global-search-results .omnibox-idle-hints {
    border-top-color: var(--bs-border-color, #4b4b4b);
}

:root[data-theme="dark"] #global-search-results .omnibox-idle-hints kbd {
    color: var(--text-muted, #a7acb1);
    background: var(--bs-body-bg, #252526);
    border-color: var(--bs-border-color, #4b4b4b);
}
