/*
 * Volantis live-chat widget. FULLY SELF-CONTAINED: every value is hardcoded (no --v-* tokens), so
 * the widget looks identical on every page (help center, dashboard, anywhere) regardless of what CSS
 * that page loads. Clean and flat, modelled on modern support widgets. Included by chat_widget.php.
 */

#volChat.vchat { position: fixed; right: 20px; bottom: 20px; z-index: 2147483000;
  font-family: 'Inter', system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif; }
#volChat.vchat *, #volChat.vchat *::before, #volChat.vchat *::after { box-sizing: border-box; margin: 0; }

/* THE RESET THAT MAKES THE "SELF-CONTAINED" CLAIM ABOVE ACTUALLY TRUE.
 *
 * The claim was only ever half kept: every value the widget THOUGHT of is hardcoded, but any
 * property it never declared was still free for the host page to supply. Host pages style bare
 * buttons wholesale - `.help-main button` (assets/support/help.css) and
 * `body.desk .adm-main button` (assets/support/desk.css) both set a full look including
 * `padding: 9px 16px`.
 *
 * `#volChat .vchat__send` sets width/height/background/radius but never padding, so on the help
 * centre the send button kept its 34x34 box and inherited 16px of side padding: 34 - 32 = 2px of
 * content, and the 17px paper-plane flex-shrank into a 2px sliver. Measured on /help/index.php,
 * /help/kb.php and /help/new.php - the button was a "tiny dot" on all three, and would be on any
 * future page that styles its buttons the same way.
 *
 * Fixed by declaring the whole surface rather than patching the one property. Specificity is
 * deliberate: `#volChat button` is (1,0,1), so the ID beats every host-page element rule, while
 * every component rule in this file - `.vchat__send`, `.vchat__launcher`, `.vchat__react` and the
 * rest, all (1,1,0) or higher - still beats THIS. Reset first, component styles on top, host page
 * locked out. Same reasoning for the fields below it. */
#volChat button {
  -webkit-appearance: none; appearance: none;
  margin: 0; padding: 0; border: 0; border-radius: 0;
  background: none; color: inherit; text-align: center;
  font: inherit; letter-spacing: normal; text-transform: none;
  min-width: 0; min-height: 0; width: auto; height: auto;
}
/* box-shadow is deliberately NOT in that list. A host page's only box-shadow on a bare button is its
   focus ring (`.help-main button:focus-visible`), and resetting it here would out-specify that and
   leave the widget's buttons with no visible focus at all. Leaking a focus ring is fine; losing one
   is not.

   The textarea is the exception: volantis-theme.css has a blanket `:focus-visible{ box-shadow:ring }`
   which drew a second rectangle INSIDE the composer card, and the card already carries the ring on
   :focus-within - the same fix thread.css needed for .vth__ta. */
#volChat textarea, #volChat input, #volChat select {
  margin: 0; font: inherit; letter-spacing: normal; min-width: 0;
}
#volChat .vchat__input:focus, #volChat .vchat__input:focus-visible { outline: none; box-shadow: none; }

/* Launcher.
   This used to be a 56px saturated blue disc sitting in a 20px blue glow
   (`box-shadow: 0 6px 20px rgba(37,99,235,.35)`), carrying a filled speech-bubble blob. Three
   problems in one object: a coloured glow is the same decoration this project has stripped
   everywhere else, a solid brand disc is the loudest thing on any page it appears on - and it
   appears on EVERY page - and a filled glyph is the only filled icon in a system that is otherwise
   entirely line work.

   Now it is a control rather than a blob: white ground, one hairline, a neutral shadow that lifts it
   off the page without tinting it, and the same stroked chat glyph used in the ticket header. It
   fills with brand blue on hover and focus, so it has presence exactly when someone reaches for it
   and none when they are reading. The hairline is drawn with an inset shadow rather than a border so
   the 50px box stays 50px and nothing shifts on hover. */
#volChat .vchat__launcher {
  width: 50px; height: 50px; border-radius: 50%; border: none; cursor: pointer; padding: 0;
  background: #fff; color: #2563EB; display: flex; align-items: center; justify-content: center;
  box-shadow: inset 0 0 0 1px #E1E7F0,
              0 2px 4px rgba(15, 23, 42, .08),
              0 10px 24px -8px rgba(15, 23, 42, .24);
  transition: transform .14s ease, background .14s ease, color .14s ease, box-shadow .14s ease;
}
#volChat .vchat__launcher:hover {
  transform: translateY(-1px);
  background: #2563EB; color: #fff;
  box-shadow: inset 0 0 0 1px #2563EB,
              0 2px 4px rgba(15, 23, 42, .10),
              0 12px 26px -8px rgba(15, 23, 42, .28);
}
#volChat .vchat__launcher:focus-visible {
  outline: none; background: #2563EB; color: #fff;
  box-shadow: inset 0 0 0 1px #2563EB, 0 0 0 4px rgba(37, 99, 235, .28);
}
#volChat .vchat__launcher svg { width: 23px; height: 23px; display: block; }
#volChat.is-open .vchat__launcher { display: none; }

/* Panel. Hidden by default and shown ONLY when the root has .is-open. Do NOT rely on the [hidden]
   attribute here: an explicit display value would override it and leave the panel stuck open on every
   page (which is exactly what happened). Visibility is driven purely by the .is-open class. */
