/* ==========================================================================
   AnswerRails Chat Widget — design-token stylesheet
   ==========================================================================
   Rebuilt 2026-07-22 (frontend overhaul Phase A; design doc
   FRONTEND_OVERHAUL_DESIGN.md). Replaces the previous sedimented stylesheet;
   visual output matches that file's effective cascade result.

   Structure — three layers, in order:
     1. TOKENS      all custom properties. Colour/spacing/type decisions live
                    here and ONLY here.
     2. COMPONENTS  launcher, window, header, messages, input, consent,
                    footer. Each selector is styled EXACTLY ONCE — if you are
                    about to restyle a selector further down the file, edit
                    the original block instead.
     3. STATES      open/closed, position variants, responsive.

   Rules of this file:
   - No !important outside the page-isolation guards on the widget root.
   - One mobile media query.
   - Every selector here is emitted by class-answerrails-core.php or
     chat-widget.js. Do not add speculative selectors.
   - Theme values arrive as CSS custom properties; Phase B injects overrides
     on the widget root (server-derived, contrast-checked). Do not hardcode
     brand colours below the token layer.
   ========================================================================== */

/* ==========================================================================
   1. TOKENS
   ========================================================================== */

#answerrails-chat-widget {
  /* Brand / accent (Phase B overrides these via inline custom properties) */
  --ar-accent: #2563eb;
  --ar-accent-hover: #1d4ed8;
  --ar-accent-contrast: #ffffff;

  /* Surfaces */
  --ar-bg: #ffffff;
  --ar-bg-muted: #fafbfc;
  --ar-bg-footer: #f8f9fa;
  --ar-bg-assistant: #f8f9fa;
  --ar-bg-typing: #f0f0f0;
  --ar-bg-consent: rgba(255, 248, 220, 0.95);
  --ar-bg-error: #ffeeee;

  /* Borders */
  --ar-border: #e5e7eb;
  --ar-border-light: #eef2f7;
  --ar-border-assistant: #e9ecef;
  --ar-border-typing: #dddddd;
  --ar-border-error: #ffcccc;

  /* Text */
  --ar-text: #111827;
  --ar-text-muted: #6b7280;
  /* #206 D3: plain (unlinked) citation label. Muted, but AA on
     --ar-bg-assistant (4.5:1 floor) — --ar-text-muted is 4.06:1 there in
     dark mode, below the widget's WCAG 2.2 AA claim. Test-pinned. */
  --ar-citation-plain: #5b6470;
  --ar-text-error: #cc3333;
  --ar-disabled: #cccccc;

  /* Header (defaults derive from accent; Phase B may override) */
  --ar-header-bg: linear-gradient(135deg, var(--ar-accent) 0%, var(--ar-accent-hover) 100%);
  --ar-header-text: #ffffff;
  --ar-header-text-soft: rgba(255, 255, 255, 0.9);

  /* Focus ring */
  --ar-focus-ring: rgba(37, 99, 235, 0.1);
  --ar-focus-border: var(--ar-accent);

  /* Shadows */
  --ar-shadow-window: 0 6px 24px rgba(0, 0, 0, 0.08);
  --ar-shadow-launcher: 0 10px 28px rgba(15, 23, 42, 0.22);
  --ar-shadow-launcher-hover: 0 18px 32px rgba(15, 23, 42, 0.26);

  /* Radii */
  --ar-radius-window: 14px;
  --ar-radius-bubble: 12px;
  --ar-radius-pill: 9999px;

  /* Window geometry (Phase C presets adjust these; limits match
     chat-widget.js RESIZE_LIMITS + maxWindowWidth()/maxWindowHeight() -
     keep the two in sync). Max width is viewport-relative (2026-07-23):
     85vw stops page takeover on narrow desktop viewports, 960px is the
     large-screen ceiling; readability is handled by the bubble content
     cap (--ar-bubble-max-width), not the window cap. */
  --ar-window-width: 380px;
  --ar-window-height: 600px;
  --ar-window-min-width: 320px;
  --ar-window-min-height: 400px;
  --ar-window-max-width: min(85vw, 960px);
  --ar-window-max-height: 90vh;
  --ar-bubble-max-width: 720px;

  /* Spacing & type */
  --ar-gap-messages: 8px;
  --ar-pad-area: 16px;
  --ar-font: system-ui, -apple-system, "Segoe UI", Roboto, Arial, sans-serif;
  --ar-line-height: 1.4;

  /* Layering. #112 (2026-07-28): the widget YIELDS to consent-manager
     surfaces — 9999 sits below the common CMP range (Complianz et al
     run 99999+; the old 99999 default painted the launcher over the
     consent dialog's Deny button, observed live on prod). Site owners
     whose theme chrome still wins can raise it with
       #answerrails-chat-widget { --ar-z-widget: <value>; }
     — the same recipe works in both directions (documented in the FAQ). */
  --ar-z-widget: 9999;
  --ar-z-overlay: 10;
}

