/* ==========================================================================
   Dash docked companion - Phase 2 (#3800)
   --------------------------------------------------------------------------
   The AI sidebar is no longer a slide-over: once opened it DOCKS to the right
   edge and the page compresses beside it, so the page and Dash are usable at
   once. Collapsed, it is the same floating Dash button the portal has always
   had (styles live in the component's own stylesheet).

   The panel keeps the portal's white chat surface - Dash is a working panel,
   not a themed one. The page brief (.ai-brief) is styled as a Dash message
   with its actions inline, so the whole panel reads as one conversation.

   Loaded from the base layout head (before overwriteThirdParty.css) so the
   compression class never flashes uncompressed on wire:navigate. Selectors
   are namespaced: `.main-wrapper[.dash-docked]` only touches the one layout
   wrapper and is inert until the class is present; everything else lives
   under `.ai-brief-*` / `.ed-row-mark*`.
   ========================================================================== */

:root {
	/* Kept in sync with the panel width in the component stylesheet - one knob
	   for both the panel and the compression it causes. */
	--dash-dock-w: 380px;
}

/* Page compression. The panel is position:fixed, so the content wrapper
   yields the same width. Desktop only - below lg the panel overlays like the
   old slide-over (with a backdrop, see the component stylesheet) and nothing
   compresses. The transition lives on the bare class so collapse/expand
   animates both ways; margin-right is 0 without .dash-docked, so this is
   inert elsewhere. */
.main-wrapper {
	transition: margin-right 0.25s ease;
}

@media (min-width: 992px) {
	.main-wrapper.dash-docked {
		margin-right: var(--dash-dock-w);
	}

	/* Dashboard / report stat-card rows: the row's horizontal scroll is dead
	   (.custom-tooltip-dashboard forces overflow visible so tooltips aren't
	   clipped, and the reports row never had it), so docked, the fixed-width
	   cards run under the panel. Let the row wrap - inert while they fit. */
	.main-wrapper.dash-docked .sales-widgets {
		flex-wrap: wrap;
	}

	/* Waiver/form builder: the canvas column is flex-grow with min-width:auto,
	   so its intrinsic width (logo row, table elements) wins over the shrunk
	   page and the canvas runs under the panel. Let it shrink and scroll. */
	.main-wrapper.dash-docked .form-builder-wrapper .form-content {
		min-width: 0;
		overflow-x: auto;
	}

	/* Manifests toolbar (date nav + filters + scan) is one nowrap row. */
	.main-wrapper.dash-docked .manifests-toolbar {
		flex-wrap: wrap;
	}

	/* POS cart header: title + action buttons don't fit the narrowed cart
	   column side by side - let the buttons drop to a second line. */
	.main-wrapper.dash-docked .pos-cart-header {
		flex-wrap: wrap;
		row-gap: 6px;
	}

	/* Settings permission chips (Team roles): a long chip is nowrap and juts
	   out of its table cell when the cell narrows - let its text wrap. */
	.main-wrapper.dash-docked .settings-content-container .badge.bg-light,
	.main-wrapper.dash-docked .settings-content-wraper .badge.bg-light {
		white-space: normal;
		text-align: left;
	}
}

/* Docked, the page must follow the same responsive pattern it would use at
   (viewport - panel) width. The portal's breakpoints key off the viewport, so
   they never fire when the panel eats 380px - a 1200px window docked renders
   full desktop chrome into ~580px and the title bar, tab rows and filter
   buttons clip under the panel. 992 + 380 = 1372: below this a docked page
   has less than the 992px desktop minimum, so the left nav goes off-canvas
   behind the hamburger and the listing toolbar wraps - exactly what style.css
   does below 992px undocked. Same rules, shifted by the panel width. */
