.panel {
    display: flex;
    flex-direction: column;
    height: 100%;
    min-height: 0;
}

.messages {
    flex: 1 1 auto;
    min-height: 0;
    /* Smaller, denser chat text (cascades into user bubble + assistant markdown
       + tool cards; the explicit-size Mantine labels keep their own size). */
    font-size: var(--mantine-font-size-xs);
}

.messageRow {
    margin-bottom: var(--mantine-spacing-md);
}

.userBubble {
    background: var(--mantine-color-gray-light);
    border-radius: var(--mantine-radius-md);
    padding: 8px 12px;
    white-space: pre-wrap;
    overflow-wrap: break-word;
    word-break: break-word;
}

/* Rendered markdown for assistant messages. Keep block margins compact. */
.markdown {
    overflow-wrap: break-word;
    word-break: break-word;
}

.markdown p {
    margin-block-start: 0;
    margin-block-end: 0.5em;
}

.markdown pre {
    background: var(--mantine-color-gray-light);
    border-radius: var(--mantine-radius-sm);
    padding: 8px;
    overflow-x: auto;
}

.markdown code {
    font-size: 0.85em;
}

.markdown ul,
.markdown ol {
    margin-block-start: 0;
    margin-block-end: 0.5em;
    padding-inline-start: 1.4em;
}

/* GFM tables in assistant markdown. The chat lives in a NARROW side panel, so a
   wide LLM table must scroll horizontally instead of collapsing its columns:
   `.markdown` sets `word-break: break-word`, which (with the default table
   layout) shrinks columns to a single glyph and wraps headers mid-word
   ("Секция" -> "Секци / я"). Make the table a horizontally scrollable block,
   give cells a readable minimum width, and restore word-boundary wrapping. */
.markdown table {
    display: block;
    /* lets the table scroll horizontally on its own */
    max-width: 100%;
    overflow-x: auto;
    border-collapse: collapse;
    margin-block-end: 0.5em;
}

.markdown th,
.markdown td {
    border: 1px solid light-dark(var(--mantine-color-gray-3), var(--mantine-color-dark-4));
    padding: 3px 8px;
    /* readable floor; the block scrolls when the row exceeds the panel */
    min-width: 6em;
    text-align: left;
    vertical-align: top;
    /* cancel the inherited break-word so words don't split mid-glyph */
    word-break: normal;
    /* still wrap genuinely long words / URLs at the cell edge */
    overflow-wrap: break-word;
}

.markdown th {
    background: light-dark(var(--mantine-color-gray-1), var(--mantine-color-dark-5));
    font-weight: 600;
}

/* GFM wraps cell text in <p>; drop its default block margin inside cells. */
.markdown table p {
    margin: 0;
}

/* Animated three-dot "typing" indicator shown while the agent is thinking but
   has not yet produced any visible text/tool parts. */
.typingDots {
    display: inline-flex;
    align-items: center;
    gap: 4px;
}

.typingDots span {
    width: 5px;
    height: 5px;
    border-radius: 50%;
    background: var(--mantine-color-dimmed, var(--mantine-color-gray-5));
    opacity: 0.4;
    animation: aiTypingBounce 1.2s infinite ease-in-out;
}

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

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

@keyframes aiTypingBounce {
    0%,
    80%,
    100% {
        transform: translateY(0);
        opacity: 0.4;
    }
    40% {
        /* Bounce height is driven by --bounce so reduced-motion can dampen it
           (below) without disabling the animation outright. */
        transform: translateY(var(--bounce, -6px));
        opacity: 1;
    }
}

/* Respect reduced-motion preferences: keep a smaller bounce instead of a full
   stop, so the "thinking" indicator still reads as active rather than frozen. */
@media (prefers-reduced-motion: reduce) {
    .typingDots span {
        --bounce: -3px;
    }
}

.toolCard {
    border: 1px solid light-dark(var(--mantine-color-gray-3), var(--mantine-color-dark-4));
    border-radius: var(--mantine-radius-sm);
    padding: 6px 10px;
    margin-bottom: 6px;
    background: light-dark(var(--mantine-color-gray-0), var(--mantine-color-dark-6));
}

/* Collapsible "Thinking" (reasoning) block: a subtle left rule, dimmer than the
   answer so it reads as secondary thinking context above the real answer. */
.reasoningBlock {
    border-left: 2px solid light-dark(var(--mantine-color-gray-3), var(--mantine-color-dark-4));
    padding-left: 8px;
}

.reasoningText {
    margin-top: 4px;
    font-size: var(--mantine-font-size-xs);
    color: light-dark(var(--mantine-color-gray-7), var(--mantine-color-dark-1));
    /* NOTE: `white-space: pre-wrap` is intentionally NOT set here. On the
       rendered markdown <div> it would turn the newlines between block tags
       (</li>\n<li>, </p>\n<ol>) into visible blank lines/indents on top of the
       margins. The plain-text fallback <Text> that needs pre-wrap sets it
       inline itself (see reasoning-block.tsx). */
}

.reasoningText p {
    margin: 0 0 4px;
}

.inputWrapper {
    flex: 0 0 auto;
    padding-top: var(--mantine-spacing-xs);
}

.conversationItem {
    cursor: pointer;
    border-radius: var(--mantine-radius-sm);
}

.conversationItem:hover {
    background: var(--mantine-color-gray-light);
}

.conversationItemActive {
    background: var(--mantine-color-gray-light);
}

/* Pending messages queued by the user while a turn is still streaming. They
   are sent automatically, FIFO, once the current turn finishes. */
.queuedList {
    padding-bottom: var(--mantine-spacing-xs);
}

.queuedItem {
    background: var(--mantine-color-gray-light);
    border-radius: var(--mantine-radius-sm);
    padding: 4px 8px;
}

.queuedIcon {
    flex: none;
    color: var(--mantine-color-dimmed);
}

.queuedText {
    flex: 1;
    min-width: 0;
    color: var(--mantine-color-dimmed);
    white-space: pre-wrap;
    overflow-wrap: break-word;
    word-break: break-word;
}
