/* ==========================================================================
   AI Voice Agent — Realtime Voice Widget Styles
   Floating launcher + centered glass card with a live audio-reactive
   ribbon wave, transcript, source links, and a single mic control.
   ========================================================================== */

:root {
	/* Brand tokens — matched to this site's Elementor Kit palette
	   (near-black primary, white foreground, "Now"/"Nunito Sans" fonts,
	   pill/20px radius language) rather than a generic widget theme. */
	--aiva-primary: #1e1e1e;
	--aiva-accent: #e2e2e2;
	/* Separate from --aiva-accent on purpose: the WebGL aura shader
	   (realtime-voice-widget.js _initAura) reads this at full strength as
	   its paint color, whereas --aiva-accent is only ever used diluted via
	   color-mix() elsewhere in this file. Reusing --aiva-accent there
	   washed out to a solid white circle instead of a colored glow — see
	   the comment in _initAura() for the full explanation. Set to this
	   site's actual Elementor Kit "White" system color (#FFFFFF) rather
	   than an arbitrary brand-agnostic cyan default — this site's real
	   palette is intentionally monochrome (White/Black/Gray system colors,
	   no colored accent anywhere in the Kit), so the aura now reads as a
	   soft white/silver glow consistent with that design instead of an
	   unrelated color. Override this token (not --aiva-accent) to recolor
	   the aura. */
	--aiva-aura-color: #ffffff;
	--aiva-error: #e5484d;
	--aiva-success: #22c55e;
	--aiva-radius: 20px;
	--aiva-launcher-size: 64px;
	--aiva-font-display: "Now", -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
	--aiva-font-body: "Nunito Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
}

/* ==========================================================================
   Host-site isolation reset
   --------------------------------------------------------------------------
   The widget is injected into arbitrary themes whose global rules (e.g.
   `h1 { color: … }`, `button { border: … }`, `div { border-radius: … }`,
   overlays that steal pointer-events) otherwise cascade straight into the
   widget and break its look AND its clickability.

   `all: revert` resets every element in the RESET SCOPE below to the browser
   default, cutting the theme's author styles out, WITHOUT touching anything
   outside .aiva-widget. It runs BEFORE every component rule below, so the
   widget's own styles (more specific and/or later) always win over it — it
   only ever overrides the *host theme*, never the widget itself. `revert`
   (not `unset`/`initial`) keeps the user-agent defaults, so a <button> still
   looks/behaves like a button before the widget restyles it.

   SCOPE NOTE: the reset deliberately targets the PANEL subtree only, NOT the
   launcher. The launcher (.aiva-launcher / .ava-launcher-container and their
   children) is owned by a SEPARATE stylesheet (assets/css/launcher.css),
   which is enqueued independently and whose load order relative to this file
   is not guaranteed — an `all: revert` on the launcher here could wipe that
   stylesheet's positioning and, ironically, break the very click we're
   fixing. The launcher instead gets only the pointer-events guarantee below.
   ========================================================================== */
.aiva-widget,
.aiva-widget * {
	box-sizing: border-box;
}

/* Wrapped in :where() so the whole reset has ZERO specificity — it can never
   accidentally out-rank the widget's own component rules below (many of which
   are single-class, e.g. .aiva-greeting-title). It only ever beats the host
   theme's cascade, which is the entire point.

   IMPORTANT: SVG internals (path/line/etc.) are EXCLUDED via :not(svg *).
   `all: revert` reverts an element's SVG presentation properties too — applied
   to a <path>/<line> it wiped their geometry rendering, collapsing the inline
   mic/send/close glyphs to a single dot (the mic button looked empty). The host
   theme never targets these inner nodes anyway, so there's nothing to reset
   there — scoping the reset to non-SVG-descendants keeps the icons intact while
   still neutralizing the theme on every real widget element. */
:where(.aiva-panel:not(svg *), .aiva-panel *:not(svg, svg *), .aiva-panel *::before, .aiva-panel *::after) {
	all: revert;
	box-sizing: border-box;
	margin: 0;
	font-family: inherit;
	color: inherit;
}

/* Restore the native [hidden] behavior that the `all: revert` reset above
   strips away. `all: revert` reverts `display` past the UA sheet's
   `[hidden] { display: none }` rule, so an element carrying the `hidden`
   attribute (e.g. .aiva-mic-denied-status, which is `hidden` until a real
   getUserMedia denial) was rendering as a visible empty styled box — a stray
   bordered strip during the connecting / greeting / live-voice phases. This
   re-hides ANY hidden element in the widget; !important so it also beats a
   host theme's `[hidden] { display: block }`. JS toggles `.hidden` to show it
   only when needed, which correctly overrides this via the element's own
   attribute cascade. */
.aiva-widget [hidden] {
	display: none !important;
}

/* Structural guarantees the widget can never be made unclickable by a host
   rule: the widget owns its stacking context and the launcher BUTTON always
   takes clicks. !important because a host theme's `* { pointer-events: … }`
   or a high-z overlay is exactly the failure mode we're defending against.

   Only the BUTTON gets pointer-events:auto — NOT its descendants. The robot
   launcher renders a Lottie <svg> animation on top of the button; if that
   decorative overlay captures pointer events, the click lands on the SVG and
   the button's handler (realtime-voice-widget.js) never fires — which is the
   reported "clicking the robot does nothing" bug. So every decorative child
   of the launcher is explicitly made click-through, letting the click fall
   to the button underneath. The message bubble is the one interactive child
   and re-enables itself in launcher.css where it's positioned. */
.aiva-widget {
	pointer-events: auto !important;
}
.aiva-launcher {
	pointer-events: auto !important;
	cursor: pointer !important;
}
.aiva-launcher .ava-lottie-container,
.aiva-launcher .ava-lottie-container *,
.aiva-launcher .aiva-agent-blob,
.aiva-launcher .aiva-agent-avatar-wrapper,
.aiva-launcher .aiva-agent-avatar {
	pointer-events: none !important;
}

.aiva-widget {
	font-family: var(--aiva-font-body);
	line-height: 1.4;
	z-index: 999999;
	/* Default here (not just inside the max-width:600px query below) so
	   it's always defined — the short-viewport/landscape query further
	   down is a HEIGHT query and needs this variable regardless of width.
	   window.visualViewport (initViewportHeightVar in
	   realtime-voice-widget.js) overwrites this with the real visible
	   height wherever supported; this 100vh default is only ever the
	   value in browsers without visualViewport, exactly like before. */
	--aiva-vvh: 100vh;
}

.aiva-sr-only {
	position: absolute;
	width: 1px;
	height: 1px;
	padding: 0;
	margin: -1px;
	overflow: hidden;
	clip: rect(0, 0, 0, 0);
	white-space: nowrap;
	border: 0;
}

/* ==========================================================================
   Positioning
   ========================================================================== */

.aiva-mode-floating {
	position: fixed;
	right: 24px;
	bottom: 24px;
}

.aiva-mode-inline,
.aiva-mode-preview {
	position: relative;
	display: block;
	width: 100%;
}

.aiva-mode-inline .aiva-panel,
.aiva-mode-preview .aiva-panel {
	position: relative;
	display: flex;
	opacity: 1;
	visibility: visible;
	transform: none;
	pointer-events: auto;
	width: 100%;
	height: 560px;
	max-height: none;
	inset: auto;
}

.aiva-mode-inline .aiva-launcher,
.aiva-mode-preview .aiva-launcher {
	display: none;
}

/* ==========================================================================
   Launcher
   ========================================================================== */

.aiva-launcher {
	position: relative;
	display: flex !important;
	/* !important on border/outline: host <button> rules were drawing a
	   rectangular colored border + focus outline around the whole launcher
	   (the reported red box around the avatar). The launcher chrome is drawn
	   entirely by its own children (blob/avatar/lottie), so the button element
	   must stay completely bare regardless of the theme. */
	border: none !important;
	outline: none !important;
	background: transparent !important;
	box-shadow: none !important;
	padding: 0 !important;
	align-items: center;
	justify-content: center;
	cursor: pointer !important;
	transition: opacity 0.2s ease, visibility 0.2s;
	flex-shrink: 0;
	z-index: 10;
}
/* Size/shape lock ONLY for the non-robot launchers (classic avatar + plain
   fallback circle). The ROBOT launcher (.aiva-launcher-robot-btn) is sized
   140px and kept transparent by launcher.css — it must NOT be forced to the
   64px --aiva-launcher-size or given a fill, or the robot renders tiny inside
   a black circle. host `button { width:auto !important }` is still overridden
   here for the variants that need a fixed box. */
.aiva-launcher:not(.aiva-launcher-robot-btn) {
	width: var(--aiva-launcher-size) !important;
	height: var(--aiva-launcher-size) !important;
	min-width: var(--aiva-launcher-size) !important;
	border-radius: 50% !important;
}
/* The plain fallback circle (no avatar, no robot) DOES want a solid fill +
   shadow. Scoped to exclude BOTH the agent (avatar) and robot variants. */
.aiva-launcher:not(.aiva-launcher-agent):not(.aiva-launcher-robot-btn) {
	background: var(--aiva-primary) !important;
	box-shadow: 0 12px 32px rgba(20, 20, 40, 0.25), 0 2px 8px rgba(20, 20, 40, 0.12) !important;
}
/* Kill any theme focus ring on the launcher and its interactive descendants —
   we provide our own :focus-visible treatment further down. */
.aiva-launcher:focus,
.aiva-launcher:focus-visible,
.aiva-launcher *:focus {
	outline: none !important;
}

/* Base launcher styles when not using agent UI (fallback) */
.aiva-launcher:not(.aiva-launcher-agent) {
	border-radius: 50%;
	background: var(--aiva-primary);
	color: #fff;
	box-shadow: 0 12px 32px rgba(20, 20, 40, 0.25), 0 2px 8px rgba(20, 20, 40, 0.12);
	transition: transform 0.2s ease, box-shadow 0.2s ease, opacity 0.2s ease, visibility 0.2s;
}
.aiva-launcher:not(.aiva-launcher-agent):hover {
	transform: translateY(-2px) scale(1.03);
}

