/*
 * AI chat widget.
 *
 * A port of the Next.js prototype's floating chat (FloatingChatButton +
 * AIConversationalForm + ChatPricingCard) to plain CSS. Geometry follows the
 * original: a round launcher bottom-right, a 420x600 popover above it on
 * desktop, and a full-height sheet on phones.
 *
 * Colours come from the theme's own custom properties, so the widget follows
 * light and dark mode without a second set of rules. The fallbacks matter:
 * the widget also renders on pages that load before the theme stylesheet.
 */

.kaiyi-chat {
	--kc-chat-primary: var(--theme-color-primary, #5eff14);
	--kc-chat-on-primary: var(--theme-color-text, #000);
	--kc-chat-surface: var(--theme-color-surface, #fff);
	--kc-chat-surface-muted: var(--theme-color-surface-muted, #fafafa);
	--kc-chat-text: var(--theme-color-text, #000);
	--kc-chat-muted: var(--theme-color-text-muted, rgba(0, 0, 0, .68));
	--kc-chat-border: var(--theme-color-border, #ececec);
	--kc-chat-danger: var(--theme-color-danger, #ef4444);
	--kc-chat-radius: 18px;

	position: fixed;
	right: 20px;
	bottom: 20px;
	z-index: 90;
	display: flex;
	flex-direction: column;
	align-items: flex-end;
	gap: 14px;
	pointer-events: none;
}

.kaiyi-chat * {
	box-sizing: border-box;
}

/* ---------------------------------------------------------------- launcher */

.kaiyi-chat__launcher {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 56px;
	height: 56px;
	padding: 0;
	border: 0;
	border-radius: 50%;
	background: var(--kc-chat-primary);
	color: var(--kc-chat-on-primary);
	cursor: pointer;
	pointer-events: auto;
	transition: transform .2s ease, opacity .2s ease;
}

.kaiyi-chat__launcher:hover {
	transform: translateY(-2px);
}

.kaiyi-chat__launcher:active {
	transform: scale(.96);
}

.kaiyi-chat__launcher svg {
	width: 24px;
	height: 24px;
}

.kaiyi-chat[data-open="true"] .kaiyi-chat__launcher {
	opacity: 0;
	pointer-events: none;
}

/* ------------------------------------------------------------------- panel */

.kaiyi-chat__panel {
	display: flex;
	flex-direction: column;
	width: 420px;
	height: 600px;
	max-height: 80vh;
	overflow: hidden;
	border: 1px solid var(--kc-chat-border);
	border-radius: var(--kc-chat-radius);
	background: var(--kc-chat-surface);
	color: var(--kc-chat-text);
	opacity: 0;
	transform: translateY(16px) scale(.96);
	visibility: hidden;
	pointer-events: none;
	transition: opacity .25s ease, transform .25s ease, visibility .25s;
}

.kaiyi-chat[data-open="true"] .kaiyi-chat__panel {
	opacity: 1;
	transform: none;
	visibility: visible;
	pointer-events: auto;
}

.kaiyi-chat__header {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 12px;
	flex: 0 0 auto;
	padding: 16px 18px;
	border-bottom: 1px solid var(--kc-chat-border);
}

.kaiyi-chat__title {
	margin: 0;
	font-size: 16px;
	font-weight: 700;
	line-height: 1.4;
}

.kaiyi-chat__close {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 32px;
	height: 32px;
	padding: 0;
	border: 0;
	border-radius: 50%;
	background: transparent;
	color: inherit;
	cursor: pointer;
}

.kaiyi-chat__close:hover {
	background: var(--kc-chat-surface-muted);
}

.kaiyi-chat__close svg {
	width: 18px;
	height: 18px;
}

/* ---------------------------------------------------------------- messages */

.kaiyi-chat__log {
	flex: 1 1 auto;
	overflow-y: auto;
	overscroll-behavior: contain;
	padding: 18px;
	display: flex;
	flex-direction: column;
	gap: 12px;
}

.kaiyi-chat__msg {
	max-width: 85%;
	padding: 11px 14px;
	border-radius: 16px;
	font-size: 15px;
	line-height: 1.7;
	word-break: break-word;
}

.kaiyi-chat__msg p {
	margin: 0 0 8px;
}

.kaiyi-chat__msg p:last-child {
	margin-bottom: 0;
}

.kaiyi-chat__msg a {
	color: inherit;
	text-decoration: underline;
}

.kaiyi-chat__msg--user {
	align-self: flex-end;
	background: var(--kc-chat-primary);
	color: var(--kc-chat-on-primary);
	border-bottom-right-radius: 4px;
}

.kaiyi-chat__msg--assistant {
	align-self: flex-start;
	background: var(--kc-chat-surface-muted);
	border: 1px solid var(--kc-chat-border);
	border-bottom-left-radius: 4px;
}

/* System notices are the widget talking, not the model — visually distinct so
   an error is never mistaken for an answer. */
.kaiyi-chat__msg--system {
	align-self: center;
	max-width: 100%;
	background: transparent;
	color: var(--kc-chat-muted);
	font-size: 13px;
	text-align: center;
}

.kaiyi-chat__typing {
	align-self: flex-start;
	display: inline-flex;
	gap: 5px;
	padding: 14px;
	border: 1px solid var(--kc-chat-border);
	border-radius: 16px;
	background: var(--kc-chat-surface-muted);
}

.kaiyi-chat__typing span {
	width: 7px;
	height: 7px;
	border-radius: 50%;
	background: var(--kc-chat-muted);
	animation: kaiyi-chat-bounce 1.3s infinite ease-in-out;
}

.kaiyi-chat__typing span:nth-child(2) { animation-delay: .16s; }
.kaiyi-chat__typing span:nth-child(3) { animation-delay: .32s; }

@keyframes kaiyi-chat-bounce {
	0%, 60%, 100% { transform: translateY(0); opacity: .45; }
	30%           { transform: translateY(-5px); opacity: 1; }
}

/* -------------------------------------------------------------------- card */

.kaiyi-chat__card {
	width: 100%;
	max-width: 320px;
	margin: 12px 0 0;
	overflow: hidden;
	border: 1px solid var(--kc-chat-border);
	border-radius: 16px;
	background: var(--kc-chat-surface);
}

.kaiyi-chat__card-media {
	display: block;
	width: 100%;
	height: 150px;
	object-fit: cover;
	background: var(--kc-chat-surface-muted);
}

.kaiyi-chat__card-body {
	padding: 16px;
}

.kaiyi-chat__card-title {
	margin: 0 0 8px;
	font-size: 17px;
	font-weight: 700;
	line-height: 1.4;
}

.kaiyi-chat__card-price {
	margin: 0;
	font-size: 26px;
	font-weight: 800;
	line-height: 1.2;
}

.kaiyi-chat__card-sub,
.kaiyi-chat__card-desc {
	margin: 6px 0 0;
	color: var(--kc-chat-muted);
	font-size: 13px;
	line-height: 1.7;
}

.kaiyi-chat__card-cta {
	display: block;
	width: 100%;
	margin-top: 14px;
	padding: 12px 16px;
	border: 0;
	border-radius: 12px;
	background: var(--kc-chat-primary);
	color: var(--kc-chat-on-primary);
	font: inherit;
	font-weight: 700;
	text-align: center;
	text-decoration: none;
	cursor: pointer;
}

/* ------------------------------------------------------------------- input */

.kaiyi-chat__form {
	flex: 0 0 auto;
	display: flex;
	align-items: flex-end;
	gap: 8px;
	padding: 12px 14px;
	border-top: 1px solid var(--kc-chat-border);
}

.kaiyi-chat__input {
	flex: 1 1 auto;
	max-height: 120px;
	min-height: 42px;
	padding: 10px 14px;
	overflow-y: auto;
	border: 1px solid var(--kc-chat-border);
	border-radius: 21px;
	background: var(--kc-chat-surface-muted);
	color: inherit;
	font: inherit;
	font-size: 15px;
	line-height: 1.5;
	resize: none;
}

.kaiyi-chat__input:focus {
	outline: 2px solid var(--kc-chat-primary);
	outline-offset: -1px;
}

.kaiyi-chat__send {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	flex: 0 0 auto;
	width: 42px;
	height: 42px;
	padding: 0;
	border: 0;
	border-radius: 50%;
	background: var(--kc-chat-primary);
	color: var(--kc-chat-on-primary);
	cursor: pointer;
}

.kaiyi-chat__send[disabled] {
	opacity: .4;
	cursor: not-allowed;
}

.kaiyi-chat__send svg {
	width: 18px;
	height: 18px;
}

.kaiyi-chat__counter {
	padding: 0 14px 10px;
	color: var(--kc-chat-muted);
	font-size: 12px;
	text-align: right;
}

/* -------------------------------------------------------------- login gate */

.kaiyi-chat__gate {
	display: flex;
	flex: 1 1 auto;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 12px;
	padding: 32px 24px;
	text-align: center;
}

.kaiyi-chat__gate p {
	margin: 0;
	color: var(--kc-chat-muted);
	font-size: 15px;
	line-height: 1.7;
}

.kaiyi-chat__gate-cta {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-height: 44px;
	padding: 10px 22px;
	border-radius: 999px;
	background: var(--kc-chat-primary);
	color: var(--kc-chat-on-primary);
	font-weight: 700;
	text-decoration: none;
}

/* ------------------------------------------------------------------ mobile */

@media (max-width: 640px) {
	.kaiyi-chat {
		right: 16px;
		bottom: 16px;
	}

	/* Full sheet rather than a popover: a 420px card does not fit, and dvh
	   keeps the input above the browser chrome when the keyboard opens. */
	.kaiyi-chat__panel {
		position: fixed;
		inset: 0;
		width: 100%;
		height: 100dvh;
		max-height: none;
		border: 0;
		border-radius: 0;
	}

	.kaiyi-chat__msg {
		max-width: 90%;
	}
}

@media (prefers-reduced-motion: reduce) {
	.kaiyi-chat__launcher,
	.kaiyi-chat__panel,
	.kaiyi-chat__typing span {
		transition: none;
		animation: none;
	}
}

/* --------------------------------------------------------------- identity */

.kaiyi-chat__identity {
	display: flex;
	align-items: center;
	gap: 10px;
	min-width: 0;
}

.kaiyi-chat__avatar {
	flex: 0 0 auto;
	width: 40px;
	height: 40px;
	object-fit: cover;
	border-radius: 50%;
	background: var(--kc-chat-surface-muted);
}

.kaiyi-chat__identity-text {
	min-width: 0;
}

.kaiyi-chat__presence {
	display: flex;
	align-items: center;
	gap: 6px;
	margin: 2px 0 0;
	color: var(--kc-chat-muted);
	font-size: 12px;
	line-height: 1.2;
}

/* The dot is the status; the word beside it is for anyone who cannot see it. */
.kaiyi-chat__presence::before {
	content: "";
	width: 7px;
	height: 7px;
	border-radius: 50%;
	background: #22c55e;
}

.kaiyi-chat__header-actions {
	display: flex;
	align-items: center;
	gap: 2px;
	flex: 0 0 auto;
}

.kaiyi-chat__icon-button {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 34px;
	height: 34px;
	padding: 0;
	border: 0;
	border-radius: 50%;
	background: transparent;
	color: inherit;
	text-decoration: none;
	cursor: pointer;
}

.kaiyi-chat__icon-button:hover {
	background: var(--kc-chat-surface-muted);
}

.kaiyi-chat__icon-button svg {
	width: 19px;
	height: 19px;
}

/* ------------------------------------------------------- message rows */

.kaiyi-chat__row {
	display: flex;
	align-items: flex-end;
	gap: 8px;
	max-width: 100%;
}

.kaiyi-chat__row--user {
	justify-content: flex-end;
}

.kaiyi-chat__row--system {
	justify-content: center;
}

.kaiyi-chat__row-avatar {
	flex: 0 0 auto;
	width: 28px;
	height: 28px;
	object-fit: cover;
	border-radius: 50%;
	background: var(--kc-chat-surface-muted);
}

.kaiyi-chat__stack {
	display: flex;
	flex-direction: column;
	min-width: 0;
	max-width: 85%;
}

.kaiyi-chat__row--user .kaiyi-chat__stack {
	align-items: flex-end;
}

.kaiyi-chat__sender {
	margin: 0 0 4px;
	color: var(--kc-chat-muted);
	font-size: 12px;
	font-weight: 700;
	line-height: 1.2;
}

.kaiyi-chat__time {
	margin: 4px 2px 0;
	color: var(--kc-chat-muted);
	font-size: 11px;
	line-height: 1.2;
}

/* The bubble sizes to its own row now, so its old cap would fight the stack. */
.kaiyi-chat__msg {
	max-width: 100%;
}

/* -------------------------------------------------------- attachments */

.kaiyi-chat__attachment-image {
	display: block;
	max-width: 100%;
	margin-top: 6px;
	border-radius: 12px;
}

.kaiyi-chat__msg > .kaiyi-chat__attachment-image:first-child {
	margin-top: 0;
}

.kaiyi-chat__attachment-file {
	display: flex;
	align-items: center;
	gap: 8px;
	margin-top: 6px;
	padding: 10px 12px;
	border-radius: 10px;
	background: var(--kc-chat-surface);
	color: inherit;
	font-size: 14px;
	text-decoration: none;
	word-break: break-all;
}

.kaiyi-chat__attachment-icon {
	flex: 0 0 auto;
}

/* ------------------------------------------------------------ toolbar */

.kaiyi-chat__toolbar {
	display: flex;
	align-items: center;
	gap: 4px;
	flex: 0 0 auto;
	padding: 0 14px 12px;
}

.kaiyi-chat__tool {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 34px;
	height: 34px;
	padding: 0;
	border: 0;
	border-radius: 50%;
	background: transparent;
	color: var(--kc-chat-muted);
	cursor: pointer;
	transition: color .2s ease, background-color .2s ease;
}

.kaiyi-chat__tool:hover {
	background: var(--kc-chat-surface-muted);
	color: var(--kc-chat-text);
}

.kaiyi-chat__tool svg {
	width: 20px;
	height: 20px;
}

/* Recording is a state the visitor needs to be certain about, so it is
   colour *and* motion rather than either alone. */
.kaiyi-chat__tool.is-recording {
	background: #ef4444;
	color: #fff;
	animation: kaiyi-chat-pulse 1.4s ease-in-out infinite;
}

@keyframes kaiyi-chat-pulse {
	0%, 100% { opacity: 1; }
	50%      { opacity: .55; }
}

/* -------------------------------------------------------------- tray */

.kaiyi-chat__tray {
	display: flex;
	align-items: center;
	gap: 10px;
	flex: 0 0 auto;
	margin: 0 14px;
	padding: 8px 10px;
	border: 1px solid var(--kc-chat-border);
	border-radius: 12px;
	background: var(--kc-chat-surface-muted);
	font-size: 13px;
}

.kaiyi-chat__tray-thumb {
	width: 34px;
	height: 34px;
	object-fit: cover;
	border-radius: 8px;
}

.kaiyi-chat__tray-name {
	flex: 1 1 auto;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.kaiyi-chat__tray-remove {
	flex: 0 0 auto;
	padding: 4px 8px;
	border: 0;
	border-radius: 8px;
	background: transparent;
	color: var(--kc-chat-muted);
	font: inherit;
	font-size: 12px;
	cursor: pointer;
}

.kaiyi-chat__tray-remove:hover {
	color: var(--kc-chat-text);
}

/* ------------------------------------------------------------ picker */

.kaiyi-chat__picker {
	display: flex;
	flex-direction: column;
	flex: 0 0 auto;
	max-height: 260px;
	margin: 0 14px 10px;
	overflow: hidden;
	border: 1px solid var(--kc-chat-border);
	border-radius: 14px;
	background: var(--kc-chat-surface);
}

.kaiyi-chat__picker-body {
	flex: 1 1 auto;
	overflow-y: auto;
	overscroll-behavior: contain;
	padding: 12px;
}

.kaiyi-chat__picker-tabs {
	display: flex;
	gap: 8px;
	flex: 0 0 auto;
	padding: 8px 12px;
	border-top: 1px solid var(--kc-chat-border);
}

.kaiyi-chat__picker-tab {
	flex: 1 1 0;
	padding: 8px 12px;
	border: 0;
	border-radius: 999px;
	background: var(--kc-chat-surface-muted);
	color: var(--kc-chat-text);
	font: inherit;
	font-size: 13px;
	font-weight: 700;
	cursor: pointer;
}

.kaiyi-chat__picker-tab.is-active {
	background: var(--kc-chat-primary);
	color: var(--kc-chat-on-primary);
}

.kaiyi-chat__picker-note {
	margin: 0;
	padding: 16px 4px;
	color: var(--kc-chat-muted);
	font-size: 13px;
	text-align: center;
}

.kaiyi-chat__emoji-grid {
	display: grid;
	grid-template-columns: repeat(6, 1fr);
	gap: 4px;
}

.kaiyi-chat__emoji {
	padding: 6px;
	border: 0;
	border-radius: 8px;
	background: transparent;
	font-size: 22px;
	line-height: 1.2;
	cursor: pointer;
}

.kaiyi-chat__emoji:hover {
	background: var(--kc-chat-surface-muted);
}

.kaiyi-chat__gif-search {
	width: 100%;
	margin-bottom: 10px;
	padding: 9px 12px;
	border: 1px solid var(--kc-chat-border);
	border-radius: 999px;
	background: var(--kc-chat-surface-muted);
	color: inherit;
	font: inherit;
	font-size: 14px;
}

.kaiyi-chat__gif-grid {
	display: grid;
	grid-template-columns: repeat(2, 1fr);
	gap: 6px;
}

.kaiyi-chat__gif {
	padding: 0;
	border: 0;
	border-radius: 10px;
	overflow: hidden;
	background: var(--kc-chat-surface-muted);
	cursor: pointer;
	aspect-ratio: 4 / 3;
}

.kaiyi-chat__gif img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

/* The paper plane is drawn pointing right; the send action reads as "up and
   away", so it is rotated rather than redrawn. */
.kaiyi-chat__send svg {
	transform: rotate(-45deg);
	transform-origin: center;
}

/* Presence colour is per state, so "offline" cannot look like "online". */
.kaiyi-chat__presence[data-state="away"]::before {
	background: #f59e0b;
}

.kaiyi-chat__presence[data-state="offline"]::before {
	background: var(--kc-chat-muted);
}

.kaiyi-chat__time--read {
	font-weight: 600;
}

/* -------------------------------------------------------------- docking */

/*
 * The launcher docks to the theme's sticky contact button, which has three
 * states, so the launcher has three positions:
 *
 *   contact on screen  - sit 30px above it, sharing its centre line
 *   contact hidden     - take over the spot it vacated
 *   no contact at all  - 30px in from the right and bottom
 *
 * The offsets come from the theme so the two cannot drift apart; the fallbacks
 * are the same values, for the case where the plugin runs under another theme.
 */
.kaiyi-chat {
	--kc-chat-launcher-size: 56px;
	--kc-chat-dock-inset: var(--kc-dock-inset, clamp(1rem, 2vw, 2rem));
	--kc-chat-dock-size: var(--kc-dock-size, clamp(88px, 8vw, 112px));
	--kc-chat-dock-gap: var(--kc-dock-gap, 30px);

	/* Centred on where the contact button sits, whether or not it is showing. */
	--kc-chat-dock-right: calc(
		var(--kc-chat-dock-inset) + (var(--kc-chat-dock-size) - var(--kc-chat-launcher-size)) / 2
	);

	right: 30px;
	bottom: 30px;
	transition: right .28s ease, bottom .28s ease;
}

body:has(.sticky-contact) .kaiyi-chat {
	right: var(--kc-chat-dock-right);
	bottom: calc(
		var(--kc-chat-dock-inset) + (var(--kc-chat-dock-size) - var(--kc-chat-launcher-size)) / 2
	);
}

body:has(.sticky-contact.is-visible) .kaiyi-chat {
	right: var(--kc-chat-dock-right);
	bottom: calc(var(--kc-chat-dock-inset) + var(--kc-chat-dock-size) + var(--kc-chat-dock-gap));
}

@media (prefers-reduced-motion: reduce) {
	.kaiyi-chat {
		transition: none;
	}
}

/* The theme hides the contact button below 768px. It stays in the DOM, so
   :has() still matches it — the docking rules have to be undone at the same
   breakpoint the theme hides it at, not at the one the panel goes full-screen
   at, or the launcher docks to a button that occupies nothing. */
@media (max-width: 767px) {
	/*
	 * The article's floating contents box docks at the same corner, and toc.js
	 * publishes how tall it currently is. Standing clear of it by the same 30px
	 * gap keeps the two from sitting on top of each other, and the variable
	 * falls to zero when the box is out of the way so the launcher drops back.
	 */
	.kaiyi-chat,
	body:has(.sticky-contact) .kaiyi-chat,
	body:has(.sticky-contact.is-visible) .kaiyi-chat {
		right: var(--theme-page-padding, 30px);
		bottom: calc(30px + var(--kaiyi-toc-height, 0px));
		transition: bottom .28s ease;
	}
}

@media (max-width: 640px) {
	/* Open full-screen, the panel has to clear the site header and the
	   WordPress admin bar. The admin bar sits at 99999 and is fixed to the top
	   of the viewport, so anything lower leaves a strip of it across the sheet.
	   Raised only while open, so the closed launcher does not float over the
	   admin bar for signed-in users. */
	.kaiyi-chat[data-open="true"] {
		z-index: 100000;
	}
}

/* ------------------------------------------------------------ corrections */

/*
 * `hidden` is a UA-stylesheet `display: none`, which any author `display` beats.
 * The picker and the tray both declare `display: flex`, so they stayed on
 * screen as empty boxes while the markup said they were hidden. Author-level
 * and !important is the only thing that reliably outranks a `display` set on
 * the element's own class.
 */
.kaiyi-chat [hidden] {
	display: none !important;
}

/*
 * The theme styles every `button` on the page — a 10px radius and a
 * `font-weight: 600 !important` among them — and the widget is on the page like
 * anything else. These reset what leaks in and re-assert the widget's own
 * shapes at a specificity the global rules cannot reach.
 */
.kaiyi-chat button,
.kaiyi-chat input,
.kaiyi-chat textarea,
.kaiyi-chat a {
	font-family: inherit;
	letter-spacing: inherit;
}

.kaiyi-chat .kaiyi-chat__launcher,
.kaiyi-chat .kaiyi-chat__send,
.kaiyi-chat .kaiyi-chat__tool,
.kaiyi-chat .kaiyi-chat__icon-button {
	border-radius: 50%;
	box-shadow: none;
	min-height: 0;
	text-transform: none;
}

.kaiyi-chat .kaiyi-chat__send {
	width: 42px;
	height: 42px;
	padding: 0;
	background: var(--kc-chat-primary);
	color: var(--kc-chat-on-primary);
}

.kaiyi-chat .kaiyi-chat__send svg {
	display: block;
	width: 18px;
	height: 18px;
	transform: rotate(-45deg);
}

.kaiyi-chat .kaiyi-chat__launcher svg,
.kaiyi-chat .kaiyi-chat__tool svg {
	display: block;
}

/* Header icons: flush, larger, and no hover plate. */
.kaiyi-chat .kaiyi-chat__icon-button {
	width: auto;
	height: auto;
	padding: 0;
	margin-left: 14px;
	background: transparent;
}

.kaiyi-chat .kaiyi-chat__icon-button:hover,
.kaiyi-chat .kaiyi-chat__icon-button:focus-visible {
	background: transparent;
	opacity: .6;
}

.kaiyi-chat .kaiyi-chat__icon-button svg {
	display: block;
	width: 24px;
	height: 24px;
}

.kaiyi-chat__header-actions {
	gap: 0;
}

/* Conversation type reads better a size down at this width. */
.kaiyi-chat__msg {
	font-size: 14px;
	line-height: 1.65;
}

/* ------------------------------------------------------- bubble + meta */

/* The meta column rides beside the bubble — outside edge of the conversation
   on both sides — with the read mark stacked above the time. */
.kaiyi-chat__line {
	display: flex;
	align-items: flex-end;
	gap: 6px;
	max-width: 100%;
}

.kaiyi-chat__row--user .kaiyi-chat__line {
	justify-content: flex-end;
}

.kaiyi-chat__meta {
	display: flex;
	flex-direction: column;
	align-items: flex-end;
	flex: 0 0 auto;
	gap: 2px;
	padding-bottom: 2px;
	color: var(--kc-chat-muted);
	font-size: 11px;
	line-height: 1.2;
	white-space: nowrap;
}

.kaiyi-chat__row--user .kaiyi-chat__meta {
	align-items: flex-start;
}

.kaiyi-chat__read {
	font-weight: 700;
}

/* The old stacked timestamp is replaced by the column above. */
.kaiyi-chat__stack > .kaiyi-chat__time {
	display: none;
}

/* ------------------------------------------------------------------ tray */

.kaiyi-chat__tray {
	margin-bottom: 6px;
	border: 0;
	background: var(--kc-chat-surface-muted);
}

/* ---------------------------------------------------------------- credit */

.kaiyi-chat__credit {
	display: flex;
	align-items: center;
	justify-content: flex-end;
	gap: 6px;
	flex: 0 0 auto;
	padding: 0 16px 12px;
	color: var(--kc-chat-muted);
	font-size: 11px;
	line-height: 1;
}

.kaiyi-chat__credit-icon {
	width: 16px;
	height: 16px;
	object-fit: cover;
	border-radius: 4px;
}

.kaiyi-chat__credit-name {
	font-weight: 700;
	color: var(--kc-chat-text);
}

/* ---------------------------------------------------- corrections, pass 2 */

/*
 * The send button kept the theme's 10px radius and its icon collapsed, through
 * two rounds of raising specificity. Nothing in the theme selects this button,
 * so the cascade is not something this file can reason about from the outside.
 * This is a widget injected into a page it does not control, so the handful of
 * declarations that decide whether it is usable are marked important rather
 * than guessed at again.
 */
.kaiyi-chat .kaiyi-chat__send {
	width: 42px !important;
	height: 42px !important;
	min-width: 42px !important;
	min-height: 42px !important;
	padding: 0 !important;
	border: 0 !important;
	border-radius: 50% !important;
	background: var(--kc-chat-primary) !important;
	color: var(--kc-chat-on-primary) !important;
	font-size: 0 !important;
}

.kaiyi-chat .kaiyi-chat__send svg {
	display: block !important;
	width: 18px !important;
	height: 18px !important;
	flex: 0 0 18px !important;
	fill: currentColor !important;
	transform: rotate(-45deg);
}

.kaiyi-chat .kaiyi-chat__launcher {
	width: 56px !important;
	height: 56px !important;
	padding: 0 !important;
	border-radius: 50% !important;
}

.kaiyi-chat .kaiyi-chat__launcher svg,
.kaiyi-chat .kaiyi-chat__tool svg,
.kaiyi-chat .kaiyi-chat__icon-button svg {
	display: block !important;
	fill: none;
}

.kaiyi-chat .kaiyi-chat__launcher svg {
	width: 26px !important;
	height: 26px !important;
	fill: currentColor !important;
}

/*
 * A flex item defaults to min-width:auto, so the bubble refused to shrink below
 * its content and pushed the meta column out of the row entirely — which is why
 * the read mark was missing on desktop, where the panel is narrow enough for it
 * to matter.
 */
.kaiyi-chat__line {
	min-width: 0;
}

.kaiyi-chat__line .kaiyi-chat__msg {
	flex: 0 1 auto;
	min-width: 0;
}

.kaiyi-chat__meta {
	flex: 0 0 auto;
}

/* Both columns hug the bubble they belong to, so the mark and the time line up
   against the message rather than drifting to the outside edge. */
.kaiyi-chat__row--assistant .kaiyi-chat__meta {
	align-items: flex-start;
}

.kaiyi-chat__row--user .kaiyi-chat__meta {
	align-items: flex-end;
}

/*
 * The avatar belongs beside the first line of the message, not its last. The
 * offset is exactly the height of the sender label above the bubble, derived
 * from the same variable the label uses so that changing the label's type does
 * not leave the avatar sitting at the wrong height.
 */
.kaiyi-chat {
	--kc-chat-sender-line: 12px;
	--kc-chat-sender-gap: 4px;
	--kc-chat-sender-block: calc((var(--kc-chat-sender-line) * 1.2) + var(--kc-chat-sender-gap));
}

.kaiyi-chat__row {
	align-items: flex-start;
}

.kaiyi-chat__sender {
	font-size: var(--kc-chat-sender-line);
	line-height: 1.2;
	margin: 0 0 var(--kc-chat-sender-gap);
}

.kaiyi-chat__row--assistant .kaiyi-chat__row-avatar {
	margin-top: var(--kc-chat-sender-block);
}

/* The credit is one line: it names a person, and a wrapped name reads as two. */
.kaiyi-chat__credit {
	white-space: nowrap;
}

.kaiyi-chat__credit-name {
	color: var(--kc-chat-text);
	text-decoration: none;
}

.kaiyi-chat__credit-name:hover {
	text-decoration: underline;
}

/* On a desktop popover the launcher is the way back out, so it stays put; the
   phone sheet covers the whole screen and has nothing to sit on. */
@media (min-width: 641px) {
	.kaiyi-chat[data-open="true"] .kaiyi-chat__launcher {
		opacity: 1;
		pointer-events: auto;
	}
}

/* ---------------------------------------------------- corrections, pass 3 */

/*
 * The bubble type was still rendering larger than this file asked for, which is
 * the same leak that reshaped the send button: the page styles paragraphs and
 * the widget's paragraphs are on the page. Stated outright, in the size and
 * leading the design calls for.
 */
.kaiyi-chat .kaiyi-chat__msg,
.kaiyi-chat .kaiyi-chat__msg p,
.kaiyi-chat .kaiyi-chat__msg li {
	font-size: 17px !important;
	line-height: 32px !important;
}

/*
 * The visitor's bubble is the brand green in both colour schemes, so its label
 * has to be dark in both. Reading the general text colour made it white in dark
 * mode — white on that green is close to unreadable.
 */
.kaiyi-chat {
	--kc-chat-on-primary: var(--theme-color-on-primary, #000);
}

.kaiyi-chat .kaiyi-chat__msg--user {
	color: var(--kc-chat-on-primary) !important;
}

/* Scroll belongs to the conversation while the panel is open. */
.kaiyi-chat__panel {
	overscroll-behavior: contain;
}

/* The launcher glyph carries the whole button, so it earns the room. */
.kaiyi-chat .kaiyi-chat__launcher svg {
	width: 30px !important;
	height: 30px !important;
}

/* ---------------------------------------------------- corrections, pass 4 */

/* Tools and credit share one row, and neither wraps. */
.kaiyi-chat__footer {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 12px;
	flex: 0 0 auto;
	padding: 0 14px 12px;
	white-space: nowrap;
}

.kaiyi-chat__toolbar,
.kaiyi-chat__credit {
	padding: 0;
	flex: 0 0 auto;
}

/* Desktop reads at a smaller size than the phone sheet, where the same text is
   held further from the eye. */
@media (min-width: 641px) {
	.kaiyi-chat .kaiyi-chat__msg,
	.kaiyi-chat .kaiyi-chat__msg p,
	.kaiyi-chat .kaiyi-chat__msg li {
		font-size: 15px !important;
		line-height: 28px !important;
	}
}

/*
 * The paper plane's mass sits below its nose, so a geometrically centred glyph
 * reads as low and left. The nudge is optical, not arithmetic.
 */
.kaiyi-chat .kaiyi-chat__send svg {
	transform: rotate(-45deg) translate(1px, -1px);
}

/* The launcher is the only thing on screen when the panel is shut, so it can
   afford the room; muted rather than brand, so the page keeps its accent. */
.kaiyi-chat .kaiyi-chat__launcher {
	width: 64px !important;
	height: 64px !important;
	background: var(--kc-chat-surface-muted) !important;
	color: var(--kc-chat-text) !important;
	/* No outline: the launcher is a solid disc, and a ring around it read as
	   a button inside a button. */
	border: 0 !important;
}

.kaiyi-chat .kaiyi-chat__launcher svg {
	width: 32px !important;
	height: 32px !important;
}

/* --------------------------------------------------------------- dialog */

.kaiyi-chat__backdrop {
	position: absolute;
	inset: 0;
	z-index: 5;
	display: flex;
	align-items: center;
	justify-content: center;
	padding: 24px;
	background: color-mix(in srgb, var(--kc-chat-surface) 55%, transparent);
	-webkit-backdrop-filter: blur(6px);
	backdrop-filter: blur(6px);
}

.kaiyi-chat__dialog {
	width: 100%;
	max-width: 300px;
	padding: 20px;
	border: 1px solid var(--kc-chat-border);
	border-radius: 16px;
	background: var(--kc-chat-surface);
	text-align: center;
}

.kaiyi-chat__dialog-title {
	margin: 0 0 8px;
	font-size: 16px;
	font-weight: 700;
	line-height: 1.4;
}

.kaiyi-chat__dialog-text {
	margin: 0 0 18px;
	color: var(--kc-chat-muted);
	font-size: 13px;
	line-height: 1.6;
}

.kaiyi-chat__dialog-actions {
	display: flex;
	gap: 8px;
}

.kaiyi-chat .kaiyi-chat__dialog-button {
	flex: 1 1 0;
	min-height: 40px;
	padding: 10px 14px;
	border: 0;
	border-radius: 10px;
	background: var(--kc-chat-surface-muted);
	color: var(--kc-chat-text);
	font: inherit;
	font-size: 14px;
	font-weight: 700;
	cursor: pointer;
}

.kaiyi-chat .kaiyi-chat__dialog-button--danger {
	background: var(--kc-chat-danger);
	color: #fff;
}

@media (prefers-reduced-motion: reduce) {
	.kaiyi-chat__backdrop {
		-webkit-backdrop-filter: none;
		backdrop-filter: none;
		background: color-mix(in srgb, var(--kc-chat-surface) 88%, transparent);
	}
}

/* The way back after ending: offered as an action, not left as a dead panel. */
.kaiyi-chat .kaiyi-chat__restart-cta {
	align-self: center;
	margin-top: 8px;
	padding: 10px 18px;
	border: 1px solid var(--kc-chat-border);
	border-radius: 999px;
	background: var(--kc-chat-surface-muted);
	color: var(--kc-chat-text);
	font: inherit;
	font-size: 13px;
	font-weight: 700;
	cursor: pointer;
}

/* --------------------------------------------------------------- welcome */

.kaiyi-chat__home {
	flex: 1 1 auto;
	overflow-y: auto;
	overscroll-behavior: contain;
	padding: 20px 18px 24px;
}

.kaiyi-chat__home-heading {
	margin: 0 0 20px;
	font-size: 24px;
	font-weight: 800;
	line-height: 1.4;
	letter-spacing: -.02em;
}

.kaiyi-chat__home-title {
	margin: 24px 0 10px;
	color: var(--kc-chat-muted);
	font-size: 12px;
	font-weight: 700;
	letter-spacing: .06em;
}

.kaiyi-chat__channels {
	display: grid;
	gap: 8px;
}

.kaiyi-chat .kaiyi-chat__channel {
	display: flex;
	align-items: center;
	gap: 12px;
	width: 100%;
	padding: 14px 16px;
	border: 1px solid var(--kc-chat-border);
	border-radius: 14px;
	background: var(--kc-chat-surface);
	color: var(--kc-chat-text);
	font: inherit;
	text-align: left;
	text-decoration: none;
	cursor: pointer;
	transition: background-color .2s ease, transform .2s ease;
}

.kaiyi-chat .kaiyi-chat__channel:hover {
	background: var(--kc-chat-surface-muted);
	transform: translateY(-1px);
}

.kaiyi-chat__channel-icon {
	display: grid;
	flex: 0 0 auto;
	place-items: center;
	width: 38px;
	height: 38px;
	border-radius: 50%;
	background: var(--kc-chat-surface-muted);
}

.kaiyi-chat__channel-icon svg {
	width: 20px;
	height: 20px;
}

.kaiyi-chat__channel-text {
	display: grid;
	flex: 1 1 auto;
	gap: 2px;
	min-width: 0;
}

.kaiyi-chat__channel-title {
	font-size: 15px;
	font-weight: 700;
	line-height: 1.4;
}

.kaiyi-chat__channel-note {
	color: var(--kc-chat-muted);
	font-size: 12px;
	line-height: 1.4;
}

.kaiyi-chat__channel-chevron {
	display: grid;
	flex: 0 0 auto;
	place-items: center;
	color: var(--kc-chat-muted);
}

.kaiyi-chat__channel-chevron svg {
	width: 18px;
	height: 18px;
}

/*
 * A row that slides aside to show what it can do.
 *
 * The button is underneath rather than beside: it is the same height as the
 * row whatever the preview wraps to, and nothing reflows when the row moves.
 */
.kaiyi-chat__recent-item {
	position: relative;
	overflow: hidden;
	margin-bottom: 6px;
	border-radius: 12px;
	transition: opacity .2s ease, height .2s ease, margin .2s ease;
}

.kaiyi-chat__recent-item.is-removing {
	opacity: 0;
}

.kaiyi-chat__recent-delete {
	position: absolute;
	top: 0;
	right: 0;
	bottom: 0;
	display: grid;
	place-items: center;
	width: 72px;
	padding: 0;
	border: 0;
	border-radius: 12px;
	background: var(--kc-chat-danger);
	color: #fff;
	cursor: pointer;
}

.kaiyi-chat__recent-delete svg {
	width: 26px;
	height: 26px;
}

.kaiyi-chat .kaiyi-chat__recent-row {
	position: relative;
	display: grid;
	gap: 3px;
	width: 100%;
	padding: 12px 14px;
	border: 0;
	border-radius: 12px;
	background: var(--kc-chat-surface-muted);
	color: var(--kc-chat-text);
	font: inherit;
	text-align: left;
	cursor: pointer;
	/* Ours horizontally, the scroller's vertically. */
	touch-action: pan-y;
	transition: transform .24s cubic-bezier(.4, 0, .2, 1);
}

/* While a finger is down the row follows it exactly; easing here would lag. */
.kaiyi-chat__recent-item.is-dragging .kaiyi-chat__recent-row {
	transition: none;
}

/*
 * Only a swipe opens it, and only the delete button's own keyboard focus does.
 * :focus-within meant an ordinary click -- which focuses the row -- slid the
 * button out from under a visitor who was only trying to open the conversation.
 */
/* Twelve past the button's own width, so the two do not touch. */
.kaiyi-chat__recent-item.is-open .kaiyi-chat__recent-row,
.kaiyi-chat__recent-item:has(.kaiyi-chat__recent-delete:focus-visible) .kaiyi-chat__recent-row {
	transform: translateX(-84px);
}

@media (prefers-reduced-motion: reduce) {
	.kaiyi-chat__recent-row,
	.kaiyi-chat__recent-item {
		transition: none;
	}
}

.kaiyi-chat__recent-preview {
	overflow: hidden;
	font-size: 14px;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.kaiyi-chat__recent-meta {
	color: var(--kc-chat-muted);
	font-size: 11px;
}

.kaiyi-chat__docs-note {
	margin: 0;
	padding: 14px;
	border: 1px dashed var(--kc-chat-border);
	border-radius: 12px;
	color: var(--kc-chat-muted);
	font-size: 13px;
	line-height: 1.6;
}

/* ------------------------------------------------------------------- nav */

.kaiyi-chat__nav {
	display: flex;
	flex: 0 0 auto;
	border-top: 1px solid var(--kc-chat-border);
}

.kaiyi-chat .kaiyi-chat__tab {
	display: grid;
	gap: 3px;
	flex: 1 1 0;
	justify-items: center;
	padding: 10px 4px 12px;
	border: 0;
	border-radius: 0;
	background: transparent;
	color: var(--kc-chat-muted);
	font: inherit;
	cursor: pointer;
}

.kaiyi-chat .kaiyi-chat__tab.is-active {
	color: var(--kc-chat-text);
}

/* Present but inert: showing where documents will live says "not yet", where
   a missing tab would say nothing at all. */
.kaiyi-chat .kaiyi-chat__tab[disabled] {
	opacity: .38;
	cursor: not-allowed;
}

.kaiyi-chat__tab-icon svg {
	display: block;
	width: 22px;
	height: 22px;
}

.kaiyi-chat__tab-label {
	font-size: 11px;
	font-weight: 700;
	line-height: 1.2;
}

/* ---------------------------------------------------------------- expand */

/* A phone sheet is already the whole screen, so there is nothing to expand
   into and the control does not appear. */
.kaiyi-chat .kaiyi-chat__expand {
	display: none;
}

@media (min-width: 641px) {
	.kaiyi-chat .kaiyi-chat__expand {
		display: inline-flex;
	}

	.kaiyi-chat[data-expanded="true"] .kaiyi-chat__panel {
		width: min(620px, calc(100vw - 60px));
		height: min(
			760px,
			calc(100vh - var(--wp-admin-bar-height, 0px) - var(--site-header-anchor-offset, 30px) - 60px)
		);
		max-height: none;
	}
}

/* ---------------------------------------------------------------- finish */

.kaiyi-chat .kaiyi-chat__finish {
	padding: 0;
	border: 0;
	background: transparent;
	color: var(--kc-chat-muted);
	font: inherit;
	font-size: 11px;
	text-decoration: underline;
	cursor: pointer;
	white-space: nowrap;
}

.kaiyi-chat .kaiyi-chat__finish:hover {
	color: var(--kc-chat-text);
}

/* The credit sits centred at the foot of the welcome screen, where a guest
   never sees the conversation footer that otherwise carries it. */
.kaiyi-chat__credit--home {
	justify-content: center;
	margin-top: 28px;
	padding: 0;
}

/* A reply from a person is labelled, because it arrives in the same place the
   assistant's do and the difference matters to whoever is reading. */
.kaiyi-chat__sender-badge {
	margin-left: 6px;
	padding: 1px 6px;
	border-radius: 999px;
	background: var(--kc-chat-primary);
	color: var(--kc-chat-on-primary);
	font-size: 10px;
}

.kaiyi-chat[data-live="true"] .kaiyi-chat__presence::before {
	background: var(--kc-chat-primary);
}

/* ---------------------------------------------------- corrections, pass 5 */

/*
 * A flex item defaults to min-height:auto, so the log refused to shrink below
 * its own content: a long conversation pushed the input, the credit row and
 * the tabs out of the panel entirely, and the log's own scroll never engaged,
 * which sent the wheel to the page behind instead.
 */
.kaiyi-chat__log,
.kaiyi-chat__home,
.kaiyi-chat__chats {
	min-height: 0;
}

.kaiyi-chat__chats {
	display: flex;
	flex-direction: column;
	flex: 1 1 auto;
	gap: 12px;
	overflow-y: auto;
	overscroll-behavior: contain;
	padding: 18px;
}

.kaiyi-chat .kaiyi-chat__start {
	flex: 0 0 auto;
	width: 100%;
	padding: 12px 16px;
	border: 0;
	border-radius: 12px;
	background: var(--kc-chat-primary);
	color: var(--kc-chat-on-primary);
	font: inherit;
	font-size: 14px;
	font-weight: 700;
	cursor: pointer;
}

/* The back arrow leads the header, so it does not take the gap the avatar
   and name share. */
.kaiyi-chat .kaiyi-chat__back {
	margin-left: 0;
	margin-right: 2px;
}

/* Offered at the point the conversation has reached an end, in the log where
   it reads as the next step, rather than parked in the toolbar where it is an
   exit sign inviting a misclick on something that cannot be undone. */
.kaiyi-chat .kaiyi-chat__end-offer {
	align-self: center;
	margin-top: 4px;
	padding: 9px 18px;
	border: 1px solid var(--kc-chat-border);
	border-radius: 999px;
	background: var(--kc-chat-surface-muted);
	color: var(--kc-chat-text);
	font: inherit;
	font-size: 13px;
	font-weight: 700;
	cursor: pointer;
}

.kaiyi-chat .kaiyi-chat__end-offer:hover {
	background: var(--kc-chat-surface);
}

/* Opening the panel hides the contact button but leaves its is-visible class
   in place, so the launcher would otherwise hover 30px above nothing. While
   the panel is open it takes the button's spot, the same as when the button
   has scrolled away. */
body.kaiyi-chat-open:has(.sticky-contact.is-visible) .kaiyi-chat {
	right: var(--kc-chat-dock-right);
	bottom: calc(
		var(--kc-chat-dock-inset) + (var(--kc-chat-dock-size) - var(--kc-chat-launcher-size)) / 2
	);
}

@media (max-width: 767px) {
	body.kaiyi-chat-open:has(.sticky-contact.is-visible) .kaiyi-chat {
		right: 30px;
		bottom: 30px;
	}
}

/* ------------------------------------------------------------ suggestions */

/* Sits with the conversation, just above the input, where a suggested reply
   goes — not among the attachment tools, which are about composing a message
   rather than leaving one. */
.kaiyi-chat__suggestions {
	display: flex;
	flex-wrap: wrap;
	gap: 6px;
	flex: 0 0 auto;
	padding: 0 14px 8px;
}

.kaiyi-chat .kaiyi-chat__suggestion {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	padding: 7px 14px;
	border: 1px solid var(--kc-chat-border);
	border-radius: 999px;
	background: var(--kc-chat-surface);
	color: var(--kc-chat-text);
	font: inherit;
	font-size: 13px;
	font-weight: 700;
	cursor: pointer;
}

.kaiyi-chat .kaiyi-chat__suggestion:hover {
	background: var(--kc-chat-surface-muted);
}

.kaiyi-chat__suggestion-icon svg {
	display: block;
	width: 16px;
	height: 16px;
}

/* A system line is the widget speaking, not the assistant. Ruled above and
   below and stamped with a time, it reads as a moment in the conversation
   rather than a stray sentence between two bubbles. */
.kaiyi-chat__notice {
	display: flex;
	align-items: baseline;
	justify-content: center;
	gap: 8px;
	width: 100%;
	padding: 10px 4px;
	border-top: 1px solid var(--kc-chat-border);
	border-bottom: 1px solid var(--kc-chat-border);
	color: var(--kc-chat-muted);
	font-size: 12px;
	line-height: 1.6;
	text-align: center;
}

.kaiyi-chat__notice-time {
	flex: 0 0 auto;
	font-size: 11px;
	opacity: .8;
}

.kaiyi-chat__row--system {
	width: 100%;
}

/* No outline around the panel: it sits on the page as a surface, and a border
   makes it read as a dialog cut out of it. */
.kaiyi-chat .kaiyi-chat__panel {
	border: 0;
	box-shadow: 0 18px 48px rgba(0, 0, 0, .16);
}

/* --------------------------------------------------------------------------
   Choices: the options as buttons
   -------------------------------------------------------------------------- */

/*
 * Offered when the assistant could not tell which thing was meant. Each button
 * carries the identifier, so pressing one is unambiguous in a way that typing
 * the name back never was.
 */
.kaiyi-chat__row--choices {
	padding-left: 0;
}

.kaiyi-chat__choices {
	display: grid;
	gap: 8px;
	width: 100%;
}

.kaiyi-chat__choices-title {
	margin: 0 0 2px;
	color: var(--kc-chat-muted);
	font-size: 12px;
}

.kaiyi-chat__choice {
	display: grid;
	gap: 3px;
	width: 100%;
	padding: 12px 14px;
	border: 1px solid var(--kc-chat-border);
	border-radius: 12px;
	background: var(--kc-chat-surface);
	color: var(--kc-chat-text);
	font: inherit;
	text-align: left;
	text-decoration: none;
	cursor: pointer;
	transition: border-color .2s ease, background-color .2s ease;
}

.kaiyi-chat__choice:is(:hover, :focus-visible) {
	border-color: var(--kc-chat-primary);
}

.kaiyi-chat__choice[disabled] {
	cursor: default;
	opacity: .5;
}

/* The one they pressed stays legible; the rest recede. */
.kaiyi-chat__choice.is-chosen[disabled] {
	border-color: var(--kc-chat-primary);
	opacity: 1;
}

.kaiyi-chat__choice-title {
	font-size: 14px;
	font-weight: 600;
}

.kaiyi-chat__choice-meta {
	color: var(--kc-chat-muted);
	font-size: 12px;
}

.kaiyi-chat__choice--confirm {
	border-color: var(--kc-chat-primary);
	background: var(--kc-chat-primary);
	color: var(--kc-chat-on-primary);
}

.kaiyi-chat__choice--confirm .kaiyi-chat__choice-meta {
	color: inherit;
	opacity: .75;
}

/* --------------------------------------------------------------------------
   Messages arrive rather than appear
   -------------------------------------------------------------------------- */

/*
 * On the row, so the greeting animates on the same terms as every reply. It
 * used to be the one line that simply existed the moment the panel did, which
 * read as canned -- and delaying it behind the typing dots only made it a
 * message that could go missing.
 */
.kaiyi-chat__row {
	animation: kaiyi-chat-arrive .32s cubic-bezier(.22, 1, .36, 1) both;
}

@keyframes kaiyi-chat-arrive {
	from { opacity: 0; transform: translateY(8px); }
	to { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
	.kaiyi-chat__row {
		animation: none;
	}
}