#volChat .vchat__panel {
  display: none;
  flex-direction: column;
  position: absolute; right: 0; bottom: 0;
  width: 374px; max-width: calc(100vw - 32px);
  height: 566px; max-height: calc(100vh - 40px);
  background: #fff; border-radius: 16px; overflow: hidden;
  box-shadow: 0 10px 40px rgba(15, 23, 42, .16), 0 2px 8px rgba(15, 23, 42, .08);
}
#volChat.is-open .vchat__panel { display: flex; }

/* ---------------------------------------------------------------------------------------------
   Panel backdrop. The field itself is generated per page load in chat_widget.php and handed in
   as --vchat-waves, so no two loads look the same and there is no tile to seam. It falls out of one of the top corners like the contours of a
   hill and is masked away radially from that same corner, so it never reaches the composer.
   --------------------------------------------------------------------------------------------- */
#volChat .vchat__panel::before {
  content: ''; position: absolute; left: 0; right: 0; top: 0; height: 74%; z-index: 0; pointer-events: none;
  background: var(--vchat-waves) no-repeat top center / 100% auto,
              linear-gradient(180deg, #F4F9FF 0%, #FBFDFF 58%, #FFFFFF 100%);
  /* faded radially from the same corner the slope falls out of, so it dies away in every
     direction instead of stopping at a horizontal line */
  -webkit-mask-image: radial-gradient(140% 125% at var(--vchat-origin, 100% 0%), #000 20%, rgba(0,0,0,.7) 48%, transparent 86%);
          mask-image: radial-gradient(140% 125% at var(--vchat-origin, 100% 0%), #000 20%, rgba(0,0,0,.7) 48%, transparent 86%);
}
#volChat .vchat__panel { background: #fff; }
#volChat .vchat__head, #volChat .vchat__log, #volChat .vchat__human,
#volChat .vchat__composer, #volChat .vchat__note { position: relative; z-index: 1; }

/* Header */
/* A white header, so the panel reads as one surface with the conversation instead of a coloured
   bar bolted on top. The presence dot's ring and the close button had to follow it off blue. */
#volChat .vchat__head { display: flex; align-items: center; gap: 11px; padding: 13px 14px;
  background: #fff; color: #0F172A; border-bottom: 1px solid #EDF1F7; }
#volChat .vchat__avatar { position: relative; width: 34px; height: 34px; flex: 0 0 auto; border-radius: 50%;
  background: #F2F6FE; display: flex; align-items: center; justify-content: center; }
/* The AI face: the sparkle is a mask over a brand gradient, so there is no inline SVG gradient id
   to collide with anything else on the page. */
#volChat .vchat__spark { width: 19px; height: 19px; display: none;
  background: linear-gradient(135deg, #2563EB 10%, #38BDF8 90%);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23000' d='M12 2c0 5.5-4.5 10-10 10 5.5 0 10 4.5 10 10 0-5.5 4.5-10 10-10-5.5 0-10-4.5-10-10z'/%3E%3C/svg%3E") center/contain no-repeat;
          mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23000' d='M12 2c0 5.5-4.5 10-10 10 5.5 0 10 4.5 10 10 0-5.5 4.5-10 10-10-5.5 0-10-4.5-10-10z'/%3E%3C/svg%3E") center/contain no-repeat; }
#volChat .vchat__mark { display: none; }
#volChat[data-stage="ai"] .vchat__spark { display: block; }
#volChat:not([data-stage="ai"]) .vchat__mark { display: block; }
#volChat .vchat__t--ai, #volChat .vchat__t--human { display: none; }
#volChat[data-stage="ai"] .vchat__t--ai { display: inline; }
#volChat:not([data-stage="ai"]) .vchat__t--human { display: inline; }
#volChat .vchat__avatar img.vchat__mark { width: 22px; height: 22px; }
#volChat .vchat__avatar::after { content: ''; position: absolute; right: -1px; bottom: -1px; width: 11px; height: 11px;
  border-radius: 50%; background: #94A3B8; border: 2.5px solid #fff; }
#volChat[data-online="1"] .vchat__avatar::after { background: #22C55E; }
#volChat .vchat__titles { min-width: 0; line-height: 1.25; }
#volChat .vchat__title { font-weight: 700; font-size: 15px; letter-spacing: -.2px; color: #0F172A; }
#volChat .vchat__status { font-size: 12px; color: #8A93A3; margin-top: 1px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
#volChat .vchat__close { margin-left: auto; appearance: none; border: none; cursor: pointer; background: transparent;
  color: #8A93A3; width: 30px; height: 30px; border-radius: 8px; padding: 0;
  display: flex; align-items: center; justify-content: center; }
#volChat .vchat__close svg { width: 16px; height: 16px; display: block; }
#volChat .vchat__close:hover { background: #F1F5FB; color: #0F172A; }

/* The AI marker beside the title, and the note under the composer. Both are shown ONLY while the
   assistant is the one answering: chat.js stamps data-stage on the root, and the moment the chat is
   handed to a person the stage changes and both disappear. Claiming AI while a human is typing
   would be worse than saying nothing. */
#volChat .vchat__note { display: none; padding: 7px 16px 10px; text-align: center;
  font-size: 11px; line-height: 1.45; color: #8A93A3; }
#volChat[data-stage="ai"] .vchat__note { display: block; }

/* Message log */
#volChat .vchat__log { flex: 1; overflow-y: auto; padding: 16px 14px; display: flex; flex-direction: column; gap: 4px; background: transparent; }
#volChat .vchat__intro { text-align: center; font-size: 12.5px; color: #6B7280; padding: 6px 20px 12px; line-height: 1.5; }
#volChat .vchat__sys { align-self: center; text-align: center; font-size: 11.5px; color: #94A3B8; background: #EEF2F7; border-radius: 10px; padding: 5px 12px; margin: 6px 0; max-width: 85%; }
/* Prominent "view your ticket" call to action shown when the chat is handed off. */
#volChat .vchat__ticket { align-self: stretch; margin: 10px 2px 4px; }
#volChat .vchat__ticket a { display: flex; align-items: center; justify-content: center; gap: 8px; font-size: 14px; font-weight: 700; color: #fff; text-decoration: none; background: #2563EB; border: none; border-radius: 12px; padding: 12px 16px; box-shadow: 0 6px 16px rgba(37, 99, 235, .3); }
#volChat .vchat__ticket a:hover { background: #1D4FD7; }
#volChat .vchat__ticket a svg { width: 16px; height: 16px; flex: 0 0 auto; }

/* AI action confirm card (customer confirms before anything runs on their server). */
#volChat .vchat__action { align-self: stretch; margin: 4px 2px 8px; background: #fff; border: 1px solid #D7E3FB; border-radius: 12px; padding: 12px 14px; box-shadow: 0 4px 12px rgba(37, 99, 235, .1); }
#volChat .vchat__action-sum { font-size: 13.5px; font-weight: 600; color: #1E293B; margin-bottom: 10px; display: flex; align-items: flex-start; gap: 8px; }
#volChat .vchat__action-sum::before { content: ""; flex: 0 0 auto; width: 16px; height: 16px; margin-top: 1px; background: #2563EB; -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 2v4M12 18v4M4.9 4.9l2.8 2.8M16.3 16.3l2.8 2.8M2 12h4M18 12h4M4.9 19.1l2.8-2.8M16.3 7.7l2.8-2.8'/%3E%3C/svg%3E") center/contain no-repeat; mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 2v4M12 18v4M4.9 4.9l2.8 2.8M16.3 16.3l2.8 2.8M2 12h4M18 12h4M4.9 19.1l2.8-2.8M16.3 7.7l2.8-2.8'/%3E%3C/svg%3E") center/contain no-repeat; }
#volChat .vchat__action-btns { display: flex; gap: 8px; }
#volChat .vchat__action-btns button { flex: 1; appearance: none; cursor: pointer; font: inherit; font-size: 13px; font-weight: 600; padding: 9px 12px; border-radius: 9px; }
#volChat .vchat__action-yes { color: #fff; background: #2563EB; border: 1px solid #2563EB; }
#volChat .vchat__action-yes:hover { background: #1D4FD7; }
#volChat .vchat__action-yes:disabled { opacity: .6; cursor: default; }
#volChat .vchat__action-no { color: #33405A; background: #fff; border: 1px solid #DCE3EE; }
#volChat .vchat__action-no:hover { background: #F3F6FB; }
/* The consequences line the SERVER wrote for this card (what it costs, whether it disconnects
   players, whether it lowers the memory). Never model prose. */
#volChat .vchat__action-note { font-size: 12.5px; line-height: 1.45; color: #55617A; margin: -4px 0 10px 24px; }

/* Destructive card: a change the change journal cannot put back (today, restoring a backup over a
   world). It looks different from the ordinary card BEFORE the first click, so the customer can see
   which kind of decision this is without reading the sentence. */
#volChat .vchat__action--danger { border-color: #F3C2C2; box-shadow: 0 4px 12px rgba(190, 50, 50, .1); }
#volChat .vchat__action--danger .vchat__action-sum { color: #8A1F1F; }
#volChat .vchat__action--danger .vchat__action-sum::before { background: #C2410C; -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M10.3 3.9 1.8 18a2 2 0 0 0 1.7 3h17a2 2 0 0 0 1.7-3L13.7 3.9a2 2 0 0 0-3.4 0zM12 9v4M12 17h.01'/%3E%3C/svg%3E") center/contain no-repeat; mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M10.3 3.9 1.8 18a2 2 0 0 0 1.7 3h17a2 2 0 0 0 1.7-3L13.7 3.9a2 2 0 0 0-3.4 0zM12 9v4M12 17h.01'/%3E%3C/svg%3E") center/contain no-repeat; }
#volChat .vchat__action--danger.is-armed { border-color: #E06666; background: #FFF8F8; }
#volChat .vchat__action-yes--danger { background: #B91C1C; border-color: #B91C1C; }
#volChat .vchat__action-yes--danger:hover { background: #991B1B; }

/* Undo, on the result of a change that is still reversible from the change journal. */
#volChat .vchat__action--undo { border-color: #DCE3EE; box-shadow: none; padding: 8px 10px; }

/* Locked state: once on a ticket, the widget composer is disabled (one reply channel). */
#volChat.is-locked .vchat__composer { opacity: .6; }
#volChat.is-locked .vchat__input { cursor: not-allowed; }

#volChat .vchat__row { display: flex; align-items: flex-end; gap: 8px; margin-top: 8px; }
#volChat .vchat__row--user { flex-direction: row-reverse; }
/* min-width:0 lets the stack shrink so the actions trigger beside it always fits. Without it a flex
   item refuses to go below its min-content width, and on a narrow phone panel the trigger was
   pushed out past the edge of the log. */
/* An assistant reply runs nearly the full width of the panel - it is prose, and prose in an 80%
   column beside an avatar wraps every few words. The customer's own message stays a pill on the
   right, which is what tells the two apart now that neither has an avatar. min-width:0 is load
   bearing: without it the flex item refuses to shrink and pushes the ... trigger off the panel. */
#volChat .vchat__stack { display: flex; flex-direction: column; gap: 2px; flex: 1 1 auto; min-width: 0; }
#volChat .vchat__row--user .vchat__stack { flex: 0 1 auto; max-width: 80%; }
#volChat .vchat__row--user .vchat__stack { align-items: flex-end; }
/* Just the letters AI, quiet, above the reply. The blue pill read as a badge stuck on the
   message; this reads as a note about it. */
#volChat .vchat__name { font-size: 9.5px; font-weight: 700; letter-spacing: .1em; color: #AEB6C2;
  padding: 0 2px; text-transform: uppercase; }
#volChat .vchat__bubble { font-size: 14px; line-height: 1.5; padding: 10px 13px; border-radius: 8px;
  white-space: pre-wrap; word-break: break-word;
  transition: background-color .16s ease, border-color .16s ease; }
