/* ==========================================================================
   MY EXOTIC — customer product controls on public surfaces
   Save control, compare toggle, compare tray, and the write toast.

   These render on listing and profile pages, outside the `.my-exotic`
   workspace scope, so the tokens are declared again here rather than
   inherited. Values are the DESIGN.md set — no second red, no gold except
   focus, no radius or spacing outside the shipped scales.
   ========================================================================== */

.mx-save,
.mx-compare-toggle,
.mx-follow,
.mx-save-search,
.mx-profile-save,
.mx-tray,
.mx-toast {
	--mx-surface: #1A1A1A;
	--mx-surface-subtle: #222222;
	--mx-surface-elevated: #2A2A2A;
	--mx-border-subtle: #2E2E2E;
	--mx-border-default: #3A3A3A;
	--mx-ink: #ECECEC;
	--mx-muted: #B4B4B4;
	--mx-gold: #E6C46A;
	--mx-error: #EF4444;
	--mx-primary: #8B0A1A;
	--mx-primary-active: #6E0816;
	--mx-radius-md: 10px;
	--mx-radius-lg: 14px;
	--mx-font: 'Manrope', 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
	box-sizing: border-box;
	font-family: var(--mx-font);
}

.mx-save:focus-visible,
.mx-compare-toggle:focus-visible,
.mx-follow:focus-visible,
.mx-save-search:focus-visible,
.mx-profile-save:focus-visible,
.mx-tray :is(a, button):focus-visible {
	outline: 2px solid var(--focus-ring-color, #FFFFFF);
	outline-offset: 3px;
}

/* ---------- Save control ----------------------------------------------------
   The visual box is 32px; the hit area is padded out to 44px. It sits at the
   bottom-right of the media because that is the reachable corner one-handed at
   390px — the badge keeps the top-left, which is a read target, not a tap one.
   -------------------------------------------------------------------------- */

.mx-save {
	position: absolute;
	right: 0;
	bottom: 0;
	z-index: 3;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	/* 44px hit area around a 32px visual box. */
	width: 44px;
	height: 44px;
	padding: 6px;
	margin: 0;
	border: 0;
	background: none;
	color: var(--mx-ink);
	cursor: pointer;
	-webkit-appearance: none;
	appearance: none;
}

.mx-save__mark {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 32px;
	height: 32px;
	border-radius: var(--mx-radius-md);
	border: 1px solid rgba(236, 236, 236, 0.28);
	background: rgba(14, 14, 14, 0.62);
	backdrop-filter: blur(6px);
	transition: background 150ms cubic-bezier(0.4, 0, 0.2, 1),
		border-color 150ms cubic-bezier(0.4, 0, 0.2, 1);
}

.mx-save:hover .mx-save__mark {
	background: rgba(20, 20, 20, 0.86);
	border-color: rgba(236, 236, 236, 0.48);
}

.mx-save.is-saved .mx-save__mark {
	border-color: rgba(236, 236, 236, 0.7);
	background: rgba(20, 20, 20, 0.9);
}

.mx-save .mx-icon {
	width: 20px;
	height: 20px;
}

.mx-save[disabled] {
	opacity: 0.5;
	cursor: default;
}

/* Pending replaces the mark with a spinner inside the same 32px box, so the
   control never changes size mid-write. */
.mx-save__spinner {
	display: none;
	position: absolute;
	width: 16px;
	height: 16px;
	border-radius: 999px;
	border: 2px solid rgba(236, 236, 236, 0.28);
	border-top-color: var(--mx-ink);
	animation: mx-spin 700ms linear infinite;
}

.mx-save.is-pending .mx-save__mark .mx-icon {
	opacity: 0;
}

.mx-save.is-pending .mx-save__spinner {
	display: block;
}

@keyframes mx-spin {
	to {
		transform: rotate(360deg);
	}
}

@media (prefers-reduced-motion: reduce) {
	.mx-save__spinner {
		animation-duration: 2s;
	}
}

/* ---------- Compare toggle ---------- */

.mx-compare-toggle {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 8px;
	min-height: 44px;
	padding: 0 16px;
	border-radius: var(--mx-radius-md);
	border: 1px solid var(--mx-border-default);
	background: var(--mx-surface-subtle);
	color: var(--mx-ink);
	font-size: 14px;
	font-weight: 600;
	line-height: 1;
	cursor: pointer;
	transition: background 150ms cubic-bezier(0.4, 0, 0.2, 1),
		border-color 150ms cubic-bezier(0.4, 0, 0.2, 1);
}

.mx-compare-toggle:hover {
	background: var(--mx-surface-elevated);
}

.mx-compare-toggle.is-selected {
	border-color: rgba(236, 236, 236, 0.6);
	background: var(--mx-surface-elevated);
}

.mx-compare-toggle[disabled] {
	opacity: 0.55;
	cursor: default;
}

.mx-compare-toggle .mx-icon {
	width: 20px;
	height: 20px;
	flex: 0 0 auto;
}

.mx-hint {
	display: block;
	margin: 8px 0 0;
	font-size: 12px;
	font-weight: 500;
	line-height: 1.4;
	color: var(--mx-muted);
}

/* ---------- Follow and saved search controls ----------------------------- */

.mx-follow,
.mx-save-search {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 8px;
	min-height: 44px;
	min-width: 132px;
	padding: 0 16px;
	border-radius: var(--mx-radius-md);
	border: 1px solid var(--mx-border-default);
	background: var(--mx-surface-subtle);
	color: var(--mx-ink);
	font-size: 14px;
	font-weight: 600;
	line-height: 1;
	cursor: pointer;
	transition: background 150ms cubic-bezier(0.4, 0, 0.2, 1),
		border-color 150ms cubic-bezier(0.4, 0, 0.2, 1),
		transform 150ms cubic-bezier(0.4, 0, 0.2, 1);
}

.mx-follow:hover,
.mx-save-search:hover {
	background: var(--mx-surface-elevated);
	border-color: rgba(236, 236, 236, 0.42);
}

.mx-follow:active,
.mx-save-search:active {
	transform: translateY(1px);
}

.mx-follow.is-following,
.mx-save-search.is-saved {
	border-color: rgba(236, 236, 236, 0.6);
	background: var(--mx-surface-elevated);
}

.mx-follow[disabled],
.mx-save-search[disabled] {
	opacity: 0.58;
	cursor: default;
	transform: none;
}

.mx-follow .mx-icon,
.mx-save-search .mx-icon {
	width: 20px;
	height: 20px;
	flex: 0 0 auto;
}

.discovery-hero__actions {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 8px;
	margin-top: 16px;
}

.listing-context__actions {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 8px;
	margin-top: 12px;
}

.discovery-hero__actions .mx-follow,
.discovery-hero__actions .mx-save-search,
.listing-context__actions .mx-follow {
	background: rgba(34, 34, 34, 0.88);
	backdrop-filter: blur(8px);
}

/* ---------- Profile detail save + compare pair ---------- */

.profile-save-actions {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: center;
	gap: 8px;
	margin: 16px 0 0;
}

.mx-profile-save {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 8px;
	min-height: 44px;
	/* Sized for the longer of the two labels so the pending and saved states
	   never reflow the row. */
	min-width: 132px;
	padding: 0 16px;
	border-radius: var(--mx-radius-md);
	border: 1px solid var(--mx-border-default);
	background: var(--mx-surface-subtle);
	color: var(--mx-ink);
	font-family: var(--mx-font);
	font-size: 14px;
	font-weight: 600;
	line-height: 1;
	cursor: pointer;
	transition: background 150ms cubic-bezier(0.4, 0, 0.2, 1),
		border-color 150ms cubic-bezier(0.4, 0, 0.2, 1);
}

.mx-profile-save:hover {
	background: var(--mx-surface-elevated);
}

.mx-profile-save.is-saved {
	border-color: rgba(236, 236, 236, 0.6);
	background: var(--mx-surface-elevated);
}

.mx-profile-save[disabled] {
	opacity: 0.6;
	cursor: default;
}

.mx-profile-save.is-pending {
	opacity: 0.75;
}

.mx-profile-save .mx-icon,
.mx-save .mx-icon,
.mx-compare-toggle .mx-icon {
	flex: 0 0 auto;
	width: 20px;
	height: 20px;
}

/* ---------- Compare tray ----------------------------------------------------
   A slim bar, not a modal: the member is mid-browse and a modal would
   interrupt the scanning the tray exists to support.

   The bottom slot has one owner. Where a profile FAB or the My Exotic bottom
   nav already occupies it, the tray docks above that instead of over it.
   -------------------------------------------------------------------------- */

.mx-tray {
	position: fixed;
	left: 0;
	right: 0;
	bottom: 0;
	z-index: 1090;
	display: none;
	padding: 0 12px calc(12px + env(safe-area-inset-bottom, 0px));
	pointer-events: none;
}

.mx-tray.is-open {
	display: block;
}

.mx-tray[hidden] {
	display: none;
}

.mx-tray__inner {
	pointer-events: auto;
	display: flex;
	align-items: center;
	gap: 12px;
	max-width: 1240px;
	margin: 0 auto;
	min-height: 56px;
	padding: 8px 12px;
	border-radius: var(--mx-radius-lg);
	border: 1px solid var(--mx-border-subtle);
	background: rgba(20, 20, 20, 0.96);
	backdrop-filter: blur(10px);
	box-shadow: 0 8px 24px rgba(0, 0, 0, 0.5);
}

.mx-tray__count {
	flex: 0 0 auto;
	font-size: 12px;
	font-weight: 600;
	line-height: 1.35;
	color: var(--mx-muted);
	white-space: nowrap;
}

.mx-tray__items {
	flex: 1 1 auto;
	display: flex;
	align-items: center;
	gap: 8px;
	margin: 0;
	padding: 0;
	list-style: none;
	overflow-x: auto;
	scrollbar-width: none;
}

.mx-tray__items::-webkit-scrollbar {
	display: none;
}

.mx-tray__item {
	position: relative;
	flex: 0 0 auto;
	width: 32px;
	height: 42px;
	border-radius: 6px;
	background: #101010;
	border: 1px solid var(--mx-border-subtle);
}

.mx-tray__item img {
	border-radius: 5px;
}

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

/* The visible × sits on a 32px thumbnail, but the hit area is padded out past
   it to 44px in both dimensions — the same "hit area extends past the visual
   box" rule the listing-card save control follows. */
.mx-tray__remove {
	position: absolute;
	top: 50%;
	left: 50%;
	transform: translate(-50%, -50%);
	width: 44px;
	height: 44px;
	display: flex;
	align-items: flex-start;
	justify-content: flex-end;
	padding: 0;
	border: 0;
	background: none;
	color: var(--mx-ink);
	font-size: 14px;
	line-height: 1;
	cursor: pointer;
}

.mx-tray__remove::before {
	content: "";
	position: absolute;
	top: 1px;
	left: 6px;
	width: 32px;
	height: 42px;
	border-radius: 6px;
	background: linear-gradient(180deg, rgba(6, 6, 6, 0.78) 0%, rgba(6, 6, 6, 0) 62%);
	pointer-events: none;
}

.mx-tray__remove span {
	position: relative;
	padding: 2px 8px 2px 4px;
}

/* The single red element in this viewport: the commit action that opens the
   comparison. Light ink on burgundy — never black. */
.mx-tray__open {
	flex: 0 0 auto;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-height: 44px;
	padding: 0 16px;
	border-radius: var(--mx-radius-md);
	border: 1px solid var(--mx-primary);
	background: var(--mx-primary);
	color: var(--mx-ink);
	font-size: 14px;
	font-weight: 600;
	line-height: 1;
	text-decoration: none;
	white-space: nowrap;
}

.mx-tray__open:hover,
.mx-tray__open:focus {
	background: var(--mx-primary-active);
	border-color: var(--mx-primary-active);
	color: var(--mx-ink);
}

/* One red per viewport, and it belongs to the commit action. On a profile page
   the commit action is Call/WhatsApp in the FAB, so the tray's open button
   steps down to neutral there — if two controls want to be red, one of them is
   not the commit action. On listing pages nothing else claims it and the tray
   keeps the burgundy. */
body.mx-has-profile-fab .mx-tray__open {
	background: var(--mx-surface-elevated);
	border-color: var(--mx-border-default);
	color: var(--mx-ink);
}

body.mx-has-profile-fab .mx-tray__open:hover,
body.mx-has-profile-fab .mx-tray__open:focus {
	background: var(--mx-surface-subtle);
	border-color: var(--mx-border-strong, #4A4A4A);
	color: var(--mx-ink);
}

/* Dock above whichever fixed bar already owns the bottom slot. The bottom nav
   is 59px tall, so 71px leaves a clear 12px channel between the two — the old
   8px let the puck's shadow bleed into the bar and read as one crowded stack. */
body.my-exotic-bottom-nav .mx-tray {
	bottom: calc(71px + env(safe-area-inset-bottom, 0px));
	padding-bottom: 0;
}

/*
 * The compare page has a compare table on it. A floating shortlist bar over the
 * surface whose entire job is showing that shortlist is one control too many.
 */
body.my-exotic-surface-compare .mx-tray {
	display: none;
}

@media (max-width: 768px) {
	/* The FAB is 66px tall and sits 14px from the bottom, so its top edge is at
	   80px. Docking at 88px leaves one 8px gap between the two bars. */
	body.mx-has-profile-fab .mx-tray {
		bottom: calc(88px + env(safe-area-inset-bottom, 0px));
		padding-bottom: 0;
	}
}

/* ---------- Collapsed tray: the puck ----------
   Scrolling down folds the bar into a 52px puck in the corner; scrolling back
   up, or tapping the puck, restores it. The bar is where you finish comparing;
   the puck is how you keep browsing without losing the shortlist. */

.mx-tray__puck {
	pointer-events: auto;
	position: absolute;
	right: 12px;
	bottom: 0;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 52px;
	height: 52px;
	padding: 0;
	border-radius: 999px;
	border: 1px solid var(--mx-border-subtle);
	background: rgba(20, 20, 20, 0.96);
	backdrop-filter: blur(10px);
	box-shadow: 0 8px 24px rgba(0, 0, 0, 0.5);
	color: var(--mx-ink);
	cursor: pointer;
	/* Transform and opacity only. */
	opacity: 0;
	transform: scale(0.8) translateY(8px);
	transition: opacity 150ms cubic-bezier(0.4, 0, 0.2, 1), transform 260ms cubic-bezier(0.22, 1, 0.36, 1);
}

.mx-tray__puck svg {
	width: 22px;
	height: 22px;
}

/* The count is a number as well as a dot, so it is never colour alone. */
.mx-tray__puck-count {
	position: absolute;
	top: -2px;
	right: -2px;
	min-width: 20px;
	height: 20px;
	padding: 0 5px;
	display: flex;
	align-items: center;
	justify-content: center;
	border-radius: 999px;
	background: var(--mx-brand, #8B0A1A);
	color: #ECECEC;
	font-size: 11px;
	font-weight: 700;
	line-height: 1;
}

/*
 * `[hidden]` is a UA rule and loses to any class selector that sets display,
 * so the two states are said explicitly in both directions.
 */
.mx-tray:not(.is-collapsed) .mx-tray__puck {
	opacity: 0;
	transform: scale(0.8) translateY(8px);
	pointer-events: none;
	visibility: hidden;
}

.mx-tray.is-collapsed .mx-tray__puck {
	opacity: 1;
	transform: none;
	pointer-events: auto;
	visibility: visible;
}

.mx-tray.is-collapsed .mx-tray__inner {
	opacity: 0;
	transform: translateY(12px) scale(0.98);
	pointer-events: none;
	visibility: hidden;
}

.mx-tray__inner {
	transition: opacity 150ms cubic-bezier(0.4, 0, 0.2, 1), transform 260ms cubic-bezier(0.22, 1, 0.36, 1);
	transform-origin: bottom right;
}

/*
 * Reduced motion keeps the state change and drops the travel. The tray still
 * collapses — the feedback is not removed, only the movement.
 */
@media (prefers-reduced-motion: reduce) {

	.mx-tray__puck,
	.mx-tray__inner {
		transition: opacity 0.01ms !important;
		transform: none !important;
	}

	.mx-tray.is-collapsed .mx-tray__inner {
		transform: none !important;
	}
}

/* Reserve room so the tray never covers the last row of results. The workspace
   stacks its own bottom-nav reservation on top of this in `my-exotic.css`. */
body.mx-tray-open {
	padding-bottom: calc(72px + env(safe-area-inset-bottom, 0px));
}

/* Collapsed, the tray only needs room for the puck. */
body.mx-tray-open.mx-tray-collapsed {
	padding-bottom: calc(24px + env(safe-area-inset-bottom, 0px));
}

@media (max-width: 768px) {
	body.mx-tray-open.mx-has-profile-fab {
		padding-bottom: calc(146px + env(safe-area-inset-bottom, 0px));
	}
}

/* ---------- Write toast ---------- */

.mx-toast {
	position: fixed;
	left: 50%;
	bottom: calc(24px + env(safe-area-inset-bottom, 0px));
	z-index: 1120;
	transform: translate(-50%, 12px);
	max-width: min(92vw, 420px);
	padding: 12px 16px;
	border-radius: var(--mx-radius-md);
	border: 1px solid var(--mx-border-subtle);
	background: rgba(26, 26, 26, 0.98);
	color: var(--mx-ink);
	font-size: 14px;
	font-weight: 600;
	line-height: 1.35;
	text-align: center;
	opacity: 0;
	pointer-events: none;
	transition: opacity 150ms cubic-bezier(0.4, 0, 0.2, 1),
		transform 150ms cubic-bezier(0.4, 0, 0.2, 1);
}

.mx-toast.is-visible {
	opacity: 1;
	transform: translate(-50%, 0);
}

.mx-toast.is-error {
	border-color: var(--mx-error);
}

body.mx-tray-open .mx-toast {
	bottom: calc(84px + env(safe-area-inset-bottom, 0px));
}

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

/* ---------- Member report control (profile pages) ---------------------------
   Phase 7. Renders in place of the parent theme's report trigger, and only for
   a signed-in member on the CRM path. The panel is closed by default: it is a
   rare action, and an open form under every profile is noise.

   The panel's only red is the send button — on a profile page the fixed FAB
   already owns the viewport's commit action, so this control is deliberately
   inside a collapsed panel and never on screen at the same time as the FAB's
   Call button in an expanded state.
   -------------------------------------------------------------------------- */

.mx-report {
	--mx-surface: #1A1A1A;
	--mx-surface-subtle: #222222;
	--mx-border-subtle: #2E2E2E;
	--mx-border-default: #3A3A3A;
	--mx-ink: #ECECEC;
	--mx-muted: #B4B4B4;
	--mx-faint: #8A8A8A;
	--mx-gold: #E6C46A;
	--mx-error: #EF4444;
	--mx-primary: #8B0A1A;
	--mx-primary-active: #6E0816;
	--mx-radius-sm: 6px;
	--mx-radius-md: 10px;
	--mx-radius-lg: 14px;
	--mx-font: 'Manrope', 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
	box-sizing: border-box;
	display: block;
	font-family: var(--mx-font);
}

.profile-page .profile-report-zone .mx-report {
	display: grid !important;
	justify-items: center !important;
	width: 100% !important;
}

.mx-report *,
.mx-report *::before,
.mx-report *::after {
	box-sizing: border-box;
}

.mx-report :is(a, button, select, textarea):focus-visible {
	outline: 2px solid var(--focus-ring-color, #FFFFFF);
	outline-offset: 3px;
}

.mx-report .mx-button {
	display: inline-flex;
	gap: 8px;
	align-items: center;
	justify-content: center;
	min-height: 44px;
	padding: 0 16px;
	border: 1px solid var(--mx-border-default);
	border-radius: var(--mx-radius-md);
	background: var(--mx-surface-subtle);
	color: var(--mx-ink);
	font-family: inherit;
	font-size: 14px;
	font-weight: 600;
	line-height: 1;
	cursor: pointer;
	text-decoration: none;
}

.profile-page .profile-report-zone .mx-report__open.mx-button {
	min-height: 44px !important;
	padding: 0 14px !important;
	border-color: rgba(236, 236, 236, 0.1) !important;
	background: transparent !important;
	color: rgba(236, 236, 236, 0.56) !important;
	font-size: 13px !important;
	font-weight: 650 !important;
}

.profile-page .profile-report-zone .mx-report__open.mx-button:hover {
	border-color: rgba(236, 236, 236, 0.2) !important;
	color: rgba(236, 236, 236, 0.76) !important;
}

.mx-report .mx-button svg {
	width: 20px;
	height: 20px;
}

/* `[hidden]` is a UA rule and loses to the class selector above, so the open
   trigger would stay on screen beside its own panel without this. */
.mx-report .mx-button[hidden] {
	display: none;
}

/* The send button is emphasised by weight and border, not by red.
   This control only ever renders on a profile page, where `#profile-fab`
   already owns the viewport's one commit action — the same rule that made the
   compare tray step down to neutral here in Phase 3. */
.mx-report .mx-button--commit {
	border-color: var(--mx-border-strong, #4A4A4A);
	background: var(--mx-surface-elevated);
	color: var(--mx-ink);
	font-weight: 700;
}

.mx-report .mx-button--commit:hover:not(:disabled) {
	border-color: var(--mx-ink);
}

.mx-report .mx-button--ghost {
	border-color: transparent;
	background: transparent;
	color: var(--mx-muted);
}

.mx-report .mx-button:disabled {
	cursor: default;
	opacity: 0.72;
}

.mx-report__panel {
	display: grid;
	gap: 16px;
	max-width: 520px;
	margin-top: 12px;
	padding: 16px;
	border: 1px solid var(--mx-border-subtle);
	border-radius: var(--mx-radius-lg);
	background: var(--mx-surface);
}

.mx-report__panel[hidden] {
	display: none;
}

.mx-report__lede {
	margin: 0;
	color: var(--mx-muted);
	font-size: 13px;
	line-height: 1.5;
}

.mx-report .mx-field {
	display: grid;
	gap: 8px;
}

.mx-report .mx-field label {
	color: var(--mx-ink);
	font-size: 13px;
	font-weight: 600;
	line-height: 1.3;
}

.mx-report .mx-field__hint {
	margin: 0;
	color: var(--mx-faint);
	font-size: 12px;
	line-height: 1.4;
}

.mx-report .mx-select,
.mx-report .mx-textarea {
	width: 100%;
	padding: 12px;
	border: 1px solid var(--mx-border-default);
	border-radius: var(--mx-radius-md);
	background: var(--mx-surface-subtle);
	color: var(--mx-ink);
	font-family: inherit;
	font-size: 16px;
	line-height: 1.4;
}

.mx-report .mx-select {
	min-height: 44px;
	padding: 0 12px;
}

.mx-report .mx-textarea {
	resize: vertical;
}

.mx-report__actions {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
	align-items: center;
}

.mx-report__state {
	margin: 0;
	color: var(--mx-muted);
	font-size: 13px;
	line-height: 1.5;
}

.mx-report__state.is-error {
	color: var(--mx-error);
}

/* Keep the panel's last control clear of the fixed profile contact bar. */
@media (max-width: 768px) {
	.mx-report__panel {
		margin-bottom: 88px;
	}
}

/* ---------- Recommended for You / Find my type -------------------------- */

.mx-find-type,
.mx-recommendations,
.mx-type-modal {
	--mx-surface: #1A1A1A;
	--mx-surface-subtle: #222222;
	--mx-surface-elevated: #2A2A2A;
	--mx-border-subtle: #2E2E2E;
	--mx-border-default: #3A3A3A;
	--mx-border-strong: #4A4A4A;
	--mx-ink: #ECECEC;
	--mx-muted: #B4B4B4;
	--mx-faint: #8A8A8A;
	--mx-primary: #8B0A1A;
	--mx-primary-active: #6E0816;
	--mx-radius-sm: 6px;
	--mx-radius-md: 10px;
	--mx-radius-lg: 14px;
	--mx-radius-hero: 26px;
	--mx-ease-sheet: 260ms cubic-bezier(0.22, 1, 0.36, 1);
	--mx-ease-fast: 150ms cubic-bezier(0.4, 0, 0.2, 1);
	--mx-font: 'Manrope', 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
	box-sizing: border-box;
	font-family: var(--mx-font);
}

.mx-find-type *,
.mx-recommendations *,
.mx-type-modal * {
	box-sizing: border-box;
}

.mx-find-type {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 10px;
	min-height: 44px;
	min-width: 176px;
	padding: 0 18px 0 12px;
	border: 1px solid rgba(236, 236, 236, 0.24);
	/*
	 * Matches `.mx-compare-toggle`, which it sits beside on the profile outro.
	 * At 14px radius, 15px type and weight 850 against that sibling's 10px, 14px
	 * and 600, the pair read as two different species of control rather than as
	 * two options of equal standing.
	 */
	border-radius: var(--mx-radius-md);
	background: linear-gradient(180deg, rgba(42, 42, 42, 0.94), rgba(26, 26, 26, 0.96));
	color: var(--mx-ink);
	font-size: 14px;
	font-weight: 700;
	line-height: 1;
	cursor: pointer;
	box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.06);
	transition: transform var(--mx-ease-fast), background-color var(--mx-ease-fast), border-color var(--mx-ease-fast), box-shadow var(--mx-ease-fast);
}

.mx-find-type__mark {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	flex: 0 0 auto;
	width: 30px;
	height: 30px;
	border-radius: 999px;
	background: rgba(139, 10, 26, 0.22);
	color: #F4D7DC;
	box-shadow: inset 0 0 0 1px rgba(244, 215, 220, 0.16);
}

.mx-find-type__mark .mx-icon {
	width: 17px;
	height: 17px;
	stroke-width: 1.8;
}

.mx-find-type__label {
	min-width: 0;
	white-space: nowrap;
}

.mx-find-type:hover {
	background: var(--mx-surface-elevated);
	border-color: rgba(236, 236, 236, 0.46);
	box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.08), 0 10px 24px rgba(0, 0, 0, 0.28);
	transform: translateY(-1px);
}

.mx-find-type:active {
	transform: translateY(0) scale(0.98);
}

.mx-find-type:focus-visible,
.mx-recommendations :is(a, button):focus-visible,
.mx-type-modal :is(a, button, [tabindex]):focus-visible {
	outline: 2px solid var(--focus-ring-color, #E6C46A);
	outline-offset: 3px;
}

.profile-outro__member .mx-find-type {
	background: linear-gradient(180deg, rgba(42, 42, 42, 0.98), rgba(26, 26, 26, 0.98));
}

.profile-outro__member {
	display: grid;
	grid-template-columns: minmax(132px, 0.82fr) minmax(186px, 1.18fr);
	gap: 8px;
	width: min(100%, 430px);
	margin-inline: auto;
}

.profile-outro__member .mx-compare-toggle,
.profile-outro__member .mx-find-type {
	width: 100%;
	min-width: 0;
}

.profile-outro__member .mx-compare-toggle {
	padding-inline: 14px;
}

.mx-recommendations {
	display: grid;
	gap: 16px;
	margin: 24px 0;
	color: var(--mx-ink);
}

.mx-recommendations__header {
	display: flex;
	align-items: flex-end;
	justify-content: space-between;
	gap: 16px;
}

.mx-recommendations__header h2 {
	margin: 0;
	color: var(--mx-ink);
	font-size: 28px;
	font-weight: 800;
	line-height: 1.12;
	letter-spacing: 0;
}

.mx-recommendations__header p {
	max-width: 62ch;
	margin: 6px 0 0;
	color: var(--mx-muted);
	font-size: 14px;
	line-height: 1.55;
}

.mx-recommendations__reset {
	flex: 0 0 auto;
	min-height: 44px;
	padding: 0 14px;
	border: 1px solid var(--mx-border-default);
	border-radius: var(--mx-radius-md);
	background: transparent;
	color: var(--mx-muted);
	font-size: 13px;
	font-weight: 700;
	cursor: pointer;
}

.mx-recommendations__rail {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
	gap: 12px;
}

.mx-recommendation-card {
	position: relative;
	min-width: 0;
	overflow: hidden;
	border: 1px solid var(--mx-border-subtle);
	border-radius: var(--mx-radius-md);
	background: var(--mx-surface);
	transition: transform var(--mx-ease-sheet), border-color var(--mx-ease-fast);
}

.mx-recommendation-card:hover {
	border-color: var(--mx-border-strong);
	transform: translateY(-2px);
}

.mx-recommendation-card__image {
	display: block;
	aspect-ratio: 3 / 4;
	background: #101010;
}

.mx-recommendation-card__image img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

.mx-recommendation-card__body {
	display: grid;
	gap: 6px;
	padding: 12px;
}

.mx-recommendation-card h3 {
	margin: 0;
	font-size: 15px;
	font-weight: 800;
	line-height: 1.22;
	letter-spacing: 0;
}

.mx-recommendation-card h3 a {
	color: var(--mx-ink);
	text-decoration: none;
}

.mx-recommendation-card p {
	margin: 0;
	color: var(--mx-muted);
	font-size: 13px;
	line-height: 1.4;
}

.mx-recommendation-card ul {
	display: flex;
	flex-wrap: wrap;
	gap: 6px;
	margin: 2px 0 0;
	padding: 0;
	list-style: none;
}

.mx-recommendation-card li {
	padding: 4px 7px;
	border: 1px solid var(--mx-border-subtle);
	border-radius: var(--mx-radius-sm);
	color: var(--mx-muted);
	font-size: 11px;
	font-weight: 700;
	line-height: 1;
}

.mx-type-modal[hidden],
.mx-type-loader[hidden],
.mx-type-deck[hidden],
.mx-type-state[hidden],
.mx-type-reset-panel[hidden],
.mx-type-signup[hidden],
.mx-type-progress[hidden],
.mx-type-modal__feedback[hidden],
.mx-type-modal__actions[hidden] {
	display: none !important;
}

.mx-type-modal {
	position: fixed;
	inset: 0;
	z-index: 11020;
	display: flex;
	align-items: center;
	justify-content: center;
	padding: 24px;
	color: var(--mx-ink);
}

.mx-type-modal__backdrop {
	position: absolute;
	inset: 0;
	background: rgba(0, 0, 0, 0.68);
	backdrop-filter: blur(2px);
	opacity: 0;
	transition: opacity var(--mx-ease-fast);
}

.mx-type-modal.is-open .mx-type-modal__backdrop {
	opacity: 1;
}

.mx-type-modal__dialog {
	position: relative;
	display: grid;
	grid-template-rows: auto minmax(22px, auto) auto minmax(0, 1fr) auto;
	gap: 12px;
	width: min(92vw, 860px);
	max-height: min(88vh, 760px);
	padding: 22px;
	border: 1px solid var(--mx-border-default);
	border-radius: var(--mx-radius-hero);
	background: var(--mx-surface);
	box-shadow: 0 18px 48px rgba(0, 0, 0, 0.56);
	overflow: hidden;
	opacity: 0;
	transform: translateY(16px) scale(0.98);
	transition: transform var(--mx-ease-sheet), opacity var(--mx-ease-fast);
}

.mx-type-modal.is-open .mx-type-modal__dialog {
	opacity: 1;
	transform: none;
}

/*
 * Pin every row explicitly. Panels inside the dialog are toggled with [hidden],
 * and without this a collapsed row would slide the flexible stage track onto a
 * different child — which is how the action dock ended up off screen.
 */
.mx-type-modal__header {
	grid-row: 1;
}

.mx-type-modal__status {
	grid-row: 2;
}

.mx-type-progress {
	grid-row: 3;
}

.mx-type-modal__stage {
	grid-row: 4;
}

.mx-type-modal__actions {
	grid-row: 5;
}

.mx-type-modal__header {
	display: flex;
	align-items: flex-start;
	justify-content: space-between;
	gap: 16px;
}

.mx-type-modal__eyebrow {
	margin: 0 0 6px;
	color: var(--mx-faint);
	font-size: 11px;
	font-weight: 800;
	line-height: 1.35;
	text-transform: uppercase;
	letter-spacing: 0;
}

.mx-type-modal__header h2 {
	margin: 0;
	color: var(--mx-ink);
	font-size: 28px;
	font-weight: 850;
	line-height: 1.08;
	letter-spacing: 0;
}

.mx-type-modal__close {
	flex: 0 0 auto;
	width: 44px;
	height: 44px;
	border: 0;
	border-radius: var(--mx-radius-md);
	background: transparent;
	color: var(--mx-muted);
	font-size: 28px;
	line-height: 1;
	cursor: pointer;
	transition: color var(--mx-ease-fast), background-color var(--mx-ease-fast), transform var(--mx-ease-fast);
}

.mx-type-modal__close:hover {
	background: var(--mx-surface-subtle);
	color: var(--mx-ink);
}

.mx-type-modal__close:active {
	transform: scale(0.96);
}

.mx-type-modal__status {
	min-height: 22px;
	max-width: 65ch;
	color: var(--mx-muted);
	font-size: 14px;
	line-height: 1.5;
}

.mx-type-modal__status.is-error {
	color: var(--mx-ink);
}

.mx-type-modal__feedback {
	position: absolute;
	left: 50%;
	bottom: 88px;
	z-index: 4;
	max-width: calc(100% - 48px);
	display: inline-flex;
	align-items: center;
	gap: 8px;
	padding: 7px 12px;
	border: 1px solid rgba(236, 236, 236, 0.14);
	border-radius: 999px;
	background: rgba(18, 18, 18, 0.86);
	backdrop-filter: blur(10px);
	color: var(--mx-muted);
	font-size: 11px;
	font-weight: 750;
	line-height: 1.2;
	text-align: center;
	box-shadow: 0 6px 16px rgba(0, 0, 0, 0.28);
	transform: translate(-50%, 6px);
	opacity: 0;
	animation: mx-type-feedback-in 180ms cubic-bezier(0.22, 1, 0.36, 1) forwards;
	pointer-events: none;
}

.mx-type-modal__feedback::before {
	content: "";
	flex: 0 0 auto;
	width: 7px;
	height: 7px;
	border-radius: 999px;
	background: currentColor;
	box-shadow: 0 0 0 4px rgba(236, 236, 236, 0.08);
}

/* Only the dot carries the colour; the chip itself stays quiet. */
.mx-type-modal.is-feedback-like .mx-type-modal__feedback::before {
	color: #E4566E;
}

.mx-type-modal.is-feedback-not-my-type .mx-type-modal__feedback::before {
	color: #EFB4BE;
}

.mx-type-modal.is-feedback-more-like-this .mx-type-modal__feedback::before {
	color: #E6C46A;
}

/* -------------------------------------------------------------- progress rail */

.mx-type-progress {
	display: grid;
	grid-template-columns: minmax(0, 1fr) auto;
	align-items: center;
	gap: 12px;
}

.mx-type-progress__bar {
	position: relative;
	display: block;
	overflow: hidden;
	height: 4px;
	border-radius: 999px;
	background: rgba(236, 236, 236, 0.12);
}

.mx-type-progress__fill {
	display: block;
	width: 0;
	height: 100%;
	border-radius: inherit;
	background: linear-gradient(90deg, var(--mx-primary), #C0304A);
	transition: width 280ms cubic-bezier(0.22, 1, 0.36, 1);
}

.mx-type-progress__label {
	color: var(--mx-faint);
	font-size: 11px;
	font-weight: 800;
	line-height: 1;
	letter-spacing: 0;
	white-space: nowrap;
	font-variant-numeric: tabular-nums;
}

/*
 * The stage is a single-cell grid and every panel shares that cell. Nothing
 * inside a card can grow the frame, so the action dock below it never moves
 * and never gets pushed off screen by a tall image.
 */
.mx-type-modal__stage {
	position: relative;
	display: grid;
	grid-template-rows: minmax(0, 1fr);
	grid-template-columns: minmax(0, 1fr);
	min-height: 372px;
	overflow: hidden;
}

.mx-type-modal__stage > * {
	grid-area: 1 / 1;
	min-width: 0;
	min-height: 0;
}

.mx-type-deck {
	display: grid;
	grid-template-rows: minmax(0, 1fr);
	grid-template-columns: minmax(0, 1fr);
	min-height: 0;
}

.mx-type-layout {
	display: grid;
	grid-template-columns: minmax(0, 1.34fr) minmax(220px, 0.66fr);
	gap: 14px;
	min-height: 372px;
}

.mx-type-feature,
.mx-type-queue {
	min-width: 0;
}

.mx-type-card {
	position: relative;
	display: block;
	width: 100%;
	min-width: 0;
	margin: 0;
	padding: 0;
	border: 1px solid var(--mx-border-subtle);
	border-radius: var(--mx-radius-lg);
	background: #101010;
	color: var(--mx-ink);
	overflow: hidden;
	text-align: left;
	text-decoration: none;
}

.mx-type-card__media,
.mx-type-card__scrim,
.mx-type-card__body {
	display: block;
}

.mx-type-card__media {
	position: relative;
	background: #101010;
}

.mx-type-card__fill {
	display: none;
}

.mx-type-card__image,
.mx-type-card__fill img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

.mx-type-card__scrim {
	position: absolute;
	inset: auto 0 0;
	height: 58%;
	background: linear-gradient(180deg, rgba(16, 16, 16, 0), rgba(16, 16, 16, 0.92));
	pointer-events: none;
}

.mx-type-card__body {
	position: absolute;
	left: 0;
	right: 0;
	bottom: 0;
	z-index: 1;
	padding: 16px;
}

.mx-type-card__name {
	display: block;
	color: var(--mx-ink);
	font-size: 24px;
	font-weight: 850;
	line-height: 1.08;
	letter-spacing: 0;
	overflow-wrap: anywhere;
}

.mx-type-card__location {
	display: block;
	margin-top: 5px;
	color: var(--mx-muted);
	font-size: 14px;
	font-weight: 600;
	line-height: 1.35;
}

.mx-type-card__reasons {
	display: flex;
	flex-wrap: wrap;
	gap: 6px;
	margin-top: 12px;
}

.mx-type-card__reasons span {
	max-width: 100%;
	padding: 5px 8px;
	border: 1px solid rgba(236, 236, 236, 0.22);
	border-radius: var(--mx-radius-sm);
	background: rgba(16, 16, 16, 0.62);
	color: var(--mx-ink);
	font-size: 11px;
	font-weight: 800;
	line-height: 1;
	white-space: nowrap;
}

.mx-type-card__profile-link {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-height: 40px;
	margin-top: 14px;
	padding: 0 12px;
	border: 1px solid rgba(236, 236, 236, 0.26);
	border-radius: var(--mx-radius-md);
	background: rgba(34, 34, 34, 0.82);
	color: var(--mx-ink);
	font-size: 13px;
	font-weight: 800;
	line-height: 1;
	text-decoration: none;
	backdrop-filter: blur(6px);
}

.mx-type-card--active {
	height: 372px;
	opacity: 1;
	transform: none;
	transition: transform var(--mx-ease-sheet), opacity var(--mx-ease-fast), border-color var(--mx-ease-fast);
}

.mx-type-card--active .mx-type-card__media {
	height: 100%;
}

.mx-type-modal.is-rating .mx-type-card--active {
	opacity: 0;
	transform: translate3d(-18px, 0, 0) scale(0.985);
}

.mx-type-modal.is-liked .mx-type-card--active {
	border-color: rgba(139, 10, 26, 0.88);
	box-shadow: 0 0 0 1px rgba(139, 10, 26, 0.42);
}

.mx-type-queue {
	display: grid;
	grid-template-rows: auto minmax(0, 1fr);
	gap: 10px;
}

.mx-type-queue__label {
	color: var(--mx-faint);
	font-size: 11px;
	font-weight: 800;
	line-height: 1.35;
	text-transform: uppercase;
	letter-spacing: 0;
}

.mx-type-queue__items {
	display: grid;
	align-content: start;
	gap: 7px;
	overflow: auto;
	padding-right: 2px;
}

.mx-type-card--queue {
	display: grid;
	grid-template-columns: 58px minmax(0, 1fr);
	gap: 10px;
	min-height: 76px;
	border-color: var(--mx-border-subtle);
	cursor: pointer;
	transition: transform var(--mx-ease-fast), background-color var(--mx-ease-fast), border-color var(--mx-ease-fast);
}

.mx-type-card--queue:hover {
	background: var(--mx-surface-subtle);
	border-color: var(--mx-border-strong);
	transform: translateX(2px);
}

.mx-type-card--queue .mx-type-card__media {
	width: 58px;
	height: 76px;
}

.mx-type-card--queue .mx-type-card__scrim {
	display: none;
}

.mx-type-card--queue .mx-type-card__body {
	position: static;
	align-self: center;
	padding: 10px 10px 10px 0;
}

.mx-type-card--queue .mx-type-card__name {
	font-size: 14px;
	line-height: 1.2;
}

.mx-type-card--queue .mx-type-card__location {
	margin-top: 4px;
	font-size: 12px;
}

.mx-type-card--queue .mx-type-card__reasons {
	margin-top: 7px;
}

.mx-type-card--queue .mx-type-card__reasons span {
	overflow: hidden;
	max-width: 100%;
	text-overflow: ellipsis;
}

.mx-type-modal__actions {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: 7px 8px;
}

.mx-type-action {
	position: relative;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 8px;
	min-height: 48px;
	padding: 0 12px;
	border: 1px solid var(--mx-border-default);
	border-radius: var(--mx-radius-md);
	background: var(--mx-surface-subtle);
	color: var(--mx-ink);
	font-size: 14px;
	font-weight: 800;
	line-height: 1.1;
	cursor: pointer;
	transition: transform var(--mx-ease-fast), background-color var(--mx-ease-fast), border-color var(--mx-ease-fast), opacity var(--mx-ease-fast);
}

.mx-type-action__icon {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	flex: 0 0 auto;
}

.mx-type-action__icon .mx-icon {
	width: 18px;
	height: 18px;
	stroke-width: 1.8;
}

.mx-type-action:hover:not(:disabled) {
	background: var(--mx-surface-elevated);
	border-color: var(--mx-border-strong);
	transform: translateY(-1px);
}

.mx-type-action:active:not(:disabled) {
	transform: scale(0.98);
}

.mx-type-action:disabled {
	cursor: default;
	opacity: 0.58;
}

.mx-type-action--primary {
	border-color: var(--mx-primary);
	background: var(--mx-primary);
	color: var(--mx-ink);
	box-shadow: 0 8px 22px rgba(139, 10, 26, 0.28);
}

.mx-type-action--primary:hover:not(:disabled) {
	background: var(--mx-primary-active);
	border-color: var(--mx-primary-active);
}

.mx-type-modal.is-liked .mx-type-action--primary {
	animation: mx-type-like-pop 220ms cubic-bezier(0.22, 1, 0.36, 1);
}

.mx-type-modal.is-feedback-like .mx-type-action--like,
.mx-type-modal.is-feedback-skip .mx-type-action--skip,
.mx-type-modal.is-feedback-not-my-type .mx-type-action--nope,
.mx-type-modal.is-feedback-more-like-this .mx-type-action--more {
	border-color: rgba(236, 236, 236, 0.62);
	transform: scale(1.035);
}

.mx-type-action--quiet {
	background: transparent;
	color: var(--mx-muted);
}

/*
 * Two decisions first, two refinements second. The previous four-column dock
 * gave every signal the same visual weight, so Skip read as consequential as
 * Like. DOM order follows this visual order to keep keyboard traversal honest.
 */
.mx-type-action--nope,
.mx-type-action--like {
	min-height: 50px;
}

.mx-type-action--skip,
.mx-type-action--more {
	min-height: 44px;
	border-color: transparent;
	background: transparent;
	color: var(--mx-muted);
	font-size: 12.5px;
	font-weight: 700;
}

.mx-type-action--skip:hover:not(:disabled),
.mx-type-action--more:hover:not(:disabled) {
	border-color: var(--mx-border-subtle);
	background: rgba(255, 255, 255, 0.035);
}

/* ==========================================================================
   FIND MY TYPE — THE WAITING STATE
   plans/private-editorial-ui-refinement-2026-09-18/plan.html, step 7.

   WHAT WAS HERE AND WHY IT WENT
   -----------------------------
   Fourteen `infinite` animations at five mutually-prime periods: an orbit at
   5s and a pop at 1.6s on each of four faces, a 1.4s scan, two 900ms dots and
   three 1.6s caption pulses. It was a loop, running for a duration that was
   already known — 2600ms — so when the deck arrived it cut in at whatever
   rotation the orbit happened to occupy. A sequence with no end cannot finish;
   it can only be interrupted.

   Worse, the faces were not the candidates. On a first open the deck was still
   in flight, so the ring was filled from a house pool and the visitor watched
   four strangers for 2.6 seconds before being shown four different people.

   WHAT IS HERE NOW
   ----------------
   One bounded three-beat sequence, driven from a single JS timeline in
   customer-product.js and expressed here as states on `[data-mx-beat]`:

     1 Gather  0-900     six slots arc inward, 90ms apart, opacity 0->1
     2 Read    900-1900  ONE scan pass, marking each portrait as it passes
     3 Resolve 1900-2600 the rest recede; the lead travels to the card origin
     handoff   +220      the first card cross-dissolves from that final pose

   Rules the sequence keeps: something strictly advances and never resets; one
   dominant motion per beat with everything else subordinate or still; nothing
   is `infinite`; transform and opacity only.

   The beats are ATTRIBUTE STATES, not animation-delay chains. A delay chain
   cannot hold beat 2 open for a slow request without desynchronising beat 3
   from the handoff, which is precisely the failure this replaces.
   ========================================================================== */

.mx-type-loader {
	display: grid;
	grid-template-columns: minmax(0, 1fr);
	grid-template-rows: minmax(0, 1fr) auto;
	align-items: stretch;
	gap: 10px;
	min-height: 372px;
}

.mx-type-loader__loop {
	position: relative;
	min-height: 304px;
	overflow: hidden;
	border: 1px solid var(--mx-border-subtle);
	border-radius: var(--mx-radius-lg);
	background: radial-gradient(circle at 50% 44%, rgba(139, 10, 26, 0.13), transparent 52%), #0F0F0F;
}

/* ------------------------------------------------------------- the core ring

   Drawn once, during beat 1, and contracted away during beat 3. It is the
   frame the candidates arrive into and it leaves before they resolve, so it
   never competes with the portrait that is becoming the first card.
   -------------------------------------------------------------------------- */

.mx-type-loader__ring {
	position: absolute;
	top: 50%;
	left: 50%;
	width: 252px;
	height: 252px;
	border: 1px solid rgba(236, 236, 236, 0.1);
	border-radius: 999px;
	opacity: 0;
	transform: translate(-50%, -50%) scale(0.92);
	transition: opacity 600ms ease, transform 600ms cubic-bezier(0.22, 1, 0.36, 1);
}

.mx-type-loader[data-mx-beat="1"] .mx-type-loader__ring,
.mx-type-loader[data-mx-beat="2"] .mx-type-loader__ring {
	opacity: 1;
	transform: translate(-50%, -50%) scale(1);
}

.mx-type-loader[data-mx-beat="3"] .mx-type-loader__ring,
.mx-type-loader[data-mx-beat="handoff"] .mx-type-loader__ring {
	opacity: 0;
	transform: translate(-50%, -50%) scale(0.86);
	transition-duration: 460ms;
}

.mx-type-loader__core {
	position: absolute;
	top: 50%;
	left: 50%;
	z-index: 2;
	display: grid;
	place-items: center;
	align-content: center;
	gap: 5px;
	width: 124px;
	height: 124px;
	border: 1px solid rgba(236, 236, 236, 0.14);
	border-radius: 999px;
	background: rgba(20, 20, 20, 0.9);
	opacity: 1;
	transform: translate(-50%, -50%) scale(1);
	transition: opacity 420ms ease, transform 420ms cubic-bezier(0.22, 1, 0.36, 1);
}

.mx-type-loader[data-mx-beat="3"] .mx-type-loader__core,
.mx-type-loader[data-mx-beat="handoff"] .mx-type-loader__core {
	opacity: 0;
	transform: translate(-50%, -50%) scale(0.9);
}

.mx-type-loader__core span,
.mx-type-loader__core strong {
	display: block;
	text-align: center;
}

.mx-type-loader__core span {
	color: var(--mx-faint);
	font-size: 10px;
	font-weight: 700;
	line-height: 1;
	letter-spacing: 0.14em;
	text-transform: uppercase;
}

.mx-type-loader__core strong {
	max-width: 100px;
	color: var(--mx-ink);
	font-size: 17px;
	font-weight: 800;
	line-height: 1.1;
}

/* ---------------------------------------------------------- the six portraits

   `--mx-slot-angle` places a slot on the ring; `--mx-slot-index` staggers it.
   Both are written once by the renderer and never animated. Everything that
   moves is one transform on this element, which is why a slot can have its
   `src` swapped mid-sequence (the deck arriving) without the motion resetting.
   -------------------------------------------------------------------------- */

.mx-type-loader__profile {
	--mx-loader-orbit: 126px;
	position: absolute;
	top: 50%;
	left: 50%;
	display: block;
	width: 76px;
	height: 76px;
	border: 1px solid rgba(236, 236, 236, 0.12);
	border-radius: 999px;
	background: #151515;
	box-shadow: 0 18px 32px rgba(0, 0, 0, 0.34);
	overflow: hidden;
	opacity: 0;
	/* Beat 1 arrives from 24px further out, on the same radial line. */
	transform:
		translate(-50%, -50%)
		rotate(var(--mx-slot-angle, 0deg))
		translateX(calc(var(--mx-loader-orbit) + 24px))
		rotate(calc(var(--mx-slot-angle, 0deg) * -1))
		scale(0.9);
	transition:
		opacity 420ms ease var(--mx-slot-delay),
		transform 620ms cubic-bezier(0.22, 1, 0.36, 1) var(--mx-slot-delay),
		border-color 320ms ease,
		box-shadow 320ms ease;
	--mx-slot-delay: calc(var(--mx-slot-index, 0) * 90ms);
}

.mx-type-loader__profile img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
	/* Swapping src mid-flight crossfades rather than popping. */
	transition: opacity 320ms ease;
}

/* Beat 1 — gather. The one dominant motion; nothing else travels. */
.mx-type-loader[data-mx-beat="1"] .mx-type-loader__profile,
.mx-type-loader[data-mx-beat="2"] .mx-type-loader__profile,
.mx-type-loader[data-mx-beat="3"] .mx-type-loader__profile,
.mx-type-loader[data-mx-beat="handoff"] .mx-type-loader__profile {
	opacity: 1;
	transform:
		translate(-50%, -50%)
		rotate(var(--mx-slot-angle, 0deg))
		translateX(var(--mx-loader-orbit))
		rotate(calc(var(--mx-slot-angle, 0deg) * -1))
		scale(1);
}

/*
 * Beat 2 — read. The portraits HOLD; only the sweep moves. Each slot is left
 * marked after the sweep reaches it, staggered on the same 90ms rhythm beat 1
 * used, so the marking reads as the same six things being considered in the
 * same order rather than as a new effect.
 */
.mx-type-loader[data-mx-beat="2"] .mx-type-loader__profile,
.mx-type-loader[data-mx-beat="3"] .mx-type-loader__profile {
	border-color: rgba(236, 236, 236, 0.34);
	box-shadow: 0 18px 32px rgba(0, 0, 0, 0.34), 0 0 0 2px rgba(236, 236, 236, 0.07);
	transition-delay: 0ms, 0ms, calc(900ms + var(--mx-slot-index, 0) * 150ms), calc(900ms + var(--mx-slot-index, 0) * 150ms);
}

/*
 * Beat 3 — resolve. Everything that is not the lead recedes; the lead travels
 * to the card origin and takes the first card's footprint, which is what the
 * cross-dissolve then hands over to. Burgundy marks the selected portrait, and
 * only it.
 */
.mx-type-loader[data-mx-beat="3"] .mx-type-loader__profile,
.mx-type-loader[data-mx-beat="handoff"] .mx-type-loader__profile {
	opacity: 0.32;
	transform:
		translate(-50%, -50%)
		rotate(var(--mx-slot-angle, 0deg))
		translateX(var(--mx-loader-orbit))
		rotate(calc(var(--mx-slot-angle, 0deg) * -1))
		scale(0.92);
	transition-duration: 520ms;
	transition-delay: 0ms;
}

.mx-type-loader[data-mx-beat="3"] .mx-type-loader__profile.is-lead,
.mx-type-loader[data-mx-beat="handoff"] .mx-type-loader__profile.is-lead {
	z-index: 3;
	opacity: 1;
	border-color: rgba(139, 10, 26, 0.85);
	border-radius: var(--mx-radius-lg);
	box-shadow: 0 26px 52px rgba(0, 0, 0, 0.5), 0 0 0 2px rgba(139, 10, 26, 0.32);
	/* The first deck card's footprint, at its origin. No rotation left. */
	transform: translate(-50%, -50%) scale(2.35);
}

/* The handoff: the lead holds its final pose and dissolves under the card. */
.mx-type-loader[data-mx-beat="handoff"] {
	opacity: 0;
	transition: opacity 220ms ease;
	pointer-events: none;
}

/* ------------------------------------------------------------------ the sweep

   ONE pass. `iteration-count: 1`, and it only exists during beat 2 — there is
   no state in which this element loops.
   -------------------------------------------------------------------------- */

.mx-type-loader__scan {
	position: absolute;
	top: 50%;
	left: 50%;
	display: block;
	width: 280px;
	height: 280px;
	border-radius: 999px;
	opacity: 0;
	background: conic-gradient(from 0deg, transparent 0deg, rgba(236, 236, 236, 0.16) 26deg, transparent 52deg);
	transform: translate(-50%, -50%) rotate(-90deg);
	mask-image: radial-gradient(circle, transparent 46%, #000 48%);
	-webkit-mask-image: radial-gradient(circle, transparent 46%, #000 48%);
}

.mx-type-loader[data-mx-beat="2"] .mx-type-loader__scan {
	opacity: 1;
	animation: mx-type-sweep 1000ms cubic-bezier(0.4, 0, 0.2, 1) 1 forwards;
}

/* --------------------------------------------------------------- the captions

   Three lines, one per beat, crossfading on the beat boundaries. They are the
   reason the wait reads as progress: each names what is happening right now.
   -------------------------------------------------------------------------- */

.mx-type-loader__caption {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	align-content: stretch;
	gap: 8px;
	padding-top: 0;
}

.mx-type-loader__caption span {
	display: flex;
	align-items: center;
	gap: 10px;
	min-height: 44px;
	padding: 9px 11px;
	border: 1px solid var(--mx-border-subtle);
	border-radius: var(--mx-radius-lg);
	background: #131313;
	color: var(--mx-faint);
	font-size: 11.5px;
	font-weight: 600;
	line-height: 1.35;
	opacity: 0.32;
	transition: opacity 320ms ease, color 320ms ease, border-color 320ms ease;
}

.mx-type-loader__caption span::before {
	content: "";
	width: 6px;
	height: 6px;
	flex: 0 0 6px;
	border-radius: 999px;
	background: currentColor;
	opacity: 0.5;
	transition: background-color 320ms ease, opacity 320ms ease;
}

.mx-type-loader__caption span.is-current {
	opacity: 1;
	color: var(--mx-ink);
	border-color: rgba(236, 236, 236, 0.2);
}

.mx-type-loader__caption span.is-current::before {
	background: var(--brand-primary, #8B0A1A);
	opacity: 1;
}

/* ------------------------------------------------- the match-building state

   The reveal's own wait. It reuses the same component so the visitor is not
   shown a second, unfamiliar loading treatment two seconds later — but it has
   NO floor. That request is the result; padding it would be making someone
   wait for nothing. It holds beat 1's gathered pose until the answer lands.
   -------------------------------------------------------------------------- */

.mx-type-loader.is-building .mx-type-loader__caption {
	display: none;
}

.mx-type-loader.is-building {
	grid-template-columns: minmax(0, 1fr);
}

.mx-type-state,
.mx-type-reset-panel {
	display: grid;
	align-content: center;
	justify-items: start;
	gap: 12px;
	min-height: 420px;
	padding: 32px;
	border: 1px solid var(--mx-border-subtle);
	border-radius: var(--mx-radius-lg);
	background: var(--mx-surface-subtle);
}

.mx-type-state strong,
.mx-type-reset-panel strong {
	color: var(--mx-ink);
	font-size: 22px;
	font-weight: 850;
	line-height: 1.16;
	letter-spacing: 0;
}

.mx-type-state p,
.mx-type-reset-panel p {
	max-width: 46ch;
	margin: 0;
	color: var(--mx-muted);
	font-size: 15px;
	line-height: 1.55;
}

.mx-type-state__actions,
.mx-type-reset-panel__actions {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
	margin-top: 4px;
}

.mx-type-state__actions button,
.mx-type-reset-panel__actions button {
	min-height: 44px;
	padding: 0 14px;
	border: 1px solid var(--mx-border-default);
	border-radius: var(--mx-radius-md);
	background: var(--mx-surface-elevated);
	color: var(--mx-ink);
	font-size: 14px;
	font-weight: 800;
	line-height: 1;
	cursor: pointer;
}

.mx-type-reset-panel__actions [data-mx-type-reset-confirm] {
	border-color: var(--mx-primary);
	background: var(--mx-primary);
}

/* --------------------------------------------------- end-of-set signup prompt */

.mx-type-signup {
	--mx-signup-pad: 32px;

	display: grid;
	/* Start, not center: the rail is a header band and must sit flush. */
	align-content: start;
	justify-items: start;
	gap: 10px;
	min-height: 420px;
	padding: var(--mx-signup-pad);
	border: 1px solid var(--mx-border-subtle);
	border-radius: var(--mx-radius-lg);
	background:
		radial-gradient(circle at 8% 0%, rgba(139, 10, 26, 0.24), transparent 56%),
		var(--mx-surface-subtle);
	overflow: hidden auto;
}

/* ---------- the profile rail ----------
   Same argument as the member gate, but made personal: once the visitor has
   liked anything, these are the faces they chose. It is never a control — no
   hover, no pointer, no tab stop. */

.mx-type-signup__faces {
	position: relative;
	justify-self: stretch;
	/* Pulled out of the panel padding so it reads as a header band, not a strip
	   floating inside the copy. */
	margin:
		calc(var(--mx-signup-pad) * -1)
		calc(var(--mx-signup-pad) * -1)
		6px;
	padding: 18px 0 16px;
	border-radius: var(--mx-radius-lg) var(--mx-radius-lg) 0 0;
	background: linear-gradient(180deg, rgba(139, 10, 26, 0.22), transparent);
	overflow: hidden;
	/* Fades at both ends so the loop has no visible entry or exit. */
	-webkit-mask-image: linear-gradient(90deg, transparent, #000 12%, #000 88%, transparent);
	mask-image: linear-gradient(90deg, transparent, #000 12%, #000 88%, transparent);
	pointer-events: none;
}

.mx-type-signup__faces-track {
	display: flex;
	align-items: center;
	gap: 8px;
	width: max-content;
	/* Two identical passes, so -50% lands on a seamless wrap. */
	animation: mx-type-face-drift 38s linear infinite;
}

.mx-type-signup__face {
	flex: 0 0 auto;
	display: block;
	overflow: hidden;
	width: 48px;
	height: 48px;
	border: 1px solid var(--mx-border-subtle);
	border-radius: 999px;
	background: var(--mx-surface-elevated);
}

.mx-type-signup__face img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

/* Their own picks get a warmer ring than the house pool. */
.mx-type-signup__faces.is-picks .mx-type-signup__face {
	border-color: rgba(196, 62, 86, 0.55);
	box-shadow: 0 0 0 2px rgba(139, 10, 26, 0.22);
}

/* Too few to loop convincingly: hold them still, centred, and larger. */
.mx-type-signup__faces.is-static {
	-webkit-mask-image: none;
	mask-image: none;
}

.mx-type-signup__faces.is-static .mx-type-signup__faces-track {
	width: auto;
	justify-content: center;
	gap: 10px;
	animation: none;
}

.mx-type-signup__faces.is-static .mx-type-signup__face {
	width: 62px;
	height: 62px;
}

@keyframes mx-type-face-drift {
	from {
		transform: translate3d(0, 0, 0);
	}

	to {
		transform: translate3d(-50%, 0, 0);
	}
}

.mx-type-signup__eyebrow {
	color: var(--mx-faint);
	font-size: 11px;
	font-weight: 800;
	line-height: 1.35;
	text-transform: uppercase;
	letter-spacing: 0;
}

.mx-type-signup strong {
	color: var(--mx-ink);
	font-size: 26px;
	font-weight: 850;
	line-height: 1.12;
	letter-spacing: 0;
}

.mx-type-signup p {
	max-width: 42ch;
	margin: 0;
	color: var(--mx-muted);
	font-size: 15px;
	line-height: 1.55;
}

.mx-type-signup__actions {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
	margin-top: 6px;
}

.mx-type-signup__primary,
.mx-type-signup__secondary {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-height: 48px;
	padding: 0 18px;
	border: 1px solid var(--mx-border-default);
	border-radius: var(--mx-radius-md);
	background: var(--mx-surface-elevated);
	color: var(--mx-ink);
	font-size: 14px;
	font-weight: 800;
	line-height: 1;
	text-decoration: none;
}

.mx-type-signup__primary {
	border-color: var(--mx-primary);
	background: var(--mx-primary);
	box-shadow: 0 8px 22px rgba(139, 10, 26, 0.28);
}

.mx-type-signup__quiet {
	display: flex;
	flex-wrap: wrap;
	gap: 14px;
	margin-top: 2px;
}

.mx-type-signup__quiet button {
	min-height: 32px;
	padding: 0;
	border: 0;
	background: none;
	color: var(--mx-muted);
	font-size: 13px;
	font-weight: 750;
	line-height: 1;
	text-decoration: underline;
	text-underline-offset: 3px;
	cursor: pointer;
}

.mx-type-signup__quiet button:hover {
	color: var(--mx-ink);
}

.mx-type-signup small {
	color: var(--mx-faint);
	font-size: 12px;
	line-height: 1.45;
}

/*
 * `.is-bare` is gone with the renderer that set it. The ring is now six fixed
 * slots that hold their shape whether or not a portrait has landed in them
 * yet, which is what lets the real deck be keyed in mid-sequence without the
 * layout moving under the visitor.
 */

/* ==========================================================================
   FIND MY TYPE — THE REVEAL
   plans/private-editorial-ui-refinement-2026-09-18/plan.html, step 7.

   Anonymous visitors used to rate a whole deck and be handed a signup block.
   They gave the feature everything it asked for and got an ask back. Now they
   see what their ratings actually produced first — up to three real, ranked
   profiles, each a working link — and the same account choices follow as a
   compact footer rather than competing with the result.

   Shortages are told truthfully: two results say "Two profiles", one says
   "One profile", zero uses the existing recovery state. Nothing is padded
   with general discovery profiles, because a profile the scorer did not pick
   presented as a match is the one thing that would make this untrustworthy.
   ========================================================================== */

/*
 * The stage stacks every state in one grid cell, because normally exactly one
 * of them is visible at a time. The reveal is the exception: the result and
 * the signup ask are BOTH on screen, in that order, so for this one mode the
 * stage becomes an ordinary vertical flow that scrolls if it has to.
 */
.mx-type-modal.is-reveal .mx-type-modal__dialog {
	grid-template-rows: auto minmax(0, 1fr);
	gap: 18px;
	width: min(94vw, 940px);
	max-height: min(90vh, 780px);
}

.mx-type-modal.is-reveal .mx-type-modal__status {
	display: none;
}

.mx-type-modal.is-reveal .mx-type-modal__stage {
	grid-row: 2;
	grid-template-rows: auto auto;
	align-content: start;
	gap: 16px;
	min-height: 0;
	max-height: min(72vh, 640px);
	padding-right: 4px;
	overflow-y: auto;
	overflow-x: hidden;
}

.mx-type-modal.is-reveal .mx-type-modal__stage > * {
	grid-area: auto;
}

.mx-type-reveal {
	display: grid;
	gap: 5px;
}

.mx-type-reveal__eyebrow {
	margin: 0;
	color: var(--mx-faint);
	font-size: 10px;
	font-weight: 600;
	letter-spacing: 0.14em;
	text-transform: uppercase;
}

.mx-type-reveal__title {
	display: block;
	color: var(--mx-ink);
	font-size: clamp(1.25rem, 2.4vw, 1.7rem);
	font-weight: 750;
	line-height: 1.12;
	letter-spacing: -0.02em;
}

/* Focus moves here on reveal, so it needs the ring but not a border. */
.mx-type-reveal__title:focus-visible {
	outline: 2px solid var(--focus-ring-color, #FFFFFF);
	outline-offset: 4px;
	border-radius: 4px;
}

.mx-type-reveal__copy {
	margin: 0 0 12px;
	color: var(--mx-muted);
	font-size: 13.5px;
	line-height: 1.5;
}

.mx-type-reveal__grid {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
	gap: 12px;
}

.mx-type-reveal__grid:has(> .mx-type-card--match:nth-child(3)) {
	grid-template-columns: minmax(0, 1.12fr) repeat(2, minmax(0, 0.94fr));
}

.mx-type-reveal__grid:not(:has(> .mx-type-card--match:nth-child(2))) {
	grid-template-columns: minmax(0, 380px);
}

/*
 * The match card is the deck card at result scale. Same component, same data,
 * but it is something to open rather than something to rate — so it is always
 * a link and never a jump button.
 */
.mx-type-reveal__grid .mx-type-card--match {
	position: relative;
	display: grid;
	grid-template-rows: auto minmax(0, 1fr);
	min-width: 0;
	border-color: var(--mx-border-subtle);
	border-radius: var(--mx-radius-md);
	background: var(--mx-surface-subtle);
	overflow: hidden;
	transition: border-color var(--mx-ease-fast), background-color var(--mx-ease-fast);
}

.mx-type-reveal__grid .mx-type-card--match:hover,
.mx-type-reveal__grid .mx-type-card--match:focus-within {
	border-color: var(--mx-border-strong);
	background: var(--mx-surface-elevated);
}

.mx-type-reveal__grid .mx-type-card--match .mx-type-card__media {
	display: block;
	height: clamp(164px, 18vw, 204px);
	overflow: hidden;
}

.mx-type-reveal__grid .mx-type-card--match .mx-type-card__media img {
	width: 100%;
	height: 100%;
	object-fit: cover;
}

.mx-type-reveal__grid .mx-type-card--match .mx-type-card__scrim {
	display: none;
}

.mx-type-reveal__grid .mx-type-card--match .mx-type-card__body {
	position: static;
	display: grid;
	align-content: start;
	gap: 4px;
	padding: 11px 12px 12px;
	min-width: 0;
	z-index: 2;
}

.mx-type-reveal__grid .mx-type-card--match .mx-type-card__name {
	display: -webkit-box;
	overflow: hidden;
	-webkit-box-orient: vertical;
	-webkit-line-clamp: 2;
	font-size: 14.5px;
	font-weight: 700;
	line-height: 1.25;
}

.mx-type-reveal__grid .mx-type-card--match .mx-type-card__location {
	overflow: hidden;
	margin-top: 1px;
	font-size: 12px;
	color: var(--mx-muted);
	text-overflow: ellipsis;
	white-space: nowrap;
}

.mx-type-reveal__grid .mx-type-card--match .mx-type-card__reasons {
	margin-top: 7px;
}

/* One reason on a result card. Three would be an argument, not a label. */
.mx-type-reveal__grid .mx-type-card--match .mx-type-card__reasons span:nth-child(n + 2) {
	display: none;
}

.mx-type-reveal__grid .mx-type-card--match .mx-type-card__profile-link {
	position: absolute;
	inset: 0;
	z-index: 3;
	/* The whole card is the target; the label stays for assistive tech. */
	font-size: 0;
	color: transparent;
	background: none;
	border: 0;
	backdrop-filter: none;
	-webkit-backdrop-filter: none;
	min-height: 0;
	margin: 0;
	padding: 0;
}

.mx-type-reveal__grid .mx-type-card--match .mx-type-card__profile-link:focus-visible {
	outline: 2px solid var(--focus-ring-color, #FFFFFF);
	outline-offset: -3px;
}

/*
 * In the reveal the signup block is a flat decision footer, not another card.
 * The matches are the result; the account prompt remains subordinate to them.
 */
.mx-type-modal.is-reveal .mx-type-signup {
	--mx-signup-pad: 0px;

	display: grid;
	grid-template-columns: minmax(0, 1fr) auto;
	grid-template-areas:
		"title actions"
		"copy actions"
		"privacy quiet";
	align-items: center;
	justify-items: stretch;
	column-gap: 24px;
	row-gap: 4px;
	min-height: 0;
	padding: 16px 0 0;
	border: 0;
	border-top: 1px solid var(--mx-border-subtle);
	border-radius: 0;
	background: none;
	overflow: visible;
	text-align: left;
}

.mx-type-modal.is-reveal .mx-type-signup__faces,
.mx-type-modal.is-reveal .mx-type-signup__eyebrow {
	display: none !important;
}

.mx-type-modal.is-reveal .mx-type-signup strong {
	grid-area: title;
	font-size: 1rem;
	line-height: 1.3;
}

.mx-type-modal.is-reveal .mx-type-signup p {
	grid-area: copy;
	font-size: 13px;
	line-height: 1.45;
}

.mx-type-modal.is-reveal .mx-type-signup__actions {
	grid-area: actions;
	flex-wrap: nowrap;
	margin: 0;
}

.mx-type-modal.is-reveal .mx-type-signup__primary,
.mx-type-modal.is-reveal .mx-type-signup__secondary {
	min-height: 44px;
	white-space: nowrap;
}

.mx-type-modal.is-reveal .mx-type-signup__quiet {
	grid-area: quiet;
	justify-self: end;
	margin: 2px 0 0;
}

.mx-type-modal.is-reveal .mx-type-signup small {
	grid-area: privacy;
	margin-top: 2px;
}

body.mx-type-modal-open {
	overflow: hidden;
}

body.mx-type-modal-open #profile-fab,
body.mx-type-modal-open .mx-tray {
	opacity: 0;
	pointer-events: none;
}

/*
 * REMOVED, and deliberately not replaced:
 *   mx-type-shimmer      defined, applied to nothing at all
 *   mx-type-scan         infinite 1.4s spinner
 *   mx-type-orbit        infinite 5s rotation, x4 faces
 *   mx-type-loader-pop   infinite 1.6s glow, x4 faces
 *   mx-type-dot          infinite 900ms, x2
 *   mx-type-caption-pulse infinite 1.6s, x3
 *
 * Fourteen infinite animations for a wait whose length was already known.
 * The loader subtree now contains exactly one @keyframes, below, and it runs
 * once per sequence.
 */

/* One pass around the ring. Never `infinite`. */
@keyframes mx-type-sweep {
	from {
		transform: translate(-50%, -50%) rotate(-90deg);
	}
	to {
		transform: translate(-50%, -50%) rotate(270deg);
	}
}

@keyframes mx-type-like-pop {
	50% {
		transform: scale(1.025);
	}
}

@keyframes mx-type-feedback-in {
	to {
		opacity: 1;
		transform: translate(-50%, 0);
	}
}

@media (max-width: 640px) {
	.profile-outro__member {
		grid-template-columns: minmax(108px, 0.72fr) minmax(164px, 1.28fr);
		width: min(100%, 390px);
	}

	.profile-outro__member .mx-compare-toggle,
	.profile-outro__member .mx-find-type {
		min-height: 52px;
	}

	.profile-outro__member .mx-compare-toggle {
		gap: 7px;
		padding-inline: 10px;
		font-size: 14px;
	}

	.profile-outro__member .mx-find-type {
		padding-inline: 10px 14px;
		font-size: 14px;
	}

	.mx-find-type__mark {
		width: 28px;
		height: 28px;
	}

	.mx-recommendations__header {
		align-items: flex-start;
		flex-direction: column;
	}

	.mx-recommendations__header h2 {
		font-size: 24px;
	}

	.mx-recommendations__rail {
		display: flex;
		gap: 10px;
		overflow-x: auto;
		scroll-snap-type: x proximity;
	}

	.mx-recommendation-card {
		flex: 0 0 72vw;
		scroll-snap-align: start;
	}

	.mx-type-modal {
		align-items: flex-end;
		padding: 0;
	}

	/*
	 * The drawer is a fixed-height sheet with fixed chrome and one flexible
	 * slot in the middle. Header, progress rail and action dock are constant
	 * rows, so the dock sits in the same place on every card regardless of
	 * what the photo behind it happens to be.
	 */
	.mx-type-modal__dialog {
		--mx-type-dock: 84px;

		display: grid;
		grid-template-rows: auto auto auto minmax(0, 1fr) var(--mx-type-dock);
		width: 100%;
		height: 85vh;
		height: 85svh;
		max-height: 85svh;
		gap: 10px;
		padding: 14px 14px calc(6px + env(safe-area-inset-bottom, 0px));
		border-right: 0;
		border-bottom: 0;
		border-left: 0;
		border-radius: var(--mx-radius-hero) var(--mx-radius-hero) 0 0;
		transform: translateY(18px);
	}

	/* Panel states have their own buttons, so the dock track gives back its room. */
	.mx-type-modal.is-empty .mx-type-modal__dialog,
	.mx-type-modal.is-error .mx-type-modal__dialog,
	.mx-type-modal.is-resetting .mx-type-modal__dialog,
	.mx-type-modal.is-signup .mx-type-modal__dialog {
		--mx-type-dock: 0px;
	}

	.mx-type-modal__header {
		align-items: center;
		gap: 12px;
	}

	.mx-type-modal__eyebrow {
		margin-bottom: 4px;
		font-size: 10px;
	}

	.mx-type-modal__header h2 {
		font-size: 23px;
		line-height: 1.06;
	}

	.mx-type-modal__close {
		width: 38px;
		height: 38px;
		font-size: 24px;
	}

	.mx-type-modal__status {
		min-height: 0;
		font-size: 14px;
		line-height: 1.45;
	}

	/* Once cards are on screen the rail is the status; the sentence is noise. */
	.mx-type-modal.is-ready .mx-type-modal__status,
	.mx-type-modal.is-rating .mx-type-modal__status,
	.mx-type-modal.is-liked .mx-type-modal__status {
		position: absolute;
		width: 1px;
		height: 1px;
		margin: -1px;
		overflow: hidden;
		clip: rect(0 0 0 0);
		white-space: nowrap;
		border: 0;
		padding: 0;
	}

	.mx-type-progress {
		gap: 10px;
	}

	.mx-type-progress__bar {
		height: 3px;
	}

	.mx-type-modal__feedback {
		bottom: calc(var(--mx-type-dock, 84px) + 14px + env(safe-area-inset-bottom, 0px));
		max-width: calc(100% - 40px);
	}

	.mx-type-modal__stage {
		min-height: 0;
		overflow: hidden;
	}

	.mx-type-layout {
		grid-template-columns: minmax(0, 1fr);
		grid-template-rows: minmax(0, 1fr);
		gap: 0;
		min-height: 0;
	}

	.mx-type-feature {
		position: relative;
		min-height: 0;
	}

	/*
	 * Bounded media slot. The card fills the slot absolutely, so its intrinsic
	 * image size can never feed back into the sheet's row sizing.
	 */
	.mx-type-card--active {
		position: absolute;
		inset: 0;
		height: auto;
		aspect-ratio: auto;
		border-radius: 20px;
	}

	.mx-type-card--active .mx-type-card__media {
		position: absolute;
		inset: 0;
		height: auto;
		background: #121212;
	}

	.mx-type-card--active .mx-type-card__fill {
		display: none;
	}

	.mx-type-card--active .mx-type-card__image {
		position: absolute;
		inset: 0;
		z-index: 1;
		width: 100%;
		height: 100%;
		object-fit: cover;
		object-position: center 22%;
	}

	.mx-type-card__scrim {
		height: 52%;
	}

	.mx-type-card__body {
		z-index: 2;
		padding: 14px;
	}

	.mx-type-card__name {
		font-size: 22px;
	}

	.mx-type-card__reasons {
		display: flex;
		flex-wrap: nowrap;
		overflow: hidden;
		gap: 6px;
		margin-top: 9px;
	}

	.mx-type-card__profile-link {
		min-height: 42px;
		margin-top: 12px;
		padding-inline: 14px;
	}

	.mx-type-queue {
		display: none;
	}

	.mx-type-loader {
		grid-template-columns: minmax(0, 1fr);
		grid-template-rows: minmax(0, 1fr);
		gap: 0;
		min-height: 0;
	}

	.mx-type-loader__loop {
		min-height: 0;
		border-radius: 20px;
	}

	/*
	 * The phone ring. The radius, the plate size and the sweep all shrink
	 * together so beat 3's lead still lands on the first card's footprint —
	 * that coincidence is the whole point of the handoff, and it has to hold
	 * at every width, not just on desktop.
	 */
	.mx-type-loader__ring {
		width: min(78vw, 300px);
		height: min(78vw, 300px);
	}

	.mx-type-loader__core {
		width: 118px;
		height: 118px;
	}

	.mx-type-loader__core strong {
		font-size: 15px;
	}

	.mx-type-loader__profile {
		--mx-loader-orbit: min(31vw, 126px);
		width: 72px;
		height: 72px;
	}

	.mx-type-loader[data-mx-beat="3"] .mx-type-loader__profile.is-lead,
	.mx-type-loader[data-mx-beat="handoff"] .mx-type-loader__profile.is-lead {
		transform: translate(-50%, -50%) scale(3.1);
	}

	.mx-type-loader__scan {
		width: min(86vw, 330px);
		height: min(86vw, 330px);
	}

	/*
	 * The captions are the only thing dropped on a phone. There is no room
	 * for a three-row rail beside a ring this size, and the status line at
	 * the top of the dialog is already announcing the same state.
	 */
	.mx-type-loader__caption {
		display: none;
	}

	/* Fixed dock: same height, same place, on every card and in every state. */
	.mx-type-modal__actions {
		display: flex;
		align-items: center;
		justify-content: center;
		gap: 12px;
		height: var(--mx-type-dock);
		min-height: 0;
		padding: 0;
	}

	.mx-type-action {
		width: 52px;
		min-width: 52px;
		height: 52px;
		min-height: 52px;
		padding: 0;
		border-radius: 999px;
		background: rgba(34, 34, 34, 0.96);
		box-shadow: 0 10px 24px rgba(0, 0, 0, 0.32);
	}

	.mx-type-action__label {
		position: absolute;
		width: 1px;
		height: 1px;
		margin: -1px;
		overflow: hidden;
		clip: rect(0 0 0 0);
		white-space: nowrap;
		border: 0;
		padding: 0;
	}

	.mx-type-action__icon .mx-icon {
		width: 24px;
		height: 24px;
		stroke-width: 1.9;
	}

	.mx-type-action--like {
		width: 64px;
		min-width: 64px;
		height: 64px;
		min-height: 64px;
		border-color: var(--mx-primary);
		background: var(--mx-primary);
		color: #F7ECEF;
	}

	.mx-type-action--more {
		color: #E6C46A;
	}

	.mx-type-action--nope {
		color: #EFB4BE;
	}

	.mx-type-action:hover:not(:disabled) {
		transform: translateY(-2px);
	}

	.mx-type-action:active:not(:disabled) {
		transform: scale(0.94);
	}

	.mx-type-state,
	.mx-type-reset-panel,
	.mx-type-signup {
		min-height: 0;
		padding: 22px;
		overflow: hidden auto;
	}

	.mx-type-signup {
		--mx-signup-pad: 22px;

		align-content: start;
		gap: 9px;
	}

	.mx-type-signup__faces {
		padding: 16px 0 14px;
	}

	.mx-type-signup__face {
		width: 44px;
		height: 44px;
	}

	.mx-type-signup__faces.is-static .mx-type-signup__face {
		width: 58px;
		height: 58px;
	}

	.mx-type-signup strong {
		font-size: 23px;
	}

	.mx-type-signup p {
		font-size: 14px;
	}

	.mx-type-signup__actions {
		display: grid;
		grid-template-columns: minmax(0, 1fr);
		width: 100%;
		gap: 8px;
	}

	/* In reveal mode this is a compact continuation, not a second full panel. */
	.mx-type-modal.is-reveal .mx-type-signup {
		--mx-signup-pad: 0px;

		grid-template-columns: minmax(0, 1fr);
		grid-template-areas:
			"title"
			"copy"
			"actions"
			"quiet"
			"privacy";
		gap: 5px;
		padding: 12px 0 0;
		background: var(--mx-surface);
		overflow: visible;
	}

	.mx-type-modal.is-reveal .mx-type-modal__dialog {
		--mx-type-dock: 0px;

		grid-template-rows: auto minmax(0, 1fr);
		height: 92vh;
		height: 92svh;
		max-height: 92svh;
		gap: 12px;
	}

	.mx-type-modal.is-reveal .mx-type-modal__status {
		display: none;
	}

	.mx-type-modal.is-reveal .mx-type-modal__stage {
		grid-row: 2;
		grid-template-rows: minmax(0, 1fr) auto;
		gap: 12px;
		max-height: none;
		padding-right: 0;
		overflow-x: hidden;
		overflow-y: hidden;
	}

	.mx-type-reveal {
		align-content: start;
		min-height: 0;
		overflow: hidden;
	}

	.mx-type-reveal__copy {
		margin-bottom: 9px;
		font-size: 13px;
	}

	.mx-type-reveal__grid,
	.mx-type-reveal__grid:has(> .mx-type-card--match:nth-child(3)),
	.mx-type-reveal__grid:not(:has(> .mx-type-card--match:nth-child(2))) {
		grid-template-columns: none;
		grid-auto-flow: column;
		grid-auto-columns: minmax(244px, 72%);
		gap: 8px;
		min-height: 0;
		overflow-x: auto;
		overflow-y: hidden;
		padding: 0 2px 5px 0;
		scroll-padding-inline: 1px;
		scroll-snap-type: x mandatory;
		overscroll-behavior-inline: contain;
		scrollbar-width: none;
		-webkit-overflow-scrolling: touch;
	}

	.mx-type-reveal__grid::-webkit-scrollbar {
		display: none;
	}

	.mx-type-reveal__grid .mx-type-card--match {
		grid-template-columns: 100px minmax(0, 1fr);
		grid-template-rows: minmax(132px, auto);
		min-height: 132px;
		scroll-snap-align: start;
	}

	.mx-type-reveal__grid .mx-type-card--match .mx-type-card__media {
		width: 100px;
		height: 100%;
		min-height: 132px;
	}

	.mx-type-reveal__grid .mx-type-card--match .mx-type-card__media img {
		object-position: center 24%;
	}

	.mx-type-reveal__grid .mx-type-card--match .mx-type-card__body {
		align-content: center;
		padding: 11px 12px;
	}

	.mx-type-reveal__grid .mx-type-card--match .mx-type-card__name {
		font-size: 15px;
	}

	.mx-type-reveal__grid .mx-type-card--match .mx-type-card__location {
		font-size: 12.5px;
	}

	.mx-type-modal.is-reveal .mx-type-signup strong {
		font-size: 18px;
	}

	.mx-type-modal.is-reveal .mx-type-signup p {
		display: -webkit-box;
		overflow: hidden;
		-webkit-box-orient: vertical;
		-webkit-line-clamp: 2;
		font-size: 13px;
		line-height: 1.4;
	}

	.mx-type-modal.is-reveal .mx-type-signup__actions {
		display: grid;
		grid-template-columns: minmax(0, 1fr) auto;
		width: 100%;
		gap: 8px;
	}

	.mx-type-modal.is-reveal .mx-type-signup__primary {
		width: 100%;
		padding-inline: 12px;
	}

	.mx-type-modal.is-reveal .mx-type-signup__secondary {
		padding-inline: 10px;
		border-color: transparent;
		background: transparent;
		font-size: 13px;
	}

	.mx-type-modal.is-reveal .mx-type-signup__quiet {
		justify-self: start;
		margin-top: 1px;
	}

	.mx-type-modal.is-reveal .mx-type-signup small {
		margin-top: 0;
	}
}

@media (max-width: 380px) {
	.mx-type-reveal__grid .mx-type-card--match {
		grid-template-columns: 92px minmax(0, 1fr);
	}

	.mx-type-reveal__grid .mx-type-card--match .mx-type-card__media {
		width: 92px;
	}

	.mx-type-modal.is-reveal .mx-type-signup__primary,
	.mx-type-modal.is-reveal .mx-type-signup__secondary {
		font-size: 12.5px;
	}
}

@media (prefers-reduced-motion: reduce) {
	.mx-find-type,
	.mx-recommendation-card,
	.mx-type-modal__backdrop,
	.mx-type-modal__dialog,
	.mx-type-modal__feedback,
	.mx-type-progress__fill,
	.mx-type-card,
	.mx-type-action {
		transition-duration: 0.01ms !important;
		transform: none !important;
	}

	.mx-type-modal__feedback,
	.mx-type-signup__faces-track,
	.mx-type-modal.is-liked .mx-type-action--primary {
		animation: none !important;
	}

	/* ----------------------------------------------------------------------
	   REDUCED MOTION — a parallel track, not a frozen frame.

	   What was here before was `animation: none !important` on the orbit, the
	   scan and the captions, on top of product-foundation.css flattening
	   every animation on `*` to 0.01ms. The result was four static circles and
	   a dead ring held for 2.6 seconds, which reads as hung, not as calm. The
	   visitor who most needs to be told what is happening was told nothing.

	   The replacement keeps all three beats and the same 2600ms wall clock,
	   expressed without travel: portraits CROSSFADE in on the same 90ms
	   stagger, beat 2 marks each one in sequence by tint and border instead of
	   a moving sweep, and beat 3 crossfades the lead to the card footprint
	   with no translation. Captions change on the same boundaries, so the
	   state communication is identical.

	   `--mx-beat-*` is the opt-in that product-foundation.css's scoped
	   exemption reads back (see section 14d there). Custom properties are not
	   animation properties, so the `*` rule at priority 130 cannot touch them;
	   this is the only mechanism that survives that cascade.
	   ---------------------------------------------------------------------- */

	.mx-type-loader__profile,
	.mx-type-loader__ring,
	.mx-type-loader__core,
	.mx-type-loader__caption span {
		--mx-beat-transition: 320ms;
		transition-property: opacity, border-color, box-shadow, color !important;
	}

	/* No travel, and no scale: the slots simply appear where they belong. */
	.mx-type-loader__profile,
	.mx-type-loader[data-mx-beat="1"] .mx-type-loader__profile,
	.mx-type-loader[data-mx-beat="2"] .mx-type-loader__profile,
	.mx-type-loader[data-mx-beat="3"] .mx-type-loader__profile,
	.mx-type-loader[data-mx-beat="handoff"] .mx-type-loader__profile {
		transform:
			translate(-50%, -50%)
			rotate(var(--mx-slot-angle, 0deg))
			translateX(var(--mx-loader-orbit))
			rotate(calc(var(--mx-slot-angle, 0deg) * -1)) !important;
	}

	.mx-type-loader__ring,
	.mx-type-loader[data-mx-beat="1"] .mx-type-loader__ring,
	.mx-type-loader[data-mx-beat="2"] .mx-type-loader__ring {
		transform: translate(-50%, -50%) !important;
	}

	.mx-type-loader__core,
	.mx-type-loader[data-mx-beat="3"] .mx-type-loader__core,
	.mx-type-loader[data-mx-beat="handoff"] .mx-type-loader__core {
		transform: translate(-50%, -50%) !important;
	}

	/*
	 * Beat 3's lead does not travel or grow. It takes the selected mark and
	 * full opacity while everything else drops away, which is the same
	 * information the movement carried.
	 */
	.mx-type-loader[data-mx-beat="3"] .mx-type-loader__profile.is-lead,
	.mx-type-loader[data-mx-beat="handoff"] .mx-type-loader__profile.is-lead {
		transform:
			translate(-50%, -50%)
			rotate(var(--mx-slot-angle, 0deg))
			translateX(var(--mx-loader-orbit))
			rotate(calc(var(--mx-slot-angle, 0deg) * -1)) !important;
		box-shadow: 0 0 0 3px rgba(139, 10, 26, 0.55) !important;
	}

	/* The sweep is the one thing with no still equivalent, so it is dropped. */
	.mx-type-loader__scan {
		display: none !important;
	}
}