@media (min-width: 992px) and (max-width: 1371.98px) {
	.main-wrapper.dash-docked .sidebar {
		margin-left: -300px;
		width: 80%;
		max-width: 300px;
	}

	.main-wrapper.dash-docked .sidebar.show {
		margin-left: 0;
	}

	.main-wrapper.dash-docked .content {
		padding-left: 0;
	}

	/* The pd-/sd- detail headers carry their own chrome instead of .title -
	   they include the same sidebar-toggle partial, shown here too. */
	.main-wrapper.dash-docked .content .title .menu-icon,
	.main-wrapper.dash-docked .content .pd-header .menu-icon,
	.main-wrapper.dash-docked .content .sd-header .menu-icon {
		display: block;
		cursor: pointer;
		margin-left: 8px;
		margin-right: 12px;
	}

	.main-wrapper.dash-docked .content .title .menu-icon:hover {
		background-color: #00000014;
	}

	/* Listing toolbar: search box and filter dropdowns wrap instead of
	   clipping (mirror of the max-width:991px booking-content-header rules). */
	.main-wrapper.dash-docked .booking-content-header > .col,
	.main-wrapper.dash-docked .booking-content-header > .col-md-3,
	.main-wrapper.dash-docked .booking-content-header > .col-md-9 {
		flex: 0 0 100%;
		max-width: 100%;
	}

	.main-wrapper.dash-docked .booking-content-header .search-input {
		justify-content: flex-start !important;
		flex-wrap: wrap;
	}

	.main-wrapper.dash-docked .booking-content-header .search-input .input-group {
		max-width: none;
		flex: 1 1 150px;
		min-width: 150px;
	}

	.main-wrapper.dash-docked .booking-content-header .search-input .dropdown-filter {
		flex-shrink: 0;
	}

	.main-wrapper.dash-docked .global-search-container {
		max-width: 100%;
	}

	/* Listing filter rows outside .booking-content-header (experiences,
	   categories) nest the search box and dropdowns in one nowrap flex row -
	   wrap the row and its inner group instead of clipping the dropdowns. */
	.main-wrapper.dash-docked .search-input,
	.main-wrapper.dash-docked .search-input > .d-flex {
		flex-wrap: wrap;
	}

	/* Bootstrap display utilities key off the viewport too, so a control a
	   page hides below lg (the title-bar global search, an extra header
	   button) stays visible docked and clips under the panel. Mirror the
	   below-lg state: shown-from-lg-up hides, shown-below-lg shows. Scoped
	   to .content: the off-canvas nav's own d-* internals (e.g. the
	   .user-info row) must keep their real-viewport behavior. */
	.main-wrapper.dash-docked .content .d-none.d-lg-block,
	.main-wrapper.dash-docked .content .d-none.d-lg-flex,
	.main-wrapper.dash-docked .content .d-none.d-lg-inline-block,
	.main-wrapper.dash-docked .content .d-none.d-lg-inline-flex {
		display: none !important;
	}

	.main-wrapper.dash-docked .content .d-flex.d-lg-none,
	.main-wrapper.dash-docked .content .d-inline-flex.d-lg-none {
		display: flex !important;
	}

	.main-wrapper.dash-docked .content .d-lg-none:not(.d-flex):not(.d-inline-flex) {
		display: block !important;
	}

	/* Tab strips (.eq-tabs) are flex-wrap:nowrap so their dropdowns aren't
	   clipped by a scroll container - docked, a long strip (program detail,
	   bookings) runs under the panel instead. Wrap: the ms-auto extras keep
	   their right alignment on whatever row they land on. */
	.main-wrapper.dash-docked .nav-tabs.eq-tabs {
		flex-wrap: wrap;
	}

	/* POS pill strip (booking-type pills + search + category/status
	   dropdowns) is one nowrap row - wrap it rather than clip the trailing
	   dropdowns. */
	.main-wrapper.dash-docked .pos-filter-strip {
		flex-wrap: wrap;
	}
}

/* /settings/ai-bookings lays its launcher form out on a 3-column grid that
   its own stylesheet collapses at 900px - mirror that at 900 + 380. */
@media (min-width: 992px) and (max-width: 1279.98px) {
	.main-wrapper.dash-docked .dash-lf-grid {
		grid-template-columns: 1fr;
	}

	.main-wrapper.dash-docked .dash-stats {
		grid-template-columns: 1fr 1fr;
	}

	.main-wrapper.dash-docked .dash-select,
	.main-wrapper.dash-docked .dash-split-l {
		min-width: 0;
		max-width: none;
		width: 100%;
	}
}

/* Below-md equivalent: 768 + 380 = 1148. Same mirror one tier down - pages
   swap header buttons and toolbars on d-md-* utilities. */