#volChat .vchat__row--user .vchat__bubble { background: #2563EB; color: #fff; border-radius: 10px; }
/* The reply sits ON the panel rather than in a card: mostly transparent at rest so the backdrop
   reads through it, filling in on hover. The border goes with it - an outline around something
   transparent is just a box. */
#volChat .vchat__row--staff .vchat__bubble,
#volChat .vchat__row--ai .vchat__bubble {
  background: rgba(243,246,250,.5); border: 1px solid transparent; color: #33405A;
}
#volChat .vchat__row--staff:hover .vchat__bubble,
#volChat .vchat__row--ai:hover .vchat__bubble {
  background: #F3F6FA; border-color: #E9EDF4;
}

/* Provenance under an assistant reply: one quiet line, opened only if asked for.
   The wording is "sources" in the toggle but the panel says what is actually true - these are the
   articles the assistant was given, not a claim about which ones the answer came from. */
#volChat .vchat__srcs { margin: 4px 0 2px; max-width: 100%; }
#volChat .vchat__srcs-t {
  display: inline-flex; align-items: center; gap: 5px; padding: 3px 8px 3px 5px;
  border: 1px solid #E6EAF1; border-radius: 999px; background: #fff; cursor: pointer;
  font: inherit; font-size: 11.5px; font-weight: 600; color: #697586;
  transition: background .14s ease, border-color .14s ease, color .14s ease;
}
#volChat .vchat__srcs-t:hover { background: #F4F7FC; border-color: #D7DEE9; color: #33405A; }
#volChat .vchat__srcs-t svg { width: 11px; height: 11px; flex: 0 0 auto; transition: transform .16s ease; }
#volChat .vchat__srcs.is-open .vchat__srcs-t svg { transform: rotate(90deg); }
/* display:flex outranks the UA rule for [hidden], so the panel stayed on screen while the DOM
   insisted it was hidden. The attribute has to be given back its authority explicitly. */
