/*!
 * RAG Chat Widget
 *
 * Every value that an administrator can change lives in a custom property.
 * PHP never rewrites this file: it only emits a `#rag-chat-widget { ... }`
 * block of custom properties after this stylesheet, which wins on cascade
 * order at equal specificity.
 *
 * The defaults below are deliberately brand-neutral. They exist so the
 * widget still renders correctly if the inline block is missing (asset
 * preview, a caching plugin stripping inline styles, a PHP failure).
 *
 * The properties are scoped to the widget root rather than `:root` so they
 * cannot collide with theme variables. Every widget element is a DOM
 * descendant of the root, including the ones that are `position: fixed`,
 * so inheritance holds.
 */

#rag-chat-widget {
  --rcw-font-family: inherit;
  --rcw-title-font-size: 0.78rem;
  --rcw-title-font-weight: 700;

  --rcw-primary: #2563eb;
  --rcw-primary-strong: #1d4ed8;
  --rcw-on-primary: #ffffff;
  --rcw-on-primary-soft: rgba(255, 255, 255, 0.08);
  /* A fill only — the hover of the header buttons. Their border is the
     on-primary colour itself: a tint this light was 1.3:1 against the header. */
  --rcw-on-primary-tint: rgba(255, 255, 255, 0.18);
  --rcw-text: #111827;
  --rcw-text-soft: #6b7280;
  --rcw-user-bg: #2563eb;
  --rcw-user-text: #ffffff;
  --rcw-bot-bg: #f3f4f6;
  --rcw-bot-text: #111827;

  /* Per-element colours. Each one falls back to a base token above, so a
     site that customises nothing still gets a coherent palette. */
  --rcw-window-bg: #ffffff;
  /* A colour under the gradient, not just the gradient: forced colours drop
     every background image that is not a url(), and would leave the panel
     with no background at all. */
  --rcw-surface-bg: #f9fafb linear-gradient(to bottom, #fcfcfd, #f9fafb);
  --rcw-header-bg: var(--rcw-primary);
  --rcw-title-color: var(--rcw-on-primary);
  /* Solid, like the title: 0.84 white on the default primary was 4.1:1. Size
     and weight keep the hierarchy, and one pair — on-primary on primary — now
     covers title, subtitle and badge whatever the palette. */
  --rcw-subtitle-color: var(--rcw-on-primary);
  --rcw-header-icon-color: var(--rcw-on-primary);
  --rcw-toggle-bg: var(--rcw-primary);
  --rcw-toggle-bg-hover: var(--rcw-primary-strong);
  --rcw-toggle-icon-color: var(--rcw-on-primary);
  --rcw-send-bg: var(--rcw-primary);
  --rcw-send-icon-color: var(--rcw-on-primary);
  --rcw-tooltip-bg: #ffffff;
  --rcw-tooltip-text: var(--rcw-text);
  --rcw-input-bg: #ffffff;
  --rcw-input-text: var(--rcw-text);
  /* 3.6:1 or more on the white box and the panel: the border is what makes
     the box, and the starter chips, read as controls (WCAG 1.4.11). */
  --rcw-input-border: #80868f;
  --rcw-starter-bg: #ffffff;
  --rcw-starter-text: var(--rcw-text);
  --rcw-starter-border: #80868f;
  --rcw-starter-bg-hover: #f9fafb;
  --rcw-muted-text: var(--rcw-text-soft);
  /* 6.5:1 on the panel's light surfaces, 5.8:1 on a bot bubble. */
  --rcw-error-text: #b91c1c;

  /* Alert triangle, used as a mask rather than a background image: that way it
     takes currentColor and stays tied to --rcw-error-text even where a site
     overrides it. A background url() would have the colour baked in. */
  --rcw-alert-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.8' stroke-linejoin='round' stroke-linecap='round'%3E%3Cpath d='M10.29 4.5 2.4 18a2 2 0 0 0 1.71 3h15.78a2 2 0 0 0 1.71-3L13.71 4.5a2 2 0 0 0-3.42 0Z'/%3E%3Cpath d='M12 9.5v4M12 16.8h.01'/%3E%3C/svg%3E");
  /* Inverted rather than tinted: white text on a light tint was 3.8:1. */
  --rcw-badge-bg: var(--rcw-on-primary);
  --rcw-badge-text: var(--rcw-primary);
  --rcw-disclosure-bg: #f8fafc;
  --rcw-disclosure-text: #475569;
  --rcw-disclosure-border: #e2e8f0;

  /* Focus: a dark ring and a light halo, one inside the other. Whatever is
     behind the element, one of the two contrasts with it — which is the point,
     since the launcher sits on a page the widget does not control. */
  --rcw-focus-ring: #111827;
  --rcw-focus-halo: #ffffff;

  --rcw-shadow: 0 20px 60px rgba(0, 0, 0, 0.18);
  --rcw-toggle-shadow: 0 12px 30px rgba(17, 24, 39, 0.28);
  --rcw-window-radius: 18px;
  --rcw-control-radius: 12px;
  --rcw-message-radius: 14px;
  --rcw-tooltip-radius: 12px;
  --rcw-tooltip-width: 220px;
  --rcw-tooltip-font-size: 14px;
  --rcw-border-color: rgba(17, 24, 39, 0.08);
  --rcw-border-width: 1px;
  --rcw-offset-x: 24px;
  --rcw-offset-y: 24px;
  --rcw-toggle-size: 64px;
  --rcw-width: 380px;
  --rcw-height: 640px;
}

