/**
 * The Dot Experience — Shopping Assistant widget.
 *
 * Styled entirely against the dot-experience theme's design tokens
 * (assets/css/tokens.css): the monochrome jet/off-white model, the pill/radius
 * scale, motion tokens, and the four-tier overlay shadow scale. Because those
 * tokens are redefined per [data-theme] (default / high-contrast / dark) by the
 * theme + accessibility-preferences plugin, this widget re-themes automatically
 * across all three profiles with no per-theme rules of its own — every colour
 * below resolves through a token. Each var() also carries a literal fallback so
 * the widget still renders in the default palette if it ever loads under a
 * theme that doesn't ship tokens.css.
 *
 * Motion note: transitions are declared normally but disabled under both the OS
 * `prefers-reduced-motion: reduce` signal and the theme's explicit
 * `html[data-motion="reduce"]` attribute, matching the theme's motion contract.
 */

/* ---- Root container: fixed, bottom-right, anchored so the bar grows LEFT --- */
.dote-assistant {
	position: fixed;
	right: clamp(1rem, 3vw, 1.5rem);
	bottom: clamp(1rem, 3vw, 1.5rem);
	z-index: 900;
	display: flex;
	flex-direction: column-reverse; /* bar first in DOM (tab order), thread visually on top */
	align-items: flex-end;
	gap: 0.75rem;
	/* Only the bar and thread capture pointer events; the transparent column
	   gap never blocks clicks on the page beneath. */
	pointer-events: none;
	font-family: Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
	font-size: 16px;
	line-height: 1.5;
	color: var(--ink, #0b0b0b);
	text-wrap: pretty;
}

.dote-assistant[hidden] {
	display: none;
}

.dote-assistant__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;
}