#volChat .vchat__srcs-b[hidden] { display: none; }
#volChat .vchat__srcs-b {
  margin-top: 5px; padding: 8px 11px; background: #fff; border: 1px solid #E9EEF6; border-radius: 11px;
  display: flex; flex-direction: column; align-items: flex-start; gap: 4px;
}
#volChat .vchat__srcs-b::before {
  content: 'The assistant was given these help articles';
  font-size: 10px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: #9AA4B2;
}
#volChat .vchat__src { font-size: 12.5px; line-height: 1.4; color: #2563EB; text-decoration: none;
  display: block; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#volChat .vchat__src:hover { text-decoration: underline; }
/* Formatting inside an assistant reply. Tight margins: this is a chat bubble, not an article,
   and default paragraph/list spacing would make a three-step answer twice as tall as it needs
   to be. */
#volChat .vchat__bubble p { margin: 0 0 8px; }
#volChat .vchat__bubble p:last-child { margin-bottom: 0; }
#volChat .vchat__bubble ul,
#volChat .vchat__bubble ol { margin: 0 0 8px; padding-left: 20px; }
#volChat .vchat__bubble ul:last-child,
#volChat .vchat__bubble ol:last-child { margin-bottom: 0; }
#volChat .vchat__bubble li { margin: 2px 0; }
#volChat .vchat__bubble strong { font-weight: 700; color: #1E293B; }
#volChat .vchat__bubble em { font-style: italic; }
#volChat .vchat__bubble code { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 12.5px; background: #EDF1F7; border-radius: 4px; padding: 1px 5px; word-break: break-all; }
#volChat .vchat__bubble pre { margin: 0 0 8px; padding: 9px 11px; background: #0F172A; border-radius: 8px;
  overflow-x: auto; }
#volChat .vchat__bubble pre:last-child { margin-bottom: 0; }
#volChat .vchat__bubble pre code { background: none; padding: 0; color: #E2E8F0; font-size: 12px;
  white-space: pre; word-break: normal; }
#volChat .vchat__bubble a { color: #2563EB; text-decoration: underline; word-break: break-word; }
/* pre-wrap plus real block elements would double every gap the markup already provides */
#volChat .vchat__row--ai .vchat__bubble:has(p),
#volChat .vchat__row--staff .vchat__bubble:has(p) { white-space: normal; }