/* ==========================================================================
   2. COMPONENTS
   ========================================================================== */

/* --- Widget root (fixed dock; the only !important rules in this file:
       they isolate the widget from theme CSS that styles generic divs) --- */
#answerrails-chat-widget {
  position: fixed !important;
  bottom: 20px !important;
  right: 20px !important;
  left: auto !important;
  z-index: var(--ar-z-widget) !important;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 14px;
  max-width: 420px;
  width: 100%;
  pointer-events: none; /* children restore it; keeps the empty dock area click-through */
  font-family: var(--ar-font);
  /* NO transform/filter/will-change on this element or any variant of it:
     a transformed ancestor becomes the containing block for position:fixed
     descendants, which would pin the Phase C floating window to this dock
     box instead of the viewport (bit us 2026-07-23). */
}

#answerrails-chat-widget > * {
  pointer-events: auto;
}

/* --- Launcher --- */
.answerrails-chat-button {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: var(--ar-launcher-gap, 0.9rem);
  border-radius: var(--ar-radius-pill);
  border: none;
  background: var(--ar-launcher-bg, var(--ar-accent));
  color: var(--ar-launcher-text, var(--ar-accent-contrast));
  padding: var(--ar-launcher-padding-y, 0.9rem) var(--ar-launcher-padding-x, 1.5rem);
  min-height: var(--ar-launcher-min-height, 78px);
  box-shadow: var(--ar-shadow-launcher);
  cursor: pointer;
  transition: transform 0.18s ease, box-shadow 0.18s ease, filter 0.18s ease;
  font-family: var(--ar-font);
  font-weight: 600;
  text-align: left;
}

.answerrails-chat-button:hover,
.answerrails-chat-button:focus-visible {
  transform: translateY(-2px);
  filter: brightness(1.05);
  box-shadow: var(--ar-shadow-launcher-hover);
}

.answerrails-chat-button:focus-visible {
  outline: 3px solid rgba(255, 255, 255, 0.6);
  outline-offset: 3px;
}

/* Launcher size presets (admin setting) */
.answerrails-launcher {
  --ar-launcher-media-size: 48px;
  --ar-launcher-title-size: 1rem;
  --ar-launcher-tagline-size: 0.85rem;
}

.answerrails-launcher--size-compact {
  --ar-launcher-padding-y: 0.65rem;
  --ar-launcher-padding-x: 1.2rem;
  --ar-launcher-gap: 0.7rem;
  --ar-launcher-min-height: 64px;
  --ar-launcher-media-size: 44px;
  --ar-launcher-title-size: 0.95rem;
  --ar-launcher-tagline-size: 0.78rem;
}

.answerrails-launcher--size-spacious {
  --ar-launcher-padding-y: 1rem;
  --ar-launcher-padding-x: 1.75rem;
  --ar-launcher-gap: 1rem;
  --ar-launcher-min-height: 88px;
  --ar-launcher-media-size: 56px;
  --ar-launcher-title-size: 1.05rem;
  --ar-launcher-tagline-size: 0.9rem;
}

.answerrails-launcher-media {
  flex: 0 0 auto;
  width: var(--ar-launcher-media-size);
  height: var(--ar-launcher-media-size);
  border-radius: var(--ar-radius-pill);
  background: rgba(255, 255, 255, 0.22);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: inherit;
}

.answerrails-launcher--avatar .answerrails-launcher-media {
  overflow: hidden;
  background: rgba(255, 255, 255, 0.32);
}

.answerrails-launcher-avatar img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: inherit;
  display: block;
}

.answerrails-chat-icon svg {
  width: 24px;
  height: 24px;
  display: block;
}

.answerrails-launcher-body {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  line-height: 1.2;
}

.answerrails-launcher-title {
  font-size: var(--ar-launcher-title-size);
  font-weight: 700;
}

.answerrails-launcher-tagline {
  font-size: var(--ar-launcher-tagline-size);
  font-weight: 500;
  opacity: 0.92;
}

/* There is no unread badge: nothing can arrive while the chat is closed,
   so it would never fire. Proactive messages would change that. */
/* --- Window --- */
.answerrails-chat-window {
  position: relative;
  display: flex;
  flex-direction: column;
  width: var(--ar-window-width);
  height: var(--ar-window-height);
  min-width: var(--ar-window-min-width);
  min-height: var(--ar-window-min-height);
  max-width: var(--ar-window-max-width);
  max-height: var(--ar-window-max-height);
  border: 1px solid var(--ar-border);
  border-radius: var(--ar-radius-window);
  background: var(--ar-bg);
  box-shadow: var(--ar-shadow-window);
  color: var(--ar-text);
  overflow: hidden;
}