#rag-chat-widget {
  position: fixed;
  right: var(--rcw-offset-x);
  bottom: var(--rcw-offset-y);
  z-index: 9999;
  font-family: var(--rcw-font-family, inherit);
}

#rag-chat-widget[data-position$="-left"] {
  right: auto;
  left: var(--rcw-offset-x);
}

#rag-chat-widget[data-position^="top-"] {
  bottom: auto;
  top: var(--rcw-offset-y);
}

/* `hidden` always hides. The browser's own rule is the weakest there is: any
   `display` of ours, or of a theme, would beat it and show the element. */
#rag-chat-widget [hidden] {
  display: none !important;
}

/* One indicator for everything focusable in the widget. Scoped to the root so
   a theme that resets `outline` cannot take it away. */
#rag-chat-widget :focus-visible {
  box-shadow: 0 0 0 2px var(--rcw-focus-halo);
  outline: 2px solid var(--rcw-focus-ring);
  outline-offset: 2px;
}

/* The launcher keeps the shadow that lifts it off the page. */
#rag-chat-widget .rag-chat-toggle:focus-visible {
  box-shadow: 0 0 0 2px var(--rcw-focus-halo), var(--rcw-toggle-shadow);
}

.rag-chat-toggle {
  font-family: inherit;
  width: var(--rcw-toggle-size);
  height: var(--rcw-toggle-size);
  box-sizing: border-box;
  /* A border nobody sees, until forced colours draw it: without one the
     button loses its shape, since its fill is forced to the page's own. */
  border: 1px solid transparent;
  border-radius: var(--rcw-control-radius);
  background: var(--rcw-toggle-bg);
  color: var(--rcw-toggle-icon-color);
  cursor: pointer;
  box-shadow: var(--rcw-toggle-shadow);
  transition: transform 0.18s ease, background 0.18s ease;
  display: flex;
  align-items: center;
  justify-content: center;
}

.rag-chat-toggle:hover {
  transform: scale(1.03);
  background: var(--rcw-toggle-bg-hover);
}

.rag-chat-toggle svg {
  width: 28px;
  height: 28px;
  display: block;
}

.rag-chat-toggle img {
  width: 34px;
  height: 34px;
  display: block;
  object-fit: contain;
}

/* Immagine a tutto pulsante: per un marchio quadrato che deve fare da
   pulsante, non per una piccola icona. */
.rag-chat-toggle img.is-cover {
  width: 100%;
  height: 100%;
  border-radius: inherit;
  object-fit: cover;
}

.rag-chat-tooltip {
  position: absolute;
  right: 0;
  bottom: calc(var(--rcw-toggle-size) + 16px);
  /* As wide as its text, up to the configured width — the bubble's own, padding
     and border included — and never wider than the screen, or it would run
     off a phone. Never narrower than its longest word, though: min-width wins
     over max-width, so a word longer than the maximum widens the bubble
     instead of sticking out of it. */
  box-sizing: border-box;
  width: max-content;
  min-width: min-content;
  max-width: min(var(--rcw-tooltip-width), calc(100vw - 2 * var(--rcw-offset-x)));
  padding: 10px 14px;
  border-radius: var(--rcw-tooltip-radius);
  background: var(--rcw-tooltip-bg);
  color: var(--rcw-tooltip-text);
  border: var(--rcw-border-width) solid var(--rcw-border-color);
  box-shadow: 0 12px 30px rgba(17, 24, 39, 0.16);
  font-size: var(--rcw-tooltip-font-size);
  line-height: 1.35;
  opacity: 0;
  visibility: hidden;
  transform: translateY(8px);
  transition: opacity 0.25s ease, transform 0.25s ease, visibility 0.25s ease;
  pointer-events: none;
}

#rag-chat-widget[data-position$="-left"] .rag-chat-tooltip {
  right: auto;
  left: 0;
}

#rag-chat-widget[data-position^="top-"] .rag-chat-tooltip {
  bottom: auto;
  top: calc(var(--rcw-toggle-size) + 16px);
  transform: translateY(-8px);
}

.rag-chat-tooltip strong {
  font-weight: 700;
}

.rag-chat-tooltip p {
  margin: 0 0 0.55em;
}