/* Human-handoff row */
#volChat .vchat__human { display: flex; justify-content: center; padding: 8px 12px 4px; background: transparent; }
#volChat .vchat__human button { appearance: none; border: 1px solid #DCE3EE; background: #fff; color: #2563EB; cursor: pointer;
  font: inherit; font-size: 12.5px; font-weight: 600; padding: 7px 14px; border-radius: 999px; }
#volChat .vchat__human button:hover { background: #F0F5FF; border-color: #C3D4F5; }
#volChat .vchat__human.is-hidden { display: none; }

/* Composer.
   One row: the field and its controls on the same line, so an empty composer costs one line of
   panel rather than two. It still grows - align-items:flex-end keeps the buttons pinned to the
   bottom as the text climbs, which is how every chat box behaves. The focus ring is on the card,
   so the whole thing lights up as one control rather than a border appearing around an inner
   input. */
#volChat .vchat__composer {
  display: flex; flex-direction: row; align-items: flex-end; gap: 6px;
  margin: 4px 12px 0; padding: 5px 5px 5px 12px;
  background: #fff; border: 1px solid #DDE4EF; border-radius: 14px;
  box-shadow: 0 1px 2px rgba(16,24,40,.04);
  transition: border-color .15s ease, box-shadow .15s ease;
}
#volChat .vchat__composer:focus-within { border-color: #2563EB; box-shadow: 0 0 0 3px rgba(37,99,235,.15); }
#volChat.is-locked .vchat__composer { border-color: #E6EAF1; box-shadow: none; }
/* Grows with the message up to a ceiling, then scrolls. chat.js sets the height; the max is here so
   a pasted crash log cannot push the send button off the bottom of the panel. */
/* min-height matches the button height so a single line sits centred against the controls beside
   it rather than dropping to the floor of the row. Padding does the centring: 20px of line inside
   34px of box. chat.js grows it from there, and the max stops a pasted crash log pushing the send
   button off the bottom of the panel. */
#volChat .vchat__input {
  flex: 1 1 auto; min-width: 0; border: none; outline: none; background: transparent; resize: none;
  font: inherit; font-size: 14px; line-height: 1.45; color: #0F172A;
  padding: 7px 2px; min-height: 34px; max-height: 132px; overflow-y: auto;
}
#volChat .vchat__tools { display: flex; align-items: center; gap: 2px; flex: 0 0 auto; }
#volChat .vchat__input::placeholder { color: #9AA4B2; }
#volChat .vchat__send { width: 34px; height: 34px; flex: 0 0 auto; border-radius: 50%; border: none; cursor: pointer;
  background: #2563EB; color: #fff; display: flex; align-items: center; justify-content: center; transition: background .12s ease; }
#volChat .vchat__send:hover { background: #1D4FD7; }
#volChat .vchat__send:disabled { background: #B9C6DE; cursor: default; }
#volChat .vchat__send svg { width: 17px; height: 17px; display: block; }

/* Typing indicator (three blinking dots in an agent-style bubble). */
#volChat .vchat__typing { display: inline-flex; gap: 4px; align-items: center; padding: 11px 13px; background: rgba(243,246,250,.6); border: 1px solid transparent; border-radius: 8px; align-self: flex-start; }
#volChat .vchat__typing span { width: 6px; height: 6px; border-radius: 50%; background: #9AA4B2; animation: vchat-blink 1.2s infinite ease-in-out both; }
/* The wording beside the dots while the assistant works. Elapsed-time only - see startThinkClock. */
/* The waiting line, with a highlight travelling across the words.

   background-clip:text over a moving gradient, so the shimmer is IN the letterforms rather than
   a bar sliding over them. The base colour is repeated as the fallback `color` because a browser
   without -webkit-text-fill-color would otherwise paint transparent text - an invisible status
   line is a worse failure than no animation. */
#volChat .vchat__think {
  font-style: normal; font-size: 12.5px; margin-left: 3px; color: #8A93A3;
  background-image: linear-gradient(100deg, #A3ACBA 32%, #2563EB 48%, #A3ACBA 64%);
  background-size: 260% 100%;
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent;
  animation: vchat-glare 2.1s linear infinite;
}
#volChat .vchat__think:empty { display: none; }
@keyframes vchat-glare { from { background-position: 160% 0; } to { background-position: -60% 0; } }
#volChat .vchat__typing { gap: 5px; padding: 11px 14px; }
#volChat .vchat__typing span:nth-child(2) { animation-delay: .18s; }
#volChat .vchat__typing span:nth-child(3) { animation-delay: .36s; }

/* The assistant's reply fading in a word at a time.
   Opacity only, on inline spans: a transform would need inline-block, and inline-block words
   stop a long URL or path from breaking mid-token, which is exactly the content this chat is
   full of. The delay per word is set inline by chat.js. */
#volChat .vchat__w { opacity: 0; animation: vchat-word .3s ease forwards; }
#volChat .vchat__bubble.is-revealed .vchat__w { animation: none; opacity: 1; }
@keyframes vchat-word { to { opacity: 1; } }