/* Resize handles (Phase C; emitted by class-answerrails-core.php, driven
   by chat-widget.js pointer events). The window is anchored to its
   bottom-right corner, so the live edges are LEFT and TOP plus the
   top-left corner. The corner sits last in the DOM so it paints above
   the edge strips it overlaps. Hidden on mobile (see the media query). */
.answerrails-resize-handle {
  position: absolute;
  z-index: var(--ar-z-overlay);
  touch-action: none;
  background: transparent;
  transition: background 0.15s ease, opacity 0.15s ease;
}

.answerrails-resize-handle--left {
  top: 0;
  left: 0;
  bottom: 0;
  width: 6px;
  cursor: ew-resize;
}

.answerrails-resize-handle--top {
  top: 0;
  left: 0;
  right: 0;
  height: 6px;
  cursor: ns-resize;
}

.answerrails-resize-handle--left:hover,
.answerrails-resize-handle--top:hover {
  background: var(--ar-focus-ring);
}

.answerrails-resize-handle--corner {
  top: 0;
  left: 0;
  width: 20px;
  height: 20px;
  cursor: nw-resize;
  border-top-left-radius: var(--ar-radius-window);
  background:
    linear-gradient(45deg, var(--ar-border) 30%, transparent 30%),
    linear-gradient(-45deg, var(--ar-border) 30%, transparent 30%);
  background-size: 6px 6px;
  background-position: 2px 2px, 2px 2px;
  background-repeat: no-repeat;
  opacity: 0.5;
}

.answerrails-chat-window:hover .answerrails-resize-handle--corner {
  opacity: 0.9;
}

/* --- Header (drag handle for the Phase C float; grab cursor is reset
       in the mobile query where drag is disabled) --- */
.answerrails-chat-header {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: var(--ar-pad-area);
  background: var(--ar-header-bg);
  color: var(--ar-header-text);
  border-bottom: 1px solid var(--ar-border-light);
  cursor: grab;
}

.answerrails-chat-avatar img {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  object-fit: cover;
  border: 2px solid rgba(255, 255, 255, 0.3);
}

.answerrails-chat-title {
  font-weight: 700;
  font-size: 1.1rem;
  color: var(--ar-header-text);
}

.answerrails-chat-subtitle {
  font-size: 0.85rem;
  color: var(--ar-header-text-soft);
}

.answerrails-chat-actions {
  margin-left: auto;
  display: flex;
  gap: 12px; /* finger-friendly separation between header actions */
}

.answerrails-chat-minimize,
.answerrails-chat-new {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: rgba(255, 255, 255, 0.2);
  border: 1px solid rgba(255, 255, 255, 0.3);
  color: var(--ar-header-text);
  /* 48px matches the send button and the recommended touch-target size */
  width: 48px;
  height: 48px;
  border-radius: 8px;
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
  transition: background 0.15s, transform 0.15s;
}

.answerrails-chat-minimize:hover,
.answerrails-chat-new:hover {
  background: rgba(255, 255, 255, 0.3);
  transform: translateY(-1px);
}

/* --- Messages area --- */
.answerrails-chat-messages {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: var(--ar-gap-messages);
  padding: var(--ar-pad-area);
  min-height: 200px;
  overflow-y: auto;
  scroll-behavior: smooth;
  background: var(--ar-bg-muted);
}

.answerrails-chat-messages::-webkit-scrollbar {
  width: 8px;
}

.answerrails-chat-messages::-webkit-scrollbar-thumb {
  background: rgba(0, 0, 0, 0.15);
  border-radius: 4px;
}

/* --- Messages --- */
.answerrails-message {
  display: flex;
  flex-direction: column;
  max-width: 100%;
}

.answerrails-message-content {
  display: flex;
  flex-direction: column;
  gap: 2px;
  max-width: min(100%, var(--ar-bubble-max-width)); /* line length stays readable however wide the window is resized */
  border: 1px solid transparent;
  border-radius: var(--ar-radius-bubble);
  padding: 6px 14px;
  line-height: var(--ar-line-height);
  white-space: pre-wrap;
  word-wrap: break-word;
}

.answerrails-message-sender {
  margin: 0;
  font-size: 0.85rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  opacity: 0.9;
}

.answerrails-message-text {
  margin: 0;
  font-size: 1rem;
  line-height: var(--ar-line-height);
}

/* Lists inside a reply (#206 D1; Codex P2 on PR #235).
   The transform emits real <ul>/<ol>, but markup alone does not fix the
   reported defect: a host theme resetting `ul, ol { list-style: none;
   padding: 0 }` would leave the items looking like the prose they were.
   These rules restate the marker and the indent INSIDE the widget, and are
   deliberately id-scoped (1,1,1) so an ordinary theme reset — usually a bare
   element or single-class selector — cannot win. That is why they do not use
   !important: specificity is enough, and it degrades honestly if a site
   really does out-specify us.
   DIRECT CHILDREN ONLY: the Sources block's own <ul> lives further down
   inside .answerrails-citations and keeps the appearance it shipped with. */