.rag-chat-tooltip p:last-child {
  margin-bottom: 0;
}

.rag-chat-tooltip::after {
  content: '';
  position: absolute;
  right: 26px;
  bottom: -7px;
  width: 14px;
  height: 14px;
  background: var(--rcw-tooltip-bg);
  border-top: var(--rcw-border-width) solid var(--rcw-border-color);
  border-right: var(--rcw-border-width) solid var(--rcw-border-color);
  transform: rotate(135deg);
}

#rag-chat-widget[data-position$="-left"] .rag-chat-tooltip::after {
  right: auto;
  left: 26px;
}

/* Sopra il pulsante la freccia va girata: punta verso il basso. */
#rag-chat-widget[data-position^="top-"] .rag-chat-tooltip::after {
  bottom: auto;
  top: -7px;
  transform: rotate(-45deg);
}

.rag-chat-tooltip.is-visible {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
}

/* È un <dialog>: gli stili del browser, e quelli di normalize.css che molti
   temi includono, gli danno left: 0, margin: auto, padding: 1em, un colore
   proprio e un display. Qui sono tutti impostati in modo esplicito.

   display: none resta sulla classe: un display dell'autore vince sul
   dialog:not([open]) del browser e mostrerebbe la finestra anche chiusa. */
.rag-chat-window {
  position: absolute;
  right: 0;
  left: auto;
  bottom: calc(var(--rcw-toggle-size) + 16px);
  width: min(var(--rcw-width), calc(100vw - 24px));
  /* L'altezza massima deve tenere conto di quanto il widget è staccato
     dal bordo: con un offset alto, altrimenti, la finestra sfora. */
  height: min(var(--rcw-height), calc(100vh - var(--rcw-offset-y) - var(--rcw-toggle-size) - 40px));
  margin: 0;
  padding: 0;
  color: inherit;
  display: none;
  flex-direction: column;
  overflow: hidden;
  border-radius: var(--rcw-window-radius);
  /* One surface for the whole body — questions, conversation, status line —
     painted once here rather than piece by piece, so nothing shows a seam.
     The header, the notice and the footer paint their own. */
  background: var(--rcw-surface-bg);
  border: var(--rcw-border-width) solid var(--rcw-border-color);
  box-shadow: var(--rcw-shadow);
}

#rag-chat-widget[data-position$="-left"] .rag-chat-window {
  right: auto;
  left: 0;
}

#rag-chat-widget[data-position^="top-"] .rag-chat-window {
  bottom: auto;
  top: calc(var(--rcw-toggle-size) + 16px);
}

.rag-chat-window[open] {
  display: flex;
}

/* Modal on phones, where the panel already covers the whole screen: no shade. */
.rag-chat-window::backdrop {
  background: none;
}

.rag-chat-header {
  padding: 10px 14px;
  color: var(--rcw-title-color);
  background: var(--rcw-header-bg);
  border-bottom: 1px solid var(--rcw-on-primary-soft);
  flex: 0 0 auto;
}

.rag-chat-title-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}

.rag-chat-header-actions {
  position: relative; /* anchors the confirmation bubble */
  display: flex;
  align-items: center;
  gap: 8px;
  flex: 0 0 auto;
}

.rag-chat-header-main {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
}

.rag-chat-avatar {
  width: 38px;
  height: 38px;
  border-radius: var(--rcw-control-radius);
  object-fit: contain;
  box-sizing: border-box;
  flex: 0 0 auto;
  /* Nessun riquadro bianco: il marchio quadrato sta meglio direttamente
     sull'intestazione. Un logo con sfondo trasparente resta comunque leggibile. */
  background: transparent;
}

.rag-chat-title-wrap {
  min-width: 0;
}

/* Themes style the text elements of the whole page, and this h2 and these
   paragraphs are on the page. Breakdance writes its global heading settings as
   `.breakdance h2` — font, size, weight, a line height in pixels, negative
   letter spacing — and that selector outranks a bare class, so a title rule
   written as `.rag-chat-title` lost every one of those properties. A 60px line
   height turned the AI badge into a vertical pill.

   The id puts the widget's own typography above any theme selector built from
   classes and tags. The title size stays adjustable without a specificity
   contest: set --rcw-title-font-size and --rcw-title-font-weight on
   #rag-chat-widget. */
#rag-chat-widget .rag-chat-title {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px 8px;
  margin: 0;
  padding: 0;
  font-family: inherit;
  font-size: var(--rcw-title-font-size);
  font-style: normal;
  font-weight: var(--rcw-title-font-weight);
  line-height: 1.2;
  letter-spacing: 0;
  text-transform: none;
  color: var(--rcw-title-color);
}

/* Marks the window as an AI assistant for as long as it is open. Unlike the
   notice above the conversation, this does not scroll away.

   Sized from the title, so it grows with it, but capped: next to a large
   title a badge at the same proportion would compete with the name instead of
   labelling it. Its line height is its own and never the heading's. */
