/* Composer — the auto-growing input itself lives in
   components/chat_composer.css (.chat-composer-input /
   .chat-composer-editor). Buttons pin to the bottom edge so they keep
   their natural height while the field grows. */
.chat-composer {
  align-items: flex-end;
}

/* Chat bubble — scoped styles for markdown content in chat messages */

/* Task list checkboxes */
.chat-bubble .task-list-item {
  list-style: none;
  margin-left: -1.5rem;
}

.chat-bubble .task-list-inline {
  display: flex;
  align-items: baseline;
  gap: 0;
  margin: 0;
  cursor: default;
}

.chat-bubble .task-list-checkbox {
  margin-right: 0.4em;
  vertical-align: middle;
  accent-color: var(--traqx-blue-600, #026CFF);
  width: 1em;
  height: 1em;
  flex-shrink: 0;
}

/* Headings inside an answer. Reboot zeroes their top margin, so a
   heading sat flush against the paragraph above it and read as that
   paragraph's tail instead of the next section's title. The gap above
   has to be clearly larger than the one below — that asymmetry is what
   binds a heading to the text it introduces. */
.chat-bubble .chat-bubble-body :is(h1, h2, h3, h4, h5, h6) {
  margin-top: 1.75rem;
  margin-bottom: 0.4rem;
  line-height: 1.35;
}

.chat-bubble .chat-bubble-body :is(h1, h2, h3, h4, h5, h6):first-child {
  margin-top: 0;
}

/* An answer's own headings compete with the workspace title above the
   thread if they keep the document-scale sizes. */
.chat-bubble .chat-bubble-body h1 { font-size: 1.2rem; }
.chat-bubble .chat-bubble-body h2 { font-size: 1.1rem; }
.chat-bubble .chat-bubble-body h3 { font-size: 1rem; }
.chat-bubble .chat-bubble-body :is(h4, h5, h6) { font-size: 0.95rem; }

/* Markdown tables inside the chat bubble — without explicit styling
   the browser default has no borders, so columns blur into each
   other on tables without padding. */
.chat-bubble .chat-bubble-body table {
  width: 100%;
  margin: 0.5em 0 1em;
  border-collapse: collapse;
  font-size: 0.95em;
}

.chat-bubble .chat-bubble-body th,
.chat-bubble .chat-bubble-body td {
  padding: 0.4em 0.6em;
  border: 1px solid var(--tblr-border-color, #e6e7e9);
  text-align: left;
  vertical-align: top;
}

.chat-bubble .chat-bubble-body th {
  background: var(--tblr-bg-surface-secondary, #f6f8fa);
  font-weight: 600;
}

/* Inline citation badges */
.chat-bubble .citation {
  display: inline;
  padding: 0.1em 0.4em;
  font-size: 0.8em;
  font-weight: 500;
  color: var(--traqx-blue-600, #026CFF);
  background-color: var(--traqx-blue-50, #F0F7FF);
  border: 1px solid var(--traqx-blue-200, #CCE0FF);
  border-radius: 4px;
  cursor: pointer;
  white-space: normal;
  overflow-wrap: anywhere;
  max-width: 100%;
  transition: background-color 120ms ease, border-color 120ms ease;
}

.chat-bubble .citation[data-chunk-id]:hover,
.chat-bubble .citation[data-document-id]:hover {
  background-color: var(--traqx-blue-100, #DBEBFF);
  border-color: var(--traqx-blue-300, #99C2FF);
}

.chat-bubble .citation::before {
  content: "📄 ";
  font-size: 0.85em;
}

/* Source-list variant: rendered as a full-width row inside the
   "Quellen" details on assistant bubbles. Reuses .citation so the
   Stimulus controller still picks it up for hover-preview and
   click-to-source, but visually presents as a list item rather
   than an inline pill. */
.chat-bubble .citation.citation--source-item {
  display: flex;
  align-items: center;
  gap: 0.2rem;
  width: 100%;
  margin: 0.15rem 0;
  padding: 0.3rem 0.5rem;
  text-align: left;
  font-size: 0.85em;
  font-weight: normal;
  color: var(--tblr-body-color, #1f2d3d);
  background-color: transparent;
  border: 1px solid transparent;
  border-radius: 4px;
}

.chat-bubble .citation.citation--source-item:hover,
.chat-bubble .citation.citation--source-item[data-chunk-id]:hover,
.chat-bubble .citation.citation--source-item[data-document-id]:hover {
  background-color: var(--traqx-blue-50, #F0F7FF);
  border-color: var(--traqx-blue-200, #CCE0FF);
}

.chat-bubble .citation.citation--source-item::before {
  content: none;
}

.citation--source-item-text {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Group label inside the sources footer: separates corpus sources
   from workspace artifacts (only rendered when both groups exist). */
.citation--source-group-label {
  display: flex;
  align-items: center;
  font-size: 0.72em;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

/* Evidence-class dot on artifact chips (Trust but Verify): green =
   human-confirmed at capture, amber = workspace-generated, unconfirmed. */
.citation--source-state {
  flex-shrink: 0;
  width: 0.5rem;
  height: 0.5rem;
  border-radius: 50%;
}

.citation--source-state--confirmed {
  background-color: var(--tblr-success, #2fb344);
}

.citation--source-state--unconfirmed {
  background-color: var(--tblr-warning, #f76707);
}

/* Verification seal next to the sources count: the amber label is
   long — allow it to wrap and shrink instead of forcing horizontal
   overflow in narrow split panes (Tabler badges are nowrap). */
.chat-bubble .citation-check-badge {
  flex-shrink: 1;
  min-width: 0;
  white-space: normal;
  text-align: start;
  line-height: 1.25;
}

/* Resolved quotes (US-214): a `[quote:]` token the server replaced by
   the source's own text. The block is the quote; the chip under it is
   the same .citation chip the hover-preview and click-to-source know.
   The text keeps its whitespace exactly as the source delivered it. */
.citation-quote {
  display: block;
  margin: 0.5rem 0;
  padding: 0.5rem 0.75rem;
  border-left: 3px solid var(--traqx-blue-300, #99C2FF);
  border-radius: 4px;
  background-color: var(--traqx-blue-50, #F0F7FF);
}

.citation-quote-text {
  display: block;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

.citation-quote-source {
  display: block;
  margin-top: 0.35rem;
}

/* A token the server could not resolve stays visible where the quote
   would have stood — never silently dropped, never shown as a quote. */
.citation-quote--unresolved {
  border-left-color: var(--tblr-danger, #d63939);
  background-color: var(--tblr-danger-lt, #fff5f5);
  font-size: 0.9em;
}

.citation-quote--unresolved .citation-quote-label {
  font-weight: 600;
  color: var(--tblr-danger, #d63939);
}

/* While the turn runs the client only knows the token; the final
   bubble replaces this with the server's resolution. */
.citation-quote--pending {
  border-left-color: var(--tblr-border-color, #e6e7e9);
  background-color: var(--tblr-bg-surface-secondary, #f6f8fa);
  color: var(--tblr-secondary, #6c757d);
  font-style: italic;
  font-size: 0.9em;
}

/* Citation hover-preview popover. Positioned via JS (citation_controller). */
.citation-popover {
  position: absolute;
  z-index: 1080;
  max-width: 360px;
  min-width: 240px;
  padding: 0.6rem 0.75rem;
  background: var(--tblr-bg-surface, #fff);
  color: var(--tblr-body-color, #1f2d3d);
  border: 1px solid var(--tblr-border-color, #e6e7e9);
  border-radius: 6px;
  box-shadow: 0 8px 24px rgba(15, 23, 42, 0.12);
  font-size: 0.85em;
  line-height: 1.45;
  pointer-events: auto;
}

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

.citation-popover-loading,
.citation-popover-error {
  font-style: italic;
  color: var(--tblr-secondary, #6b7280);
}

.citation-preview-header {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
  align-items: center;
  margin-bottom: 0.4rem;
  padding-bottom: 0.35rem;
  border-bottom: 1px solid var(--tblr-border-color-translucent, #e6e7e9);
  font-size: 0.85em;
}

.citation-preview-kb {
  color: var(--traqx-blue-600, #026CFF);
  font-weight: 500;
}

.citation-preview-doc {
  font-weight: 500;
}

.citation-preview-heading {
  font-weight: normal;
}

.citation-preview-note {
  display: flex;
  align-items: center;
  margin-block-end: 0.35rem;
}

.citation-preview-body {
  word-break: break-word;
  color: var(--tblr-body-color, #1f2d3d);
  max-height: 240px;
  overflow-y: auto;
}

/* Compact markdown styles inside the popover. The chunk text is
   sliced to ~500 chars but may still bring headings, lists, tables
   along — keep them readable but small. */
.citation-preview-body > :first-child { margin-top: 0; }
.citation-preview-body > :last-child  { margin-bottom: 0; }

.citation-preview-body p,
.citation-preview-body ul,
.citation-preview-body ol,
.citation-preview-body blockquote,
.citation-preview-body pre,
.citation-preview-body table {
  margin: 0 0 0.5em;
}

.citation-preview-body h1,
.citation-preview-body h2,
.citation-preview-body h3,
.citation-preview-body h4,
.citation-preview-body h5,
.citation-preview-body h6 {
  margin: 0.4em 0 0.25em;
  font-size: 0.95em;
  font-weight: 600;
  line-height: 1.3;
}

.citation-preview-body ul,
.citation-preview-body ol {
  padding-left: 1.25em;
}

.citation-preview-body li + li { margin-top: 0.15em; }

.citation-preview-body code {
  padding: 0.1em 0.3em;
  background: var(--tblr-bg-surface-secondary, #f6f8fa);
  border-radius: 3px;
  font-size: 0.9em;
}

.citation-preview-body pre {
  padding: 0.4em 0.6em;
  background: var(--tblr-bg-surface-secondary, #f6f8fa);
  border-radius: 4px;
  font-size: 0.85em;
  overflow-x: auto;
}

.citation-preview-body pre code {
  padding: 0;
  background: transparent;
}

.citation-preview-body table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.9em;
}

.citation-preview-body th,
.citation-preview-body td {
  padding: 0.25em 0.5em;
  border: 1px solid var(--tblr-border-color, #e6e7e9);
  text-align: left;
  vertical-align: top;
}

.citation-preview-body blockquote {
  padding-left: 0.75em;
  border-left: 3px solid var(--tblr-border-color, #e6e7e9);
  color: var(--tblr-secondary, #6b7280);
}

/* Side-panel (Offcanvas) — click-to-source.
   Bootstrap drives offcanvas width via the --bs-offcanvas-width custom
   property; setting `width:` directly loses to `.offcanvas.offcanvas-end`
   in some Tabler builds. Override the variable instead. */
.offcanvas.citation-source-panel,
.citation-source-panel {
  --bs-offcanvas-width: min(820px, 92vw);
  width: min(820px, 92vw);
  max-width: 92vw;
}

/* The Turbo Frame wraps both header and body so a single response
   fills the panel. Bootstrap's offcanvas uses `display: flex;
   flex-direction: column` and expects header + body as direct flex
   children — the frame in between would break that and the body
   would never get its `flex-grow: 1; overflow-y: auto` shape. We
   make the frame transparent to layout so its children inherit the
   parent's flex slots. */
.citation-source-panel > turbo-frame {
  display: contents;
}

/* The breadcrumb + open-document button live inside the offcanvas
   header (slotted there by the citation Stimulus controller) so they
   stay visible while the user scrolls the chunks below.

   Layout: a 2-row meta block on the left, the close-X stays
   centered on the right (Bootstrap default). Row 1 has the document
   name + button; row 2 has the KB and section heading as a small
   secondary line. */
.citation-source-panel-header {
  align-items: center;
  gap: 0.75rem;
  padding-top: 0.6rem;
  padding-bottom: 0.6rem;
}

.citation-source-panel-meta {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
}

.citation-source-meta-primary {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  min-width: 0;
}

.citation-source-meta-primary .citation-source-doc {
  flex: 1;
  min-width: 0;
  display: inline-flex;
  align-items: center;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.citation-source-meta-primary .citation-source-doc strong {
  overflow: hidden;
  text-overflow: ellipsis;
}

.citation-source-meta-primary .citation-source-actions {
  flex-shrink: 0;
}

.citation-source-meta-secondary {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  flex-wrap: wrap;
  font-size: 0.8em;
  line-height: 1.4;
}

.citation-source-meta-secondary .citation-source-kb {
  color: var(--traqx-blue-600, #026CFF);
  font-weight: 500;
  display: inline-flex;
  align-items: center;
}

.citation-source-sep {
  color: var(--tblr-secondary, #6b7280);
}

.citation-source-chunk {
  padding: 0.4rem 0.6rem;
  margin: 0 0 0.85rem;
  border-radius: 0;
  border: 0;
  color: var(--tblr-secondary, #6b7280);
  background: transparent;
  scroll-margin-top: 1rem;
}

.citation-source-chunk:first-child {
  padding-top: 0;
}

.citation-source-chunk:last-child {
  margin-bottom: 0;
}

/* Textmarker-Optik für den Ziel-Chunk. Der gelbe Streifen liegt als
   ::before-Layer unter dem Text (z-index -1) statt als Block-Background,
   damit wir ihn leicht schräg drehen, mit unregelmäßigen Ecken
   versehen und horizontal etwas einrücken können — fühlt sich an wie
   ein echter, von Hand gezogener Marker statt wie eine eckige Karte. */
.citation-source-chunk--target {
  position: relative;
  z-index: 0;
  color: var(--tblr-body-color, #1f2d3d);
  background: transparent;
  box-shadow: none;
}

.citation-source-chunk--target::before {
  content: "";
  position: absolute;
  inset: 0.15rem 0.5rem;
  z-index: -1;
  background-image: linear-gradient(
    100deg,
    rgba(255, 235, 59, 0) 0%,
    rgba(255, 235, 59, 0.5) 3%,
    rgba(255, 235, 59, 0.6) 50%,
    rgba(255, 235, 59, 0.5) 97%,
    rgba(255, 235, 59, 0) 100%
  );
  transform: rotate(-0.3deg);
  /* Leicht unregelmäßige Ecken — wirkt nicht wie ein Rechteck. */
  border-radius: 2px 5px 3px 4px;
  pointer-events: none;
}

.citation-source-chunk-heading {
  margin-bottom: 0.35rem;
  font-weight: 500;
}

.citation-source-chunk-body {
  word-break: break-word;
}

.citation-source-chunk-body > :first-child { margin-top: 0; }
.citation-source-chunk-body > :last-child  { margin-bottom: 0; }

.citation-source-chunk-body p,
.citation-source-chunk-body ul,
.citation-source-chunk-body ol,
.citation-source-chunk-body blockquote,
.citation-source-chunk-body pre,
.citation-source-chunk-body table {
  margin: 0 0 0.6em;
}

.citation-source-chunk-body h1,
.citation-source-chunk-body h2,
.citation-source-chunk-body h3,
.citation-source-chunk-body h4,
.citation-source-chunk-body h5,
.citation-source-chunk-body h6 {
  margin: 0.5em 0 0.3em;
  font-size: 1em;
  font-weight: 600;
}

.citation-source-chunk-body table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.9em;
}

.citation-source-chunk-body th,
.citation-source-chunk-body td {
  padding: 0.3em 0.5em;
  border: 1px solid var(--tblr-border-color, #e6e7e9);
  text-align: left;
  vertical-align: top;
}

.citation-source-empty {
  padding: 1rem 0;
  text-align: center;
}

/* Full-document viewer typography. Scoped to `.citation-document` so
   it doesn't leak into the side-panel partial (which reuses the same
   `.citation-source-chunk-body` markup but in a much smaller box). */
.citation-document {
  font-size: 1rem;
  line-height: 1.7;
  color: var(--tblr-body-color, #1f2d3d);
}

.citation-document .citation-source-chunk {
  padding: 0.25rem 1rem;
  margin: 0 0 1.75rem;
  /* Page header sits above the chunk on full-page navigation;
     leave room so the anchored chunk lands below it after scroll. */
  scroll-margin-top: 5rem;
}

.citation-document .citation-source-chunk:last-child {
  margin-bottom: 0;
}

/* Per-chunk section heading (from the chunker's `heading` metadata).
   Shown as the dominant level in the document view because the
   chunker stripped the `#`/`##` level information at extract time. */
.citation-document-chunk-heading {
  margin: 0 0 0.5rem;
  padding-bottom: 0.3rem;
  font-size: 1.35rem;
  font-weight: 600;
  line-height: 1.3;
  color: var(--tblr-body-color, #1f2d3d);
  border-bottom: 1px solid var(--tblr-border-color, #e6e7e9);
}

/* Sub-headings inside the chunk content (from markdown `##`, `###`, …)
   get a clear visual hierarchy. Override the compact panel-context
   styles inherited via `.citation-source-chunk-body`. */
.citation-document .citation-source-chunk-body h1,
.citation-document .citation-source-chunk-body h2,
.citation-document .citation-source-chunk-body h3,
.citation-document .citation-source-chunk-body h4,
.citation-document .citation-source-chunk-body h5,
.citation-document .citation-source-chunk-body h6 {
  font-weight: 600;
  line-height: 1.3;
  color: var(--tblr-body-color, #1f2d3d);
}

.citation-document .citation-source-chunk-body h1 {
  font-size: 1.5rem;
  margin: 1.4rem 0 0.7rem;
}

.citation-document .citation-source-chunk-body h2 {
  font-size: 1.25rem;
  margin: 1.2rem 0 0.6rem;
}

.citation-document .citation-source-chunk-body h3 {
  font-size: 1.1rem;
  margin: 1rem 0 0.5rem;
}

.citation-document .citation-source-chunk-body h4 {
  font-size: 1rem;
  margin: 0.85rem 0 0.4rem;
}

.citation-document .citation-source-chunk-body h5 {
  font-size: 0.95rem;
  margin: 0.75rem 0 0.35rem;
  color: var(--tblr-secondary, #6b7280);
}

.citation-document .citation-source-chunk-body h6 {
  font-size: 0.85rem;
  margin: 0.7rem 0 0.3rem;
  color: var(--tblr-secondary, #6b7280);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.citation-document .citation-source-chunk-body p {
  margin: 0 0 0.85em;
}

.citation-document .citation-source-chunk-body ul,
.citation-document .citation-source-chunk-body ol {
  margin: 0 0 0.85em;
  padding-left: 1.6em;
}

.citation-document .citation-source-chunk-body li + li {
  margin-top: 0.25em;
}

.citation-document .citation-source-chunk-body blockquote {
  margin: 0 0 1em;
  padding: 0.5em 0.9em;
  border-left: 3px solid var(--traqx-blue-300, #99C2FF);
  background: var(--traqx-blue-50, #F0F7FF);
  color: var(--tblr-body-color, #1f2d3d);
}

.citation-document .citation-source-chunk-body table {
  width: 100%;
  margin: 0 0 1em;
  border-collapse: collapse;
}

.citation-document .citation-source-chunk-body th,
.citation-document .citation-source-chunk-body td {
  padding: 0.4em 0.6em;
  border: 1px solid var(--tblr-border-color, #e6e7e9);
  text-align: left;
  vertical-align: top;
}

.citation-document .citation-source-chunk-body th {
  background: var(--tblr-bg-surface-secondary, #f6f8fa);
  font-weight: 600;
}

.citation-document .citation-source-chunk-body code {
  padding: 0.1em 0.35em;
  background: var(--tblr-bg-surface-secondary, #f6f8fa);
  border-radius: 3px;
  font-size: 0.92em;
}

.citation-document .citation-source-chunk-body pre {
  padding: 0.75em 1em;
  margin: 0 0 1em;
  background: var(--tblr-bg-surface-secondary, #f6f8fa);
  border-radius: 4px;
  font-size: 0.92em;
  overflow-x: auto;
}

.citation-document .citation-source-chunk-body pre code {
  padding: 0;
  background: transparent;
}

/* The streaming bubble's date slot shows a small activity spinner
   while the turn runs (sized here, not inline — FE-8). */
.chat-bubble .chat-bubble-date .spinner-border {
  width: 0.8rem;
  height: 0.8rem;
}

/* Transient status ticker shown during tool calls before first token arrives */
.chat-bubble .chat-bubble-status {
  font-size: 0.85em;
  font-style: italic;
  color: var(--tblr-secondary, #6b7280);
  opacity: 0.85;
  margin-bottom: 0.25rem;
  display: flex;
  align-items: center;
  gap: 0.4em;
}

/* The base class sets display:flex, which beats the UA's [hidden]
   rule — restore the attribute's meaning (visibility rides `hidden`,
   toggled by chat--status-ticker; FE-4). */
.chat-bubble .chat-bubble-status[hidden] {
  display: none;
}

.chat-bubble .chat-bubble-status::before {
  content: "";
  width: 0.6em;
  height: 0.6em;
  border-radius: 50%;
  background: var(--traqx-blue-400, #4D9AFF);
  animation: chat-status-pulse 1.2s ease-in-out infinite;
  flex-shrink: 0;
}

@keyframes chat-status-pulse {
  0%, 100% { opacity: 0.3; }
  50%      { opacity: 1; }
}

/* Approval bubble — disclosure card attached to its assistant turn.
   Pending state opens by default; decided states collapse to a one-line
   summary, click to expand for audit/details. */
.approval-bubble-list {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}

.approval-bubble {
  border: 1px solid var(--tblr-border-color, #e6e7e9);
  border-radius: 0.5rem;
  background: var(--tblr-bg-surface-secondary, #fafbfc);
  overflow: hidden;
  position: relative;
}

/* Bootstrap's `.accordion-item:first-of-type` / `:last-of-type` rules
   set per-corner radii using the Tabler `--bs-accordion-border-radius`
   variable, which on a stand-alone item leaves the corners square.
   Pin them back to our 0.5rem so single-bubble cards have a visible
   round. Doesn't apply inside `.approval-accordion` because the
   accordion wrapper handles the rounding via clip. */
.accordion-item.approval-bubble:first-of-type {
  border-top-left-radius: 0.5rem;
  border-top-right-radius: 0.5rem;
}

.accordion-item.approval-bubble:last-of-type {
  border-bottom-left-radius: 0.5rem;
  border-bottom-right-radius: 0.5rem;
}

.approval-bubble__impact-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 1.25rem;
  height: 1.25rem;
}

.approval-bubble[open] {
  background: #fff;
}

/* Tabler accordion wrap when an assistant turn produced 2+ approval
   bubbles. Without this they'd render as separate cards with a
   visible gap between them — the accordion glues them into one
   visual unit with one outer frame + thin separators between items,
   and each item still keeps its pending/decided/etc. colour cue
   via the `.approval-bubble--<status>` modifiers. */
.approval-accordion {
  border: 1px solid var(--tblr-border-color, #e6e7e9);
  border-radius: 0.5rem;
  overflow: hidden;
}

/* Inside the accordion, the per-bubble outer card border falls
   away (the accordion wrapper draws it once, and a thin top-border
   on each non-first item separates them). Border-radius too —
   only the wrapper's corners should round. The status tint still
   shows because it lives on background/box-shadow, not on the
   border. */
.approval-accordion .accordion-item.approval-bubble {
  border-color: transparent;
  border-radius: 0;
}

/* Each bubble is wrapped in its own `<turbo-frame>` (so approve /
   reject can target it individually), which means the
   accordion-item siblings aren't actually direct DOM siblings —
   their `<turbo-frame>` parents are. Hang the separator off the
   frames themselves. `display: block` because `<turbo-frame>` is
   inline by default. */
.approval-accordion > turbo-frame {
  display: block;
}

.approval-accordion > turbo-frame + turbo-frame {
  border-top: 1px solid var(--tblr-border-color, #e6e7e9);
}

/* We render our own chevron in `.accordion-button-toggle` (Tabler's
   icon-variant pattern), so the default Bootstrap `::after`
   chevron has to disappear on every approval-bubble accordion
   button. */
.approval-bubble .accordion-button::after {
  display: none !important;
}

/* Tighten Bootstrap's default 1rem 1.25rem accordion padding —
   approval bubbles are inline chat cards, not a page-level FAQ.
   Also drop the active-state colour swap so the pending halo
   reads cleanly through. */
.approval-bubble .accordion-button {
  padding: 0.375rem 0.625rem;
  background: transparent;
  box-shadow: none;
  font-size: 0.875rem;
  line-height: 1.3;
  color: inherit;
  gap: 0.5rem;
}

.approval-bubble .accordion-button:not(.collapsed) {
  background: transparent;
  box-shadow: none;
  color: inherit;
}

/* The Tabler icon-variant wrappers come with their own margin /
   sizing defaults (designed for full-page FAQ accordions). Pull
   them in for the inline chat-bubble use case. */
.approval-bubble .accordion-button-icon,
.approval-bubble .accordion-button-toggle {
  flex-shrink: 0;
  margin: 0;
  width: 1.125rem;
  height: 1.125rem;
}

.approval-bubble .accordion-button-icon .icon,
.approval-bubble .accordion-button-toggle .icon {
  width: 1.125rem;
  height: 1.125rem;
}

.approval-bubble .accordion-body {
  padding: 0.375rem 0.625rem 0.625rem;
}

/* The status badge is in a flex container — pin it from stretching
   vertically and keep it tabular-nice. */
.approval-bubble .accordion-button .badge {
  flex-shrink: 0;
  align-self: center;
  font-size: 0.7rem;
  padding: 0.2rem 0.5rem;
}

/* Pending header is non-collapsible — no chevron rendered, button
   reads as a static heading. */
.approval-bubble .accordion-button--locked {
  cursor: default;
  pointer-events: none;
}

/* Pending = action required. Subtle yellow tint + soft pulsing halo
   so the user sees at a glance that this card wants attention, without
   being noisy enough to feel like an alert. */
.approval-bubble--pending {
  background: rgba(245, 159, 0, 0.05);
  box-shadow: 0 0 0 1px rgba(245, 159, 0, 0.18), 0 1px 2px rgba(0, 0, 0, 0.04);
  animation: approval-bubble-pulse 2.4s ease-in-out infinite;
}

.approval-bubble--pending[open] {
  background: rgba(245, 159, 0, 0.04);
}

.approval-bubble--pending .approval-bubble__title {
  font-weight: 600;
}

@keyframes approval-bubble-pulse {
  0%, 100% { box-shadow: 0 0 0 1px rgba(245, 159, 0, 0.18), 0 1px 2px rgba(0, 0, 0, 0.04); }
  50%      { box-shadow: 0 0 0 3px rgba(245, 159, 0, 0.28), 0 1px 4px rgba(245, 159, 0, 0.12); }
}

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

.approval-bubble--rejected,
.approval-bubble--expired,
.approval-bubble--cancelled {
  opacity: 0.85;
}

/* Optimistic in-between state: the user just clicked Approve / Reject,
   the POST is in flight, the server hasn't replaced the bubble yet.
   Stops the pending pulse, locks the action buttons (Stimulus
   handles `disabled`), and runs a sweep-bar across the top edge so
   the card visibly registers the click. */
.approval-bubble--deciding {
  animation: none;
  position: relative;
  overflow: hidden;
}

.approval-bubble--deciding .approval-bubble__actions button {
  cursor: wait;
}

.approval-bubble--deciding::before {
  content: "";
  position: absolute;
  top: 0;
  left: -30%;
  width: 30%;
  height: 2px;
  background: linear-gradient(
    90deg,
    transparent,
    rgba(2, 108, 255, 0.7) 50%,
    transparent
  );
  animation: approval-bubble-progress 1.4s ease-in-out infinite;
}

@keyframes approval-bubble-progress {
  0%   { left: -30%; }
  100% { left: 100%; }
}

@media (prefers-reduced-motion: reduce) {
  .approval-bubble--deciding::before {
    animation: none;
    left: 0;
    width: 100%;
    opacity: 0.5;
  }
}

.approval-bubble__title {
  font-weight: 500;
  flex: 1;
  text-align: left;
  color: var(--tblr-body-color, #232e3c);
}

.approval-bubble__detail {
  margin-bottom: 0.5rem;
  font-size: 0.8125rem;
}

.approval-bubble__meta {
  display: flex;
  gap: 0.4rem;
  flex-wrap: wrap;
}

/* Action buttons sit immediately under the description — no
   separator line; the body itself is one card-section. */
.approval-bubble__actions {
  display: flex;
  gap: 0.5rem;
  margin-top: 0.75rem;
}

.approval-bubble__actions .btn {
  display: inline-flex;
  align-items: center;
}

.approval-bubble__actions .btn-primary {
  font-weight: 500;
}

.approval-bubble__actions form {
  margin: 0;
}

.approval-bubble__footer {
  font-size: 0.75rem;
}

/* In normal flow below the card content — it used to float
   absolutely in the body's bottom-right corner, which overlapped the
   Approve/Reject row whenever that was the last content. */
.approval-bubble__id {
  display: block;
  margin-block-start: 0.5rem;
  text-align: end;
  font-size: 9px;
  color: var(--tblr-text-muted, #94a3b8);
  background: transparent;
  border: 0;
  padding: 0;
  font-family: var(--tblr-font-monospace);
  user-select: all;
  opacity: 0.6;
}

.approval-bubble__id:hover {
  opacity: 1;
}