#answerrails-chat-widget .answerrails-message-text > ul,
#answerrails-chat-widget .answerrails-message-text > ol {
  margin: 0.5em 0;
  padding-left: 1.5em;
  list-style-position: outside;
}

#answerrails-chat-widget .answerrails-message-text > ul {
  list-style-type: disc;
}

#answerrails-chat-widget .answerrails-message-text > ol {
  list-style-type: decimal;
}

#answerrails-chat-widget .answerrails-message-text > ul > li,
#answerrails-chat-widget .answerrails-message-text > ol > li {
  margin: 0.25em 0;
  padding-left: 0;
  list-style: inherit;
}

/* User (right, accent) */
.answerrails-message-user {
  align-items: flex-end;
}

.answerrails-message-user .answerrails-message-content {
  background: var(--ar-accent);
  border-color: var(--ar-accent);
  color: var(--ar-accent-contrast);
}

.answerrails-message-user .answerrails-message-sender {
  color: rgba(255, 255, 255, 0.9);
}

/* Assistant (left, surface) */
.answerrails-message-assistant {
  align-items: flex-start;
}

.answerrails-message-assistant .answerrails-message-content {
  background: var(--ar-bg-assistant);
  border-color: var(--ar-border-assistant);
  color: var(--ar-text);
}

/* System (centred) */
.answerrails-message-system {
  align-items: center;
}

/* Deflection (#157): the assistant declining honestly IS an assistant
   reply — assistant look, never the error tokens. */
.answerrails-message-deflection {
  align-items: flex-start;
}

.answerrails-message-deflection .answerrails-message-content {
  background: var(--ar-bg-assistant);
  border-color: var(--ar-border-assistant);
  color: var(--ar-text);
}

.answerrails-error-message {
  background: var(--ar-bg-error);
  border: 1px solid var(--ar-border-error);
  color: var(--ar-text-error);
  border-radius: var(--ar-radius-bubble);
  padding: 12px 16px;
  margin: 8px 0;
  font-size: 0.9rem;
  text-align: left;
}

/* Typing indicator */
.answerrails-typing-dots {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 12px 16px;
  background: var(--ar-bg-typing);
  border: 1px solid var(--ar-border-typing);
  border-radius: 20px;
  animation: answerrails-pulse 1.5s infinite;
}

@keyframes answerrails-pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.6; }
}

/* --- Input area --- */
.answerrails-chat-input-area {
  position: relative;
  background: var(--ar-bg);
  border-top: 1px solid var(--ar-border-light);
  padding: var(--ar-pad-area);
}

.answerrails-chat-input {
  display: flex;
  align-items: center;
  gap: 10px;
}

#answerrails-message-input {
  flex: 1;
  min-height: 44px;
  max-height: 160px;
  padding: 12px 20px;
  border: 2px solid var(--ar-border);
  border-radius: 25px;
  background: var(--ar-bg);
  color: var(--ar-text); /* textareas don't inherit colour — without this, typed text is UA-black on the dark surface */
  resize: vertical;
  font: inherit;
  font-size: 0.95rem;
  line-height: var(--ar-line-height);
  transition: border-color 0.2s ease;
}

#answerrails-message-input::placeholder {
  color: var(--ar-text-muted);
}

#answerrails-message-input:focus {
  border-color: var(--ar-focus-border);
  box-shadow: 0 0 0 3px var(--ar-focus-ring);
  outline: none;
}

#answerrails-send-button {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 48px;
  height: 48px;
  border-radius: 50%;
  border: none;
  background: var(--ar-accent);
  color: var(--ar-accent-contrast);
  cursor: pointer;
  transition: all 0.2s ease;
}

#answerrails-send-button:hover:not(:disabled) {
  background: var(--ar-accent-hover);
  transform: scale(1.05);
}

#answerrails-send-button:disabled {
  background: var(--ar-disabled);
  cursor: not-allowed;
}

/* --- Visually hidden (#122) ---
   Standard clip pattern: content stays in the accessibility tree (live
   regions, SR-only text) but renders nothing. Display-neutral by design —
   MUST NOT use display:none/visibility:hidden (which silence live regions)
   and has no effect on takeover geometry. */
.ar-visually-hidden {
  position: absolute !important;
  width: 1px !important;
  height: 1px !important;
  padding: 0 !important;
  margin: -1px !important;
  overflow: hidden !important;
  clip: rect(0, 0, 0, 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0 !important;
}

/* --- Consent overlay --- */
.answerrails-consent-notice {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  background: var(--ar-bg-consent);
  border-top: 2px solid var(--ar-accent);
  padding: var(--ar-pad-area);
  z-index: var(--ar-z-overlay);
  backdrop-filter: blur(2px);
  font-size: 0.9rem;
  line-height: var(--ar-line-height);
}

/* #122 (D4): disclaimer paragraph above the agree row — was inline inside
   the label pre-restructure. Same type size as the notice; tight margins so
   the compact/ultra tier maths is unaffected (the notice still shrinks via
   its own tier rules; no min-heights, per the takeover contract). */
.answerrails-consent-text {
  margin: 0 0 6px;
}

.answerrails-consent-agree {
  display: inline-flex;
  align-items: center;
  cursor: pointer;
  font-weight: 600;
}

#answerrails-consent-checkbox {
  margin: 2px 6px 0 0;
  transform: scale(1.1);
}