#rag-chat-widget .rag-chat-badge {
  display: inline-block;
  flex: 0 0 auto;
  margin: 0;
  padding: 0.3em 0.65em 0.25em;
  border-radius: 999px;
  background: var(--rcw-badge-bg);
  color: var(--rcw-badge-text);
  font-size: min(0.8em, 0.7rem);
  font-weight: 700;
  line-height: 1;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  white-space: nowrap;
  outline: 1px solid transparent; /* keeps the badge's shape when forced colours paint the background away */
}

/* Niente opacity: il colore del sottotitolo è già smorzato nella sua
   variabile, così una personalizzazione esce esattamente come scelta. */
#rag-chat-widget .rag-chat-subtitle {
  margin: 2px 0 0;
  padding: 0;
  font-size: 0.72rem;
  line-height: 1.25;
  letter-spacing: 0;
  color: var(--rcw-subtitle-color);
}

.rag-chat-action {
  font-family: inherit;
  position: relative;
  width: 34px;
  height: 34px;
  /* Solid, and at full strength: the header's own pair, as for the title. */
  border: 1px solid var(--rcw-on-primary);
  border-radius: var(--rcw-tooltip-radius);
  background: var(--rcw-on-primary-soft);
  color: var(--rcw-header-icon-color);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  padding: 0;
  transition: background 0.18s ease, border-color 0.18s ease, color 0.18s ease;
}

.rag-chat-action:hover,
.rag-chat-action:focus-visible {
  background: var(--rcw-on-primary-tint);
}


.rag-chat-action svg {
  width: 16px;
  height: 16px;
  display: block;
}


/* The buttons' tooltip and the confirmation bubble: one look, one place.
   Right under the buttons, with no gap: the pointer goes from the button onto
   the tooltip without ever leaving the button's hover (WCAG 1.4.13). */
.rag-chat-action::after,
.rag-chat-confirm-hint {
  position: absolute;
  top: 100%;
  right: 0;
  padding: 6px 8px;
  border-radius: var(--rcw-control-radius);
  background: #111827;
  border: 1px solid transparent;
  color: #fff;
  font-size: 0.72rem;
  line-height: 1;
  white-space: nowrap;
  box-shadow: 0 10px 24px rgba(0, 0, 0, 0.2);
}

.rag-chat-action::after {
  /* The tooltip is the button's accessible name made visible, so it reads
     the same attribute: what shows and what a screen reader says cannot drift
     apart. aria-label wins over generated content, so nothing is read twice. */
  content: attr(aria-label);
  transform: translateY(-4px);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.18s ease, transform 0.18s ease;
}

/* Esc dismisses it (is-tip-dismissed, set from the script) until both the
   pointer and the focus have gone. */
.rag-chat-action:not(.is-tip-dismissed):is(:hover, :focus-visible)::after {
  opacity: 1;
  transform: translateY(0);
}

/* Brought up by the pointer, it takes the pointer too: part of the button, it
   keeps the button hovered. Brought up by the keyboard it lets clicks through
   to what it covers. */
.rag-chat-action:not(.is-tip-dismissed):hover::after {
  pointer-events: auto;
}

/* Armed: inverted against the header, and the icon becomes a tick. */
.rag-chat-new.is-confirming {
  background: var(--rcw-on-primary);
  border-color: var(--rcw-on-primary);
  color: var(--rcw-primary);
}

/* It stays in the accessibility tree even when empty: a live region has to be
   there before it speaks, or the first thing written into it may go
   unannounced. */
.rag-chat-confirm-hint {
  z-index: 1;
  margin: 0;
}

.rag-chat-confirm-hint:empty {
  opacity: 0;
  pointer-events: none;
}

/* Armed, the button hands its place to the bubble rather than stacking its own
   tooltip, with the same words, on top of it. */
.rag-chat-new.is-confirming::after {
  display: none;
}

.rag-chat-new .rag-chat-confirm-icon,
.rag-chat-new.is-confirming .rag-chat-new-icon {
  display: none;
}

.rag-chat-new.is-confirming .rag-chat-confirm-icon {
  display: block;
}

/* Unavailable: its icon and border fade, and its fill goes. Not the button as a
   whole — opacity would fade its tooltip too, which stays as readable as any.
   `:hover` and `:focus-visible` match an unavailable button too, so this comes
   after them. */
.rag-chat-action[aria-disabled="true"] {
  background: none;
  border-color: color-mix(in srgb, var(--rcw-on-primary) 45%, transparent);
  color: color-mix(in srgb, var(--rcw-header-icon-color) 45%, transparent);
  cursor: not-allowed;
}

/* Sits above the starter questions so it is read before the first message,
   not after. Once the conversation begins it shrinks rather than disappearing:
   still reachable, no longer in the way. */