/* Agent UI specific styles — sized off the same --aiva-launcher-size token
   the fallback circular launcher uses, so the mobile breakpoint's 10%
   reduction (see Responsive section) applies here too instead of leaving
   the agent launcher fixed at desktop size on small screens. */
.aiva-launcher-agent {
	width: calc(var(--aiva-launcher-size) * 1) !important;
	height: calc(var(--aiva-launcher-size) * 1) !important;
	min-width: calc(var(--aiva-launcher-size) * 1) !important;
}

/* Glow ring — same dark-glass + accent-glow language as .aiva-panel, so the
   closed launcher reads as the same surface as the card it opens rather
   than an unrelated chatbot-widget bubble. */
.aiva-agent-blob {
	display: none; /* Hide the black circle background */
}

.aiva-agent-avatar-wrapper {
	position: absolute;
	bottom: 0;
	left: 50%;
	transform: translateX(-50%);
	width: 100%;
	height: 100%;
	/* !important on shape/border: host themes were overriding border-color
	   (showing a red/pink ring instead of the clean white one) and clobbering
	   border-radius/overflow (the circular avatar rendered as a bordered
	   rectangle). These are locked so no theme rule can touch them. */
	border-radius: 50% !important;
	border: 1px solid #ffffff !important;
	box-shadow: 0 8px 24px rgba(0, 0, 0, 0.25) !important;
	outline: none !important;
	background: transparent !important;
	z-index: 2;
	overflow: hidden !important;
	pointer-events: none;
}

.aiva-agent-avatar {
	width: 100%;
	height: 100%;
	object-fit: cover !important;
	object-position: center 15%; /* Keep face centered properly without translating the box */
	transform: scale(1.1); /* Slight zoom to ensure it perfectly fills the circle */
	transform-origin: center center;
	transition: transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
	/* Host img rules (borders, radius, max-width, filters) were reshaping the
	   avatar — pin the ones that matter so it always fills the circle cleanly. */
	border: none !important;
	border-radius: 0 !important;
	max-width: none !important;
	max-height: none !important;
	pointer-events: none;
}

/* Hover effects */
.aiva-launcher-agent:hover .aiva-agent-blob {
	transform: translateX(-50%) scale(1.05);
	box-shadow:
		0 0 0 1px rgba(255, 255, 255, 0.2) inset,
		0 12px 36px rgba(0, 0, 0, 0.4),
		0 0 44px color-mix(in srgb, var(--aiva-accent) 45%, transparent);
	animation-play-state: paused;
}

.aiva-launcher-agent:hover .aiva-agent-avatar-wrapper {
	/* Just a slight scale on hover for interactivity */
	transform: translateX(-50%) scale(1.05);
	transition: transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
}

/* Message Bubble CTA */
.aiva-agent-message {
	position: absolute;
	right: 100%;
	bottom: 75px; /* Shifted even higher up as requested */
	margin-right: 4px; /* Shifted further right (closer to the avatar) */
	background: #ffffff;
	color: #111111;
	border: 1px solid rgba(0, 0, 0, 0.06);
	padding: 10px 18px;
	border-radius: 20px 20px 4px 20px; /* Classic chat bubble pointing bottom-right */
	box-shadow: 0 12px 32px rgba(0, 0, 0, 0.12), 0 4px 12px rgba(0, 0, 0, 0.05);
	font-family: inherit; /* Inherit website's font */
	font-size: 15px;
	font-weight: 500;
	white-space: nowrap;
	z-index: 3;
	opacity: 0;
	transform-origin: bottom right;
	transform: translateX(10px) translateY(5px) scale(0.95);
	pointer-events: auto; /* Make it clickable */
	cursor: pointer;
	transition: opacity 0.4s ease, transform 0.4s cubic-bezier(0.34, 1.56, 0.64, 1), box-shadow 0.2s ease;
}

.aiva-agent-message:hover {
	box-shadow: 0 16px 40px rgba(0, 0, 0, 0.18), 0 6px 16px rgba(0, 0, 0, 0.08);
	transform: translateX(0) translateY(0) scale(1.02);
}

.aiva-agent-message.is-visible {
	opacity: 1;
	transform: translateY(50%) translateX(0) scale(1);
}

.aiva-agent-message-text {
	display: inline-block;
}

/* Text slot-machine animations */
.aiva-slide-up-out {
	animation: aiva-text-slide-out 0.4s cubic-bezier(0.34, 1.56, 0.64, 1) forwards;
}

.aiva-slide-up-in {
	animation: aiva-text-slide-in 0.4s cubic-bezier(0.34, 1.56, 0.64, 1) forwards;
}

@keyframes aiva-text-slide-out {
	0% { transform: translateY(0); opacity: 1; }
	100% { transform: translateY(-15px); opacity: 0; }
}

@keyframes aiva-text-slide-in {
	0% { transform: translateY(15px); opacity: 0; }
	100% { transform: translateY(0); opacity: 1; }
}

.aiva-agent-message-text.is-fading-out {
	opacity: 0;
}

/* Focus state */
.aiva-launcher:focus-visible {
	outline: 3px solid var(--aiva-accent);
	outline-offset: 3px;
	border-radius: 12px;
}

.aiva-launcher-agent:focus-visible {
	border-radius: 50%;
}

/* Animations */
@keyframes aiva-float-blob {
	0%, 100% {
		transform: translateX(-50%) translateY(0);
	}
	50% {
		transform: translateX(-50%) translateY(-6px);
	}
}

@keyframes aiva-float-avatar {
	0%, 100% {
		transform: translateX(-50%) translateY(0);
	}
	50% {
		transform: translateX(-50%) translateY(-8px);
	}
}

/* Idle "breathing" glow on the closed launcher — echoes the aura's own
   listening/speaking pulse so the closed button previews that the panel
   behind it is alive, not a static icon. */
@keyframes aiva-glow-pulse {
	0%, 100% {
		box-shadow:
			0 0 0 1px rgba(255, 255, 255, 0.14) inset,
			0 8px 28px rgba(0, 0, 0, 0.35),
			0 0 32px color-mix(in srgb, var(--aiva-accent) 35%, transparent);
	}
	50% {
		box-shadow:
			0 0 0 1px rgba(255, 255, 255, 0.14) inset,
			0 8px 28px rgba(0, 0, 0, 0.35),
			0 0 44px color-mix(in srgb, var(--aiva-accent) 55%, transparent);
	}
}

/* Note: the launcher itself is hidden whenever a session is actually
   connecting/live (see .aiva-mode-floating.aiva-panel-open .aiva-launcher
   below — start() adds aiva-panel-open before connect() ever changes
   state), so the glow only ever needs an idle treatment above; there is no
   visible "connecting" or "speaking" launcher state to style. */
.aiva-widget[data-aiva-state="error"] .aiva-agent-blob {
	animation-play-state: paused;
	box-shadow:
		0 0 0 1px rgba(255, 255, 255, 0.18) inset,
		0 8px 28px rgba(0, 0, 0, 0.35),
		0 0 40px color-mix(in srgb, var(--aiva-error) 45%, transparent);
}

.aiva-mode-floating.aiva-panel-open .aiva-launcher {
	opacity: 0;
	visibility: hidden;
	pointer-events: none;
}

.aiva-backdrop {
	display: none; /* Hide on desktop */
	position: fixed;
	inset: 0;
	background: rgba(2, 4, 12, 0.6);
	backdrop-filter: blur(6px);
	-webkit-backdrop-filter: blur(6px);
	opacity: 0;
	visibility: hidden;
	transition: opacity 0.28s ease, visibility 0.28s;
	pointer-events: none;
}

.aiva-widget.aiva-panel-open .aiva-backdrop {
	opacity: 1;
	visibility: visible;
	pointer-events: auto;
}

/* ==========================================================================
   Panel — centered glass card
   ========================================================================== */