/* Consent gate: disable the input row and footer, NOT the whole area —
   the consent notice (and its checkbox) lives inside the input area and
   must stay clickable or the visitor can never leave this state
   (deadlock found 2026-07-23). */
.answerrails-chat-input-area.consent-required .answerrails-chat-input,
.answerrails-chat-input-area.consent-required .answerrails-chat-footer {
  pointer-events: none;
  opacity: 0.5;
}

/* #262 D6: the over-limit notice under the composer. Shown only while the
   typed message exceeds the byte ceiling — the widget toggles `hidden`, so
   nothing here fights that attribute. Sits in the input area's horizontal
   padding like the small-print row below it, and spends the same minimal
   vertical space, so the takeover fit maths (#120-B / #90 F5) is
   unaffected. */
.answerrails-composer-notice {
  margin-top: 4px;
  font-size: 0.75rem;
  color: var(--ar-text-muted);
}

.answerrails-composer-notice[hidden] {
  display: none;
}

/* #120: the small-print row — ONE flex row under the input hosting the
   fine print: Edit consent LEFT (clear of the send button — missed taps
   can't land on Send), reCAPTCHA attribution RIGHT; wraps on narrow
   widths. Spends minimal vertical space so the takeover fit maths
   (#120-B / #90 F5) is unaffected. Children inherit the input-area's
   horizontal padding and do NOT self-pad — per-block padding gives a
   stacked, ragged look. */
.answerrails-chat-smallprint {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 2px 12px;
  margin-top: 4px;
}

/* Withdraw affordance — GDPR Art. 7(3), withdrawal as easy as the tick.
   Hidden pre-consent (the checkbox IS the affordance then; JS shows this
   only while granted). Link-styled. */
.answerrails-consent-withdraw {
  margin: 0;
  padding: 2px 4px 2px 0;
  background: none;
  border: none;
  font-size: 0.75rem;
  color: var(--ar-text-muted);
  text-decoration: underline;
  cursor: pointer;
}

.answerrails-consent-withdraw:focus-visible {
  outline: 2px solid var(--ar-focus-border);
  outline-offset: 2px;
}

/* --- Footer --- */
.answerrails-chat-footer {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 8px var(--ar-pad-area);
  background: var(--ar-bg-footer);
  border-top: 1px solid var(--ar-border-light);
  font-size: 0.75rem;
}

.answerrails-powered-by {
  color: var(--ar-text-muted);
}

.answerrails-powered-by a {
  color: var(--ar-accent);
  text-decoration: none;
}

/* ==========================================================================
   3. STATES
   ========================================================================== */

/* Position variants (admin launcher setting) */
#answerrails-chat-widget.answerrails-launcher-pos-bottom-left {
  right: auto !important;
  left: 20px !important;
  align-items: flex-start;
}

/* Google reCAPTCHA v3 badge (#51): Google pins it fixed bottom-right
   (bottom: 14px) — directly under our bottom-right launcher dock. When
   the widget docks bottom-right, lift the badge above the launcher:
   dock offset 20px + tallest launcher preset 88px + dock gap 14px ≈
   124px. Repositioning the badge is permitted by Google's terms
   (HIDING it is what requires the disclosure text — see design D7).
   Scoped with :has() so bottom-left/centre launchers leave the badge
   in its native spot; browsers without :has() simply keep the default
   position (overlap, not breakage). NOT a rule on our own root — the
   badge element belongs to Google's script, outside the widget. */
body:has(#answerrails-chat-widget.answerrails-launcher-pos-bottom-right) .grecaptcha-badge {
  bottom: 124px !important;
}

#answerrails-chat-widget.answerrails-launcher-pos-bottom-center {
  /* Centred by spanning the dock across the full viewport width and
     flex-centring the children. NOT translateX(-50%) (a transform on
     the root breaks the fixed-position floating window) and NOT a
     calc(min())-derived negative margin (computed to 0 on the prod
     theme's pages, leaving the launcher half off-screen; 2026-07-23).
     The empty dock area stays click-through via the root's
     pointer-events:none. */
  right: 0 !important;
  left: 0 !important;
  max-width: none;
  align-items: center;
}