/* Motion: panel pop-in on open, each message slides up as it lands. */
#volChat.is-open .vchat__panel { animation: vchat-pop .2s cubic-bezier(.2, .8, .3, 1); transform-origin: bottom right; }
#volChat .vchat__row--in { animation: vchat-in .22s cubic-bezier(.2, .7, .3, 1); }
@keyframes vchat-pop { from { opacity: 0; transform: translateY(12px) scale(.98); } to { opacity: 1; transform: none; } }
@keyframes vchat-in { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
@keyframes vchat-blink { 0%, 80%, 100% { opacity: .3; transform: translateY(0); } 40% { opacity: 1; transform: translateY(-2px); } }

@media (prefers-reduced-motion: reduce) {
  #volChat.is-open .vchat__panel, #volChat .vchat__row--in { animation: none; }
  /* Belt and braces: chat.js already skips the reveal entirely under reduced motion, so these
     spans should never exist here. If one ever does, it must not be invisible. */
  #volChat .vchat__w { animation: none; opacity: 1; }
  #volChat .vchat__think { animation: none; -webkit-text-fill-color: #8A93A3; }
  #volChat .vchat__typing span { animation: none; opacity: .55; }
}

@media (max-width: 480px) {
  #volChat.vchat { right: 12px; bottom: 12px; }
  #volChat .vchat__panel { width: calc(100vw - 24px); height: calc(100vh - 24px); }
}
@media (prefers-reduced-motion: reduce) { #volChat .vchat__launcher { transition: none; } }

/* ============ launcher unread state (rebuilt 2026-07-26) ============ */
/*
 * What was here, and why it went:
 *
 *  - An `::after` ring pulsing every 2.6s, `infinite`, on `:not(.is-open)`. That was not tied to
 *    unread messages at all, so the launcher pinged forever on every page for every visitor with
 *    nothing whatsoever to look at. Constant motion in the corner of the eye is the definition of
 *    obnoxious, and it made the real unread signal meaningless.
 *  - `vchat-nudge ... infinite` on has-unread: the launcher bounced without end until it was opened.
 *
 * Motion now only happens when something ACTUALLY happened, and it stops on its own. The steady-state
 * signal is the badge: silent, countable, and impossible to miss when it matters.
 */
#volChat .vchat__launcher { position: relative; }

/* A short bump replayed by chat.js on each new message. Finite by design: two hops and done. */
#volChat .vchat__launcher.is-bump { animation: vchat-nudge .48s ease-in-out 2; }
@keyframes vchat-nudge { 0%, 100% { transform: translateY(0); } 30% { transform: translateY(-5px); } 60% { transform: translateY(0); } }

/* While unread, the launcher takes the brand fill it otherwise only takes on hover - so the state is
   carried by the button itself, not by a coloured haze around it. The old rule swapped the glow for
   a bigger glow, which said "something changed" without saying what. */
#volChat.has-unread:not(.is-open) .vchat__launcher {
  background: #2563EB; color: #fff;
  box-shadow: inset 0 0 0 1px #2563EB,
              0 2px 4px rgba(15, 23, 42, .10),
              0 10px 24px -8px rgba(15, 23, 42, .26);
}

/* The count, flat. The 6px red bloom under it was the same decoration as the launcher's own glow,
   and on a 20px chip it mostly read as a smudge. A white ring is what separates it from the button;
   nothing else is needed. */
.vchat__badge {
  position: absolute; top: -2px; right: -2px; min-width: 18px; height: 18px; padding: 0 5px;
  border-radius: 9px; background: #EF4444; color: #fff;
  font: 700 10.5px/18px 'Inter', system-ui, -apple-system, sans-serif; text-align: center;
  box-shadow: 0 0 0 2px #fff;
}
#volChat.has-unread:not(.is-open) .vchat__badge { box-shadow: 0 0 0 2px #2563EB; }
.vchat__badge[hidden] { display: none; }

/* "Matching you with a support agent..." while an escalated chat waits for a person. */
#volChat .vchat__matching { align-self: center; display: inline-flex; align-items: center; gap: 9px; margin: 10px 0 4px; padding: 9px 15px; background: #eef4ff; border: 1px solid #d7e3fb; border-radius: 14px; color: #1e4fd7; font-size: 12.5px; font-weight: 600; }
#volChat .vchat__spin { flex: 0 0 auto; width: 14px; height: 14px; border-radius: 50%; border: 2px solid #bcd2fb; border-top-color: #2563EB; animation: vchat-spin .8s linear infinite; }
@keyframes vchat-spin { to { transform: rotate(360deg); } }

/* Buttons that are waiting on the network.
 *
 * Asking for a human now pages the on-call team over Discord inside the request, so it is no longer
 * instant, and a control that looks idle for a second reads as broken and gets clicked again. JS
 * pins the button's width before swapping its contents, so nothing collapses or shifts. */
#volChat .is-busy { cursor: default; display: inline-flex; align-items: center; justify-content: center; gap: 8px; }
#volChat .is-busy .vchat__spin { width: 13px; height: 13px; }
/* The send and attach buttons are round icon buttons on a dark or tinted ground, so their spinner
   needs its own colours rather than the blue-on-pale-blue used by the matching row. */
#volChat .vchat__send.is-busy { background: #2563EB; opacity: .85; }
#volChat .vchat__send.is-busy .vchat__spin { border-color: rgba(255,255,255,.45); border-top-color: #fff; }
#volChat .vchat__attach.is-busy .vchat__spin { border-color: #DCE3EE; border-top-color: #697586; }
#volChat .vchat__human button.is-busy { background: #F0F5FF; border-color: #C3D4F5; color: #2563EB; }

/* Header online dot. Static: it is a status indicator, not an alert, and it only exists inside the
   open panel where the customer is already looking. It used to pulse every 2s forever. */
#volChat[data-online="1"] .vchat__avatar::after { box-shadow: 0 0 0 2px rgba(34, 197, 94, .22); }

@media (prefers-reduced-motion: reduce) {
  /* The launcher ring and the online-dot pulse are gone entirely, so only the new bump and the
     loading spinner need suppressing here. */
  #volChat .vchat__launcher.is-bump, #volChat .vchat__spin { animation: none; }
}

/* ==========================================================================
   Rich messages in the widget: reactions, images, edit/delete, seen.
   Parity with what the agent has on the ticket - includes/support/chat_ext.php
   is the shared layer, so a reaction added here is the one they see there.
   ========================================================================== */

/* Rows need to position the hover strip, and the strip must not push layout. */
#volChat .vchat__row { position: relative; }
#volChat .vchat__bubble.is-empty { display: none; }   /* image-only message: no empty bubble */

/* ---- attachments ---- */
#volChat .vchat__atts { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 4px; }
#volChat .vchat__att { display: block; border-radius: 12px; overflow: hidden; border: 1px solid #E6EAF1;
  background: #fff; line-height: 0; max-width: 200px; }
#volChat .vchat__att img { display: block; width: 100%; height: auto; max-height: 220px; object-fit: cover; }
#volChat .vchat__att:hover { border-color: #B9C6DE; }

/* ---- reactions ---- */
#volChat .vchat__reacts { display: flex; flex-wrap: wrap; gap: 4px; }
#volChat .vchat__reacts:empty { display: none; }
#volChat .vchat__react { border: 1px solid #E6EAF1; background: #fff; border-radius: 999px;
  padding: 1px 8px; font-size: 12px; line-height: 1.7; cursor: pointer; font-family: inherit; color: #33405A; }
#volChat .vchat__react:hover { border-color: #B9C6DE; background: #F6F8FB; }

/* ---- message actions trigger ----
 *
 * A REAL FLEX ITEM in the row, not an overlay. The previous strip was absolutely positioned at
 * top:-8px, which put it on top of the bubble above and covered the text. This sits in the gutter
 * the 80% stack always leaves free, so it cannot overlap a bubble at any width.
 *
 * It reserves its space at all times and only changes visibility, so revealing it on hover moves
 * nothing. On touch there is no hover to reveal it, so it stays visible - it costs no layout there
 * either, because the space was always reserved.
 */
/* On an assistant or agent row the trigger is taken OUT of the flex line and parked beside the
   AI label, which is empty space. In the line it was a 24px flex item, so the moment it was
   appended - which is when the stream finishes - the bubble lost that width and every line
   re-wrapped narrower. The customer's own row keeps it in flow: that stack is capped at 80%,
   so there is already a gutter for it and nothing moves. */
#volChat .vchat__row--ai .vchat__more,
#volChat .vchat__row--staff .vchat__more { position: absolute; top: -3px; right: 0; align-self: auto; margin: 0; }
#volChat .vchat__more { flex: 0 0 auto; align-self: flex-end; width: 24px; height: 24px; margin-bottom: 2px;
  border: 0; background: none; padding: 0; cursor: pointer; border-radius: 999px; color: #A3AEC0;
  display: grid; place-items: center;
  visibility: hidden; opacity: 0; transition: opacity .12s ease, background .12s ease, color .12s ease; }