.rag-chat-disclosure {
  padding: 12px 14px;
  background: var(--rcw-disclosure-bg);
  color: var(--rcw-disclosure-text);
  border-bottom: 1px solid var(--rcw-disclosure-border);
  font-size: 0.78rem;
  line-height: 1.5;
  flex: 0 0 auto;
  transition: padding 0.2s ease, font-size 0.2s ease;
}

/* Same colour as the text around it, so the underline is the one cue a link
   has: scoped to the root, where a theme's `a { text-decoration: none }`
   cannot take it. */
#rag-chat-widget .rag-chat-disclosure a {
  color: inherit;
  text-decoration: underline;
}

.rag-chat-disclosure strong {
  color: inherit;
  font-weight: 700;
}

/* The short form only exists once the notice has collapsed, and the full one
   only before that: never both, never a clipped version of either. */
.rag-chat-disclosure-short {
  display: none;
}

.rag-chat-disclosure.is-compact {
  padding: 7px 14px;
  font-size: 0.72rem;
}

.rag-chat-disclosure.is-compact .rag-chat-disclosure-text {
  display: none;
}

.rag-chat-disclosure.is-compact .rag-chat-disclosure-short {
  display: block;
}

/* Accepted, the checkbox folds away with the long text it refers to, and
   comes back with it on a new chat. */
.rag-chat-disclosure.is-accepted .rag-chat-consent {
  display: none;
}

/* Inside the notice's box: its colour and size, no margins of its own at the
   sides — the box already has the padding. */
.rag-chat-consent {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  margin: 10px 0 0;
  color: inherit;
  font-size: inherit;
  line-height: 1.4;
  cursor: pointer;
}

/* A box holding the consent alone, with the notice switched off. */
.rag-chat-consent:first-child {
  margin-top: 0;
}

/* Shown only after someone presses a control the notice is holding. */
.rag-chat-consent-hint {
  display: flex;
  align-items: flex-start;
  gap: 6px;
  margin: 6px 0 0;
  color: var(--rcw-error-text);
  font-size: inherit;
  line-height: 1.4;
}

.rag-chat-consent input {
  margin: 2px 0 0;
  flex: 0 0 auto;
}

.rag-chat-starters {
  padding: 14px 14px 4px;
  flex: 0 0 auto;
}

#rag-chat-widget .rag-chat-starters-title {
  margin: 0 0 10px;
  padding: 0;
  font-size: 0.85rem;
  line-height: 1.3;
  letter-spacing: 0;
  color: var(--rcw-muted-text);
}

.rag-chat-starters-list {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.rag-chat-starter {
  font-family: inherit;
  border: 1px solid var(--rcw-starter-border);
  background: var(--rcw-starter-bg);
  color: var(--rcw-starter-text);
  padding: 10px 12px;
  border-radius: var(--rcw-message-radius);
  cursor: pointer;
  font-size: 0.88rem;
  line-height: 1.35;
  text-align: left;
  /* Named properties, not `all`: a focus indicator has to be there at once,
     not fade in over 0.18s. */
  transition: background 0.18s ease, border-color 0.18s ease;
}

.rag-chat-starter:not([aria-disabled="true"]):hover {
  border-color: var(--rcw-primary);
  background: var(--rcw-starter-bg-hover);
}

.rag-chat-messages {
  flex: 1;
  overflow-y: auto;
  /* Keeps a trackpad flick from carrying on into the page once the list hits
     its end. Only covers the case where this element is actually scrolling —
     see the wheel handler in the runtime for the rest. */
  overscroll-behavior: contain;
  padding: 18px 14px;
  scroll-behavior: smooth;
}

/* The list takes focus so it can be scrolled from the keyboard. Its rings are
   drawn inwards — halo at 0-2px, ring at 2-4px — because the list reaches the
   window's edge and the window clips anything outside it. */
#rag-chat-widget .rag-chat-messages:focus-visible {
  box-shadow: inset 0 0 0 2px var(--rcw-focus-halo);
  outline-offset: -4px;
}

/* Read by screen readers, not shown: who wrote each message. Scoped to the
   root so a theme's own rules cannot make it visible again. */
#rag-chat-widget .rag-chat-sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.rag-chat-message {
  max-width: 85%;
  margin-bottom: 12px;
  padding: 12px 14px;
  border-radius: var(--rcw-control-radius);
  font-size: 0.95rem;
  line-height: 1.5;
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.04);
  word-break: break-word;
}

.rag-chat-message.bot {
  background: var(--rcw-bot-bg);
  color: var(--rcw-bot-text);
  border: 1px solid rgba(17, 24, 39, 0.06);
}

.rag-chat-message.user {
  margin-left: auto;
  background: var(--rcw-user-bg);
  color: var(--rcw-user-text);
  white-space: pre-wrap;
  /* Invisible, until forced colours paint the background away: then it is the
     bubble's outline, as the bot's own border is, drawn in a system colour. */
  border: 1px solid transparent;
}