/* Window presets (Phase C): admin default geometry, applied by
   overriding the geometry tokens. 'standard' is the token defaults, so
   it has no block here (the class is still emitted for debuggability).
   A visitor's saved drag/resize wins over any preset: chat-widget.js
   applies it as inline width/height on the window element. */
#answerrails-chat-widget.answerrails-window-preset-compact {
  --ar-window-width: 360px;
  --ar-window-height: 520px;
}

#answerrails-chat-widget.answerrails-window-preset-tall {
  --ar-window-width: 420px;
  --ar-window-height: 85vh;
}

/* Drag-float (Phase C): dragging the header lifts the window out of the
   dock into fixed positioning; left/top arrive inline from
   chat-widget.js. The launcher stays docked. Double-click on the header
   restores the dock (chat-widget.js removes the class). */
.answerrails-chat-window.is-floating {
  position: fixed;
}

.answerrails-chat-window.is-dragging {
  user-select: none;
}

.answerrails-chat-window.is-dragging .answerrails-chat-header {
  cursor: grabbing;
}

/* Closed (default): window fully removed from layout. ⚠ display:none, NOT
   visibility:hidden — a visibility-hidden window still occupies the
   dock's flex column, pushing the launcher its full height up the page,
   and off-screen entirely in short landscape viewports. */
#answerrails-chat-widget .answerrails-chat-window {
  display: none;
  opacity: 0;
  transform: translateY(8px);
}

/* Open: window revealed, launcher hidden. The fade/slide-in runs via
   @starting-style (transition from display:none); browsers without
   @starting-style support simply show the window instantly. */
#answerrails-chat-widget.is-open .answerrails-chat-window {
  display: flex;
  opacity: 1;
  transform: translateY(0);
  transition: opacity 0.18s ease, transform 0.18s ease;
}

@starting-style {
  #answerrails-chat-widget.is-open .answerrails-chat-window {
    opacity: 0;
    transform: translateY(8px);
  }
}

#answerrails-chat-widget.is-open .answerrails-chat-button {
  display: none;
}

/* Dark mode (Phase B): surface/text token overrides only — accent-derived
   values arrive themed from PHP and are mode-independent. TWO blocks below
   (explicit dark, and auto following the OS): they MUST stay identical;
   edit both together. */
#answerrails-chat-widget[data-ar-mode="dark"] {
  --ar-bg: #1f2937;
  --ar-bg-muted: #111827;
  --ar-bg-footer: #111827;
  --ar-bg-assistant: #374151;
  --ar-bg-typing: #374151;
  --ar-bg-consent: rgba(66, 55, 22, 0.95);
  --ar-bg-error: #3f1d1d;
  --ar-border: #374151;
  --ar-border-light: #2b3544;
  --ar-border-assistant: #4b5563;
  --ar-border-typing: #4b5563;
  --ar-border-error: #7f1d1d;
  --ar-text: #f9fafb;
  --ar-text-muted: #9ca3af;
  --ar-citation-plain: #b0b7c3; /* #206 D3 — see the light-mode note */
  --ar-text-error: #fca5a5;
  --ar-disabled: #4b5563;
}

@media (prefers-color-scheme: dark) {
  #answerrails-chat-widget[data-ar-mode="auto"] {
    --ar-bg: #1f2937;
    --ar-bg-muted: #111827;
    --ar-bg-footer: #111827;
    --ar-bg-assistant: #374151;
    --ar-bg-typing: #374151;
    --ar-bg-consent: rgba(66, 55, 22, 0.95);
    --ar-bg-error: #3f1d1d;
    --ar-border: #374151;
    --ar-border-light: #2b3544;
    --ar-border-assistant: #4b5563;
    --ar-border-typing: #4b5563;
    --ar-border-error: #7f1d1d;
    --ar-text: #f9fafb;
    --ar-text-muted: #9ca3af;
    --ar-citation-plain: #b0b7c3; /* #206 D3 — see the light-mode note */
    --ar-text-error: #fca5a5;
    --ar-disabled: #4b5563;
  }
}

/* Responsive (single mobile query): full-screen DM-style takeover
   (Phase C). The open window covers the visual viewport, anchored to
   the TOP so that when the on-screen keyboard shrinks the visual
   viewport, the window bottom (the input) rises with it. --ar-vvh is
   maintained by chat-widget.js from visualViewport; 100dvh is the
   no-JS fallback. Launcher, open/close states and the header minimize
   are unchanged; drag/resize are desktop-only (handles hidden here,
   and every drag/resize/persist code path is gated by
   isMobileViewport() — inline desktop sizes are stripped on breakpoint
   crossing).
   Applies when the viewport is NARROW (portrait phones/tablets) or
   SHORT (landscape phones, ~412px tall — float/resize is useless
   there). MUST match MOBILE_MEDIA_QUERY in chat-widget.js. */