#volChat .vchat__more svg { width: 16px; height: 16px; display: block; fill: currentColor; }
#volChat .vchat__row:hover .vchat__more,
#volChat .vchat__row:focus-within .vchat__more,
#volChat .vchat__more[aria-expanded="true"] { visibility: visible; opacity: 1; }
#volChat .vchat__more:hover { background: #E8EDF5; color: #33405A; }
#volChat .vchat__more:focus-visible { outline: none; visibility: visible; opacity: 1; box-shadow: 0 0 0 3px rgba(37,99,235,.25); }
@media (hover: none) { #volChat .vchat__more { visibility: visible; opacity: .75; } }

/* ---- message menu ----
 * Parented to the panel, not the row: the log scrolls and clips, so a menu inside a row gets cut
 * off near either end of the transcript. JS positions it and clamps it inside the panel, so it is
 * always whole. Hidden until placed, or it flashes at 0,0 for one frame while being measured.
 */
#volChat .vchat__menu { position: absolute; z-index: 6; width: 216px; padding: 6px;
  background: #fff; border: 1px solid #E3E9F2; border-radius: 14px;
  box-shadow: 0 12px 32px rgba(15,23,42,.16), 0 2px 6px rgba(15,23,42,.06);
  visibility: hidden; }
#volChat .vchat__menu.is-placed { visibility: visible; animation: vchat-menu .13s cubic-bezier(.2,.7,.3,1); }
@keyframes vchat-menu { from { opacity: 0; transform: translateY(-4px) scale(.97); } to { opacity: 1; transform: none; } }

#volChat .vchat__emoji { display: grid; grid-template-columns: repeat(4, 1fr); gap: 2px; }
#volChat .vchat__emoji button { height: 34px; border: 0; background: none; cursor: pointer;
  border-radius: 9px; font-size: 17px; line-height: 1; padding: 0; }