@media (min-width: 992px) and (max-width: 1147.98px) {
	.main-wrapper.dash-docked .content .d-none.d-md-block,
	.main-wrapper.dash-docked .content .d-none.d-md-flex,
	.main-wrapper.dash-docked .content .d-none.d-md-inline-block,
	.main-wrapper.dash-docked .content .d-none.d-md-inline-flex {
		display: none !important;
	}

	.main-wrapper.dash-docked .content .d-flex.d-md-none,
	.main-wrapper.dash-docked .content .d-inline-flex.d-md-none {
		display: flex !important;
	}

	.main-wrapper.dash-docked .content .d-md-none:not(.d-flex):not(.d-inline-flex) {
		display: block !important;
	}

	/* Stack-below-md rows (.flex-column.flex-md-row) stack docked too. */
	.main-wrapper.dash-docked .flex-column.flex-md-row {
		flex-direction: column !important;
	}

	/* Settings data tables must scroll, never crush (the same fix style.css
	   carries at max-width:767px - docked below 1148 the page has the same
	   effective width, so the same squeeze applies: columns snap to
	   min-content and the rest clips under the panel). */
	.main-wrapper.dash-docked .settings-content-wraper .table-responsive > table,
	.main-wrapper.dash-docked .settings-content-container .table-responsive > table {
		width: max-content;
		min-width: 100%;
	}

	.main-wrapper.dash-docked .table-responsive > table.table-fixed-cols {
		table-layout: auto;
		width: max-content;
		min-width: 100%;
	}

	.main-wrapper.dash-docked .inv-accordion {
		overflow-x: auto;
	}

	/* POS: the cart is d-none d-md-flex, so the mirror above would hide it -
	   but a cashier needs the cart. Use the page's own phone pattern instead
	   (the max-width:575px block): stack it under the catalog, full width. */
	.main-wrapper.dash-docked .booking-layout {
		flex-direction: column;
	}

	.main-wrapper.dash-docked .booking-layout .booking-content,
	.main-wrapper.dash-docked .booking-layout .booking-checkout {
		max-width: 100%;
		flex: 0 0 100%;
		width: 100%;
	}

	.main-wrapper.dash-docked .booking-layout .booking-checkout {
		display: flex !important;
		border-top: 1px solid var(--pos-line, #E8ECF1);
	}
}

/* --- The page brief (#3800 unified panel) ---------------------------------
   One bubble pinned above the composer: greeting lede, fact rows with their
   action button inline, per-page suggested questions. Styled like a Dash
   message so the whole panel reads as one conversation. */
.ai-brief {
	margin: 8px 14px 10px;
	background: #F3F4F6;
	border-radius: 12px;
	padding: 11px 13px 9px;
	flex-shrink: 0;
	max-height: 45%;
	overflow-y: auto;
}

.ai-brief-lede {
	font-size: 12.5px;
	line-height: 1.5;
	color: #1F2A37;
	margin-bottom: 4px;
}

.ai-brief-clear {
	font-size: 12.5px;
	line-height: 1.5;
	color: #1F2A37;
}

.ai-brief-item {
	padding: 7px 0;
}

.ai-brief-item-row {
	display: flex;
	align-items: center;
	gap: 9px;
}

.ai-brief-item + .ai-brief-item {
	border-top: 1px solid #E5E7EB;
}

.ai-brief-icon {
	flex-shrink: 0;
	display: inline-flex;
	width: 16px;
	justify-content: center;
	color: var(--ed-text-muted, #5A7089);
}

.ai-brief-icon-warning { color: #b45309; }
.ai-brief-icon-danger { color: #dc2626; }

.ai-brief-text {
	flex: 1;
	min-width: 0;
	font-size: 12px;
	line-height: 1.4;
	color: #1F2A37;
}

/* The action beside its fact. White on the grey bubble, portal navy. */
.ai-brief-act {
	flex-shrink: 0;
	background: #fff;
	border: 1px solid #CBD5E1;
	border-radius: 8px;
	padding: 5.5px 11px;
	font-size: 11px;
	font-weight: 600;
	color: #003264;
	cursor: pointer;
	white-space: nowrap;
	transition: background 0.15s ease, border-color 0.15s ease;
}

.ai-brief-act:hover:not(:disabled) {
	background: #F1F5F9;
	border-color: #94A3B8;
}

.ai-brief-act:disabled {
	opacity: 0.6;
	cursor: default;
}

/* Approve? / Cancel for money and customer-facing actions (#4036). The fact
   text sits on the same row, so "Approve?" is unambiguous - and it pulses
   once a second so the eye cannot miss which button is armed. */
.ai-brief-act.ai-brief-act-approve {
	background: #16a34a;
	border-color: #16a34a;
	color: #fff;
	animation: ai-approve-pulse 1.2s ease-in-out infinite;
}

.ai-brief-act.ai-brief-act-approve:hover:not(:disabled) {
	background: #15803d;
	border-color: #15803d;
	animation: none;
}

@keyframes ai-approve-pulse {
	0%, 100% { box-shadow: 0 0 0 0 rgba(22, 163, 74, 0.45); }
	50% { box-shadow: 0 0 0 5px rgba(22, 163, 74, 0); }
}

.ai-brief-act.ai-brief-act-cancel {
	background: transparent;
	border-color: transparent;
	color: var(--ed-text-muted, #5A7089);
}

.ai-brief-act.ai-brief-act-cancel:hover:not(:disabled) {
	background: #F1F5F9;
	border-color: transparent;
	color: #1F2A37;
}

/* Navigate chips read as links, not commands. */
.ai-brief-act.ai-brief-act-link {
	background: transparent;
	border-color: transparent;
	text-decoration: underline;
	padding-left: 4px;
	padding-right: 4px;
}

.ai-brief-act.ai-brief-act-link:hover:not(:disabled) {
	background: transparent;
	border-color: transparent;
	color: #00264d;
}

/* The result of a run: its own full-width line under the fact (#4035). */
.ai-brief-outcome {
	margin: 5px 0 0 25px;
	font-size: 11px;
	font-weight: 600;
	line-height: 1.45;
	color: #166534;
}

.ai-brief-outcome.ai-brief-outcome-error {
	color: #b91c1c;
}

/* style.css sets a global a { display: block }; the "Show them" link must
   flow inside the outcome sentence. */
.ai-brief-outcome a {
	display: inline;
	color: inherit;
	font-weight: 700;
	text-decoration: underline;
}

/* Suggested questions - tappable prompts, per page family. */
.ai-brief-sugs {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 6px;
	margin-top: 9px;
}

.ai-brief-sug {
	background: #fff;
	border: 1px solid #E2E8F0;
	border-radius: 999px;
	padding: 6px 13px;
	font-size: 11.5px;
	color: var(--ed-text-muted, #5A7089);
	cursor: pointer;
	text-align: left;
	transition: color 0.15s ease, border-color 0.15s ease;
}

.ai-brief-sug:hover {
	border-color: #94A3B8;
	color: #003264;
}

/* --- In-place row markers (#3803) ------------------------------------------
   The "Chased · Returns · 2m ago" pill on list rows after a chip runs.
   Rendered server-side from the recent-action cache and instantly by
   public/js/ai-row-marks.js - same look both ways. */
.ed-row-mark {
	display: inline-block;
	margin-top: 4px;
	font-size: 10.5px;
	font-weight: 700;
	color: #003264;
	background: #E2E8F0;
	border-radius: 999px;
	padding: 2.5px 10px;
	white-space: nowrap;
}

.ed-row-mark-link {
	display: inline; /* style.css sets a global a { display: block } */
	margin-left: 6px;
	font-weight: 700;
	color: #003264;
	text-decoration: none;
}

.ed-row-mark-link:hover {
	text-decoration: underline;
}

/* --- Inline Dash input, expand-to-dock (#3800) -----------------------------
   The embedded page input and the docked panel are ONE companion: the input
   carries an expand control that docks the panel, and the input hides itself
   while the panel is docked so the page never shows two Dash affordances. */
.inline-ai-dock-btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	flex-shrink: 0;
	width: 26px;
	height: 26px;
	margin-left: 2px;
	padding: 0;
	border: none;
	border-radius: 7px;
	background: transparent;
	color: var(--ed-text-muted, #5A7089);
	cursor: pointer;
	transition: background 0.15s ease, color 0.15s ease;
}

.inline-ai-dock-btn:hover {
	background: #F1F5F9;
	color: #003264;
}

/* One Dash per page. While the panel is docked the embedded input is
   redundant - and two Dash inputs on one screen is exactly the "which one do
   I use?" the companion is meant to end. Driven off the same .dash-docked
   class the layout renders server-side and the panel's Alpine keeps in sync,
   so it tracks dock/collapse in both directions with no events. */
.main-wrapper.dash-docked .inline-ai-input {
	display: none;
}
/* Mobile: the brief's buttons and suggestion pills meet the 44px touch
   minimum (ui-design rule). Desktop keeps the compact size. */
@media (max-width: 576px) {
	.ai-brief-act {
		min-height: 44px;
		padding: 10px 14px;
		font-size: 12px;
	}

	.inline-ai-dock-btn {
		width: 44px;
		height: 44px;
	}

	.ai-brief-sug {
		min-height: 44px;
		display: inline-flex;
		align-items: center;
		padding: 10px 16px;
		font-size: 12.5px;
	}
}