@media (max-width: 768px), (max-height: 480px) {
  .answerrails-chat-window {
    position: fixed;
    /* #90 F1: --ar-vvh-top tracks visualViewport.offsetTop — iOS pans
       the visual viewport when a USER TAP focuses the input (fixed
       elements anchor in the layout viewport, so without this the
       takeover slides out of the visible region; found in the
       final-verify device session, 2026-07-28). 0 whenever there is no
       pan; chat-widget.js maintains it per frame. */
    inset: var(--ar-vvh-top, 0px) 0 auto 0;
    width: 100vw;
    min-width: 0;
    /* #90 F5: the desktop min-height floor (400px) must not apply when
       the keyboard shrinks --ar-vvh below it — a window that refuses to
       shrink overflows its own contents into the keyboard seam
       (measured on a real iPhone 17 Pro, 2026-07-28: input.top 440 in
       a 404px-tall window). */
    min-height: 0;
    max-width: none;
    height: 100dvh;
    height: var(--ar-vvh, 100dvh);
    max-height: none;
    border: none;
    border-radius: 0;
  }

  .answerrails-resize-handle {
    display: none; /* no resize on mobile */
  }

  .answerrails-chat-header {
    cursor: default; /* no drag on mobile */
  }

  /* Mini launcher: icon/avatar only — the full pill is too wide for
     phone-class viewports (clipped off-screen when centred). The
     button's aria-label keeps the full accessible name. */
  .answerrails-launcher-body {
    display: none;
  }

  .answerrails-chat-button {
    padding: 0.7rem;
    min-height: 0;
  }

  .answerrails-chat-messages {
    gap: 10px;
    padding: 14px;
    /* #90 F5 (the actual root cause): the base 200px min-height is a
       flex floor this item cannot shrink below, so at keyboard-open
       heights the takeover's content (header + messages + consent +
       input) exceeded var(--ar-vvh) and the INPUT ROW overflowed out of
       the window's bottom edge — iOS then silently scrolled the window
       container to "reveal" the focused input (the reported jumping).
       min-height: 0 lets the transcript shrink to nothing (it scrolls
       internally); header + consent + input always fit the box. */
    min-height: 0;
    -webkit-overflow-scrolling: touch; /* legacy iOS momentum scroll */
    overscroll-behavior: contain; /* don't scroll-chain to the page behind */
  }

  .answerrails-chat-input-area {
    /* Clear the iOS home-indicator / notch safe area */
    padding-bottom: calc(var(--ar-pad-area) + env(safe-area-inset-bottom, 0px));
  }

  /* Consent notice: in normal flow ABOVE the input row. The desktop
     absolute bottom-anchored overlay sits at the takeover's bottom
     edge, under the keyboard / browser UI in short viewports —
     obscured and untappable (found 2026-07-23, landscape phone). */
  .answerrails-consent-notice {
    position: static;
    backdrop-filter: none;
    /* #90 F5: compressible at keyboard-open heights — the notice must
       never push the input row out of the window box. A third of the
       visual viewport is its ceiling; longer notices scroll within it. */
    max-height: calc(var(--ar-vvh, 100dvh) / 3);
    overflow-y: auto;
  }

  /* #120 option B: desktop parity — until consent is ticked, the input
     row and footer do not render in the takeover. Desktop hides them
     behind the absolute consent overlay; a mobile flow layout that leaves
     the input visible and tappable pre-consent lets a stray touch read as
     a consent bypass. The consent-required class is applied from first
     paint
     (#91). Bonus: the pre-consent stack is shorter, easing the F5
     keyboard-height fit. */
  .answerrails-chat-input-area.consent-required .answerrails-chat-input,
  .answerrails-chat-input-area.consent-required .answerrails-chat-footer {
    display: none;
  }

  /* #90 F5 compact mode: chat-widget.js sets .answerrails-vvh-compact
     on the widget root when --ar-vvh drops below 280px — in practice a
     landscape phone with the keyboard open (~150pt of visual viewport;
     measured on-device 2026-07-28, where the full-size header + consent
     + input stack could not fit). The header slims to one row (avatar
     and subtitle hidden, smaller action buttons — a deliberate
     touch-target compromise for a state where the alternative is an
     unusable input), and the consent ceiling tightens to a quarter. */
  #answerrails-chat-widget.answerrails-vvh-compact .answerrails-chat-avatar,
  #answerrails-chat-widget.answerrails-vvh-compact .answerrails-chat-subtitle {
    display: none;
  }

  #answerrails-chat-widget.answerrails-vvh-compact .answerrails-chat-header {
    padding: 4px var(--ar-pad-area);
  }

  #answerrails-chat-widget.answerrails-vvh-compact .answerrails-chat-title {
    font-size: 0.95rem;
  }

  #answerrails-chat-widget.answerrails-vvh-compact .answerrails-chat-minimize,
  #answerrails-chat-widget.answerrails-vvh-compact .answerrails-chat-new {
    width: 36px;
    height: 36px;
    font-size: 18px;
  }

  #answerrails-chat-widget.answerrails-vvh-compact .answerrails-consent-notice {
    max-height: calc(var(--ar-vvh, 100dvh) / 4);
    font-size: 0.8rem;
    padding: 6px var(--ar-pad-area);
  }

  #answerrails-chat-widget.answerrails-vvh-compact .answerrails-chat-input-area {
    padding-top: 6px;
  }

  /* #90 F5 ultra-compact: below 180px of visual viewport (a real phone in
     landscape with the keyboard open measures ~105pt) NO arrangement fits
     header + consent + input. The
     input always wins: chrome and transcript yield entirely while the
     keyboard owns the screen, and return the moment it closes (vv.h
     springs back and chat-widget.js drops the class). */
  #answerrails-chat-widget.answerrails-vvh-ultra .answerrails-chat-header,
  #answerrails-chat-widget.answerrails-vvh-ultra .answerrails-chat-messages,
  #answerrails-chat-widget.answerrails-vvh-ultra .answerrails-chat-footer {
    display: none;
  }

  #answerrails-chat-widget.answerrails-vvh-ultra .answerrails-consent-notice {
    max-height: 40px;
  }

  .answerrails-message-content {
    padding: 4px 10px;
  }

  .answerrails-message-text {
    font-size: 0.95rem;
  }

  .answerrails-message-sender {
    font-size: 0.8rem;
  }
}