#volChat .vchat__emoji button:hover { background: #F1F5F9; transform: scale(1.12); }
#volChat .vchat__emoji button:focus-visible { outline: none; background: #F1F5F9; box-shadow: 0 0 0 2px rgba(37,99,235,.3); }

/* The divider is on the first item rather than a separate element, so a menu with no commands on it
   (anything that is not your own message) has no stray rule floating at the bottom. */
#volChat .vchat__item { display: flex; align-items: center; gap: 10px; width: 100%; padding: 9px 8px;
  border: 0; background: none; cursor: pointer; border-radius: 9px; text-align: left;
  font-family: inherit; font-size: 13.5px; font-weight: 500; color: #33405A; }
#volChat .vchat__item + .vchat__item { margin-top: 1px; }
#volChat .vchat__emoji + .vchat__item { margin-top: 5px; padding-top: 12px; border-top: 1px solid #EEF1F6; border-radius: 0 0 9px 9px; }
#volChat .vchat__item-ico { flex: 0 0 auto; width: 16px; height: 16px; display: block; color: #8A93A3; }
#volChat .vchat__item-ico svg { width: 16px; height: 16px; display: block; }
#volChat .vchat__item:hover { background: #F1F5F9; color: #0F172A; }
#volChat .vchat__item:hover .vchat__item-ico { color: #33405A; }
#volChat .vchat__item:focus-visible { outline: none; background: #F1F5F9; box-shadow: 0 0 0 2px rgba(37,99,235,.3); }
#volChat .vchat__item--danger { color: #B4332B; }
#volChat .vchat__item--danger .vchat__item-ico { color: #C9564D; }
#volChat .vchat__item--danger:hover { background: #FDECEA; color: #92251E; }
#volChat .vchat__item--danger:hover .vchat__item-ico { color: #92251E; }

/* Delete confirmation, inside the menu. No native confirm() dialog over the page. */
#volChat .vchat__menu--confirm { width: 210px; padding: 12px; }
#volChat .vchat__confirm-q { font-size: 13.5px; font-weight: 600; color: #0F172A; margin-bottom: 10px; }
#volChat .vchat__confirm-acts { display: flex; gap: 6px; }
#volChat .vchat__confirm-acts button { flex: 1; cursor: pointer; font-family: inherit; font-size: 13px;
  font-weight: 600; padding: 8px 10px; border-radius: 9px; }
#volChat .vchat__confirm-no { color: #33405A; background: #fff; border: 1px solid #DCE3EE; }
#volChat .vchat__confirm-no:hover { background: #F3F6FB; }
#volChat .vchat__confirm-yes { color: #fff; background: #DC2626; border: 1px solid #DC2626; }
#volChat .vchat__confirm-yes:hover { background: #B91C1C; }

/* ---- inline edit ----
 * Replaces prompt(). The bubble is hidden and the editor takes its place in the stack, so the
 * message is edited where it lives and the conversation stays on screen.
 */
#volChat .vchat__edit { width: 100%; min-width: 190px; background: #fff; border: 1px solid #C3D4F5;
  border-radius: 14px; padding: 8px; box-shadow: 0 0 0 3px rgba(37,99,235,.12); }
#volChat .vchat__edit-input { display: block; width: 100%; resize: none; border: 0; outline: none;
  font-family: inherit; font-size: 14px; line-height: 1.5; color: #0F172A; background: transparent;
  padding: 0 2px; max-height: 140px; overflow-y: auto; }
#volChat .vchat__edit-input:disabled { color: #8A93A3; }
#volChat .vchat__edit-acts { display: flex; justify-content: flex-end; gap: 6px; margin-top: 8px; }
#volChat .vchat__edit-acts button { cursor: pointer; font-family: inherit; font-size: 12.5px;
  font-weight: 600; padding: 6px 12px; border-radius: 8px; }
#volChat .vchat__edit-acts button:disabled { opacity: .55; cursor: default; }
#volChat .vchat__edit-no { color: #33405A; background: #fff; border: 1px solid #DCE3EE; }
#volChat .vchat__edit-no:hover:not(:disabled) { background: #F3F6FB; }
#volChat .vchat__edit-yes { color: #fff; background: #2563EB; border: 1px solid #2563EB; }
#volChat .vchat__edit-yes:hover:not(:disabled) { background: #1D4FD7; }

@media (prefers-reduced-motion: reduce) {
  #volChat .vchat__menu.is-placed { animation: none; }
  #volChat .vchat__emoji button:hover { transform: none; }
}

/* ---- edited / seen ---- */
#volChat .vchat__edited { font-size: 10.5px; color: #98A3B3; }
#volChat .vchat__edited:empty { display: none; }
#volChat .vchat__seen { font-size: 10.5px; color: #98A3B3; text-align: right; padding: 1px 2px 0; }

/* ---- composer attach ----
   One block only. There were two, and the later one silently won, so edits made to the earlier
   one had no effect at all. Squared off to sit inside the composer card rather than beside it. */
#volChat .vchat__attach { width: 34px; height: 34px; flex: 0 0 auto; border-radius: 9px; border: 0;
  background: none; cursor: pointer; color: #8A93A3; display: grid; place-items: center; padding: 0; }
#volChat .vchat__attach svg { width: 17px; height: 17px; }
#volChat .vchat__attach:hover { background: #F1F5FB; color: #33405A; }

/* Drag a screenshot anywhere onto the panel. */
#volChat .vchat__panel.is-drop { outline: 2px dashed #2563EB; outline-offset: -6px; }