.dote-assistant :focus-visible {
	outline: 3px solid var(--focus, #0b0b0b);
	outline-offset: 2px;
}

/* ---- The bar: a pill that morphs from a round launcher into a search field - */
.dote-assistant__bar {
	pointer-events: auto;
	display: flex;
	align-items: center;
	gap: 10px;
	/* Matches .dote-assistant__thread's width so the bar and the panel it
	   opens above read as one component rather than a wide bar feeding a
	   narrower panel. */
	width: min(25rem, calc(100vw - 2rem));
	max-width: calc(100vw - 2rem);
	padding: 6px;
	overflow: hidden;
	border-radius: 9999px;
	background: var(--surface, #ffffff);
	border: 1px solid var(--line, rgba(11, 11, 11, 0.08));
	box-shadow: var(--shadow-dropdown, 0 24px 50px rgba(0, 0, 0, 0.1));
	transition:
		width var(--motion-med, 300ms) var(--ease, cubic-bezier(0.22, 1, 0.36, 1)),
		padding var(--motion-med, 300ms) var(--ease, cubic-bezier(0.22, 1, 0.36, 1)),
		background-color var(--motion-fast, 160ms) var(--ease, cubic-bezier(0.22, 1, 0.36, 1)),
		border-color var(--motion-fast, 160ms) var(--ease, cubic-bezier(0.22, 1, 0.36, 1)),
		box-shadow var(--motion-fast, 160ms) var(--ease, cubic-bezier(0.22, 1, 0.36, 1));
}

/* Collapsed: shrink to exactly the launcher circle, drop the pill chrome so
   only the accent FAB reads on the page. */
.dote-assistant[data-state="collapsed"] .dote-assistant__bar {
	width: 52px;
	padding: 0;
	background: transparent;
	border-color: transparent;
	box-shadow: none;
}

/* ---- Corner control: launcher (collapsed) + submit (expanded) -------------
   Scoped to #dote-assistant (the widget's own container ID, not just the
   .dote-assistant__action class) specifically to out-specificity WooCommerce's
   bundled twenty-twenty-three.css compatibility stylesheet, which the theme
   enqueues sitewide whenever WooCommerce is active (see dot_experience_styles()
   in functions.php). That stylesheet's `.woocommerce button[type="submit"]
   :not(.wp-block-search__button)` rule is (0,3,1) specificity — higher than a
   bare `.dote-assistant__action` class selector (0,1,0) — so on any page where
   <body> carries the `.woocommerce`/`.woocommerce-page` class (shop, single
   product, cart, checkout, my-account — i.e. every "interior" WooCommerce
   page, but NOT the plain static front page) it was winning the cascade and
   forcing padding: 1rem 2rem + margin-top: 1rem + display: inline-block onto
   this button. With box-sizing: border-box, that padding is wider than the
   52px width can contain, so the browser was rendering a ~64x52px box instead
   of a 52x52 circle — the lopsided/"deformed circle" look reported on
   interior pages. The `#dote-assistant` ID prefix (1,0,0) trivially beats WC's
   rule for any property both declare (namely `display`), and the explicit
   `padding: 0` / `margin: 0` below neutralize the properties WC's rule sets
   that this rule previously left undeclared (so WC's value fell through
   uncontested regardless of specificity). Do not drop this ID scoping without
   re-checking that WC's compat stylesheet is still being enqueued sitewide. */
#dote-assistant .dote-assistant__action {
	flex: 0 0 auto;
	position: relative;
	width: 52px;
	height: 52px;
	margin: 0;
	padding: 0;
	border-radius: 9999px;
	border: 0;
	background: var(--accent, #0b0b0b);
	color: var(--accent-ink, #faf8f2);
	cursor: pointer;
	display: grid;
	place-items: center;
	text-align: center;
	text-decoration: none;
	box-shadow: var(--shadow-popover, 0 12px 32px rgba(0, 0, 0, 0.16));
	transition:
		transform var(--motion-fast, 160ms) var(--ease, cubic-bezier(0.22, 1, 0.36, 1)),
		box-shadow var(--motion-fast, 160ms) var(--ease, cubic-bezier(0.22, 1, 0.36, 1)),
		filter var(--motion-fast, 160ms) var(--ease, cubic-bezier(0.22, 1, 0.36, 1));
}

.dote-assistant__action:hover {
	filter: brightness(1.06);
}

/* The lift-on-hover only makes sense for the round collapsed launcher (a
   floating FAB). Once expanded, this button is a flex-centered row item
   pixel-aligned with the input and close button at a shared 44px height —
   lifting it alone on hover makes it visibly overhang that row. Scope the
   translateY to the collapsed state only; the expanded action button keeps
   just the brightness cue on hover. */
.dote-assistant[data-state="collapsed"] .dote-assistant__action:hover {
	transform: translateY(-2px);
}

.dote-assistant[data-state="collapsed"] .dote-assistant__action:active {
	transform: translateY(0) scale(0.97);
}

.dote-assistant[data-state="expanded"] .dote-assistant__action:active {
	transform: scale(0.97);
}

/* Once inside the surface pill, the button no longer needs to float. Also
   drop it from the 52px collapsed-launcher size down to the input's 44px so
   the row's flex-centered children (close/input/action) share one height
   instead of the 52px circle overhanging the 44px input's edges.
   ID-prefixed (#dote-assistant.dote-assistant[data-state="expanded"] ...)
   to out-specificity the #dote-assistant .dote-assistant__action base rule
   above (1 id + 1 class = 0,1,1,0). A bare `.dote-assistant[data-state=
   "expanded"] .dote-assistant__action` (0 ids, 3 classes/attrs) loses to
   that ID rule regardless of source order, so width/height/box-shadow here
   were previously never applying — the button stayed 52x52 with its full
   popover shadow even when expanded, oversized for the 44px input row and
   partially clipped by the pill's overflow:hidden + rounded cap, which read
   as the input/button being "cut off" at the panel's bottom-right corner. */
#dote-assistant.dote-assistant[data-state="expanded"] .dote-assistant__action {
	box-shadow: none;
	width: 44px;
	height: 44px;
}

/* Cross-fade the two glyphs in the same slot so the round icon reads as
   "becoming" the send arrow when the bar opens. */
.dote-assistant__icon {
	grid-area: 1 / 1;
	display: grid;
	place-items: center;
	transition: opacity var(--motion-fast, 160ms) var(--ease, cubic-bezier(0.22, 1, 0.36, 1));
}

.dote-assistant[data-state="collapsed"] .dote-assistant__icon--send,
.dote-assistant[data-state="expanded"] .dote-assistant__icon--open {
	opacity: 0;
}

/* ---- Input --------------------------------------------------------------- */
.dote-assistant__input {
	flex: 1 1 auto;
	min-width: 0;
	height: 44px;
	padding: 0 0.5rem 0 0.75rem;
	border: 0;
	border-radius: 0;
	/* Chrome's UA stylesheet gives input[type="search"] its own ~4px
	   border-radius and native field chrome regardless of the `border: 0`
	   above. That leftover near-square radius is invisible while unfocused,
	   but this field auto-focuses the instant the widget opens, and the
	   sitewide :focus-visible outline below then traces THAT small
	   corner — not the bar's 9999px pill cap. Because the input sits flush
	   against the bar's rounded left edge, the near-rectangular ring reads as
	   a hard flat clip line cutting across where the soft pill curve should
	   be. appearance: none strips the native chrome/radius entirely so the
	   input is a plain borderless box with no shape of its own to clash with
	   the pill (see the :focus-visible override below for the other half of
	   this fix). */
	appearance: none;
	-webkit-appearance: none;
	background: transparent;
	color: var(--ink, #0b0b0b);
	font: inherit;
	font-size: 1rem;
	letter-spacing: var(--letter-spacing-body, 0);
	outline: none;
	opacity: 1;
	transition: opacity var(--motion-med, 300ms) var(--ease, cubic-bezier(0.22, 1, 0.36, 1));
}

.dote-assistant__input::placeholder {
	color: var(--muted, #6b6760);
	opacity: 1;
}

/* Clear the platform search-cancel affordance so it doesn't fight the pill. */
.dote-assistant__input::-webkit-search-decoration,
.dote-assistant__input::-webkit-search-cancel-button {
	-webkit-appearance: none;
	appearance: none;
}

/* Move the focus ring from the input itself to the bar it lives in. The
   input has no rounded corners of its own (see above), so its own
   :focus-visible ring would be a flat rectangle sitting almost flush with
   the bar's fully-rounded (9999px) left/right caps — the same clipped-edge
   clash this rule set exists to prevent. Suppress the input's own ring and
   let the bar (which already owns the pill shape) draw one ring around the
   whole component instead, scoped with :has() so it only fires for the
   input's focus, not the send button's (that button's own ring, from the
   general `.dote-assistant :focus-visible` rule, is unaffected). */
.dote-assistant__input:focus-visible {
	outline: none;
}

.dote-assistant__bar:has(> .dote-assistant__input:focus-visible) {
	outline: 3px solid var(--focus, #0b0b0b);
	outline-offset: 2px;
}

.dote-assistant[data-state="collapsed"] .dote-assistant__input {
	opacity: 0;
}

/* ---- Close (collapse) control ---------------------------------------------
   Lives in the panel header now (top-right of the expanded panel), not in the
   input bar — see .dote-assistant__panel-header below. Collapsed-state
   hiding is handled at the .dote-assistant__panel level (the whole panel,
   header included, disappears together), so this button no longer needs its
   own collapsed-state width/opacity hack. */
.dote-assistant__close {
	flex: 0 0 auto;
	width: 44px;
	height: 44px;
	border-radius: 9999px;
	border: 0;
	background: transparent;
	color: var(--muted, #6b6760);
	cursor: pointer;
	display: grid;
	place-items: center;
	opacity: 1;
	transition:
		color var(--motion-fast, 160ms) var(--ease, cubic-bezier(0.22, 1, 0.36, 1)),
		background-color var(--motion-fast, 160ms) var(--ease, cubic-bezier(0.22, 1, 0.36, 1)),
		opacity var(--motion-fast, 160ms) var(--ease, cubic-bezier(0.22, 1, 0.36, 1));
}

.dote-assistant__close:hover {
	color: var(--ink, #0b0b0b);
	background: var(--line, rgba(11, 11, 11, 0.08));
}

/* ---- Conversation panel ---------------------------------------------------
   Wraps the fixed-position header (close button, top-right) and the
   scrollable thread log beneath it. This element now owns the visual "card"
   chrome (surface/border/radius/shadow) and the panel's overall size that
   .dote-assistant__thread used to own by itself, so the header can sit
   outside the scrolling log but still inside the same rounded card. */
.dote-assistant__panel {
	pointer-events: auto;
	/* Narrower, taller "portrait phone" proportions rather than the previous
	   ~9:8 landscape card — roughly 400px wide with a 3:2 height:width max,
	   clamped to the viewport on small screens. */
	width: min(25rem, calc(100vw - 2rem));
	max-width: calc(100vw - 2rem);
	/* Explicit height (not just max-height) so the panel is a CONSTANT size
	   from the moment it expands, regardless of how much thread content has
	   accumulated — the thread's own overflow-y:auto (below) handles scroll
	   once content exceeds this. */
	height: min(65vh, 37.5rem);
	display: flex;
	flex-direction: column;
	overflow: hidden;
	background: var(--surface, #ffffff);
	border: 1px solid var(--line, rgba(11, 11, 11, 0.08));
	border-radius: var(--r-lg, 28px);
	box-shadow: var(--shadow-dropdown, 0 24px 50px rgba(0, 0, 0, 0.1));
}

/* Hidden until the widget is expanded (and only shown once the thread has
   content) — same "before expansion" contract .dote-assistant__thread used
   to enforce alone, now applied to the whole panel (header included) so the
   close button never renders as a visible empty box before the widget opens. */
.dote-assistant[data-state="collapsed"] .dote-assistant__panel,
.dote-assistant__panel:has(> .dote-assistant__thread:empty) {
	display: none;
}

/* Small fixed header row at the top of the panel, holding just the close
   control, top-right. Separate from the input/send row entirely. */
.dote-assistant__panel-header {
	flex: 0 0 auto;
	display: flex;
	justify-content: flex-end;
	padding: 6px 6px 0;
}

/* Reorder the launcher to the front of the row while collapsed so it always
   paints in full — any leftover space from the shrunk input spills off the
   right edge of the overflow:hidden bar instead of clipping the visible
   circle. */
.dote-assistant[data-state="collapsed"] .dote-assistant__action {
	order: -1;
}

/* ---- Conversation thread ------------------------------------------------- */
.dote-assistant__thread {
	/* Takes the remaining panel height below the fixed header and scrolls
	   internally once content exceeds it. */
	flex: 1 1 auto;
	min-height: 0;
	padding: 0 1rem 1rem;
	overflow-y: auto;
	overscroll-behavior: contain;
	scrollbar-width: thin;
}

/* ---- Messages ------------------------------------------------------------ */
.dote-assistant__msg {
	display: flex;
	align-items: flex-end;
	flex-wrap: wrap;
	gap: 8px;
	margin-bottom: 14px;
}

.dote-assistant__msg:last-child {
	margin-bottom: 0;
}

.dote-assistant__msg--user {
	flex-direction: row-reverse;
}

.dote-assistant__bubble {
	max-width: 84%;
	padding: 10px 14px;
	border-radius: var(--r-md, 20px);
	font-size: 0.95rem;
	line-height: 1.5;
}

.dote-assistant__msg--bot .dote-assistant__bubble {
	background: var(--bg, #faf8f2);
	color: var(--ink, #0b0b0b);
	border: 1px solid var(--line, rgba(11, 11, 11, 0.08));
	border-bottom-left-radius: 6px;
}

.dote-assistant__msg--user .dote-assistant__bubble {
	background: var(--accent, #0b0b0b);
	color: var(--accent-ink, #faf8f2);
	border-bottom-right-radius: 6px;
}

/* ---- Result cards --------------------------------------------------------
   Rendered by dotsa-assistant.js as a SIBLING of .dote-assistant__bubble
   inside the message container (.dote-assistant__msg), not nested inside
   the bubble — so cards span the thread's own content width (only the
   thread's own padding applies) instead of being squeezed inside the
   bubble's max-width/padding. `flex: 1 1 100%` forces this item onto its own
   full-width line in the (flex-wrap: wrap) message row, below the bubble. */
.dote-assistant__cards {
	display: flex;
	flex-direction: column;
	gap: 8px;
	flex: 1 1 100%;
}

.dote-assistant__card {
	display: flex;
	align-items: center;
	gap: 12px;
	padding: 8px;
	border: 1px solid var(--line, rgba(11, 11, 11, 0.08));
	border-radius: var(--r-md, 20px);
	background: var(--surface, #ffffff);
	color: var(--ink, #0b0b0b);
	text-decoration: none;
	transition:
		transform var(--motion-fast, 160ms) var(--ease, cubic-bezier(0.22, 1, 0.36, 1)),
		border-color var(--motion-fast, 160ms) var(--ease, cubic-bezier(0.22, 1, 0.36, 1));
}

.dote-assistant__card:hover,
.dote-assistant__card:focus-visible {
	transform: translateY(-1px);
	border-color: var(--ink, #0b0b0b);
}

.dote-assistant__thumb {
	flex: 0 0 auto;
	width: 56px;
	height: 56px;
	border-radius: var(--r-sm, 12px);
	object-fit: cover;
	background: var(--placeholder-base, rgba(11, 11, 11, 0.035));
}

/* Image-less products / page results get an on-brand "dot" placeholder tile
   instead of a stock or AI-generated image. */
.dote-assistant__thumb--empty {
	display: grid;
	place-items: center;
	color: var(--muted, #6b6760);
}

.dote-assistant__thumb--empty::after {
	content: "";
	width: 14px;
	height: 14px;
	border-radius: 9999px;
	background: currentColor;
	opacity: 0.55;
}

.dote-assistant__card-body {
	display: flex;
	flex-direction: column;
	gap: 3px;
	min-width: 0;
}

.dote-assistant__card-title {
	font-weight: 600;
	font-size: 0.92rem;
	line-height: 1.3;
	/* Two-line clamp so long ticket names don't blow out the card. */
	display: -webkit-box;
	-webkit-line-clamp: 2;
	-webkit-box-orient: vertical;
	overflow: hidden;
}

.dote-assistant__card-meta {
	display: flex;
	align-items: center;
	gap: 8px;
	flex-wrap: wrap;
	font-size: 0.8rem;
	color: var(--muted, #6b6760);
}

.dote-assistant__price {
	font-weight: 600;
	color: var(--ink, #0b0b0b);
}

.dote-assistant__tag {
	font-size: 0.68rem;
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: 0.08em;
	padding: 2px 8px;
	border-radius: 9999px;
	background: var(--bg, #faf8f2);
	border: 1px solid var(--line, rgba(11, 11, 11, 0.08));
	color: var(--muted, #6b6760);
}

.dote-assistant__oos {
	color: var(--muted, #6b6760);
	font-style: italic;
}

/* ---- Fallback / hand-off links inside a bot bubble ----------------------- */
.dote-assistant__links {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
	margin-top: 10px;
}

.dote-assistant__pill-link {
	display: inline-flex;
	align-items: center;
	padding: 8px 16px;
	border-radius: 9999px;
	font-size: 0.85rem;
	font-weight: 600;
	text-decoration: none;
	background: var(--accent, #0b0b0b);
	color: var(--accent-ink, #faf8f2);
	border: 1.5px solid var(--accent, #0b0b0b);
	transition: transform var(--motion-fast, 160ms) var(--ease, cubic-bezier(0.22, 1, 0.36, 1));
}

.dote-assistant__pill-link--ghost {
	background: transparent;
	color: var(--ink, #0b0b0b);
	border-color: var(--ink, #0b0b0b);
}

.dote-assistant__pill-link:hover,
.dote-assistant__pill-link:focus-visible {
	transform: translateY(-1px);
}

/* ---- "Searching…" typing indicator --------------------------------------- */
.dote-assistant__typing {
	display: inline-flex;
	align-items: center;
	gap: 5px;
}

.dote-assistant__typing span {
	width: 6px;
	height: 6px;
	border-radius: 9999px;
	background: currentColor;
	opacity: 0.5;
	animation: dote-assistant-bounce 1.2s infinite ease-in-out;
}

.dote-assistant__typing span:nth-child(2) {
	animation-delay: 0.15s;
}

.dote-assistant__typing span:nth-child(3) {
	animation-delay: 0.3s;
}

@keyframes dote-assistant-bounce {
	0%, 80%, 100% {
		transform: translateY(0);
		opacity: 0.35;
	}
	40% {
		transform: translateY(-4px);
		opacity: 0.9;
	}
}

/* ---- Reduced motion: honour both the OS signal and the theme's explicit
   data-motion="reduce" attribute. The morph, hover lifts, and typing dots all
   settle to a static state. ------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
	.dote-assistant *,
	.dote-assistant *::before,
	.dote-assistant *::after {
		transition-duration: 0.001ms !important;
		animation-duration: 0.001ms !important;
		animation-iteration-count: 1 !important;
	}
}

html[data-motion="reduce"] .dote-assistant *,
html[data-motion="reduce"] .dote-assistant *::before,
html[data-motion="reduce"] .dote-assistant *::after {
	transition-duration: 0.001ms !important;
	animation-duration: 0.001ms !important;
	animation-iteration-count: 1 !important;
}