/* --- #121 (D7): reCAPTCHA badge vs the takeover consent notice ---
   In the takeover the badge floated over the consent text (#120-B made
   the notice the bottom-most element). Google's documented allowance:
   the badge may be HIDDEN where the attribution text is shown. So:
   takeover open → badge hidden + in-window attribution visible; desktop
   → badge kept (#51 lift), attribution display:none. Same :has() pattern
   and graceful degradation as #51: a browser without :has() keeps the
   badge visible — overlap, not a compliance gap (badge + attribution
   both shown is fine; hidden badge without attribution never happens). */

.answerrails-recaptcha-attribution {
  display: none;
}

@media (max-width: 768px), (max-height: 480px) {
  #answerrails-chat-widget.is-open .answerrails-recaptcha-attribution {
    /* #120 tidy-up: now a flex child of the small-print row —
       right-aligned, no self-padding (the row inherits the input-area
       padding; the old per-block padding double-indented it). */
    display: block;
    margin-left: auto;
    text-align: right;
    padding: 0;
    font-size: 0.7rem;
    line-height: 1.35;
    color: var(--ar-text-muted);
  }

  .answerrails-recaptcha-attribution a {
    color: inherit;
    text-decoration: underline;
  }

  body:has(#answerrails-chat-widget.is-open) .grecaptcha-badge {
    visibility: hidden !important;
  }
}

/* --- Citation affordance (#206 D3) ---
   A Sources list mixes linked sources with knowledge-base entries that have
   nowhere to go. Rendered as bare text those were indistinguishable from the
   links beside them (the anchor colour comes from the host theme, so we
   cannot differentiate by styling the links). The plain ones are therefore
   marked here: muted AND italic, so the cue survives greyscale, forced
   colours and colour-blind vision — colour is never the only carrier
   (WCAG 1.4.1). The AT half of the same affordance is the visually-hidden
   "(reference)" suffix the renderer emits. */
.answerrails-citations .ar-citation-plain {
  color: var(--ar-citation-plain);
  font-style: italic;
}

/* --- Focus visibility (#122) ---
   One consistent keyboard-focus treatment across every widget control.
   Placed LAST so these rules win the cascade over earlier :focus styles
   (the input's old 12%-alpha shadow stays as decoration; the outline is
   the indicator). The launcher keeps its own white ring above — it sits
   on the accent, where an accent ring would vanish; same reason the
   header controls ring in the header text colour. */

.answerrails-chat-new:focus-visible,
.answerrails-chat-minimize:focus-visible {
  outline: 2px solid var(--ar-header-text);
  outline-offset: 2px;
}

#answerrails-send-button:focus-visible,
#answerrails-consent-checkbox:focus-visible,
.answerrails-consent-text a:focus-visible,
.answerrails-message-text a:focus-visible,
.answerrails-citations a:focus-visible,
.answerrails-chat-footer a:focus-visible {
  outline: 2px solid var(--ar-focus-border);
  outline-offset: 2px;
}

#answerrails-message-input:focus-visible {
  outline: 2px solid var(--ar-focus-border);
  outline-offset: 2px;
}

/* --- Reduced motion (#122) ---
   Blanket within the widget: no animation or transition when the visitor
   asks for reduced motion. The typing dots stay VISIBLE (state preserved,
   static); only the pulse stops. */
@media (prefers-reduced-motion: reduce) {
  #answerrails-chat-widget,
  #answerrails-chat-widget * {
    animation: none !important;
    transition: none !important;
  }
}