.rag-chat-message.bot p,
.rag-chat-message.bot ul,
.rag-chat-message.bot ol {
  margin: 0 0 0.7em;
}

.rag-chat-message.bot p:last-child,
.rag-chat-message.bot ul:last-child,
.rag-chat-message.bot ol:last-child {
  margin-bottom: 0;
}

.rag-chat-message.bot ul,
.rag-chat-message.bot ol {
  padding-left: 1.2em;
}

/* Size, bullets and spacing belong to the bubble. Scoped to the root because
   themes — and wp-admin, around the preview — reset p, ul and li with rules
   that would otherwise reach in. */
#rag-chat-widget .rag-chat-message p,
#rag-chat-widget .rag-chat-message li {
  font-size: inherit;
  line-height: inherit;
}

#rag-chat-widget .rag-chat-message ul {
  list-style: disc outside;
}

#rag-chat-widget .rag-chat-message ol {
  list-style: decimal outside;
}

#rag-chat-widget .rag-chat-message li {
  margin: 0;
}

.rag-chat-message.bot hr {
  border: 0;
  border-top: 1px solid rgba(17, 24, 39, 0.12);
  margin: 0.9em 0;
}

/* A failed request is not an answer, and must not read as one. The colour and
   the icon are the quick cues; the sender prefix carries the same thing in
   words, for whoever gets neither. */
.rag-chat-message.bot.is-error {
  position: relative;
  padding-left: 40px;
  color: var(--rcw-error-text);
}

/* The alert triangle, for whatever carries the class. `content: ''` stays out
   of the accessibility tree, so the icon adds nothing to read: the words are
   already there. */
.rag-chat-alert::before {
  content: '';
  width: 1.05em;
  height: 1.05em;
  flex: 0 0 auto;
  background-color: currentColor;
  -webkit-mask: var(--rcw-alert-icon) center / contain no-repeat;
  mask: var(--rcw-alert-icon) center / contain no-repeat;
}

/* Out of the flow, so Markdown with several paragraphs keeps its layout: as a
   flex item, every paragraph would become one of its own. */
.rag-chat-message.bot.is-error::before {
  position: absolute;
  left: 14px;
  top: calc(12px + 0.22em);
}

.rag-chat-message.bot a {
  color: inherit;
  text-decoration: underline;
}

/* Three dots holding the reply's place. Decorative: the status line says it in
   words, and the dots are aria-hidden. As wide as the dots, not as a reply. */
.rag-chat-message.bot.is-pending {
  width: fit-content;
}

.rag-chat-typing {
  display: flex;
  align-items: center;
  gap: 0.3em;
  /* One line of text: the bubble keeps its height when the words come. */
  height: 1.5em;
}

/* In em, so they grow with the text. */
.rag-chat-typing span {
  width: 0.45em;
  height: 0.45em;
  border-radius: 50%;
  background: currentColor;
  opacity: 0.35;
  animation: rag-chat-typing 1.2s ease-in-out infinite;
}

.rag-chat-typing span:nth-child(2) {
  animation-delay: 0.15s;
}

.rag-chat-typing span:nth-child(3) {
  animation-delay: 0.3s;
}

@keyframes rag-chat-typing {
  0%, 60%, 100% {
    opacity: 0.35;
    transform: translateY(0);
  }
  30% {
    opacity: 1;
    transform: translateY(-0.2em);
  }
}

/* The room around the form is padding on a wrapper rather than a margin on the
   form: when the footer sticks to the bottom of a scrolling panel, what passes
   under it has to be covered, and a margin is transparent. */
.rag-chat-footer {
  flex: 0 0 auto;
  padding: 12px;
  background: var(--rcw-window-bg);
}

.rag-chat-input {
  position: relative;
  display: flex;
  align-items: center;
  margin: 0;
  padding: 4px 48px 4px 12px;
  border: 1px solid var(--rcw-input-border);
  border-radius: var(--rcw-control-radius);
  background: var(--rcw-input-bg);
  flex: 0 0 auto;
  box-sizing: border-box;
}

.rag-chat-textarea {
  font-family: inherit;
  overscroll-behavior: contain;
  flex: 1;
  min-height: 42px;
  max-height: 112px;
  resize: none;
  border: 0;
  background: transparent;
  color: var(--rcw-input-text);
  padding: 9px 0;
  font-size: 16px;
  line-height: 1.4;
  outline: 0;
  box-sizing: border-box;
  width: 100%;
}

/* Set here rather than left to the browser: Chromium's default is 4.6:1, but
   Safari's is 2.4:1 and Firefox fades it to 3.9:1. Opacity 1 undoes the fade. */
#rag-chat-widget .rag-chat-textarea::placeholder {
  color: var(--rcw-muted-text);
  opacity: 1;
}