.aiva-panel {
	position: fixed;
	inset: auto;
	bottom: 24px;
	right: 24px;
	margin: 0;
	width: 400px;
	height: calc(100vh - 48px);
	/* dvh (dynamic viewport height) tracks the actual visible viewport,
	   shrinking when a mobile on-screen keyboard opens instead of staying
	   pinned to the pre-keyboard 100vh — this is what stops the panel from
	   visibly resizing/jumping under the visitor's message as they type.
	   Falls back to the vh line above in browsers without dvh support. */
	height: calc(100dvh - 48px);
	max-width: 94vw;
	max-height: 680px;
	/* !important on the panel's own surface: on busy/colored host backgrounds
	   (e.g. a red hero section) the theme's styles were bleeding through and
	   tinting the whole panel. Raised the primary tint to 82% and locked the
	   background/border/shape so the panel always reads as its own dark glass
	   card, independent of whatever section it floats over. */
	background:
		radial-gradient(ellipse 90% 60% at 50% 100%, color-mix(in srgb, var(--aiva-accent) 14%, transparent) 0%, transparent 60%),
		linear-gradient(180deg, color-mix(in srgb, #ffffff 12%, transparent) 0%, color-mix(in srgb, #ffffff 3%, transparent) 100%),
		color-mix(in srgb, var(--aiva-primary) 82%, transparent) !important;
	backdrop-filter: blur(28px) saturate(150%);
	-webkit-backdrop-filter: blur(28px) saturate(150%);
	color: #f4f6fb !important;
	border-radius: var(--aiva-radius) !important;
	border: 1px solid rgba(255, 255, 255, 0.16) !important;
	box-shadow:
		0 8px 32px rgba(0, 0, 0, 0.35),
		inset 0 1px 0 rgba(255, 255, 255, 0.12),
		0 0 100px color-mix(in srgb, var(--aiva-accent) 16%, transparent);
	display: flex;
	flex-direction: column;
	overflow: hidden;
	opacity: 0;
	visibility: hidden;
	transform: translateX(100%) scale(0.96); /* slide from right */
	transition: opacity 0.35s ease, transform 0.4s cubic-bezier(0.34, 1.56, 0.64, 1), visibility 0.35s;
	pointer-events: none;
}

/* Frosted-glass fallback for browsers without backdrop-filter support —
   raise the panel's own opacity so it stays legible without the blur. */
@supports not (backdrop-filter: blur(1px)) {
	.aiva-panel {
		background:
			radial-gradient(ellipse 90% 60% at 50% 100%, color-mix(in srgb, var(--aiva-accent) 16%, transparent) 0%, transparent 60%),
			radial-gradient(ellipse 120% 70% at 50% 0%, #232323 0%, #121212 55%, var(--aiva-primary) 100%);
	}
}

.aiva-widget.aiva-panel-open .aiva-panel {
	opacity: 1;
	visibility: visible;
	transform: translateX(0) scale(1);
	pointer-events: auto;
}

.aiva-panel-dots {
	position: absolute;
	inset: 0;
	background-image: radial-gradient(rgba(255, 255, 255, 0.14) 1px, transparent 1px);
	background-size: 16px 16px;
	-webkit-mask-image: radial-gradient(ellipse 90% 70% at 50% 100%, #000 0%, transparent 75%);
	mask-image: radial-gradient(ellipse 90% 70% at 50% 100%, #000 0%, transparent 75%);
	pointer-events: none;
	z-index: 0;
}

/* ==========================================================================
   Header
   ========================================================================== */

.aiva-panel-header {
	display: flex;
	align-items: center;
	justify-content: flex-end;
	padding: 18px 18px 0;
	flex-shrink: 0;
	position: relative;
	z-index: 2;
}

/* Explicit background/color (with !important) on this and .aiva-send-btn:
   theme/page-builder/cache-generated CSS on the surrounding site (e.g.
   Elementor's own generic button styles, or a critical-CSS optimizer)
   can otherwise leak in and override these to a default white button with
   an invisible white-on-white icon. Pinning the two properties that were
   actually getting clobbered is enough — no need for !important elsewhere
   in this file where no such conflict exists. */
.aiva-icon-btn {
	width: 36px !important;
	height: 36px !important;
	min-width: 36px !important;
	padding: 0 !important;
	border-radius: 50% !important;
	border: none !important;
	background: rgba(255, 255, 255, 0.08) !important;
	color: #f4f6fb !important;
	align-items: center;
	justify-content: center;
	cursor: pointer;
	transition: background 0.15s ease;
}

.aiva-icon-btn:not([hidden]) {
	display: flex;
}

.aiva-icon-btn svg {
	stroke: currentColor !important;
	fill: none !important;
	flex-shrink: 0;
}

.aiva-icon-btn:hover {
	background: rgba(255, 255, 255, 0.16) !important;
}

/* Plain mouse click leaves the button focused; without this a bright ring
   (from the :focus-visible rule below) stays around the close/mic/send
   button after every click. Reset the ring on ordinary :focus and only
   restore it via :focus-visible, which browsers reserve for genuine keyboard
   navigation — keeps the accessibility affordance without the mouse-click
   leftover. Same pattern already used for .aiva-launcher above. */
.aiva-icon-btn:focus {
	outline: none;
}

.aiva-icon-btn:focus-visible {
	outline: 2px solid #fff;
	outline-offset: 2px;
}

/* ==========================================================================
   Body: greeting, transcript, wave, sources
   ========================================================================== */

.aiva-panel-body {
	--aiva-body-inset: 28px;
	flex: 1;
	overflow-y: auto;
	/* .aiva-aura-canvas intentionally renders at 150% of .aiva-aura-stage
	   (see realtime-voice-widget.js _onAuraResize) so the glow can bleed
	   past the stage's own edges — on narrow mobile viewports that 150%
	   canvas is wider than the available panel width, which pushed this
	   flex column (and the page, in inline/preview mode) into horizontal
	   scroll. Clipping X here keeps the bleed effect intact while
	   preventing it from ever widening this container. */
	overflow-x: hidden;
	padding: 8px var(--aiva-body-inset) 0;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: space-evenly;
	gap: 16px;
	min-height: 0;
	text-align: center;
	position: relative;
	z-index: 1;
}

.aiva-greeting {
	max-width: 480px;
	/* Base state for the connecting -> connected reveal. While connecting the
	   greeting is collapsed + faded (see the [data-aiva-state="connecting"]
	   rule further down); on connect these transition back to their natural
	   values, so the aura appears to settle and the title rises in beneath it
	   with no reflow jump. transition-delay staggers it after the aura. */
	opacity: 1;
	transform: translateY(0);
	max-height: 40vh;
	transition: opacity 0.45s ease, transform 0.45s cubic-bezier(0.22, 1, 0.36, 1), max-height 0.45s ease;
	transition-delay: 0.18s;
	will-change: opacity, transform;
}

/* These are <span>s (see class-plugin.php) so host tag styles can't touch
   them; display:block + explicit sizing here restore the intended layout. */
.aiva-greeting-eyebrow {
	display: block !important;
	margin: 0 0 6px !important;
	padding: 0 !important;
	font-size: 13px !important;
	font-weight: 500 !important;
	line-height: 1.4 !important;
	color: rgba(244, 246, 251, 0.55) !important;
}

.aiva-greeting-title {
	display: block !important;
	margin: 0 !important;
	padding: 0 !important;
	font-family: var(--aiva-font-display) !important;
	font-size: clamp(20px, 4vw, 30px) !important;
	font-weight: 700 !important;
	line-height: 1.25 !important;
	color: #f4f6fb !important;
	letter-spacing: -0.01em !important;
}

/* Transcript — collapsed entirely (via the native `hidden` attribute) until
   the first message arrives; JS reveals it on first append (see req: chat
   only shown when needed). */
.aiva-transcript {
	width: 100%;
	max-width: 480px;
	flex-direction: column;
	gap: 8px;
	overflow-y: auto;
	max-height: 26vh;
}

/* Thin, theme-matched scrollbar for the two scrollable chat surfaces
   (.aiva-panel-body in voice mode, .aiva-transcript in chat mode) — covers
   every current desktop engine on both Windows and macOS:
     - Firefox: scrollbar-width/scrollbar-color (its only styling API).
     - Chrome/Edge/Opera/other Chromium, plus Safari: ::-webkit-scrollbar*.
   macOS Safari/Chrome with "Show scroll bars: When scrolling" already
   overlay a thin auto-hiding bar by OS default; these rules only take over
   the (much more common) always-visible case — Windows Chromium/Firefox,
   and macOS set to "Always show scrollbars". */
.aiva-panel-body,
.aiva-transcript {
	scrollbar-width: thin;
	/* Very subtle: a faint accent-tinted thumb on a transparent track. Kept
	   deliberately low-opacity so the bar barely registers at a glance and
	   blends into the panel; it firms up a little on hover. */
	scrollbar-color: color-mix(in srgb, var(--aiva-accent) 22%, transparent) transparent;
}

/* Ultra-slim ~2px bar. The thumb is inset via a transparent border so the
   visible pill reads even thinner and softer than the track width. */
.aiva-panel-body::-webkit-scrollbar,
.aiva-transcript::-webkit-scrollbar {
	width: 4px;
	height: 4px;
}

.aiva-panel-body::-webkit-scrollbar-track,
.aiva-transcript::-webkit-scrollbar-track {
	background: transparent;
}

.aiva-panel-body::-webkit-scrollbar-thumb,
.aiva-transcript::-webkit-scrollbar-thumb {
	/* ~2px visible pill: a 4px track minus a 1px transparent border each side.
	   Low-opacity accent tint so it's barely noticeable and blends naturally. */
	background-color: color-mix(in srgb, var(--aiva-accent) 22%, transparent);
	border-radius: 999px;
	border: 1px solid transparent;
	background-clip: padding-box;
	transition: background-color 0.2s ease;
}

.aiva-panel-body:hover::-webkit-scrollbar-thumb,
.aiva-transcript:hover::-webkit-scrollbar-thumb {
	background-color: color-mix(in srgb, var(--aiva-accent) 40%, transparent);
}

.aiva-panel-body::-webkit-scrollbar-corner,
.aiva-transcript::-webkit-scrollbar-corner {
	background: transparent;
}

/* Chat mode — once the visitor has typed a message (see
   text-widget-fallback.js), this is a real text conversation, not a voice
   call: drop the voice orbit/aura entirely and let the transcript behave
   like a normal chat list instead of a small scroll box squeezed under it. */
.aiva-widget[data-aiva-chat-mode="true"] .aiva-aura-stage {
	display: none;
}

.aiva-widget[data-aiva-chat-mode="true"] .aiva-greeting {
	display: none;
}

.aiva-widget[data-aiva-chat-mode="true"] .aiva-panel-body {
	justify-content: flex-start;
	padding-top: 16px;
}

.aiva-widget[data-aiva-chat-mode="true"] .aiva-transcript {
	max-width: none;
	max-height: none;
	flex: 1;
	width: 100%;
}

/* Voice-chat mode — set on the widget root (data-aiva-voice-chat) once the
   first message appears in a *voice* call (distinct from data-aiva-chat-mode,
   which is the typed-text path). As the spoken conversation grows the small
   capped transcript box feels cramped under the orb + greeting, so here we:
     - hide the title/subtitle,
     - drop the aura out of the flex flow and pin it as a dimmed BACKGROUND
       layer behind the chat (it keeps animating, so the glow stays visible),
     - let the transcript fill the whole panel and scroll.
   Guarded with :not([data-aiva-chat-mode="true"]) so the typed-text layout,
   which removes the aura entirely, always wins when both could apply. */
.aiva-widget[data-aiva-voice-chat="true"]:not([data-aiva-chat-mode="true"]) .aiva-greeting {
	display: none;
}

.aiva-widget[data-aiva-voice-chat="true"]:not([data-aiva-chat-mode="true"]) .aiva-panel-body {
	justify-content: flex-start;
	padding-top: 16px;
	/* Drop the position:relative it carries by default so it stops acting as
	   the containing block for the absolutely-positioned aura below — the aura
	   then anchors to the non-scrolling .aiva-panel and stays put while only
	   this column's content scrolls. Its own stacking (z-index:1) still works
	   via the flex/isolation context, keeping the chat above the aura. */
	position: static;
}

.aiva-widget[data-aiva-voice-chat="true"]:not([data-aiva-chat-mode="true"]) .aiva-aura-stage {
	/* Absolutely positioned against .aiva-panel (which is position:fixed, so it
	   is the containing block now that .aiva-panel-body is static) and centered.
	   Because it's anchored to the panel, not the scrolling body, it stays
	   fixed and centered no matter how far the chat scrolls. Small, compact,
	   1:1 so it reads as a tight blob rather than a stretched ellipse. */
	position: absolute;
	/* NB: do NOT add `inset: auto` here — as shorthand it resets top/left back
	   to auto and the aura snaps to the top-left corner instead of centering.
	   The base .aiva-aura-stage rule sets no inset, so top/left alone suffice. */
	top: 50%;
	left: 50%;
	transform: translate(-50%, -50%);
	right: auto;
	bottom: auto;
	margin: 0;
	max-width: none;
	width: 42%;
	height: auto;
	aspect-ratio: 1 / 1;
	z-index: 0;
	opacity: 0.5;
	pointer-events: none;
}

/* Drop the round clip in the background aura so it reads as the natural
   waveform blob rather than a circle. */
.aiva-widget[data-aiva-voice-chat="true"]:not([data-aiva-chat-mode="true"]) .aiva-aura-canvas {
	border-radius: 0;
}

.aiva-widget[data-aiva-voice-chat="true"]:not([data-aiva-chat-mode="true"]) .aiva-transcript {
	position: relative;
	z-index: 1;
	max-width: none;
	max-height: none;
	flex: 1;
	width: 100%;
}

.aiva-transcript:not([hidden]) {
	display: flex;
}

.aiva-message {
	max-width: 88%;
	padding: 9px 14px;
	border-radius: 16px;
	font-size: 13.5px;
	word-wrap: break-word;
	text-align: left;
	animation: aiva-msg-in 0.18s ease;
}

@keyframes aiva-msg-in {
	from { opacity: 0; transform: translateY(4px); }
	to { opacity: 1; transform: translateY(0); }
}

.aiva-message-user {
	align-self: flex-end;
	background: var(--aiva-primary);
	color: #fff;
	border-bottom-right-radius: 4px;
}

.aiva-message-agent {
	align-self: flex-start;
	background: rgba(255, 255, 255, 0.08);
	color: #f4f6fb;
	border-bottom-left-radius: 4px;
}

/* An assistant bubble that ended up with no text (e.g. a placeholder created
   only to anchor an action button, when the reply was audio-only with no
   transcript) must not show as an empty box. Once it's no longer streaming and
   has no content, collapse it. The :empty check ignores whitespace-only text
   nodes, so a bubble with a stray space still hides via the JS cleanup that
   strips the streaming class. */
.aiva-message-agent:not(.aiva-message-streaming):empty {
	display: none;
}

/* A user bubble reserved at speech-start but not yet filled with the
   transcribed text. Kept in the DOM to hold the visitor's turn *above* the
   assistant's reply (which streams in first), but visually collapsed so no
   empty box flashes while the transcription is still in flight. */
.aiva-message-user.aiva-message-pending {
	display: none;
}

.aiva-message-streaming::after {
	content: '';
	display: inline-block;
	width: 6px;
	height: 6px;
	margin-left: 4px;
	border-radius: 50%;
	background: currentColor;
	opacity: 0.6;
	animation: aiva-blink 1s ease-in-out infinite;
	vertical-align: middle;
}

@keyframes aiva-blink {
	0%, 100% { opacity: 0.2; }
	50% { opacity: 0.9; }
}

/* Center animated visual — the widget's main focal point. A self-contained
   canvas-drawn "aura" (soft glowing blobs) replaces the old ribbon wave;
   AIVoiceAgentRealtime draws into the canvas per animation frame based on
   the current state + live microphone/assistant audio amplitude. */
.aiva-aura-stage {
	position: relative;
	width: 100%;
	/* Scales with available viewport height, not just a fixed 240px, so it
	   shrinks automatically in any short-viewport situation — landscape
	   phones (see the max-height media query below) and a mobile keyboard
	   eating vertical space (--aiva-vvh, set from window.visualViewport in
	   realtime-voice-widget.js) — instead of staying full-size and forcing
	   the rest of the panel to compress or scroll around it. 18vh keeps it
	   proportional to whatever room is actually left; the two clamp bounds
	   are the original 240px ceiling and a floor small enough to stay
	   legible/tappable even in a very short landscape strip. */
	max-width: clamp(120px, 18vh, 240px);
	aspect-ratio: 1 / 1;
	flex: 0 0 auto;
	display: flex;
	align-items: center;
	justify-content: center;
	isolation: isolate;
	/* Eases the size change between the enlarged connecting aura and the normal
	   size once the title/controls reveal on connect. */
	transition: max-width 0.45s cubic-bezier(0.22, 1, 0.36, 1);
}

.aiva-aura-stage::before {
	content: "";
	position: absolute;
	inset: -30%;
	background: radial-gradient(ellipse 60% 60% at 50% 50%, color-mix(in srgb, var(--aiva-accent) 26%, transparent) 0%, transparent 70%);
	filter: blur(32px);
	opacity: 0.6;
	pointer-events: none;
	animation: aiva-glow-pulse 3.6s ease-in-out infinite;
}

@keyframes aiva-glow-pulse {
	0%, 100% { opacity: 0.45; transform: scale(0.96); }
	50% { opacity: 0.8; transform: scale(1.05); }
}

.aiva-widget[data-aiva-state="speaking"] .aiva-aura-stage::before,
.aiva-widget[data-aiva-state="listening"] .aiva-aura-stage::before {
	animation-duration: 2.2s;
}

.aiva-aura-canvas {
	position: absolute;
	top: 50%;
	left: 50%;
	transform: translate(-50%, -50%);
	width: 150%;
	height: 150%;
	display: block;
	border-radius: 50%;
	opacity: 1;
	transition: opacity 0.25s ease;
	/* Forces its own compositor layer, separate from .aiva-panel's
	   backdrop-filter raster pass — without this, several Android
	   Chrome/WebView + GPU driver combinations flatten this WebGL canvas's
	   alpha channel and paint it as an opaque white circle instead of the
	   transparent glow (see the matching comment in _initAura() in
	   realtime-voice-widget.js, which is the other half of this fix). */
	will-change: transform;
	transform-style: preserve-3d;
	isolation: isolate;
}

.aiva-widget[data-aiva-state="disconnected"] .aiva-aura-stage,
.aiva-widget[data-aiva-state="offline"] .aiva-aura-stage {
	filter: grayscale(0.85) brightness(0.6);
}

/* "Connecting…" text — shown only while the widget is fetching its
   ephemeral client secret from our own backend (POST
   {restUrl}/realtime/client-secret). The widget flips data-aiva-state to
   "listening" as soon as that call resolves (see connect() in
   realtime-voice-widget.js) — the RTCPeerConnection/SDP exchange with
   OpenAI and ICE/DTLS/SCTP negotiation that follow happen in the
   background against an already-live UI, not behind this label. */
/* "Connecting…" label. Pinned to the FOOT of the widget while connecting (aura
   animating in the center, this label at the bottom). It's a direct child of
   .aiva-panel-body (position: relative), so bottom anchors to the panel body's
   lower edge — and since the input bar is collapsed during connecting, that's
   effectively the bottom of the widget. */
.aiva-connecting-status {
	position: absolute;
	left: 50%;
	bottom: 22px;
	transform: translateX(-50%);
	font-size: 14px;
	font-weight: 500;
	color: rgba(244, 246, 251, 0.75);
	letter-spacing: 0.01em;
	opacity: 0;
	pointer-events: none;
	transition: opacity 0.25s ease;
}

@keyframes aiva-connecting-pulse {
	0%, 100% { opacity: 0.5; }
	50% { opacity: 1; }
}

/* ---- Connecting screen: only the aura (calm) + the bottom label ----
   The aura canvas stays visible while connecting but dimmed and calm; it then
   ramps to full opacity/intensity on connect (the canvas already has an
   opacity transition). The title + input bar are collapsed and faded so the
   aura is the sole, centered focus. */
/* Make the aura a bit larger while connecting — it's the sole focus of the
   screen (title/controls collapsed), so give it more presence. Scales up from
   the base clamp; the transition on .aiva-aura-stage lets it ease back down as
   the title/controls reveal on connect.
   Excludes [data-aiva-voice-chat="true"]: that flag is already set (see
   _bindControlButtons' mic-button handler in realtime-voice-widget.js) when
   reconnecting from text mode back to voice mid-conversation — the visitor
   already has a transcript/input bar on screen, so re-collapsing the whole
   panel into the bare "connecting" screen just to reveal it again a moment
   later is a jarring layout jump. That case shows a small loading spinner in
   the send button instead (data-aiva-send-mode="loading") and otherwise
   leaves the layout exactly as it was.

   ALSO excludes [data-aiva-reconnecting="true"]: set by
   _handleConnectionDropped() in realtime-voice-widget.js for a mid-call
   drop/retry — distinct from data-aiva-voice-chat because a drop can happen
   before the visitor's first message has even rendered (data-aiva-voice-chat
   isn't set yet at that point), which without this guard collapsed the
   panel-controls/greeting the same as a genuine first connect and made
   buttons appear to vanish on any early timeout. A true first-ever connect
   never has this attribute set, so it still gets the calm bare-aura screen
   below exactly as before. */
.aiva-widget[data-aiva-state="connecting"]:not([data-aiva-voice-chat="true"]):not([data-aiva-reconnecting="true"]) .aiva-aura-stage {
	max-width: clamp(160px, 26vh, 320px);
}

.aiva-widget[data-aiva-state="connecting"]:not([data-aiva-voice-chat="true"]):not([data-aiva-reconnecting="true"]) .aiva-aura-canvas {
	opacity: 0.55;
}

.aiva-widget[data-aiva-state="connecting"]:not([data-aiva-voice-chat="true"]) .aiva-connecting-status,
.aiva-widget[data-aiva-state="connecting"][data-aiva-reconnecting="true"] .aiva-connecting-status,
.aiva-widget[data-aiva-state="error"][data-aiva-reconnecting="true"] .aiva-connecting-status {
	opacity: 1;
	pointer-events: auto;
	animation: aiva-connecting-pulse 1.4s ease-in-out infinite;
}

/* Calmer, slower glow while connecting; the base 3.6s pulse already applies,
   this just dims it a touch so "connect" feels like it brightens. */
.aiva-widget[data-aiva-state="connecting"]:not([data-aiva-voice-chat="true"]):not([data-aiva-reconnecting="true"]) .aiva-aura-stage::before {
	opacity: 0.35;
}

/* Hide the title/eyebrow and the whole input bar during connecting (and the
   brief disconnected state right before it), collapsed out of layout so the
   aura is truly centered in the panel body. They animate back in (opacity +
   slide up) once the state leaves "connecting" — see the transitions on
   .aiva-greeting / .aiva-panel-controls. Including "disconnected" here means
   the panel's very first painted frame on open already has the input hidden,
   so it can never flash into view before "connecting" takes over.

   :not([data-aiva-reconnecting="true"]) throughout this block: a mid-call
   drop (see _handleConnectionDropped in realtime-voice-widget.js) can hit
   'connecting' — or even briefly 'error' once retries are exhausted — before
   the visitor's first message has rendered, i.e. before data-aiva-voice-chat
   exists to protect the layout the way it already does for a later drop.
   Without this guard the input bar/buttons/greeting collapsed on ANY early
   timeout, which read as "everything just broke." A genuine first-ever
   connect never has data-aiva-reconnecting set, so it is unaffected. */
.aiva-widget[data-aiva-state="connecting"]:not([data-aiva-voice-chat="true"]):not([data-aiva-reconnecting="true"]) .aiva-greeting,
.aiva-widget[data-aiva-state="connecting"]:not([data-aiva-voice-chat="true"]):not([data-aiva-reconnecting="true"]) .aiva-panel-controls,
.aiva-widget[data-aiva-state="disconnected"]:not([data-aiva-chat-mode="true"]):not([data-aiva-voice-chat="true"]):not([data-aiva-reconnecting="true"]) .aiva-greeting,
.aiva-widget[data-aiva-state="disconnected"]:not([data-aiva-chat-mode="true"]):not([data-aiva-voice-chat="true"]):not([data-aiva-reconnecting="true"]) .aiva-panel-controls {
	opacity: 0;
	transform: translateY(14px);
	pointer-events: none;
	/* No stagger on the way OUT — collapse immediately so the connecting
	   screen never briefly shows the old content. The stagger delay only
	   applies to the reveal (the base-rule delay), so override to 0 here. */
	transition-delay: 0s;
}

/* Kill the reveal transition entirely while the widget is CLOSED or in the
   pre-connect states, so opening the panel never animates the input bar in/out
   (the flicker). The reveal animation only runs once the widget is open AND has
   actually connected (listening/speaking/thinking), handled by the base
   .aiva-greeting / .aiva-panel-controls transitions. */
.aiva-widget:not(.aiva-panel-open) .aiva-greeting,
.aiva-widget:not(.aiva-panel-open) .aiva-panel-controls,
.aiva-widget[data-aiva-state="disconnected"]:not([data-aiva-chat-mode="true"]):not([data-aiva-voice-chat="true"]):not([data-aiva-reconnecting="true"]) .aiva-greeting,
.aiva-widget[data-aiva-state="disconnected"]:not([data-aiva-chat-mode="true"]):not([data-aiva-voice-chat="true"]):not([data-aiva-reconnecting="true"]) .aiva-panel-controls,
.aiva-widget[data-aiva-state="connecting"]:not([data-aiva-voice-chat="true"]):not([data-aiva-reconnecting="true"]) .aiva-greeting,
.aiva-widget[data-aiva-state="connecting"]:not([data-aiva-voice-chat="true"]):not([data-aiva-reconnecting="true"]) .aiva-panel-controls {
	transition: none;
}

/* Keep the greeting/controls from occupying vertical space while collapsed so
   the aura sits dead-center. max-height + margins clamp their box; the
   opacity/transform above handle the visible fade/slide. */
.aiva-widget[data-aiva-state="connecting"]:not([data-aiva-voice-chat="true"]):not([data-aiva-reconnecting="true"]) .aiva-greeting,
.aiva-widget[data-aiva-state="disconnected"]:not([data-aiva-chat-mode="true"]):not([data-aiva-reconnecting="true"]) .aiva-greeting {
	max-height: 0;
	margin: 0;
	overflow: hidden;
}

/* While connecting, the greeting/controls are collapsed to nothing, so re-
   center the aura in the body even on short viewports (where the base body
   rule switches to flex-start to reclaim space for a full conversation). */
.aiva-widget[data-aiva-state="connecting"]:not([data-aiva-voice-chat="true"]):not([data-aiva-reconnecting="true"]) .aiva-panel-body,
.aiva-widget[data-aiva-state="disconnected"]:not([data-aiva-chat-mode="true"]):not([data-aiva-voice-chat="true"]):not([data-aiva-reconnecting="true"]) .aiva-panel-body {
	justify-content: center;
}

.aiva-widget[data-aiva-state="connecting"]:not([data-aiva-voice-chat="true"]):not([data-aiva-reconnecting="true"]) .aiva-panel-controls,
.aiva-widget[data-aiva-state="disconnected"]:not([data-aiva-chat-mode="true"]):not([data-aiva-voice-chat="true"]):not([data-aiva-reconnecting="true"]) .aiva-panel-controls {
	max-height: 0;
	padding-top: 0;
	padding-bottom: 0;
	overflow: hidden;
}



.aiva-widget[data-aiva-state="error"] .aiva-aura-stage {
	animation: aiva-aura-shake 420ms ease;
}

@keyframes aiva-aura-shake {
	10%, 90% { transform: translateX(-1px); }
	20%, 80% { transform: translateX(2px); }
	30%, 50%, 70% { transform: translateX(-4px); }
	40%, 60% { transform: translateX(4px); }
}

@media (prefers-reduced-motion: reduce) {
	.aiva-aura-stage,
	.aiva-aura-stage::before,
	.aiva-aura-stage::after,
	.aiva-connecting-status {
		animation: none !important;
	}

	/* Reveal the title/controls instantly rather than sliding/fading them in —
	   the collapse-vs-shown state still changes, it just doesn't animate. */
	.aiva-greeting,
	.aiva-panel-controls {
		transition: none !important;
	}
}

/* Microphone-permission-denied notice — unlike .aiva-connecting-status this
   carries an actual explanatory sentence, so it reads as a small banner
   rather than a centered pulsing label; JS unhides it and sets its text
   only when getUserMedia rejects with NotAllowedError (see
   _handleConnectError in realtime-voice-widget.js). */
.aiva-mic-denied-status {
	/* display:block because this is now a <span> (inline by default) — it needs
	   to render as a full-width message box. The `.aiva-widget [hidden]` guard
	   still hides it (with !important) while the `hidden` attribute is present;
	   JS removes `hidden` to reveal it on a real mic denial, at which point this
	   block layout takes over. */
	display: block;
	margin: 0 0 12px;
	padding: 10px 14px;
	border-radius: calc(var(--aiva-radius) * 0.5);
	background: color-mix(in srgb, var(--aiva-error) 16%, transparent);
	border: 1px solid color-mix(in srgb, var(--aiva-error) 32%, transparent);
	color: #f4f6fb;
	font-size: 13px;
	line-height: 1.4;
	text-align: center;
}

.aiva-widget[data-aiva-state="mic-denied"] .aiva-aura-stage {
	animation: aiva-aura-shake 420ms ease;
}

/* Per-message action buttons (Call / Email / Get Directions / Book Now) —
   rendered directly under the specific chat bubble they belong to, never a
   shared panel repeated across every message. */
.aiva-message-actions {
	display: flex;
	flex-wrap: wrap;
	gap: 6px;
	margin-top: 8px;
	max-width: 88%;
	align-self: flex-start;
}

.aiva-action-btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 6px;
	/* Explicit box-model reset: the widget renders directly in the page (no
	   Shadow DOM isolation), so a theme's or page builder's generic
	   button/.button rules (larger padding, min-height, line-height) can
	   otherwise leak in and inflate this beyond the intended compact pill
	   size — pin every relevant property here instead of relying on cascade
	   order to keep it. */
	box-sizing: border-box;
	margin: 0;
	padding: 5px 12px;
	min-height: 0;
	line-height: 1.3;
	border-radius: 999px;
	background: rgba(255, 255, 255, 0.1);
	border: 1px solid rgba(255, 255, 255, 0.16);
	color: #f4f6fb;
	font-family: inherit;
	font-size: 12.5px;
	font-weight: 600;
	text-decoration: none;
	white-space: nowrap;
	cursor: pointer;
	transition: all 0.3s ease;
}

/* Matches this site's Elementor CTA buttons (e.g. "Talk to our Expert"),
   which have no custom hover state configured anywhere in the Elementor Kit
   or per-widget settings — only Elementor core's own generic default
   (color:#fff on hover/focus/visited, animated by the button's own
   transition). Reproduced literally and self-contained here so the plugin
   never depends on Elementor/theme CSS actually being present. */
.aiva-action-btn:hover,
.aiva-action-btn:focus-visible,
.aiva-action-btn:visited {
	color: #fff;
}

.aiva-action-btn:focus-visible {
	outline: 2px solid var(--aiva-accent);
	outline-offset: 2px;
}

.aiva-action-btn svg {
	width: 14px;
	height: 14px;
	flex-shrink: 0;
}

/* Per-message source accordion — collapsed by default (just the toggle
   line); clicking reveals the preview card directly under that one message
   only, instead of a single shared box repeated below every reply. */
.aiva-message-source {
	max-width: 88%;
	align-self: flex-start;
	margin-top: 6px;
}

/* Same pill shape/sizing as .aiva-action-btn (Call/Email/Directions/Book
   Now) so "View source" reads as one consistent family of buttons rather
   than a separate underlined text link. Deliberately does NOT use
   transform/translateY for its hover/active feedback (unlike
   .aiva-action-btn, which is a static link) — this is a real <button> the
   visitor repeatedly clicks to expand/collapse, so any position shift on
   press is far more noticeable here; background/border/box-shadow changes
   only, so the button never moves. */
.aiva-source-toggle {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 6px;
	box-sizing: border-box;
	margin: 0;
	padding: 5px 12px;
	min-height: 0;
	border: 1px solid rgba(255, 255, 255, 0.16);
	border-radius: 999px;
	background: rgba(255, 255, 255, 0.1);
	color: #f4f6fb;
	font-family: inherit;
	font-size: 12.5px;
	font-weight: 600;
	line-height: 1.3;
	cursor: pointer;
	text-decoration: none;
	white-space: nowrap;
	transition: background 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease;
}

.aiva-source-toggle:hover {
	background: rgba(255, 255, 255, 0.16);
	border-color: rgba(255, 255, 255, 0.28);
}

.aiva-source-toggle:active {
	background: rgba(255, 255, 255, 0.2);
	border-color: rgba(255, 255, 255, 0.32);
	box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.2);
}

.aiva-source-toggle:focus-visible {
	outline: 2px solid var(--aiva-accent);
	outline-offset: 2px;
}

/* Active/expanded state — the toggle itself (not just the chevron icon)
   reflects that the source card is open, so "View source" reads clearly as
   pressed/active rather than only relying on the rotated arrow. */
.aiva-message-source.aiva-source-expanded .aiva-source-toggle {
	background: rgba(255, 255, 255, 0.16);
	border-color: rgba(255, 255, 255, 0.28);
}

.aiva-source-toggle-icon {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	line-height: 1;
	transition: transform 0.15s ease;
}

.aiva-message-source.aiva-source-expanded .aiva-source-toggle-icon {
	transform: rotate(180deg);
}

.aiva-source-toggle-label {
	display: inline-block;
	line-height: 1.3;
}

.aiva-message-source .aiva-source-preview {
	margin-top: 8px;
	display: none;
}

.aiva-message-source.aiva-source-expanded .aiva-source-preview {
	display: flex;
}

/* Source preview card — the image area (when a featured image exists) is a
   large rectangle, not a small square thumbnail: 4:3 on desktop, capped in
   height so the card never dominates the whole panel; a shorter wide ratio
   on mobile where vertical space in the widget is tighter (see the
   responsive block below). */
.aiva-source-preview {
	flex-direction: column;
	width: 100%;
	max-width: 320px;
	min-height: 84px;
	border-radius: 16px;
	overflow: hidden;
	background: rgba(255, 255, 255, 0.06);
	border: 1px solid rgba(255, 255, 255, 0.12);
	/* Explicit color reset: this is an <a> wrapping plain <span>s with no
	   color of their own (e.g. .aiva-source-preview-label below), so
	   without this they inherit the browser's default link-blue instead of
	   the widget's dark-theme text color — set here once so every child
	   text element inherits the correct neutral color instead of blue. */
	color: #f4f6fb;
	text-align: left;
	text-decoration: none;
	transition: background 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease;
}

.aiva-source-preview:hover,
.aiva-source-preview:focus-visible {
	background: rgba(255, 255, 255, 0.1);
	border-color: rgba(255, 255, 255, 0.2);
	box-shadow: 0 6px 16px rgba(0, 0, 0, 0.18);
}

.aiva-source-preview:focus-visible {
	outline: 2px solid var(--aiva-accent);
	outline-offset: 2px;
}

.aiva-source-preview:active {
	background: rgba(255, 255, 255, 0.14);
	border-color: rgba(255, 255, 255, 0.24);
	box-shadow: 0 2px 6px rgba(0, 0, 0, 0.16);
}

.aiva-source-preview-media {
	width: 100%;
	aspect-ratio: 4 / 3;
	max-height: 220px;
	background: rgba(255, 255, 255, 0.04);
	overflow: hidden;
}

.aiva-source-preview-img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
}

.aiva-source-preview-body {
	display: flex;
	flex-direction: column;
	gap: 4px;
	padding: 14px 18px 16px;
}

.aiva-source-preview-label {
	color: #f4f6fb;
	font-size: 11px;
	text-transform: uppercase;
	letter-spacing: 0.04em;
	opacity: 0.5;
	font-weight: 600;
}

.aiva-source-preview-title {
	font-family: var(--aiva-font-display);
	font-size: 15px;
	font-weight: 700;
	color: #f4f6fb;
	line-height: 1.3;
}

/* Neutral light grey, matching the rest of the dark-theme text hierarchy —
   intentionally not var(--aiva-accent) (a link-style accent color) so this
   never reads as a blue "link" color against the dark card. */
.aiva-source-preview-url {
	font-size: 12px;
	color: #f4f6fb;
	opacity: 0.6;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

/* ==========================================================================
   Controls
   ========================================================================== */

.aiva-panel-controls {
	flex-shrink: 0;
	padding: 18px 22px 30px;
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 12px;
	position: relative;
	z-index: 1;
	/* Reveal target for the connecting -> connected transition (mirrors
	   .aiva-greeting). Revealed slightly after the title for a gentle stagger. */
	opacity: 1;
	transform: translateY(0);
	max-height: 40vh;
	transition: opacity 0.45s ease, transform 0.45s cubic-bezier(0.22, 1, 0.36, 1), max-height 0.45s ease, padding 0.45s ease;
	transition-delay: 0.26s;
	will-change: opacity, transform;
}

/* "Powered by …" footer line — now a <span> (see class-plugin.php). Previously
   had no rule, so it inherited the host theme's <p> font-size (≈23px) and
   rendered oversized. Explicit, locked sizing keeps it a small caption. */
.aiva-powered-by {
	display: block !important;
	margin: 0 !important;
	padding: 10px 0 0 !important;
	text-align: center !important;
	font-family: var(--aiva-font-body) !important;
	font-size: 12px !important;
	font-weight: 500 !important;
	line-height: 1.3 !important;
	letter-spacing: 0.01em !important;
	color: rgba(244, 246, 251, 0.5) !important;
}

/* Text fallback */
.aiva-text-fallback {
	width: 100%;
	max-width: 420px;
	display: flex;
	align-items: center;
	gap: 8px;
	background: rgba(255, 255, 255, 0.08);
	border: 1px solid rgba(255, 255, 255, 0.14);
	border-radius: 999px;
	padding: 6px 8px 6px 18px;
}

.aiva-text-input {
	flex: 1;
	min-width: 0;
	min-height: 40px;
	/* !important: host themes ship global `input { border; border-radius;
	   padding; background }` rules that were showing a grey bordered/rounded
	   box inside the composer instead of the clean borderless field. Lock the
	   field's own appearance so no theme input-reset can restyle it. */
	border: none !important;
	border-radius: 0 !important;
	background: transparent !important;
	box-shadow: none !important;
	outline: none !important;
	padding: 0 8px !important;
	margin: 0 !important;
	color: #fff !important;
	font-size: 14px !important;
	line-height: 1.4 !important;
	font-family: inherit !important;
	-webkit-appearance: none !important;
	appearance: none !important;
}

.aiva-text-input::placeholder {
	color: rgba(255, 255, 255, 0.55) !important;
}

.aiva-text-input:focus {
	outline: none !important;
	border: none !important;
	box-shadow: none !important;
}

/* Send / voice button — solid black circle, white icon (matches the design
   reference). It shows a waveform glyph while the input is empty ("voice"
   mode) and swaps to a forward arrow once the visitor has typed something
   ("send" mode); the mode is driven by data-aiva-send-mode, toggled in
   realtime-voice-widget.js. Kept explicitly black/white with !important for
   the same theme-leak reason documented on .aiva-icon-btn above. */
.aiva-send-btn {
	/* Lock the circle's box: host `button { padding; width; min-width }` resets
	   were stretching this into a white pill with an off-centre glyph. */
	width: 40px !important;
	height: 40px !important;
	min-width: 40px !important;
	padding: 0 !important;
	border: none !important;
	border-radius: 50% !important;
	background: #111 !important;
	color: #fff !important;
	flex-shrink: 0;
}

.aiva-send-btn:hover {
	background: #000 !important;
}

.aiva-send-icon {
	display: none;
	align-items: center;
	justify-content: center;
	line-height: 0;
}

.aiva-send-btn[data-aiva-send-mode="voice"] .aiva-send-icon-voice,
.aiva-send-btn[data-aiva-send-mode="arrow"] .aiva-send-icon-arrow,
.aiva-send-btn[data-aiva-send-mode="loading"] .aiva-send-icon-loading {
	display: inline-flex;
}

/* Restart mode: the voice session auto-closed (timeout/inactivity) with the
   input bar left visible (see the disconnected-state guards above) — the
   send button becomes "start a new conversation" instead of "resume this
   one," since the session behind it is already fully torn down server-side
   (closeSessionContext runs before this state is ever reached). Driven
   directly off the root's own state/mode attributes, the same way every
   other .aiva-panel-controls visibility rule in this file is — no JS needs
   to toggle data-aiva-send-mode for this case, only the click handler
   (realtime-voice-widget.js) needs to know to treat a click as "restart"
   rather than "resume" while these attributes hold. :not([data-aiva-chat-
   mode="true"]) — a typed conversation's send button keeps its normal
   arrow/voice behavior; only a voice conversation's auto-close gets this
   treatment, matching the collapse guard's own scope. */
.aiva-widget[data-aiva-state="disconnected"][data-aiva-voice-chat="true"]:not([data-aiva-chat-mode="true"]) .aiva-send-btn .aiva-send-icon-restart {
	display: inline-flex;
}
.aiva-widget[data-aiva-state="disconnected"][data-aiva-voice-chat="true"]:not([data-aiva-chat-mode="true"]) .aiva-send-btn .aiva-send-icon-voice,
.aiva-widget[data-aiva-state="disconnected"][data-aiva-voice-chat="true"]:not([data-aiva-chat-mode="true"]) .aiva-send-btn .aiva-send-icon-arrow,
.aiva-widget[data-aiva-state="disconnected"][data-aiva-voice-chat="true"]:not([data-aiva-chat-mode="true"]) .aiva-send-btn .aiva-send-icon-loading {
	display: none;
}

/* Manual details fallback — the "Prefer to type your details?" link and the
   form it reveals. Always available (not conditioned on voice/call state)
   since its whole point is working when speech capture isn't. */
.aiva-manual-details-toggle {
	all: unset;
	cursor: pointer;
	width: 100%;
	max-width: 420px;
	text-align: center;
	font-family: var(--aiva-font-body) !important;
	font-size: 12.5px !important;
	font-weight: 500 !important;
	color: rgba(244, 246, 251, 0.55) !important;
	padding: 2px 0 !important;
	transition: color 0.15s ease;
}

.aiva-manual-details-toggle:hover,
.aiva-manual-details-toggle:focus-visible {
	color: rgba(244, 246, 251, 0.9) !important;
	text-decoration: underline;
}

.aiva-manual-details-form {
	width: 100%;
	max-width: 420px;
	display: flex;
	flex-direction: column;
	gap: 8px;
	background: rgba(255, 255, 255, 0.06);
	border: 1px solid rgba(255, 255, 255, 0.14);
	border-radius: 16px;
	padding: 14px 14px 12px;
}

.aiva-manual-details-form[hidden] {
	display: none;
}

.aiva-manual-details-header {
	display: flex;
	align-items: center;
	justify-content: space-between;
	font-family: var(--aiva-font-body) !important;
	font-size: 13px !important;
	font-weight: 600 !important;
	color: rgba(244, 246, 251, 0.85) !important;
	margin-bottom: 2px;
}

.aiva-manual-details-close {
	width: 24px !important;
	height: 24px !important;
	min-width: 24px !important;
	padding: 0 !important;
	border: none !important;
	border-radius: 50% !important;
	background: transparent !important;
	color: rgba(244, 246, 251, 0.6) !important;
}

.aiva-manual-details-close:hover {
	background: rgba(255, 255, 255, 0.1) !important;
	color: #fff !important;
}

.aiva-manual-details-input {
	width: 100% !important;
	box-sizing: border-box !important;
	border: 1px solid rgba(255, 255, 255, 0.14) !important;
	border-radius: 10px !important;
	background: rgba(255, 255, 255, 0.06) !important;
	color: #fff !important;
	font-size: 13.5px !important;
	font-family: inherit !important;
	padding: 9px 12px !important;
	outline: none !important;
	box-shadow: none !important;
	-webkit-appearance: none !important;
	appearance: none !important;
}

.aiva-manual-details-input::placeholder {
	color: rgba(255, 255, 255, 0.45) !important;
}

.aiva-manual-details-input:focus {
	border-color: rgba(255, 255, 255, 0.35) !important;
}

.aiva-manual-details-textarea {
	resize: vertical !important;
	min-height: 56px !important;
	line-height: 1.4 !important;
}

.aiva-manual-details-status {
	min-height: 16px;
	font-family: var(--aiva-font-body) !important;
	font-size: 12px !important;
	color: var(--aiva-success) !important;
}

.aiva-manual-details-status-error {
	color: var(--aiva-error) !important;
}

.aiva-manual-details-submit {
	width: 100% !important;
	border: none !important;
	border-radius: 10px !important;
	background: #111 !important;
	color: #fff !important;
	font-size: 13.5px !important;
	font-weight: 600 !important;
	font-family: inherit !important;
	padding: 10px !important;
	cursor: pointer;
	transition: background 0.15s ease, opacity 0.15s ease;
}

.aiva-manual-details-submit:hover {
	background: #000 !important;
}

.aiva-manual-details-submit:disabled {
	opacity: 0.6;
	cursor: default;
}

@keyframes aiva-spin {
	0% { transform: rotate(0deg); }
	100% { transform: rotate(360deg); }
}
.aiva-spinner {
	animation: aiva-spin 1s linear infinite;
}

/* Mic mute/unmute button — white circle with a dark outline mic by default
   (unmuted). When muted (data-aiva-muted="true") it turns solid red with a
   white slashed-mic glyph. Sits between the input and the send button.
   Default = unmuted. Hidden entirely in chat/text mode (see the
   data-aiva-chat-mode rule below). */
.aiva-mic-btn {
	width: 40px !important;
	height: 40px !important;
	min-width: 40px !important;
	padding: 0 !important;
	border: none !important;
	border-radius: 50% !important;
	background: #fff !important;
	color: #1a1a1a !important;
	flex-shrink: 0;
}

.aiva-mic-btn:hover {
	background: #f0f0f0 !important;
}

.aiva-mic-icon {
	display: none;
	align-items: center;
	justify-content: center;
	line-height: 0;
}

.aiva-mic-btn[data-aiva-muted="false"] .aiva-mic-icon-on,
.aiva-mic-btn[data-aiva-muted="true"] .aiva-mic-icon-off {
	display: inline-flex;
}

/* Lock the inline icon SVGs' size + stroke. Host themes ship global
   `svg { width: auto }` / `img, svg { max-width: 100% }` / `svg { stroke-width }`
   rules that were collapsing these glyphs to 0×0 (the mic button showed only a
   broken stray line, the icon invisible). The SVGs carry width/height/stroke
   attributes, but those lose to a host CSS rule — so pin them here. Covers the
   mic, send, and header/close icon buttons in one place. */
.aiva-mic-btn svg,
.aiva-send-btn svg,
.aiva-icon-btn svg {
	width: 20px !important;
	height: 20px !important;
	min-width: 20px !important;
	max-width: none !important;
	max-height: none !important;
	stroke-width: 1.8px !important;
	flex-shrink: 0 !important;
	display: block !important;
	/* Re-assert stroke/fill HERE (not only on .aiva-icon-btn svg above): this
	   is the last, size-locking rule that touches these glyphs, so a host
	   theme's global `svg { stroke: none }` / `path { fill: currentColor }`
	   was winning over line 563 and collapsing the mic/send glyph to nothing
	   (the button showed as an empty circle). Pinning them here keeps the
	   1.8px outline icons visible regardless of the surrounding site's CSS. */
	stroke: currentColor !important;
	fill: none !important;
	visibility: visible !important;
	opacity: 1 !important;
}

/* The inner primitives of the outline icons must also stay stroked, never
   filled — a host `path, line, polyline { fill: currentColor }` (common in
   icon-font resets) would otherwise flood the mic/send glyph solid or hide it.
   Scoped to the widget's own control SVGs so nothing else on the page is
   affected. */
.aiva-mic-btn svg :where(path, line, polyline, circle),
.aiva-send-btn svg :where(path, line, polyline, circle),
.aiva-icon-btn svg :where(path, line, polyline, circle) {
	stroke: currentColor !important;
	fill: none !important;
	stroke-width: 1.8px !important;
	vector-effect: non-scaling-stroke;
}

.aiva-mic-btn[data-aiva-muted="true"] {
	background: #e5484d !important;
	color: #fff !important;
}

.aiva-mic-btn[data-aiva-muted="true"]:hover {
	background: #d93a3f !important;
}

/* The mic mute button is only meaningful during a live voice call, so it is
   shown ONLY in the voice-active states (connecting/listening/thinking/
   speaking) and hidden everywhere else — including chat/text mode
   (data-aiva-chat-mode, set by text-widget-fallback.js the moment the visitor
   types) and the disconnected/offline/error states. Because it keys off the
   live data-aiva-state, it correctly reappears if the widget returns to a
   voice call. Hidden by default; each voice state re-shows it below. */
.aiva-mic-btn {
	display: none !important;
}

.aiva-widget[data-aiva-state="connecting"] .aiva-mic-btn,
.aiva-widget[data-aiva-state="listening"] .aiva-mic-btn,
.aiva-widget[data-aiva-state="thinking"] .aiva-mic-btn,
.aiva-widget[data-aiva-state="speaking"] .aiva-mic-btn {
	display: inline-flex !important;
}

.aiva-widget[data-aiva-chat-mode="true"] .aiva-mic-btn {
	display: inline-flex !important;
	background: #fff !important;
	color: #1a1a1a !important;
}
.aiva-widget[data-aiva-chat-mode="true"] .aiva-mic-btn .aiva-mic-icon-on {
	display: inline-flex !important;
}
.aiva-widget[data-aiva-chat-mode="true"] .aiva-mic-btn .aiva-mic-icon-off {
	display: none !important;
}

/* ==========================================================================
   Responsive
   ========================================================================== */

@media (max-width: 600px) {
	.aiva-backdrop {
		display: block; /* Restore on mobile */
	}

	.aiva-panel {
		/* Centered modal on mobile: margin:auto only distributes slack space
		   when all four inset edges are pinned to 0 - leaving right/bottom as
		   auto (as this previously did) gives margin:auto nothing to split,
		   so the panel just sits pinned to the top-left corner instead. */
		inset: 0;
		margin: auto;
		width: min(94vw, 480px);
		height: min(80vh, 740px);
		max-width: 94vw;
		max-height: 80vh;
		transform: translateY(40px) scale(0.96); /* slide from bottom */
	}

	@supports ( height: 100dvh ) {
		/* Same dvh rationale as the desktop .aiva-panel rule above — on
		   mobile this is the rule that actually matters, since this is the
		   breakpoint active while a visitor is typing into the on-screen
		   keyboard. min()/max() don't support mixed vh/dvh cleanly across
		   engines yet, so this is gated behind @supports and repeats the
		   min() with dvh substituted rather than trying to mix units. */
		.aiva-panel {
			height: min(80dvh, 740px);
			max-height: 80dvh;
		}
	}

	/* Strongest override: --aiva-vvh (defaulted at the top of this file,
	   overwritten from window.visualViewport.height by
	   initViewportHeightVar() in realtime-voice-widget.js wherever
	   supported) is the one signal that reliably reflects the space
	   actually left after a mobile on-screen keyboard opens — dvh's
	   keyboard behavior is inconsistent enough across engines (iOS Safari
	   in particular: the layout viewport doesn't shrink on keyboard-open,
	   only the visual one does) that it isn't sufficient alone. */
	.aiva-panel {
		height: min(80vh, 740px, calc(var(--aiva-vvh) * 0.8));
		max-height: min(80vh, calc(var(--aiva-vvh) * 0.8));
	}

	.aiva-widget.aiva-panel-open .aiva-panel {
		transform: translateY(0) scale(1);
	}

	.aiva-widget {
		/* 10% smaller than the desktop 64px launcher (Task: reduce mic
		   launcher size on mobile) — overridden only inside this breakpoint
		   so desktop is untouched. */
		--aiva-launcher-size: 57.6px;
	}

	.aiva-launcher-agent {
		/* Overwrite the desktop 1.25 multiplier to shrink the massive avatar on mobile */
		width: calc(var(--aiva-launcher-size) * 1.0);
		height: calc(var(--aiva-launcher-size) * 1.0);
	}

	.aiva-agent-message {
		/* Scale down the message bubble and tuck it closer */
		padding: 10px 14px;
		font-size: 13px;
		margin-right: 0px;
		bottom: 65px;
	}

	.aiva-panel-body {
		--aiva-body-inset: 18px;
		padding-top: 0;
		gap: 14px;
	}

	.aiva-greeting-title {
		font-size: clamp(18px, 6vw, 24px);
	}

	.aiva-panel-controls {
		padding: 14px 16px 26px;
	}

	/* Wider/shorter than the desktop 4:3 crop — mobile widget height is
	   more constrained, so the image trades some vertical presence for
	   more room for the transcript/status below it. */
	.aiva-source-preview-media {
		aspect-ratio: 16 / 9;
		max-height: 160px;
	}
}

/* ==========================================================================
   Short viewport (landscape phones, and a very reduced height once a
   mobile keyboard is open) — a HEIGHT query, deliberately independent of
   the max-width: 600px query above: a landscape phone is commonly
   600-900px wide but only ~320-420px tall, so the width query alone never
   fires there and the panel was falling back to the desktop sizing (up to
   680px tall, fixed paddings/gaps) on a viewport nowhere near that tall.
   CSS-only, no JS involved — this reflows purely from the viewport
   itself, and layers on top of (doesn't replace) the --aiva-vvh keyboard
   handling above, which already shrinks .aiva-panel's outer height; this
   query additionally shrinks what's *inside* it so short viewports get a
   proportionally tightened layout instead of the same fixed-size content
   scrolling inside a shorter box.
   ========================================================================== */
@media (max-height: 500px) {
	.aiva-panel {
		/* Nearly the full short viewport, not a fixed vh/px budget sized
		   for portrait — 8px top/bottom breathing room is enough once the
		   panel is this short. */
		height: min(calc(100dvh - 16px), calc(var(--aiva-vvh, 100vh) - 16px));
		max-height: none;
	}

	.aiva-panel-header {
		padding: 10px 14px 0;
	}

	.aiva-panel-body {
		--aiva-body-inset: 16px;
		gap: 8px;
		padding-top: 4px;
		/* justify-content: space-evenly (the base rule) fights for space
		   it doesn't have once every element is already shrunk as far as
		   it usefully can go — flex-start plus the tightened gap above
		   lets the body scroll cleanly (see the shared scrollbar styling)
		   instead of stretching gaps to fill a height that isn't there. */
		justify-content: flex-start;
	}

	.aiva-greeting-eyebrow {
		margin: 0 0 2px;
	}

	.aiva-greeting-title {
		font-size: clamp(16px, 4vh, 22px);
	}

	.aiva-transcript {
		max-height: 40vh;
	}

	.aiva-panel-controls {
		padding: 8px 16px 12px;
		gap: 6px;
	}

	.aiva-text-input {
		min-height: 34px;
	}

	.aiva-send-btn,
	.aiva-icon-btn {
		width: 32px;
		height: 32px;
	}
}

/* ==========================================================================
   Cases, Products & Select Chips
   ========================================================================== */
.aiva-select-chips {
	display: flex;
	flex-wrap: wrap;
	gap: 6px;
	margin-top: 8px;
	margin-bottom: 8px;
	justify-content: center;
	width: 100%;
}

.aiva-select-chip {
	background: rgba(255, 255, 255, 0.08) !important;
	border: 1px solid rgba(255, 255, 255, 0.16) !important;
	border-radius: 16px !important;
	color: #f4f6fb !important;
	padding: 6px 14px !important;
	font-size: 13px !important;
	cursor: pointer;
	transition: background 0.2s, border-color 0.2s;
}

.aiva-select-chip:hover {
	background: rgba(255, 255, 255, 0.18) !important;
	border-color: rgba(255, 255, 255, 0.3) !important;
}

/* Case Card UI */
.aiva-case-card {
	background: rgba(255, 255, 255, 0.04);
	border: 1px solid rgba(255, 255, 255, 0.1);
	border-radius: 12px;
	padding: 12px;
	margin-top: 8px;
	text-align: left;
	width: 100%;
}

.aiva-case-card-header {
	display: flex;
	justify-content: space-between;
	align-items: center;
	margin-bottom: 6px;
}

.aiva-case-card-title {
	font-weight: 600;
	font-size: 14px;
	color: #ffffff;
}

.aiva-case-card-badge {
	border-radius: 12px;
	padding: 2px 8px;
	font-size: 11px;
	font-weight: 600;
	text-transform: uppercase;
}

.aiva-case-badge-new {
	background: #1d4ed8;
	color: #ffffff;
}

.aiva-case-badge-progress {
	background: #ea580c;
	color: #ffffff;
}

.aiva-case-badge-closed {
	background: #16a34a;
	color: #ffffff;
}

.aiva-case-card-desc {
	font-size: 12px;
	color: rgba(255, 255, 255, 0.7);
}

/* Product Card UI */
.aiva-products-container {
	display: flex;
	flex-direction: column;
	gap: 8px;
	width: 100%;
	margin-top: 8px;
}

.aiva-product-card {
	background: rgba(255, 255, 255, 0.04);
	border: 1px solid rgba(255, 255, 255, 0.1);
	border-radius: 12px;
	padding: 12px;
	text-align: left;
	display: flex;
	flex-direction: column;
	gap: 6px;
}

.aiva-product-title {
	font-weight: 600;
	font-size: 14px;
	color: #ffffff;
}

.aiva-product-price {
	font-size: 13px;
	font-weight: 700;
	color: #38bdf8;
}

.aiva-product-desc {
	font-size: 12px;
	color: rgba(255, 255, 255, 0.7);
}

/* ==========================================================================
   Interactive input components (FIELD / CONFIRM / OPTIONS) — mid-call
   structured input the AI can request instead of (or alongside) asking
   aloud. Same dark-glass card language as .aiva-case-card/.aiva-product-card
   above so a visitor sees one consistent UI vocabulary, not three styles.
   ========================================================================== */
.aiva-interactive {
	background: rgba(255, 255, 255, 0.04);
	border: 1px solid rgba(255, 255, 255, 0.1);
	border-radius: 12px;
	padding: 12px;
	margin-top: 8px;
	text-align: left;
	width: 100%;
	display: flex;
	flex-direction: column;
	gap: 8px;
}

/* A control that has already been answered (or gone stale because a newer
   response started) dims in place rather than disappearing — the visitor
   can still see what was asked and what they answered, they just can't
   interact with it again. Matches _attachInteractiveComponent's settle()/
   _disableStaleInteractiveComponents(), which disable the inner
   inputs/buttons at the same moment this attribute is set. */
.aiva-interactive[data-aiva-answered="true"],
.aiva-interactive[data-aiva-stale="true"] {
	opacity: 0.55;
}

.aiva-field-label {
	font-size: 13px;
	font-weight: 600;
	color: #f4f6fb;
}

.aiva-field-row {
	display: flex;
	gap: 8px;
	align-items: center;
}

.aiva-field-input {
	flex: 1;
	min-width: 0;
	background: rgba(255, 255, 255, 0.06);
	border: 1px solid rgba(255, 255, 255, 0.16);
	border-radius: 10px;
	color: #f4f6fb;
	padding: 8px 12px;
	font-size: 14px;
}

.aiva-field-input:focus {
	outline: none;
	border-color: rgba(56, 189, 248, 0.6);
}

.aiva-field-input:disabled {
	opacity: 0.6;
}

.aiva-field-submit {
	flex-shrink: 0;
	background: #38bdf8;
	border: none;
	border-radius: 10px;
	color: #06202b;
	font-weight: 600;
	font-size: 13px;
	padding: 8px 14px;
	cursor: pointer;
	transition: background 0.2s, opacity 0.2s;
}

.aiva-field-submit:hover:not(:disabled) {
	background: #5fd0fb;
}

.aiva-field-submit:disabled {
	opacity: 0.4;
	cursor: not-allowed;
}

.aiva-confirm-buttons,
.aiva-options-list {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
}

.aiva-confirm-btn {
	border-radius: 16px;
	padding: 8px 20px;
	font-size: 13px;
	font-weight: 600;
	border: 1px solid rgba(255, 255, 255, 0.16);
	cursor: pointer;
	transition: background 0.2s, border-color 0.2s;
}

.aiva-confirm-btn-yes {
	background: rgba(34, 197, 94, 0.18);
	color: #86efac;
	border-color: rgba(34, 197, 94, 0.4);
}

.aiva-confirm-btn-yes:hover:not(:disabled) {
	background: rgba(34, 197, 94, 0.3);
}

.aiva-confirm-btn-no {
	background: rgba(255, 255, 255, 0.06);
	color: #f4f6fb;
}

.aiva-confirm-btn-no:hover:not(:disabled) {
	background: rgba(255, 255, 255, 0.14);
}

.aiva-confirm-btn:disabled,
.aiva-options-list .aiva-select-chip:disabled {
	opacity: 0.5;
	cursor: not-allowed;
}