.rag-chat-input:focus-within {
  border-color: var(--rcw-primary);
  box-shadow: 0 0 0 3px rgba(17, 24, 39, 0.08);
}

/* While a past conversation is fetched, the body waits instead of showing a
   fresh chat that is about to be replaced. Header and footer stay: the panel
   keeps its shape, only its content is pending. */
.rag-chat-window.is-restoring .rag-chat-disclosure,
.rag-chat-window.is-restoring .rag-chat-starters {
  display: none;
}

/* Next to the words it goes with, and sized to them. Decorative: the status
   line says the same thing, and an empty `content` adds nothing to read. */
.rag-chat-window.is-restoring .rag-chat-status {
  display: flex;
  align-items: center;
  gap: 8px;
}

.rag-chat-window.is-restoring .rag-chat-status::before {
  content: '';
  flex: 0 0 auto;
  width: 1em;
  height: 1em;
  box-sizing: border-box;
  border: 2px solid rgba(17, 24, 39, 0.12);
  border-top-color: var(--rcw-primary);
  border-radius: 50%;
  animation: rag-chat-spin 0.8s linear infinite;
}

@keyframes rag-chat-spin {
  to {
    transform: rotate(360deg);
  }
}

@media (prefers-reduced-motion: reduce) {
  .rag-chat-window.is-restoring .rag-chat-status::before {
    animation: none;
  }

  .rag-chat-typing span {
    animation: none;
    opacity: 0.6;
  }
}

/* WCAG technique C34, set from syncStickiness(). Past the first step the
   panel scrolls as one instead of the message list alone, and the header and
   the footer stay put with `sticky` until their own turn comes. */
.rag-chat-window.is-notice-free {
  overflow-y: auto;
  overscroll-behavior: contain;
}

.rag-chat-window.is-notice-free .rag-chat-messages {
  flex: 1 0 auto;
  overflow: visible;
}

.rag-chat-window.is-notice-free .rag-chat-header {
  position: sticky;
  top: 0;
  z-index: 2;
}

.rag-chat-window.is-notice-free .rag-chat-footer {
  position: sticky;
  bottom: 0;
  z-index: 1;
}

.rag-chat-window.is-header-free .rag-chat-header {
  position: static;
}

.rag-chat-window.is-footer-free .rag-chat-footer {
  position: static;
}

/* The text box fills a bordered wrapper, so its own rings would cut a square
   through the rounded box. They go on the wrapper instead, which is what the
   visitor sees as the field. */
#rag-chat-widget .rag-chat-input:has(.rag-chat-textarea:focus-visible) {
  box-shadow: 0 0 0 2px var(--rcw-focus-halo);
  outline: 2px solid var(--rcw-focus-ring);
  outline-offset: 2px;
}

#rag-chat-widget .rag-chat-textarea:focus-visible {
  box-shadow: none;
  outline: 0;
}

.rag-chat-send {
  font-family: inherit;
  position: absolute;
  right: 7px;
  top: 50%;
  width: 36px;
  height: 36px;
  box-sizing: border-box;
  border: 1px solid transparent;
  border-radius: calc(var(--rcw-control-radius) - 2px);
  background: var(--rcw-send-bg);
  color: var(--rcw-send-icon-color);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  font-size: 18px;
  line-height: 1;
  cursor: pointer;
  transform: translateY(-50%);
  transition: transform 0.18s ease, background 0.18s ease, color 0.18s ease;
}

.rag-chat-send:hover {
  transform: translateY(-50%) translateY(-1px);
}

/* Faded by its own colours, as the header's buttons are: opacity would take
   the focus ring down with it, and says nothing to forced colours. */
.rag-chat-send[aria-disabled="true"] {
  background: color-mix(in srgb, var(--rcw-send-bg) 60%, transparent);
  color: color-mix(in srgb, var(--rcw-send-icon-color) 60%, transparent);
  cursor: not-allowed;
  /* Not `none`: that would undo the translate that centres the button, and
     drop it below the middle of the field. Only the hover lift goes. */
  transform: translateY(-50%);
}

/* Nothing in the widget is `disabled` any more: a disabled control drops the
   focus it holds. The box goes read only — which it never is otherwise — and
   the buttons take aria-disabled. */
.rag-chat-textarea:read-only,
.rag-chat-starter[aria-disabled="true"] {
  background: color-mix(in srgb, var(--rcw-starter-bg) 55%, transparent);
  border-color: color-mix(in srgb, var(--rcw-starter-border) 55%, transparent);
  color: color-mix(in srgb, var(--rcw-starter-text) 55%, transparent);
  cursor: not-allowed;
}

/* wp-admin, and some themes, paint a read-only field grey; this one sits in a
   bordered wrapper and must stay see-through, faded only by its opacity. */
#rag-chat-widget .rag-chat-textarea {
  background: transparent;
}

.rag-chat-status {
  padding: 0 16px 10px;
  font-size: 0.8rem;
  color: var(--rcw-muted-text);
  flex: 0 0 auto;
}

/* Empty, it takes no room — but it stays rendered: a live region has to be in
   the accessibility tree before its first change, or that change may go
   unannounced. */
.rag-chat-status:empty {
  padding: 0;
}

/* A fleeting line on its way out. The transition lives on this state only, so
   whatever is written next shows at once, without fading in. */
.rag-chat-status.is-fading {
  opacity: 0;
  transition: opacity 0.6s ease;
}

/* Thinking… breathes. Through colour, not opacity: the line sits just above
   4.5:1 at rest, and any transparency would take it under while it is still
   there to be read. It swings towards the text colour and back, never below
   where it started. */
.rag-chat-window.is-loading .rag-chat-status {
  animation: rag-chat-pulse 1.6s ease-in-out infinite;
}

@keyframes rag-chat-pulse {
  50% {
    color: var(--rcw-bot-text);
  }
}

/* A single fade out is not motion and stays; a pulse that keeps going stops. */
@media (prefers-reduced-motion: reduce) {
  .rag-chat-window.is-loading .rag-chat-status {
    animation: none;
  }
}

@media (max-width: 640px) {
  #rag-chat-widget {
    right: 0;
    bottom: 0;
    left: 0;
  }

  .rag-chat-toggle {
    position: fixed;
    right: 12px;
    bottom: 12px;
    margin-left: 0;
    display: flex;
    z-index: 10001;
  }

  /* The open chat covers the screen, launcher included. */
  .rag-chat-toggle[aria-expanded="true"] {
    display: none;
  }

  #rag-chat-widget[data-position$="-left"] .rag-chat-toggle {
    right: auto;
    left: 12px;
  }

  #rag-chat-widget[data-position^="top-"] .rag-chat-toggle {
    bottom: auto;
    top: 12px;
  }

  .rag-chat-window {
    position: fixed;
    inset: 0;
    width: 100vw;
    height: 100dvh;
    max-width: none;
    max-height: none;
    border-radius: 0;
    right: 0;
    bottom: 0;
    left: 0;
    border: 0;
  }

  /* The corner rules above outrank a bare `inset: 0`: without this, a top
     position pushed the full-screen panel 80px down, with the text box and
     Send off the bottom of the screen. */
  #rag-chat-widget[data-position^="top-"] .rag-chat-window,
  #rag-chat-widget[data-position$="-left"] .rag-chat-window {
    inset: 0;
  }

  .rag-chat-window[open] {
    display: flex;
  }

  .rag-chat-header {
    padding-top: max(10px, env(safe-area-inset-top));
  }

  .rag-chat-footer {
    padding-bottom: max(12px, env(safe-area-inset-bottom));
  }

  .rag-chat-send {
    right: 7px;
  }

  /* The configured maximum here too, within what is left of the screen: the
     bubble sits 12px in from the widget's edge and keeps 12px on the other side. */
  .rag-chat-tooltip {
    right: 12px;
    bottom: calc(var(--rcw-toggle-size) + 24px);
    max-width: min(var(--rcw-tooltip-width), calc(100vw - var(--rcw-offset-x) - 24px));
    transform: translateY(10px);
  }

  #rag-chat-widget[data-position$="-left"] .rag-chat-tooltip {
    right: auto;
    left: 12px;
  }

  #rag-chat-widget[data-position^="top-"] .rag-chat-tooltip {
    bottom: auto;
    top: calc(var(--rcw-toggle-size) + 24px);
    transform: translateY(-10px);
  }

  .rag-chat-action::after {
    display: none;
  }
}

/* Only what the rules above cannot prepare on their own. Forced colours take
   every colour from the system, drop every background image that is not a
   url(), and know nothing about opacity — which is why nothing in the widget
   is drawn with a gradient alone, fades with opacity, or goes without a
   border. What is left here cannot be written any other way:

   - shapes made of a background — the alert triangle and the typing dots;
   - the spinner, which needs two border colours to show that it turns;
   - the system's grey for a control that is unavailable without being
     `disabled`, which is how the browser would know by itself.

   The alert triangle matters most: the error colour is gone too, and it is
   the one sign left on screen that a bubble is not an answer. After every
   rule it overrides, since the selectors weigh the same. */
@media (forced-colors: active) {
  .rag-chat-alert::before,
  .rag-chat-typing span {
    background-color: CanvasText;
  }

  .rag-chat-window.is-restoring .rag-chat-status::before {
    border-color: Canvas;
    border-top-color: CanvasText;
  }

  .rag-chat-action[aria-disabled="true"],
  .rag-chat-starter[aria-disabled="true"],
  .rag-chat-send[aria-disabled="true"] {
    border-color: GrayText;
    color: GrayText;
  }
}
