/**
 * AeroIDX, admin settings page.
 * Loaded only on the AeroIDX top-level page (see SettingsPage::enqueueAssets).
 *
 * Styling follows the AeroIDX Design System (Figma "AeroIDX/Tokens"), light
 * mode. Every colour, radius and easing comes from tokens.css, which is
 * enqueued as a dependency of this stylesheet, this file declares none of its
 * own. No native wp-admin form components (form-table, nav-tab) are used: the
 * markup is custom so the page reads as a modern panel, not legacy wp-admin.
 */

/*
 * FULL WIDTH, on purpose. This carried a 1200px cap, which on a modern admin
 * left a third of the screen empty while the status tiles wrapped to two rows.
 * Nothing here is long-form reading; it is a control surface, and the caps that
 * matter for legibility now sit on the two things that actually need them: form
 * fields (.aeroidx-field) and prose (.aeroidx-card__intro).
 */
.aeroidx-settings {
	font-family: var(--ax-font-body);
	color: var(--ax-ink);

	/*
	 * WordPress core's accent, repointed at ours inside the plugin screens.
	 *
	 * Core draws a focused, hovered or pressed .button (and focused fields,
	 * checked boxes) in --wp-admin-theme-color, blue by default, at a
	 * specificity our resting colours lose to. A mouse click leaves the button
	 * focused, so "Create page" turned blue the moment it was pressed, spinner
	 * included, and stayed blue for the whole round trip. Overriding every
	 * variant's :focus one by one would need a rule per coloured button; this
	 * changes the one input they all read.
	 *
	 * All four, because core reads all four: the base for focus, darker-10/20
	 * for hover and active, and the rgb triplet for the faint hover fill.
	 * #6d28d9 is --ax-violet-700; the darker two are its 800 and 900 steps.
	 */
	--wp-admin-theme-color: var(--ax-violet-700);
	--wp-admin-theme-color--rgb: 109, 40, 217;
	--wp-admin-theme-color-darker-10: #5b21b6;
	--wp-admin-theme-color-darker-20: #4c1d95;
}

/* --- Sidebar brand (logo + wordmark, top of the nav) -------------------- */

/*
 * One image, not a symbol plus a text wordmark. The gap and the flex row went
 * with the second child; the padding stays because it is the nav's own rhythm.
 */
.aeroidx-sidebar__brand {
	padding: 2px 12px 16px;
	margin-bottom: 12px;
}

/*
 * Sized by height so the lockup's 625x150 aspect drives the width: 30px tall
 * lands at 125px wide, inside the 176px the 200px sidebar leaves after its
 * padding. `max-width: 100%` is the guard for a future export with a different
 * aspect, which would otherwise push the nav sideways.
 */
.aeroidx-sidebar__logo {
	display: block;
	height: 30px;
	width: auto;
	max-width: 100%;
}

/* --- Two-column layout: sidebar + content ------------------------------- */

/*
 * .aeroidx-layout is the grid container wrapping the nav sidebar and the main
 * content column. The sidebar is a fixed column; the content column takes all
 * remaining space (minmax(0,1fr) prevents overflow from long words/code in
 * panels).
 *
 * THE 200px, MEASURED RATHER THAN GUESSED
 * It was 260px, sized for the old accordion whose widest row was "General
 * Settings" beside an 18px chevron. Both are gone: flat nav dropped the chevron
 * and the labels are now one word each. The widest is "Appearance", ~85px in
 * the bundled Poppins at 14px/500, in a row carrying 16px padding + 22px icon +
 * 16px gap + label + 16px padding = ~155px. 200px leaves ~45px of slack for the
 * fallback stack, which is wider than Poppins if the bundled font is slow or
 * blocked.
 *
 * A long translation (German "Erscheinungsbild") exceeds that and WRAPS to a
 * second line rather than overflowing: the row is a centred flex box with no
 * white-space rule, so it just grows taller. Degrading, not breaking, which is
 * the right trade for 60px given back to the content on every screen.
 */
.aeroidx-layout {
	display: grid;
	grid-template-columns: 200px minmax(0, 1fr);
	gap: 28px;
	align-items: start;
	margin-top: 20px;
}

/* --- Sidebar (vertical section tabs) ------------------------------------ */

/*
 * Sticky so the sidebar stays visible while scrolling tall panels.
 * align-self: start prevents it from stretching to the content height.
 * top: 32px clears the WP Toolbar (32px) + a small breathing gap.
 */
.aeroidx-sidebar {
	position: sticky;
	top: 32px;
	align-self: start;
}

/*
 * Flat navigation: one list, one level, one label per destination.
 *
 * This replaced an accordion of five groups. Four of them held exactly one
 * child, so the chevron promised a depth that was not there and reaching a
 * destination cost two clicks. There is nothing to expand any more, which is
 * why there is no group header, no chevron and no collapsed state below.
 */
.aeroidx-nav {
	margin: 0;
	padding: 0;
	list-style: none;
}

/*
 * Nav item: icon + label on one row, full width, no indent. The 16px gap and
 * 16px padding put the label at the same optical position the old group labels
 * held, so the sidebar keeps its rhythm even though a level came out of it.
 */
.aeroidx-nav-item {
	display: flex;
	align-items: center;
	gap: 16px;
	padding: 12px 16px;
	margin: 0 0 2px;
	font-size: 14px;
	font-weight: 500;
	line-height: 1.3;
	text-decoration: none;
	color: var(--ax-secondary);
	border-radius: var(--ax-radius-nav);
	transition: background 150ms var(--ax-ease), color 150ms var(--ax-ease), box-shadow 150ms var(--ax-ease);
}

.aeroidx-nav-item:hover,
.aeroidx-nav-item:focus {
	background: var(--ax-card);
	color: var(--ax-ink);
	text-decoration: none;
}

/*
 * Selected state, unchanged from the sub-item it replaces: gray fill plus the
 * violet ring. It is the only "you are here" signal the sidebar needs now that
 * there is no group header to tint as well.
 */
.aeroidx-nav-item.is-active {
	background: var(--ax-selected);
	color: var(--ax-ink);
	font-weight: 600;
	box-shadow: 0 0 0 2px var(--ax-violet-500);
}

.aeroidx-nav-item:focus-visible {
	outline: 2px solid var(--ax-violet-500);
	outline-offset: 2px;
}

.aeroidx-nav-item__icon {
	display: flex;
	flex-shrink: 0;
	color: var(--ax-muted);
}

.aeroidx-nav-item__icon svg {
	display: block;
	width: 22px;
	height: 22px;
}

.aeroidx-nav-item.is-active .aeroidx-nav-item__icon {
	color: var(--ax-violet-700);
}

.aeroidx-nav-item__label {
	flex: 1 1 auto;
}

/*
 * Hairline above Settings. It is the one destination you configure rather than
 * look at, so it sits apart from the four content screens instead of reading as
 * a fifth one. Presentational, so it carries role="presentation" and is skipped
 * by screen readers walking the list.
 */
.aeroidx-nav__rule {
	height: 1px;
	margin: 10px 12px;
	background: var(--ax-border-soft);
}

/* --- Content column ------------------------------------------------------- */

/*
 * min-width:0 prevents inner content (e.g. long URLs, wide tables) from
 * overflowing the grid cell; minmax(0,1fr) in the parent already handles
 * this at the track level, but belt-and-suspenders for nested grids.
 */
.aeroidx-content {
	min-width: 0;
}

/* --- Tab panels --------------------------------------------------------- */

/*
 * Every panel is in the DOM at all times, only the active one is shown.
 * This is deliberate: the API Key field must always travel with the POST.
 *
 * Visibility keys on ONE class, is-active, set by PHP for the first paint and
 * re-toggled by admin.js on every nav click. It deliberately does NOT
 * enumerate panel names.
 *
 * WHY THAT MATTERS: this rule used to list each [data-panel="…"] beside its
 * matching wrapper attribute, which meant a new panel rendered perfectly
 * valid markup and then stayed invisible forever, no error, no console
 * warning, nothing to grep for. The Markets tab shipped that way. CSS cannot
 * compare an attribute on the wrapper against one on a descendant, so the
 * comparison belongs where it can actually be made once: in the code that
 * already knows which screen is active.
 */
.aeroidx-tab-panel {
	display: none;
}

.aeroidx-tab-panel.is-active {
	display: block;
}

/*
 * Every screen runs the full width of the content column. The per-screen
 * max-width list that used to live here is gone with it, which also retires a
 * hand-maintained list of panel names, the shape of mistake that once hid a
 * whole tab.
 *
 * The API screen's field is NOT exempted any more. It used to lift the
 * .aeroidx-field cap so a lone input filled its 800px card; with no card cap
 * left, that exemption would stretch one credential input across the monitor.
 * It now keeps the ordinary 520px field width, which is the right size for what
 * it holds.
 */

/* --- Home screen -------------------------------------------------------- */

/*
 * Stat tiles: the whole install read before any of it is read.
 *
 * State is encoded in FORM as well as in number — a coloured rail down the left
 * edge and a filled meter under each ratio — so a tile that needs attention is
 * visible at a glance rather than only on inspection. The rail colours are
 * semantic (good / needs-you) and deliberately NOT the violet accent, which
 * means "interactive" everywhere else in this admin.
 */
/* Container-query context for the tile grid. Scoped to its own element on
   purpose: container-type establishes a containing block for position:fixed
   descendants, and the confirm dialog is fixed and full-viewport. */
.aeroidx-stats-wrap {
	container-type: inline-size;
}

.aeroidx-stats {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
	gap: 12px;
	margin-top: 18px;
}

/*
 * Four across, explicitly, once the GRID ITSELF can hold them.
 *
 * auto-fit alone is not enough: it packs as many as fit, so at some widths it
 * lands on three and orphans the fourth onto its own row, which reads as a
 * fifth thing that failed rather than as one row of four.
 *
 * This was a @media (min-width: 1180px) rule, and 1180 was measured against the
 * VIEWPORT while the constraint lives in the CONTAINER. The two differ by 388px
 * here (160px wp-admin menu + 200px sidebar + 28px gap) before the card's own
 * 56px of padding, so between roughly 1180 and 1290px the override was handing
 * four tiles a container that only fits three of them at their stated minimum,
 * and minmax(0, 1fr) has no floor to stop it. The tiles went narrower than the
 * 190px the rule above declares as their minimum, and the uppercase labels
 * wrapped.
 *
 * 796px = 4 x 190 + 3 x 12, the real width four tiles need, asked of the box
 * that actually has to supply it.
 */
@container (min-width: 796px) {
	.aeroidx-stats {
		grid-template-columns: repeat(4, minmax(0, 1fr));
	}
}

.aeroidx-stat {
	padding: 14px 18px;
	background: var(--ax-card);
	border: 1px solid var(--ax-border-soft);
	border-radius: var(--ax-radius-card);
	box-shadow: 0 1px 2px var(--ax-shadow-a04);
}

/*
 * STATE IS NOT CARRIED BY COLOUR HERE.
 *
 * This used to be a 3px coloured rail down the left edge of every tile. It went
 * for three reasons, all measured:
 *
 *   1. The "needs you" rail used --ax-warning-edge (#fde68a), which is 1.25:1
 *      against the card. A non-text indicator carrying meaning needs 3:1. The
 *      "all good" rail measured 3.77:1, so the urgent signal was three times
 *      LESS visible than the calm one.
 *   2. Nothing but colour distinguished the two states, so the four tiles were
 *      identical to anyone who cannot separate green from pale amber, and the
 *      rail vanished outright in forced-colors mode.
 *   3. Being a pseudo-element, it did not exist for a screen reader at all.
 *
 * A "!" mark now marks the tiles that want something, with a screen-reader word
 * on every tile (see HomePanel::tile). Colour reinforces the mark; it is never
 * the only thing saying it. Dropping the rail also let overflow:hidden go, so a
 * focus ring on this tile is no longer clipped on all four edges.
 */
.aeroidx-stat__label {
	display: flex;
	align-items: center;
	gap: 6px;
	font-size: 11px;
	font-weight: 600;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--ax-muted);
}

/* --ax-warning-ink is 7.09:1 on the card, against the 1.25:1 it replaces. */
.aeroidx-stat__mark {
	display: grid;
	place-items: center;
	flex: none;
	width: 16px;
	height: 16px;
	border-radius: 50%;
	background: var(--ax-warning-ink);
	color: var(--ax-on-accent);
	font-size: 11px;
	font-weight: 700;
	letter-spacing: 0;
	line-height: 1;
}

.aeroidx-stat__value {
	display: flex;
	align-items: baseline;
	flex-wrap: wrap;
	gap: 6px;
	margin-top: 4px;
	font-size: 26px;
	font-weight: 600;
	line-height: 1.15;
	letter-spacing: -0.02em;
	color: var(--ax-ink);
	font-variant-numeric: tabular-nums;
}

/* The Account tile's value is a state, not a number, so it opts out of the
   numeral sizing and lets the pill carry its own. */
.aeroidx-stat__value--status {
	font-size: inherit;
	font-weight: inherit;
	letter-spacing: 0;
	margin-top: 7px;
}

.aeroidx-stat__value small {
	font-size: 13px;
	font-weight: 500;
	letter-spacing: 0;
	color: var(--ax-muted);
}

/* A number that was not free to read. Muted, not alarming: nothing is wrong,
   it simply costs a round-trip this screen will not spend uninvited. */
.aeroidx-stat__value--resting {
	font-size: 16px;
	font-style: italic;
	font-weight: 500;
	color: var(--ax-muted);
}

.aeroidx-stat__foot {
	margin-top: 6px;
	font-size: 12px;
	line-height: 1.4;
	color: var(--ax-secondary);
}

.aeroidx-meter {
	height: 4px;
	margin-top: 10px;
	border-radius: 99px;
	background: var(--ax-neutral-100);
	overflow: hidden;
}

.aeroidx-meter i {
	display: block;
	height: 100%;
	border-radius: 99px;
	background: var(--ax-violet-500);
}

.aeroidx-meter i.is-full {
	background: var(--ax-success);
}

/* --- Home: next steps ---------------------------------------------------- */

.aeroidx-steps {
	margin: 18px 0 0;
	padding: 0;
	list-style: none;
	display: flex;
	flex-direction: column;
	gap: 10px;
}

/*
 * An explicit grid, not flex-wrap: the mark, the text and the action have very
 * different widths, and flex-wrap drops the button to its own line at widths
 * that are perfectly common in wp-admin. Same reasoning as the Markets rows.
 */
.aeroidx-step {
	display: grid;
	grid-template-columns: auto minmax(0, 1fr) auto;
	align-items: center;
	gap: 14px;
	margin: 0;
	padding: 14px 16px;
	border-radius: var(--ax-radius-card);
	border: 1px solid var(--ax-warning-edge);
	background: var(--ax-warning-wash);
	font-size: 13px;
	line-height: 1.5;
	color: var(--ax-secondary);
}

.aeroidx-step__mark {
	display: grid;
	place-items: center;
	flex: none;
	width: 20px;
	height: 20px;
	border-radius: 50%;
	background: var(--ax-warning-ink);
	color: var(--ax-on-accent);
	font-size: 12px;
	font-weight: 700;
	line-height: 1;
}

.aeroidx-step__text strong {
	color: var(--ax-ink);
	font-weight: 600;
}

.aeroidx-step__action {
	justify-self: end;
}

/* The finished state: one quiet line, no tiles of zeroes, no banner that never
   leaves. A congratulation that outstays its welcome is a nag with manners. */
.aeroidx-home__done {
	display: flex;
	align-items: flex-start;
	gap: 14px;
}

.aeroidx-home__done-mark {
	display: grid;
	place-items: center;
	flex: none;
	width: 36px;
	height: 36px;
	border-radius: 50%;
	background: var(--ax-notice-success-bg);
	border: 1px solid var(--ax-notice-success-edge);
	color: var(--ax-success-ink);
}

.aeroidx-home__cta {
	margin: 16px 0 0;
}

.aeroidx-home__resting {
	margin: 16px 0 0;
	font-size: 13px;
	line-height: 1.5;
	color: var(--ax-muted);
}

@media screen and (max-width: 600px) {
	.aeroidx-step {
		grid-template-columns: auto minmax(0, 1fr);
	}

	.aeroidx-step__action {
		grid-column: 2;
		justify-self: start;
	}
}

/* --- Card --------------------------------------------------------------- */

.aeroidx-card {
	background: var(--ax-card);
	border: 1px solid var(--ax-border-soft);
	border-radius: var(--ax-radius-card);
	padding: 24px 28px;
	box-shadow: 0 1px 2px var(--ax-shadow-a04),
		0 6px 16px var(--ax-shadow-a05);
}

/*
 * NO MEASURE, ON EVERY SCREEN. This is the last of the prose caps to go, and
 * the comment it replaces argued the opposite: "a 200-character line is
 * unreadable no matter how much room there is for it." That is true of books.
 * It is less true of a settings panel, where the intro is two or three
 * sentences read once and the alternative is a column that stops two thirds of
 * the way across a card the user was told is full width.
 *
 * The decision is the admin's, applied consistently rather than screen by
 * screen: left-aligned text runs to the card edge like everything else. The one
 * survivor is .aeroidx-panelstate__body, and for a different reason — see there.
 */
.aeroidx-card__intro {
	margin: 0 0 20px;
	color: var(--ax-secondary);
	font-size: 13px;
	line-height: 1.6;
}

/* Card header row: section title on the left, detected-builder chip pushed to
 * the right. */
.aeroidx-card__head {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 12px;
	margin: 4px 0 14px;
}

/* "Create all pages" sits on its own row, right-aligned, between the IDX Pages
 * intro and the page list. */
.aeroidx-pages__bulk {
	display: flex;
	justify-content: flex-end;
	margin: 0 0 14px;
}

/* Detected-builder chip: logo + name (editor-agnostic, both the logo URL and
 * the label come from the active provider, never hardcoded here). Reads as a
 * status pill, not part of the title. */
.aeroidx-card__builder {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	flex: none;
	padding: 4px 10px;
	background: var(--ax-input);
	border: 1px solid var(--ax-border-soft);
	border-radius: var(--ax-radius-pill);
}

.aeroidx-card__builder-name {
	font-size: 12px;
	font-weight: 600;
	line-height: 1;
	color: var(--ax-secondary);
}

.aeroidx-card__logo {
	width: 18px;
	height: 18px;
	object-fit: contain;
	flex: none;
}

/*
 * Responsive, ≤782px (WP admin menu folds at this breakpoint).
 *
 * - Stack the sidebar above the content (single-column layout).
 * - Drop sticky positioning, nothing to stick to on a narrow layout.
 */
@media (max-width: 782px) {
	.aeroidx-layout {
		grid-template-columns: 1fr;
	}

	.aeroidx-sidebar {
		position: static;
	}
}

/* --- Form field (label on top) ----------------------------------------- */
/*
 * CONTROLS SPAN THE CARD; PROSE DOES NOT.
 *
 * The panels went full width and the controls did not follow, so this field
 * stopped at 520px inside a card around 1250px wide while .aeroidx-actions
 * pinned Save to the card's right edge — roughly 700px of empty space between
 * a control and the button that submits it, with nothing in between to explain
 * the gap. The button did not look aligned to anything; it looked lost.
 *
 * The rule that fixes it, and the one to apply on the other screens: an
 * interactive element is sized by its container, so it runs the full width and
 * everything lines up on both edges. Running TEXT keeps a measure regardless —
 * .aeroidx-card__intro at 90ch, .aeroidx-field__help at 60ch — because a
 * 1250px line of prose has no readable return sweep. Those two are not
 * exceptions to the full-width decision; they are a different kind of content.
 */

.aeroidx-field {
	display: flex;
	flex-direction: column;
	gap: 6px;
}

.aeroidx-field__title {
	display: block;
	margin: 0 0 6px;
	font-size: 16px;
	font-weight: 600;
	color: var(--ax-ink);
}

.aeroidx-settings .aeroidx-field__input {
	width: 100%;
	box-sizing: border-box;
	margin: 0;
	padding: 9px 12px;
	font-size: 14px;
	line-height: 1.4;
	background: var(--ax-input);
	border: 1px solid var(--ax-border);
	border-radius: var(--ax-radius-input);
	color: var(--ax-ink);
	box-shadow: none;
	transition: border-color 150ms var(--ax-ease),
		box-shadow 150ms var(--ax-ease), background 150ms var(--ax-ease);
}

.aeroidx-settings .aeroidx-field__input:focus {
	background: var(--ax-input-focus);
	border-color: var(--ax-violet-500);
	box-shadow: 0 0 0 1px var(--ax-violet-500);
	outline: 2px solid transparent; /* preserved for forced-colors mode */
}

/*
 * DECLARE THE PLACEHOLDER. Inheriting it was a contrast bug we caused without
 * writing a single colour.
 *
 * WordPress core sets ::placeholder to #757575, chosen against core's own WHITE
 * input, where it lands at 4.61:1, a pass with 0.11 to spare. We repaint the
 * field #eeeeee, and that alone drops it to 3.97:1 (4.26:1 on the focus fill).
 * Both under the 4.5:1 that 14px normal-weight text needs.
 *
 * --ax-muted is NOT the answer either, which is the trap: it clears 4.5:1 on the
 * white card but measures 4.17 and 4.47 on these two fills. Hence the dedicated
 * on-fill token, 6.66 and 7.15.
 */
.aeroidx-settings .aeroidx-field__input::placeholder {
	color: var(--ax-muted-on-fill);
	opacity: 1; /* Firefox dims placeholders by default; that would undo the fix. */
}

/* Read-only value shown when the field is set via a wp-config.php constant. */
.aeroidx-field__locked {
	align-self: flex-start;
	background: var(--ax-locked);
	color: var(--ax-ink);
	padding: 9px 12px;
	border-radius: var(--ax-radius-input);
	font-size: 13px;
}

/*
 * NO MEASURE HERE, BY DECISION — and the reasoning that lost is worth keeping.
 *
 * The argument for the 60ch cap that used to sit here: a line of running text
 * spanning a 1250px card has no readable return sweep, so the eye loses its
 * place on every wrap. That still holds for PARAGRAPHS, and .aeroidx-card__intro
 * keeps its 90ch for exactly that reason.
 *
 * It lost here because these are not paragraphs. A field hint is one short
 * sentence tied to the control above it, and once the redundant half of this
 * screen's hint was deleted it fit on a single line either way — at which point
 * the cap only bought a narrower ragged block under a full-width field. The
 * decision is the admin's: controls and their labels align to the card.
 *
 * WHAT TO WATCH. The longest string wearing this class is the wp-config notice
 * ("Set by the AEROIDX_API_KEY constant…", ~110 chars), which now sets as one
 * long line on a wide screen. If that reads badly, shorten the sentence rather
 * than putting the cap back — a cap here would re-narrow the hints that are
 * already the right length.
 */
.aeroidx-field__help {
	margin: 0;
	font-size: 12px;
	line-height: 1.5;
	color: var(--ax-muted);
}

/* --- Panel empty / connect / error state --------------------------------- */
/*
 * One centred component for the seven places a panel has nothing to show.
 * Replaces two implementations that never knew about each other: HomePanel's
 * hand-written card and SettingsPage's private renderPanelNotice(). See
 * Admin\PanelState for the register model.
 */

.aeroidx-panelstate {
	display: flex;
	align-items: center;
	justify-content: center;
	padding: 48px 28px;
	/*
	 * FILL, WITH A CEILING AND A FLOOR.
	 *
	 * "Centre it in the available height" is what this wants to mean, but a
	 * panel has no height of its own to centre in — it is as tall as its
	 * content, so a percentage resolves against nothing and collapses. Hence a
	 * viewport measure. min() supplies the ceiling: on a tall display 60vh
	 * would push the button below the fold on the one screen whose entire job
	 * is getting that button pressed. The padding above is the floor, so a
	 * short viewport degrades to a comfortable block instead of a cramped one.
	 */
	min-height: min(560px, 60vh);
}

.aeroidx-panelstate__body {
	display: flex;
	flex-direction: column;
	align-items: center;
	text-align: center;
	/*
	 * THE ONE MEASURE THAT SURVIVED, because centred text is not the same
	 * question as left-aligned text.
	 *
	 * Every other cap in this file went when the admin went full width. This
	 * one stays: a long LEFT-ALIGNED line is harder to read but still has a
	 * straight left edge to return to on every wrap. A long CENTRED line has
	 * neither edge, so the eye has to hunt for the start of each line. That is
	 * a different defect, and widening this would not make the state look more
	 * full-width, only harder to read.
	 */
	max-width: 46ch;
}

.aeroidx-panelstate__icon {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 56px;
	height: 56px;
	border-radius: var(--ax-radius-full);
	background: var(--ax-violet-a10);
	color: var(--ax-violet-700);
}

.aeroidx-panelstate__title {
	margin: 16px 0 0;
	font-size: 18px;
	font-weight: 600;
	letter-spacing: -0.01em;
	color: var(--ax-ink);
	text-wrap: balance;
}

.aeroidx-panelstate__text {
	margin: 8px 0 0;
	font-size: 13px;
	line-height: 1.65;
	color: var(--ax-secondary);
}

.aeroidx-panelstate__actions {
	margin: 22px 0 0;
}

.aeroidx-settings .aeroidx-panelstate__actions .button-primary {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	text-decoration: none;
}

.aeroidx-panelstate__arrow {
	line-height: 1;
}

/* The quiet second way out. A text link, not a second button: two controls of
 * equal weight force a choice before the user has read anything. */
.aeroidx-panelstate__secondary {
	margin-top: 12px;
	font-size: 12px;
	color: var(--ax-muted);
	text-underline-offset: 2px;
}

.aeroidx-panelstate__secondary:hover,
.aeroidx-panelstate__secondary:focus-visible {
	color: var(--ax-violet-700);
}

/*
 * The error register borrows the danger family so the state cannot read as an
 * invitation. Shapes are identical; only the hue moves, and the wording carries
 * the meaning on its own — so this survives being read in greyscale.
 */
.aeroidx-panelstate--error .aeroidx-panelstate__icon {
	background: var(--ax-danger-wash);
	color: var(--ax-wp-error);
}

/* --- Settings tab: connection status ------------------------------------ */
/*
 * Whether AeroIDX is answering, stated before the field rather than after it.
 * The state is carried by the WORDS ("Connected" / "Not connected"), so the
 * colour is reinforcement and 1.4.1 holds if it is stripped.
 */

.aeroidx-conn {
	display: grid;
	grid-template-columns: auto 1fr;
	gap: 2px 10px;
	align-items: baseline;
	margin: 0 0 18px;
	padding: 12px 14px;
	border: 1px solid transparent;
	border-radius: var(--ax-radius-tile);
	font-size: 13px;
	line-height: 1.5;
}

.aeroidx-conn__headline {
	font-weight: 600;
}

.aeroidx-conn__detail {
	grid-column: 1 / -1;
}

.aeroidx-conn__when {
	justify-self: end;
	font-size: 12px;
	opacity: 0.8;
}

.aeroidx-conn--ok {
	background: var(--ax-notice-success-bg);
	border-color: var(--ax-notice-success-edge);
	color: var(--ax-notice-success-ink);
}

.aeroidx-conn--error {
	background: var(--ax-danger-wash);
	border-color: var(--ax-danger-edge);
	color: var(--ax-wp-error);
}

.aeroidx-conn--warning {
	background: var(--ax-warning-wash);
	border-color: var(--ax-warning-edge);
	color: var(--ax-warning-ink);
}

/* Nothing has gone wrong — a key is saved and no call has been made lately.
 * Deliberately the quietest of the four: it is a report, not a problem. */
.aeroidx-conn--info {
	background: var(--ax-zebra);
	border-color: var(--ax-border-soft);
	color: var(--ax-secondary);
}

/* A failed reveal. Hidden until the JS fills it, so role="alert" announces on
 * the transition rather than on page load. */
.aeroidx-field__error {
	color: var(--ax-wp-error);
}

.aeroidx-field__error[hidden] {
	display: none;
}

.aeroidx-settings .aeroidx-reveal.is-reveal-failed {
	color: var(--ax-wp-error);
}

/* --- Listing URL tab: slug field + live address preview ---------------- */

.aeroidx-url-preview {
	margin: 16px 0 0;
	display: flex;
	flex-direction: column;
	gap: 6px;
}

.aeroidx-url-preview__caption {
	font-size: 12px;
	color: var(--ax-muted);
}

.aeroidx-url-preview__value {
	display: block;
	padding: 10px 12px;
	background: var(--ax-input);
	border: 1px solid var(--ax-border-soft);
	border-radius: var(--ax-radius-input);
	font-size: 13px;
	line-height: 1.5;
	color: var(--ax-secondary);
	word-break: break-all;
}

.aeroidx-url-preview__slug {
	font-weight: 600;
	color: var(--ax-violet-700);
}

/* --- Reveal toggle (API key) ------------------------------------------- */

.aeroidx-reveal-field {
	position: relative;
}

.aeroidx-reveal-field .aeroidx-field__input {
	padding-right: 44px;
}

.aeroidx-settings .aeroidx-reveal {
	position: absolute;
	top: 1px;
	right: 1px;
	bottom: 1px;
	width: 40px;
	display: flex;
	align-items: center;
	justify-content: center;
	padding: 0;
	background: transparent;
	border: none;
	border-radius: 0 var(--ax-radius-input) var(--ax-radius-input) 0;
	color: var(--ax-muted);
	cursor: pointer;
	transition: color 150ms var(--ax-ease);
}

.aeroidx-settings .aeroidx-reveal:hover,
.aeroidx-settings .aeroidx-reveal:focus {
	color: var(--ax-violet-700);
}

.aeroidx-settings .aeroidx-reveal:focus-visible {
	outline: 2px solid var(--ax-violet-500);
	outline-offset: -2px;
}

.aeroidx-reveal__icon {
	display: block;
	width: 20px;
	height: 20px;
}

.aeroidx-reveal__icon--hide {
	display: none;
}

.aeroidx-reveal.is-revealed .aeroidx-reveal__icon--show {
	display: none;
}

.aeroidx-reveal.is-revealed .aeroidx-reveal__icon--hide {
	display: block;
}

/*
 * Loading state. admin.js sets aria-busy while the reveal request is in flight
 * and clears it on both the success and the failure path; until now nothing
 * rendered it, so the button sat inert for the whole round trip and a slow
 * connection read as a dead control.
 *
 * Design System, Buttons › States: "loading, aria-busy · animate-spin", drawn
 * as a brand violet arc. Keyed off the attribute rather than a companion class
 * so what the screen shows and what assistive technology announces can never
 * drift apart.
 *
 * Specificity note: the rule hiding the icons matches (0,3,0), the same as
 * `.aeroidx-reveal.is-revealed .aeroidx-reveal__icon--hide` above it, and wins
 * on source order, so the spinner also replaces the icon in the revealed
 * state, not just the resting one.
 */
.aeroidx-settings .aeroidx-reveal[aria-busy="true"] {
	cursor: progress;
}

.aeroidx-reveal[aria-busy="true"] .aeroidx-reveal__icon {
	display: none;
}

.aeroidx-reveal[aria-busy="true"]::after {
	content: "";
	width: 16px;
	height: 16px;
	border: 2px solid var(--ax-violet-a12);
	border-top-color: var(--ax-violet-500);
	border-radius: 50%;
	animation: aeroidx-spin 1s linear infinite;
}

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

/*
 * Reduced motion slows the spin rather than stopping it: a frozen ring carries
 * no information, and the point of the control is to say "something is
 * happening". Linear easing is kept, the Design System reserves
 * easing/linear for continuous motion like this.
 */
@media (prefers-reduced-motion: reduce) {
	.aeroidx-reveal[aria-busy="true"]::after {
		animation-duration: 3s;
	}
}

/*
 * Submit buttons in flight. admin.js (startBusy) puts `is-busy` on the button
 * the admin pressed, alongside aria-busy. The class is what marks it as ours:
 * the reveal and the widget menu use aria-busy alone and draw their own states.
 * Not aria-disabled, which WordPress 7.1 core answers with grey !important
 * text (see startBusy).
 *
 * The ring takes currentColor rather than brand violet: the same rule has to
 * read on a filled violet primary, an outlined secondary and the red delete
 * icon, and only the button's own text colour contrasts with all three.
 * Icon-only buttons lose their svg to the ring; labelled ones keep the label
 * admin.js swapped in beside it.
 *
 * The button's own display is left alone. It used to be switched to
 * inline-flex here, but `.aeroidx-settings .button.button-primary` sets
 * inline-block at a higher specificity and won, which left the ring an inline
 * box: width and height ignored, only a sliver of border drawn. The ring is an
 * inline-block of its own instead, so it keeps its size whether the button is
 * block, inline-block or flex.
 */
.aeroidx-settings button.is-busy {
	cursor: progress;
	pointer-events: none;
}

.aeroidx-settings button.is-busy > svg {
	display: none;
}

.aeroidx-settings button.is-busy .aeroidx-busy__label {
	margin-left: 8px;
	vertical-align: middle;
}

/* The market button is already inline-flex with a 6px gap, which the margin
 * above would add to. Two more makes the same 8px as everywhere else. */
.aeroidx-settings .aeroidx-market-action--primary.is-busy .aeroidx-busy__label {
	margin-left: 2px;
}

.aeroidx-settings button.is-busy::before {
	content: "";
	display: inline-block;
	flex: none;
	vertical-align: middle;
	width: 14px;
	height: 14px;
	box-sizing: border-box;
	border: 2px solid currentColor;
	border-right-color: transparent;
	border-radius: 50%;
	animation: aeroidx-spin 0.8s linear infinite;
}

@media (prefers-reduced-motion: reduce) {
	.aeroidx-settings button.is-busy::before {
		animation-duration: 3s;
	}
}

/* --- Actions row -------------------------------------------------------- */

.aeroidx-actions {
	display: flex;
	justify-content: flex-end;
	margin: 20px 0 0;
	padding: 0;
}

/* --- Primary button (Save Changes) ------------------------------------- */
/* Design System PrimaryButton: violet gradient, pill, uppercase label. */

/* No uppercase, no tracking. ALL CAPS at pill size shouted louder than
   anything else on every screen, for no reason the user could act on: it was a
   CSS decision, never a decision about the words. Applies to every primary
   button in the plugin admin. */
.aeroidx-settings .button.button-primary {
	display: inline-block;
	background: linear-gradient(141deg, var(--ax-grad-from), var(--ax-grad-to));
	border: none;
	border-radius: var(--ax-radius-pill);
	color: var(--ax-on-accent);
	font-family: inherit;
	font-size: 12px;
	font-weight: 600;
	text-shadow: none;
	padding: 9px 26px;
	height: auto;
	min-height: 0;
	line-height: 1.5;
	box-shadow: 0 1px 2px var(--ax-shadow-a12);
	cursor: pointer;
	transition: filter 150ms var(--ax-ease), box-shadow 150ms var(--ax-ease);
}

/* :focus-visible rather than :focus, matching the secondary button, otherwise
 * a mouse click leaves the button brightened and lifted until you click
 * something else, which reads as a stuck state. The box-shadow here also
 * happens to be what overrides WordPress core's blue focus ring on this
 * variant; the secondary button needs an explicit reset for the same job. */
.aeroidx-settings .button.button-primary:hover,
.aeroidx-settings .button.button-primary:focus-visible {
	background: linear-gradient(141deg, var(--ax-grad-from), var(--ax-grad-to));
	border: none;
	color: var(--ax-on-accent);
	filter: brightness(1.08);
	box-shadow: 0 3px 10px var(--ax-violet-a38);
}

/*
 * Core's blue ring again, but scoped :focus:not(:focus-visible), because a
 * keyboard-focused element matches BOTH pseudo-classes. A blanket :focus reset
 * here would have the same specificity as the rule above and, coming later,
 * would strip the violet lift from keyboard focus too.
 */
.aeroidx-settings .button.button-primary:focus:not(:focus-visible) {
	box-shadow: none;
}

.aeroidx-settings .button.button-primary:focus-visible {
	outline: 2px solid var(--ax-violet-700);
	outline-offset: 2px;
}

.aeroidx-settings .button.button-primary:active {
	filter: brightness(0.96);
	box-shadow: 0 1px 2px var(--ax-shadow-a12);
}

/* --- Secondary button --------------------------------------------------- */
/*
 * Design System SecondaryButton: white fill, gray border, 6px radius.
 * submit_button() with type 'secondary' emits only `class="button"` (it
 * never adds `button-secondary`), so the base `.button` rule IS the
 * secondary style. The primary button still wins via the more specific
 * `.button.button-primary` selector above.
 */

.aeroidx-settings .button {
	background: var(--ax-card);
	border: 1px solid var(--ax-border);
	border-radius: var(--ax-radius-input);
	color: var(--ax-secondary);
	font-family: inherit;
	transition: border-color 150ms var(--ax-ease), color 150ms var(--ax-ease);
}

/*
 * KILL WORDPRESS CORE'S BLUE FOCUS RING.
 *
 * buttons.css rings a focused .button with
 * `box-shadow: 0 0 0 1.5px var(--wp-admin-theme-color, #3858e9)`. Our own
 * :focus rule below never touched box-shadow, so core's ring survived, a blue
 * ring in the middle of a violet panel, and one that fired on a plain mouse
 * click. The plugin owns exactly one focus language and it is violet.
 *
 * This is a reset, NOT a suppression: :focus-visible below paints our own
 * indicator. Do not collapse the two.
 */
.aeroidx-settings .button:focus {
	box-shadow: none;
}

/*
 * :focus-visible, not :focus, for the tint.
 *
 * With :focus this fired on every mouse click and stayed until you clicked
 * elsewhere, which is what made the copy chip look stuck in a "selected" state
 * after being pressed. :focus-visible is the browser's own answer to "did this
 * come from the keyboard?", so keyboard users keep the full treatment and mouse
 * users get nothing lingering.
 */
.aeroidx-settings .button:hover,
.aeroidx-settings .button:focus-visible {
	background: var(--ax-card);
	border-color: var(--ax-violet-500);
	color: var(--ax-violet-700);
}

.aeroidx-settings .button:focus-visible {
	outline: 2px solid var(--ax-violet-500);
	outline-offset: 2px;
}

/* --- Appearance panel (docs) -------------------------------------------- */
/*
 * The Appearance tab is reference docs: a list of styling hooks and one
 * copy-paste CSS snippet. WP's default <pre><code> styling renders each line of
 * a multi-line code block as a separate gray pill, which looks broken. The
 * rules below give the snippet a single unified surface and align the list +
 * inline code with the violet design system.
 *
 * THIS WAS A <table> AND IS NOW A <dl>, which is the reason most of the old
 * rules here are gone. Two columns holding a token and a paragraph are not
 * tabular — nothing is compared across rows, and their intrinsic widths are
 * irreconcilable. `table-layout: auto` apportions from min/max-content, so a
 * ~300-character prose column claimed nearly everything and a 47-character
 * selector broke across three lines inside a panel 900px wide. The old fix for
 * that was `word-break: break-word` on the chip, which made it worse: that
 * value is defined as `overflow-wrap: anywhere`, and `anywhere` is counted when
 * min-content is computed, so the column then declared its minimum as one
 * character. Stacked rows have no column to starve.
 */

.aeroidx-settings .aeroidx-hooks {
	margin: 16px 0 8px;
	border: 1px solid var(--ax-border-soft);
	border-radius: var(--ax-radius-card);
	overflow: hidden;
	background: var(--ax-card);
}

.aeroidx-hook {
	padding: 14px 16px;
	border-bottom: 1px solid var(--ax-border-soft);
}

.aeroidx-hook:last-child {
	border-bottom: none;
}

/* Chip and button on one line, name above it. flex-wrap is what makes this
 * responsive with no media query: on a narrow admin the button drops to its own
 * line instead of strangling the selector. */
.aeroidx-hook__head {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 10px;
	margin: 0 0 6px;
}

/* The scan target. Every selector on this screen starts with the same handful
 * of characters, so without this the eye has no way to find a row and reads all
 * of them, every visit. */
.aeroidx-hook__name {
	flex-basis: 100%;
	font-size: 14px;
	font-weight: 600;
	color: var(--ax-ink);
}

.aeroidx-settings .aeroidx-hooks code {
	background: var(--ax-violet-a10);
	color: var(--ax-violet-700);
	padding: 2px 6px;
	border-radius: var(--ax-radius-chip);
	font-size: 12px;
	font-family: var(--ax-font-mono);
}

.aeroidx-hook__where {
	margin: 0;
	font-size: 13px;
	line-height: 1.6;
	color: var(--ax-secondary);
}

/* A fact about the plugin's own output, not about the selector's scope, so it
 * gets its own line rather than another clause. */
.aeroidx-hook__headsup {
	display: block;
	margin-top: 4px;
	color: var(--ax-muted);
}

/* Rendered when the running theme is a block theme. The row stays so the
 * reference stays complete; it just stops pretending to be available. */
.aeroidx-hook.is-unavailable {
	background: var(--ax-zebra);
}

.aeroidx-hook.is-unavailable code {
	opacity: 0.55;
}

.aeroidx-hook.is-unavailable .aeroidx-hook__where {
	color: var(--ax-muted);
}

.aeroidx-hook__flag {
	margin-left: auto;
	padding: 2px 8px;
	border-radius: var(--ax-radius-pill);
	background: var(--ax-fill-locked);
	color: var(--ax-muted);
	font-size: 11px;
	white-space: nowrap;
}

.aeroidx-settings .aeroidx-hooks__copy {
	flex: none;
	margin-left: auto;
	display: inline-flex;
	align-items: center;
	gap: 6px;
	min-height: 0;
	padding: 3px 9px;
	font-size: 12px;
	line-height: 1.5;
}

/* Straight into the Customizer panel the intro paragraph names. */
.aeroidx-hooks__editor-link {
	margin: 0 0 4px;
	font-size: 13px;
}

/* Rendered only on block themes, where it is the fact that decides whether two
 * of the rows above apply at all. */
.aeroidx-hooks__note {
	margin: 12px 0 0;
	padding-left: 12px;
	border-left: 2px solid var(--ax-border-soft);
	color: var(--ax-secondary);
	font-size: 13px;
}

/* The worked example. The copy button sits in a header strip rather than
 * floating over the code: floated, it was pinned to the container while the
 * <pre> was the scroll box, so at narrow widths the end of the first line
 * scrolled underneath it and could never be read. */
.aeroidx-hooks__example {
	margin-top: 28px;
	border: 1px solid var(--ax-border-soft);
	border-radius: var(--ax-radius-card);
	background: var(--ax-card);
	overflow: hidden;
}

.aeroidx-hooks__example-bar {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 10px;
	padding: 8px 10px 8px 16px;
	background: var(--ax-thead);
	border-bottom: 1px solid var(--ax-border-soft);
}

/* A caption on the block below it, not a heading governing a section. As an
 * <h3> at 13px/600/secondary it was pixel-identical to the old table's column
 * headers, so it read as a stray fifth header. */
.aeroidx-hooks__example-cap {
	font-size: 12px;
	font-weight: 600;
	color: var(--ax-muted);
}

.aeroidx-hooks__example pre {
	margin: 0;
	padding: 14px 16px;
	overflow-x: auto;
}

/* Block code, not the inline violet chip the hook rows use: no pill
 * background, no padding of its own, and it must keep its newlines. */
.aeroidx-hooks__example code {
	display: block;
	background: none;
	padding: 0;
	color: var(--ax-secondary);
	font-family: var(--ax-font-mono);
	font-size: 12px;
	line-height: 1.7;
	white-space: pre;
}

/* The <pre> is a scroll container, so it is focusable; say so visibly. */
.aeroidx-hooks__example pre:focus-visible {
	outline: 2px solid var(--ax-violet-500);
	outline-offset: -2px;
}

/* Section headings inside the Theme Integration panel.
 * Reuse .aeroidx-field__title for h2 (matches design system) but add the
 * vertical rhythm a docs page needs. */
.aeroidx-tab-panel[data-panel="theme"] .aeroidx-field__title {
	margin: 28px 0 14px;
}

.aeroidx-tab-panel[data-panel="theme"] .aeroidx-field__title:first-of-type {
	margin-top: 4px;
}

/* Inside the header row the flex container owns the spacing, zero the title's
 * own margins so it stays vertically centered against the builder chip. */
.aeroidx-tab-panel[data-panel="theme"] .aeroidx-card__head .aeroidx-field__title {
	margin: 0;
}

/* Vertical gap between stacked cards within a panel. The second selector is
 * for cards that each sit in their own <form> (the Settings screen), which
 * makes them cousins rather than siblings. Not :first-child: settings_fields()
 * prints its hidden inputs ahead of the card, so the card never is one. */
.aeroidx-settings .aeroidx-card + .aeroidx-card,
.aeroidx-settings form + form > .aeroidx-card {
	margin-top: 20px;
}

/* --- Widgets picker ----------------------------------------------------- */
/*
 * The Widgets submenu page reuses .aeroidx-settings for the design tokens
 * above, then lists each saved widget as a row: name + type badge on top,
 * a readonly shortcode field with a Copy button below.
 */

/* ---- Widgets sub-tabs (Your library / Create) -------------------------- */
.aeroidx-widget-tabs__nav {
	display: flex;
	gap: 4px;
	margin-bottom: 20px;
	border-bottom: 1px solid var(--ax-border-soft);
}

.aeroidx-widget-tab {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	padding: 10px 16px;
	margin-bottom: -1px;
	font: inherit;
	font-weight: 600;
	color: var(--ax-muted);
	background: none;
	border: 0;
	border-bottom: 2px solid transparent;
	cursor: pointer;
	transition: color 150ms var(--ax-ease), border-color 150ms var(--ax-ease);
}

.aeroidx-widget-tab:hover {
	color: var(--ax-ink);
}

.aeroidx-widget-tab.is-active {
	color: var(--ax-grad-from);
	border-bottom-color: var(--ax-grad-from);
}

.aeroidx-widget-tab:focus-visible {
	outline: 2px solid var(--ax-grad-to);
	outline-offset: 2px;
}

.aeroidx-widget-tab__count {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-width: 20px;
	height: 20px;
	padding: 0 6px;
	font-size: 12px;
	font-weight: 600;
	color: var(--ax-violet-700);
	background: rgba(139, 92, 246, 0.10);
	border-radius: 9999px;
}

.aeroidx-widget-list {
	margin: 0;
	padding: 0;
	list-style: none;
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
	gap: 16px;
}

.aeroidx-widget-item {
	position: relative;
	display: flex;
	flex-direction: column;
	border: 1px solid var(--ax-border-soft);
	border-radius: var(--ax-radius-card);
	background: var(--ax-card);
}

/* The [hidden] attribute must win over the display:flex above, or the search
   filter and pagination (which toggle item.hidden) can never hide a card. */
.aeroidx-widget-item[hidden] {
	display: none;
}

/* Preview banner reuses the picker skeletons so a saved widget reads the same
   as its type card above. */
.aeroidx-widget-item__preview {
	position: relative;
	overflow: hidden;
	border-bottom: 1px solid var(--ax-border-soft);
	/* Own the top corners now that the card no longer clips with overflow:hidden
	   (that clipping used to cut off the ⋮ dropdown). */
	border-radius: var(--ax-radius-card) var(--ax-radius-card) 0 0;
}

/* ⋮ overflow menu, pinned to the preview's top-right corner. */
.aeroidx-widget-menu {
	position: absolute;
	top: 8px;
	right: 8px;
	z-index: 3;
}

.aeroidx-widget-menu__trigger {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 30px;
	height: 30px;
	padding: 0;
	color: #4b5563;
	background: #fff;
	border: 1px solid var(--ax-border-soft);
	border-radius: var(--ax-radius-input);
	box-shadow: 0 1px 3px rgba(17, 24, 39, 0.12);
	cursor: pointer;
	transition: background 0.15s ease, color 0.15s ease, box-shadow 0.15s ease;
}

.aeroidx-widget-menu__trigger:hover {
	color: var(--ax-violet-700);
	background: #fff;
	box-shadow: 0 2px 6px rgba(109, 40, 217, 0.2);
}

.aeroidx-widget-menu__trigger:focus-visible {
	outline: none;
	box-shadow: 0 0 0 2px var(--ax-violet-500);
}

.aeroidx-widget-menu__list {
	position: absolute;
	top: calc(100% + 6px);
	right: 0;
	min-width: 168px;
	padding: 6px;
	background: var(--ax-card);
	border: 1px solid var(--ax-border-soft);
	border-radius: var(--ax-radius-input);
	box-shadow: 0 12px 28px rgba(17, 24, 39, 0.14);
}

.aeroidx-widget-menu__list[hidden] {
	display: none;
}

.aeroidx-widget-menu__item {
	display: flex;
	align-items: center;
	gap: 10px;
	width: 100%;
	padding: 9px 10px;
	font-size: 13px;
	font-weight: 500;
	text-align: left;
	color: var(--ax-ink, #111827);
	background: none;
	border: 0;
	border-radius: 8px;
	cursor: pointer;
	transition: background 0.15s ease, color 0.15s ease;
}

.aeroidx-widget-menu__item svg {
	flex: 0 0 auto;
	color: var(--ax-muted);
}

.aeroidx-widget-menu__item:hover {
	background: var(--ax-violet-wash);
	color: var(--ax-violet-700);
}

.aeroidx-widget-menu__item:hover svg {
	color: var(--ax-violet-700);
}

.aeroidx-widget-menu__item:focus-visible {
	outline: none;
	box-shadow: inset 0 0 0 2px var(--ax-violet-500);
}

.aeroidx-widget-menu__item--danger {
	color: #dc2626;
}

.aeroidx-widget-menu__item--danger svg {
	color: #dc2626;
}

.aeroidx-widget-menu__item--danger:hover {
	color: #b91c1c;
	background: #fef2f2;
}

.aeroidx-widget-menu__item--danger:hover svg {
	color: #b91c1c;
}

.aeroidx-widget-menu__item[aria-busy="true"] {
	opacity: 0.6;
	pointer-events: none;
}

.aeroidx-widget-item__body {
	display: flex;
	flex-direction: column;
	gap: 10px;
	padding: 16px 18px;
}

.aeroidx-widget-item__head {
	display: flex;
	align-items: flex-start;
	gap: 10px;
	margin: 0;
}

.aeroidx-widget-item__icon {
	flex: 0 0 auto;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 34px;
	height: 34px;
	color: var(--ax-grad-from);
	background: var(--ax-violet-wash);
	border-radius: var(--ax-radius-input);
}

.aeroidx-widget-item__icon .aeroidx-type-card__glyph {
	width: 20px;
	height: 20px;
}

.aeroidx-widget-item__titles {
	display: flex;
	flex-direction: column;
	gap: 4px;
	min-width: 0;
}

.aeroidx-widget-item__name {
	font-size: 14px;
	font-weight: 600;
	color: var(--ax-ink);
	word-break: break-word;
}

/*
 * A subtitle, not a badge.
 *
 * It was an uppercase violet pill, which put a second loud element right under
 * the widget's own name and competed with it: on a grid the eye scans, the name
 * is what someone is looking for and the type is context. The AeroIDX dashboard
 * renders the same fact as plain grey text under the name, and this is the same
 * person's other window onto the same widgets.
 *
 * --ax-muted measures 4.83:1 on the card, which clears AA for this size.
 */
.aeroidx-widget-item__type {
	font-size: 12.5px;
	font-weight: 400;
	line-height: 1.35;
	color: var(--ax-muted);
}

.aeroidx-widget-item__desc {
	margin: 0;
	font-size: 12px;
	line-height: 1.5;
	color: var(--ax-muted);
}

.aeroidx-widget-item__meta {
	margin: 0;
	font-size: 12px;
	color: var(--ax-muted);
}

.aeroidx-widget-item__actions {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
	margin-top: 4px;
	padding-top: 12px;
	border-top: 1px solid var(--ax-border-soft);
}

.aeroidx-settings .aeroidx-widget-item__action {
	flex: 1 1 auto;
	justify-content: center;
}

/* Edit: outlined violet (the primary action). Embed: outlined neutral. Both
   mirror the AeroIDX dashboard widget card.
   The Markets tab's primary action joins this selector rather than restating
   the same six declarations, one treatment, one place to change it. Note it is
   an OUTLINE, not a filled pill: WordPress's own .button-primary reads as a
   different design language next to these and should not be used here. */
.aeroidx-settings .aeroidx-widget-item__edit,
.aeroidx-settings .aeroidx-step__action--outline,
.aeroidx-settings .aeroidx-market-action--primary {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 6px;
	color: var(--ax-violet-700);
	border-color: var(--ax-violet-500);
	background: var(--ax-card);
}

/*
 * :focus-visible, NOT :focus, and it was the latter for a long time.
 *
 * On bare :focus a mouse click leaves the control tinted after the pointer has
 * moved away, so it reads as still-selected — the exact failure the base button
 * rules were written to avoid, and the one FocusRingTest exists to catch. It
 * went unnoticed because the tint is identical to the hover state, so while the
 * pointer was still there it looked correct.
 *
 * Safe to narrow: all three of these are .button, so the actual keyboard
 * indicator is the 2px outline on `.aeroidx-settings .button:focus-visible`.
 * This rule only tints; it was never the thing a keyboard user relied on.
 */
.aeroidx-settings .aeroidx-widget-item__edit:hover,
.aeroidx-settings .aeroidx-widget-item__edit:focus-visible,
.aeroidx-settings .aeroidx-step__action--outline:hover,
.aeroidx-settings .aeroidx-step__action--outline:focus-visible,
.aeroidx-settings .aeroidx-market-action--primary:hover,
.aeroidx-settings .aeroidx-market-action--primary:focus-visible {
	color: var(--ax-violet-700);
	border-color: var(--ax-violet-700);
	background: var(--ax-violet-wash);
}

.aeroidx-widget-item__edit-icon {
	display: inline-flex;
	color: var(--ax-violet-700);
}

.aeroidx-widget-item__edit[aria-busy="true"] {
	opacity: 0.6;
}

.aeroidx-settings .aeroidx-copy {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	flex: 0 0 auto;
	white-space: nowrap;
	cursor: pointer;
}

.aeroidx-settings .aeroidx-copy.is-copied {
	border-color: var(--ax-violet-500);
	color: var(--ax-violet-700);
}

.aeroidx-copy__icon {
	display: inline-flex;
}

/* Swap clipboard → check on the copied state (the JS only toggles is-copied
 * and the label text). */
.aeroidx-copy__icon--check {
	display: none;
}

.aeroidx-copy.is-copied .aeroidx-copy__icon--copy {
	display: none;
}

.aeroidx-copy.is-copied .aeroidx-copy__icon--check {
	display: inline-flex;
}

/* Both clipboard paths failed. legacyCopy() has already selected the text, so
 * this state is an instruction rather than an apology — and it has to look
 * unlike the copied state, because before this existed the two were
 * indistinguishable: nothing happened at all. */
.aeroidx-settings .aeroidx-copy.is-copy-failed {
	border-color: var(--ax-danger-edge);
	background: var(--ax-danger-wash);
	color: var(--ax-wp-error);
}

.aeroidx-copy.is-copy-failed .aeroidx-copy__icon--copy {
	display: none;
}

/* --- Widgets picker: header, count, search, empty state ----------------- */

.aeroidx-widgets__head {
	margin: 0 0 18px;
}

.aeroidx-widgets__title {
	display: flex;
	align-items: center;
	gap: 10px;
	margin-bottom: 8px;
}

.aeroidx-widgets__head .aeroidx-card__intro {
	margin-bottom: 0;
}

.aeroidx-widgets__controls {
	display: flex;
	gap: 12px;
	align-items: center;
	margin: 0 0 16px;
}

.aeroidx-widgets__search {
	position: relative;
	flex: 1 1 auto;
	min-width: 0;
}

.aeroidx-settings .aeroidx-widgets__filter,
.aeroidx-settings .aeroidx-widgets__sort {
	flex: 0 0 auto;
	width: auto;
	min-width: 150px;
}

/*
 * GIVE THE SELECTS THEIR ARROW BACK.
 *
 * wp-admin styles <select> with `appearance: none` plus a chevron delivered as
 * a background-image, and reserves room for it with padding-right. Our
 * .aeroidx-field__input rule wins on specificity and sets `background`, the
 * SHORTHAND, which resets background-image to none, plus a padding that
 * reclaims the reserved space. `appearance: none` is in neither shorthand, so it
 * survives. Net effect: WordPress suppresses the native arrow and we suppress
 * WordPress's replacement, leaving a dropdown that looks exactly like the text
 * input sitting next to it.
 *
 * The chevron is an inline data-URI: no external asset, nothing for the wp.org
 * review to flag. Data-URIs cannot inherit currentColor, so the muted grey is
 * written out (%2371717a = #71717a). It is a non-text indicator at 4.83:1 on
 * the fill, well past the 3:1 it needs.
 */
.aeroidx-settings select.aeroidx-field__input {
	--aeroidx-chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%2371717a' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
	appearance: none;
	-webkit-appearance: none;
	padding-right: 32px;
	background-image: var(--aeroidx-chevron);
	background-repeat: no-repeat;
	background-position: right 10px center;
	background-size: 16px 16px;
}

/*
 * The focus rule above is `.aeroidx-settings .aeroidx-field__input:focus`
 * (0,3,0), which outranks the select rule (0,2,1), and it repaints with the
 * `background` SHORTHAND. A shorthand resets EVERY background longhand, so
 * the chevron's image, repeat, position and size all went back to their
 * initial values the moment the control was focused.
 *
 * This rule used to set background-color alone and say the arrow stayed. It
 * did not: nothing restated the image, so a focused select, which is every
 * select right after you pick an option, showed no arrow and read as a stuck
 * button until you clicked elsewhere. All four are restated here, at (0,3,1),
 * with the image read from the custom property so the data-URI lives once.
 */
.aeroidx-settings select.aeroidx-field__input:focus {
	background-color: var(--ax-input-focus);
	background-image: var(--aeroidx-chevron);
	background-repeat: no-repeat;
	background-position: right 10px center;
	background-size: 16px 16px;
}

/*
 * Core darkens a hovered <select> to near-black (forms.css,
 * `.wp-core-ui select:hover`, border and text #1e1e1e), written out rather than
 * read from --wp-admin-theme-color, so the accent override on .aeroidx-settings
 * does not reach it. Violet at (0,3,1) against core's (0,2,1): the same colour
 * as focus, which still reads as the stronger state through its 1px ring.
 */
.aeroidx-settings select.aeroidx-field__input:hover {
	color: var(--ax-ink);
	border-color: var(--ax-violet-500);
}

/*
 * THE FOCUS LOOK IS FOR THE KEYBOARD.
 *
 * A select keeps focus after the mouse picks an option, and after the click
 * outside that closes it, so the violet border, ring and white fill stayed on
 * a control the admin had finished with until they clicked somewhere else.
 * Browsers do not match :focus-visible when a pointer puts focus on a select,
 * so focus that arrived by mouse goes back to the resting look here; Tab still
 * gets the full treatment from the :focus rules above.
 *
 * The border is split out behind :not(:hover): this rule outranks the hover
 * rule above ((0,4,1) against (0,3,1)), and without the split the pointer
 * resting on a just-used select would lose its violet hover border.
 */
.aeroidx-settings select.aeroidx-field__input:focus:not(:focus-visible) {
	background-color: var(--ax-input);
	box-shadow: none;
}

.aeroidx-settings select.aeroidx-field__input:focus:not(:focus-visible):not(:hover) {
	border-color: var(--ax-border);
}

/*
 * "12 markets" / "3 of 12 markets match". Sits under the controls, always
 * present, and is the only place on the screen that ever states how many
 * markets an account has. Doubles as the search's result feedback, the pager's
 * own status hides itself below two pages, which is exactly when a filter is
 * most likely to have narrowed things.
 */
.aeroidx-widgets__count {
	margin: -6px 0 14px;
	font-size: 13px;
	color: var(--ax-muted);
	font-variant-numeric: tabular-nums;
}

.aeroidx-widgets__count:empty {
	display: none;
}

@media (max-width: 600px) {
	.aeroidx-widgets__controls {
		flex-direction: column;
		align-items: stretch;
	}

	.aeroidx-settings .aeroidx-widgets__filter,
	.aeroidx-settings .aeroidx-widgets__sort {
		width: 100%;
	}
}

/* Client-side pager. Hidden until there are more matches than fit one page. */
.aeroidx-widgets__pager {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 12px;
	margin-top: 24px;
}

/* The [hidden] attribute must win over the display:flex above, or the pager
   would show even when the JS hides it (one page of results). */
.aeroidx-widgets__pager[hidden] {
	display: none;
}

.aeroidx-widgets__pages {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: 6px;
}

/* Numbered page buttons: square, outlined, active one filled violet. */
.aeroidx-widgets__page {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-width: 36px;
	height: 36px;
	padding: 0 8px;
	font: inherit;
	font-weight: 600;
	color: var(--ax-secondary);
	background: var(--ax-card);
	border: 1px solid var(--ax-border-soft);
	border-radius: var(--ax-radius-input);
	cursor: pointer;
	font-variant-numeric: tabular-nums;
	transition: border-color 120ms var(--ax-ease), color 120ms var(--ax-ease),
		background 120ms var(--ax-ease);
}

.aeroidx-widgets__page:hover {
	border-color: var(--ax-violet-500);
	color: var(--ax-violet-700);
}

.aeroidx-widgets__page:focus-visible {
	outline: 2px solid var(--ax-grad-to);
	outline-offset: 2px;
}

/*
 * violet-700, not violet-500. This is the one element on the pager that MUST be
 * readable, it marks where you are, and white on violet-500 measures 4.23:1
 * at 13px/600, under the 4.5:1 that size needs. violet-700 takes it to 7.10.
 */
.aeroidx-widgets__page.is-active {
	color: #fff;
	background: var(--ax-violet-700);
	border-color: var(--ax-violet-700);
	cursor: default;
}

.aeroidx-widgets__page--arrow {
	font-size: 18px;
	line-height: 1;
}

.aeroidx-widgets__page-gap {
	display: inline-flex;
	align-items: flex-end;
	padding: 0 4px;
	color: var(--ax-muted);
}

.aeroidx-widgets__page-status {
	margin: 0;
	font-size: 13px;
	color: var(--ax-muted);
	font-variant-numeric: tabular-nums;
}

.aeroidx-widgets__search-icon {
	position: absolute;
	left: 12px;
	top: 50%;
	transform: translateY(-50%);
	color: var(--ax-muted);
	pointer-events: none;
}

.aeroidx-settings .aeroidx-widgets__search-input {
	width: 100%;
	box-sizing: border-box;
	padding-left: 36px;
}

/*
 * Empty result for the widgets filter, and for the Markets tab's, both screens
 * live under section=widgets and share these controls rather than growing a
 * second set that would drift. A column rather than a bare line now that it
 * carries a way out as well as a message: gap keeps the two apart without
 * margins that collapse against the list above.
 */
.aeroidx-widgets__empty {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 14px;
	margin: 4px 0 0;
	padding: 28px 0;
}

/* [hidden] loses to display:flex on specificity, so restore it. */
.aeroidx-widgets__empty[hidden] {
	display: none;
}

.aeroidx-widgets__empty-text {
	margin: 0;
	font-size: 13px;
	color: var(--ax-muted);
}

/* --- IDX Pages list ----------------------------------------------------- */

.aeroidx-page-list {
	margin: 0;
	padding: 0;
	list-style: none;
	display: flex;
	flex-direction: column;
	gap: 10px;
}

.aeroidx-page-item {
	padding: 16px 18px;
	border: 1px solid var(--ax-border-soft);
	border-radius: var(--ax-radius-card);
	background: var(--ax-card);
}

.aeroidx-page-item__row {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 16px;
}

.aeroidx-page-item__info {
	display: flex;
	flex-direction: column;
	gap: 2px;
	min-width: 0;
}

.aeroidx-page-item__name {
	font-size: 14px;
	font-weight: 600;
	color: var(--ax-ink);
}

.aeroidx-page-item__slug {
	font-size: 12px;
	color: var(--ax-muted);
	font-family: var(--ax-font-mono);
}

/* Subtle one-liner under the Details slug: it's a virtual page, so unlike the
 * catalog rows it never adds a managed page to WordPress. */
.aeroidx-page-item__note {
	font-size: 12px;
	font-style: italic;
	color: var(--ax-muted);
}

.aeroidx-page-item__action {
	display: flex;
	align-items: center;
	gap: 10px;
	flex: none;
}

.aeroidx-page-item__action form {
	margin: 0;
}

/*
 * The status column is .aeroidx-market-status now, shared with the Markets
 * screen. The rules that lived here were text-only and used --ax-success as
 * ink, which measures 3.77:1 on the white row: under the 4.5:1 that 13px/600
 * needs, and exactly what tokens.css warns against. The pill carries the
 * correct -ink token, a dot so the state is not colour-only, and nowrap so a
 * longer translation cannot grow the row.
 */

/* --- Markets tab -------------------------------------------------------- */

/*
 * A GRID OF CARDS. This replaced a full-width row per market.
 *
 * The rows had already been fought over once: three flex groups that just fit
 * on one line at the widest admin and dropped the actions to a second line a
 * couple of hundred pixels narrower, so row height jumped from ~66px to ~114px
 * with no cause the user could see. That was fixed by pinning three explicit
 * columns, which held the rhythm but did not remove the cause. The cause was
 * the shortcode: ~26 characters of monospace in every row, competing with the
 * name, the status and the buttons for one horizontal line. The card gives each
 * of those its own line, and the shortcode is now a button that says "Embed".
 *
 * auto-fill, not a fixed column count: the admin content area changes width
 * with the WordPress menu's collapsed state and with the viewport, so the
 * number of columns has to be free to change with it. Nothing here assumes
 * three.
 */
.aeroidx-market-grid {
	margin: 0;
	padding: 0;
	list-style: none;
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(min(260px, 100%), 1fr));
	gap: 16px;
}

.aeroidx-market-card {
	position: relative; /* anchors the ⋮ menu */
	display: flex;
	flex-direction: column;
	gap: 12px;
	padding: 16px 18px;
	border: 1px solid var(--ax-border-soft);
	border-radius: var(--ax-radius-card);
	background: var(--ax-card);
}

/*
 * The widget card's ⋮, reused. That card has a preview image under its menu;
 * this one has the market name, so the menu sits level with the card's own
 * padding instead of floating over a picture, and the name keeps clear of it.
 */
.aeroidx-market-card__menu {
	top: 12px;
	right: 12px;
}

.aeroidx-market-card__menu ~ .aeroidx-market-card__body .aeroidx-market-card__info {
	padding-right: 36px;
}

/* Delete page posts a form, which the widget menu's items never needed. */
.aeroidx-market-card__menu form {
	margin: 0;
}

/*
 * THIS RULE IS LOAD-BEARING. Do not delete it as redundant.
 *
 * The search and filter hide cards by setting the `hidden` property, which
 * works through the UA stylesheet's `[hidden] { display: none }`. An AUTHOR
 * rule beats a UA rule regardless of specificity, so the `display: flex` above
 * silently defeats it and filtering stops hiding anything, with no error and no
 * visible clue except that the filter appears to do nothing.
 *
 * The widget library learned this the same way; WidgetFilterResetTest exists
 * because of it.
 */
.aeroidx-market-card[hidden] {
	display: none;
}

.aeroidx-market-card__body {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 8px;
	flex: 1;
}

.aeroidx-market-card__info {
	display: flex;
	flex-direction: column;
	gap: 2px;
	min-width: 0;
	max-width: 100%;
}

.aeroidx-market-card__name {
	font-size: 15px;
	font-weight: 600;
	color: var(--ax-ink);
	/* Place names are not short and a card is not wide. Breaking inside a long
	 * word beats a name that runs out past the card's own border. */
	overflow-wrap: anywhere;
}

.aeroidx-market-card__slug,
.aeroidx-market-card__meta {
	font-size: 12px;
	color: var(--ax-muted);
	max-width: 100%;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.aeroidx-market-card__meta {
	/* Its own line, below the divider-free body, so it never shares a baseline
	 * with the address above it. */
	display: block;
}

/*
 * The address, which is also the link to it. This took over from a View button.
 *
 * VIOLET AND NOT UNDERLINED AT REST is a deliberate pair, not a bare colour
 * choice: alone, colour would be the only thing separating a link from the grey
 * mono text it sits beside, and colour alone fails WCAG 1.4.1. The underline
 * arrives on hover and focus, and the leading arrow glyph is present at all
 * times — that glyph is the non-colour signal that carries the resting state.
 */
.aeroidx-market-card__link {
	display: inline-flex;
	align-items: center;
	gap: 5px;
	min-width: 0;
	max-width: 100%;
	color: var(--ax-violet-700);
	text-decoration: none;
}

.aeroidx-market-card__link:hover,
.aeroidx-market-card__link:focus-visible {
	color: var(--ax-violet-700);
	text-decoration: underline;
}

.aeroidx-market-card__slug {
	font-family: var(--ax-font-mono);
	/* Inherit the link's colour rather than the muted grey above; the shared
	 * rule sets both, and this is the half that lives inside an anchor. */
	color: inherit;
}

/*
 * Actions sit on the card's floor, separated by a rule, so a card with two
 * controls and a card with three still line their buttons up with each other
 * across a row of the grid. margin-top: auto is what pins them there when the
 * cards in a row have different body heights.
 */
.aeroidx-market-card__actions {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 8px;
	margin-top: auto;
	padding-top: 12px;
	border-top: 1px solid var(--ax-border-soft);
}

/* Not display: contents, though it would line the button up one level higher.
 * It is a known a11y hazard on several elements across browser versions, and
 * the only thing it buys here is skipping one wrapper that already sizes to its
 * button. */
.aeroidx-market-card__actions form {
	margin: 0;
}

/*
 * WHY THESE BUTTONS ARE FLEX, and it is a bug fix rather than a preference.
 *
 * An inline <svg> inside a WordPress .button sits on the TEXT BASELINE, not on
 * the centre of the button, so it rides visibly low next to its label. It was
 * only obvious once on the screen (the new-tab marker on View), so it read as a
 * quirk of that one glyph; with an icon on every button it would have been four
 * of them. align-items: center is the fix, and it has to live on the button
 * because that is the box the baseline belongs to.
 *
 * justify-content: center matters when a card is narrow enough that the actions
 * wrap and a button stretches: the label should sit in the middle of the space
 * it was given, not pinned to the left of it.
 */
.aeroidx-market-card__actions .button {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 6px;
	/*
	 * THE BOX IS DECLARED HERE, not inherited, and that is the fix for a real
	 * mismatch: "Edit" is an <a class="button"> and "Create page" is a
	 * <button class="button">, and they rendered at different heights.
	 *
	 * Neither element sets its own size in this stylesheet — `.aeroidx-settings
	 * .button` above declares colour and border and nothing else — so both fell
	 * through to core's `.wp-core-ui .button`, which gives height entirely to
	 * `line-height` and `min-height` with NO vertical padding. An anchor and a
	 * native button resolve that differently, so the two sat at different
	 * heights side by side in the same grid.
	 *
	 * Chasing the difference with a nudge on one of them would leave the next
	 * person with two controls that agree by coincidence. Declaring padding, a
	 * min-height and a line-height makes the box the same for both by
	 * construction, whatever element carries it. box-sizing so min-height
	 * counts the border rather than adding to it.
	 */
	box-sizing: border-box;
	min-height: 38px;
	padding: 8px 14px;
	line-height: 1.4;
}

/*
 * SHARE THE ROW EQUALLY, edge to edge.
 *
 * "Create page" is a third wider than "Embed", so sized to content the pair
 * stopped short of the card's right padding while touching its left one, and
 * every card in the grid ended on a different x. flex-basis: 0 (not auto) is
 * what makes the split even rather than proportional to the label lengths, so
 * the two controls match each other on every card regardless of which two they
 * are.
 *
 * THE FORM IS IN THIS SELECTOR FOR A REASON. "Create page" is a submit wrapped
 * in its own <form>, so the form is the flex item and the button is its child;
 * sizing only .button leaves that one control shrink-to-fit while its neighbour
 * stretches, which is the exact ragged edge this rule exists to remove.
 */
.aeroidx-market-card__actions > .button,
.aeroidx-market-card__actions > form {
	flex: 1 1 0;
	/*
	 * fit-content, NOT 0, and this is the floor that decides how the row fails.
	 *
	 * "Create page" is a third longer than "Embed", and at the narrow end of the
	 * grid — two columns on a cramped admin — half a card is not quite enough
	 * for it once the padding above is counted. With a floor of 0 the flex
	 * algorithm keeps shrinking past the label and, since core sets
	 * white-space: nowrap, the text simply runs out of its own button.
	 *
	 * With this floor it cannot shrink below its label, so flex-wrap on the
	 * container takes over and the two controls stack, each full width. Both
	 * outcomes look deliberate; overflowing text does not.
	 */
	min-width: fit-content;
}

.aeroidx-market-card__actions form .button {
	width: 100%;
}

/* Never let the glyph absorb the shrink; a squashed icon beside an intact
 * label looks like a rendering fault rather than a tight fit. */
.aeroidx-btn-icon {
	flex: none;
}

/*
 * Page status, named rather than inferred from which button is missing.
 * Shared with the IDX Pages list, as a pill because
 * this list is scanned down a column rather than read row by row, the dot and
 * the fill are what carry it at a glance, not the words.
 */
.aeroidx-market-status {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	flex: none;
	font-size: 12px;
	font-weight: 600;
	padding: 3px 10px;
	border-radius: 999px;
	white-space: nowrap;
	/* The -ink variant, not the plain indicator colour, that one measures
	 * 3.32:1 on this wash and this is 12px text. See tokens.css. */
	color: var(--ax-success-ink);
	background: var(--ax-success-wash);
}

.aeroidx-market-status::before {
	content: "";
	width: 6px;
	height: 6px;
	border-radius: 50%;
	background: currentColor;
	flex: none;
}

.aeroidx-market-status--none {
	color: var(--ax-muted-on-fill);
	background: var(--ax-locked);
}

/*
 * The shortcode chip's rules lived here, and they are gone with it.
 *
 * Its history in one line: a readonly text input wearing the editable search
 * box's fill and focus ring, then a chip whose visible content was the code
 * itself. Both put ~26 characters of monospace in every row, which is what made
 * the row wrap. The control is now an ordinary .button labelled "Embed", so it
 * needs no rules of its own; it inherits the same treatment, focus ring
 * included, as every other button on the screen.
 */

/* The new-tab marker on View. The IDX Pages tab uses the same glyph. */
/*
 * .aeroidx-external is gone with the View button that was its only caller.
 *
 * It dimmed the new-tab marker to .65 so it would not compete with the icons
 * that named an action. Its replacement must NOT inherit that: the marker on
 * the card's address is now the non-colour half of what distinguishes a link
 * from the grey mono text beside it, and colour alone fails WCAG 1.4.1. A
 * signal doing that job is not decoration and does not get faded.
 *
 * The IDX Pages tab still draws the same SHAPE from its own inline copy, in
 * Lucide at stroke 2. That tab has had no icon pass; it never used this class.
 */
.aeroidx-market-card__link-icon {
	flex: none;
}

/*
 * TWO COLUMNS, NOT ONE FULL-WIDTH STACK.
 *
 * These fields used to be a single 460px column with the rest of a ~1200px
 * card empty beside it, which is what prompted this. The obvious fix is the
 * one applied everywhere else in this admin — let the control fill the card —
 * and here it is the wrong one. A control's size is a claim about what goes in
 * it, and a 1200px box for a CSS class like `bg-theme`, or for a Status
 * dropdown with two options, is a claim the value cannot honour. The API key
 * field spans because a key is a long opaque string you paste; `bg-theme` is
 * not.
 *
 * So the space is used by pairing fields instead of stretching them. Row-major
 * order, no cell spanning and no `dense` packing, so the visual order and the
 * DOM order stay identical and tab order still follows what the eye reads.
 *
 * The form itself is the grid: every direct child is either a __field or the
 * __actions row, and the hidden inputs from wp_nonce_field()/settings_fields()
 * are display:none, so they never become grid items.
 */
.aeroidx-page-config {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: 18px 24px;
	align-items: start;
}

/*
 * Measured, not guessed: the admin menu is 160px and the plugin nav is 200px,
 * so the card is roughly the viewport minus 400px of fixed chrome. Two columns
 * need about 700px of card to stay comfortable, which puts the floor at a
 * ~1100px viewport. Below that they stack.
 */
@media (max-width: 1100px) {
	.aeroidx-page-config {
		grid-template-columns: 1fr;
	}
}

.aeroidx-page-config__field {
	display: block;
	margin: 0;
	min-width: 0;
}

.aeroidx-page-config__label {
	display: block;
	margin: 0 0 5px;
	font-size: 13px;
	font-weight: 600;
	color: var(--ax-ink);
}

/* Every config input spans the field width. WordPress otherwise caps the
 * width of <select>, leaving the Theme/Status dropdowns narrower than the rest. */
.aeroidx-settings .aeroidx-page-config__field .aeroidx-field__input {
	width: 100%;
	max-width: none;
}

/* Permalink: one input-looking box, muted base prefix + a borderless editable
 * segment, so the part you edit reads as part of a single field. */
.aeroidx-page-config__permalink {
	display: flex;
	align-items: stretch;
	border: 1px solid var(--ax-border);
	border-radius: var(--ax-radius-input);
	background: var(--ax-input);
	overflow: hidden;
}

.aeroidx-page-config__permalink:focus-within {
	border-color: var(--ax-violet-500);
	box-shadow: 0 0 0 1px var(--ax-violet-500);
	background: var(--ax-input-focus);
}

.aeroidx-page-config__permalink-base {
	flex: none;
	display: flex;
	align-items: center;
	max-width: 45%;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
	padding: 0 2px 0 12px;
	font-size: 13px;
	color: var(--ax-muted);
}

.aeroidx-settings .aeroidx-page-config__permalink .aeroidx-field__input {
	flex: 1 1 auto;
	min-width: 0;
	border: 0;
	border-radius: 0;
	background: transparent;
	box-shadow: none;
}

.aeroidx-settings .aeroidx-page-config__permalink .aeroidx-field__input:focus {
	background: transparent;
	box-shadow: none;
}

/* Pattern permalink (Details): editable base sized to its word, with a muted
 * read-only token suffix so the full /{base}/{address}/{id} shape is visible. */
.aeroidx-settings .aeroidx-page-config__permalink--pattern .aeroidx-field__input {
	flex: 0 1 auto;
	width: auto;
	min-width: 4ch;
	padding-right: 2px;
}

.aeroidx-page-config__permalink-suffix {
	flex: none;
	display: flex;
	align-items: center;
	padding: 0 12px 0 2px;
	font-size: 13px;
	color: var(--ax-muted);
	white-space: nowrap;
}

/*
 * Save spans the full grid and sits at its right edge, so it lands under the
 * right edge of the right-hand column rather than orphaned under the left one.
 * The same alignment the Settings screen uses.
 */
.aeroidx-page-config__actions {
	grid-column: 1 / -1;
	display: flex;
	justify-content: flex-end;
	align-items: center;
	gap: 8px;
	margin-top: 4px;
}

/* Cancel ships hidden until admin.js wires it, and `.aeroidx-settings .button`
 * sets a display that would otherwise beat the UA's [hidden] rule. */
.aeroidx-settings .aeroidx-page-config__actions .button[hidden] {
	display: none;
}

/* Pill, to sit beside the pill Save rather than read as a different kind of
 * control. Same type as the primary, and 1px less padding to make up for the
 * border the primary does not have, so the two match in height. */
.aeroidx-settings .aeroidx-page-config__actions .button:not(.button-primary) {
	border-radius: var(--ax-radius-pill);
	padding: 8px 22px;
	font-size: 12px;
	font-weight: 600;
	line-height: 1.5;
	height: auto;
	min-height: 0;
}

.aeroidx-settings .aeroidx-page-item__icon {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	box-sizing: border-box;
	width: 34px;
	min-width: 34px;
	height: 34px;
	min-height: 34px;
	padding: 0;
	line-height: 1;
}

.aeroidx-settings .aeroidx-page-item__delete {
	color: var(--ax-wp-error);
	border-color: var(--ax-wp-error-edge);
	background: transparent;
}

.aeroidx-settings .aeroidx-page-item__delete:hover,
.aeroidx-settings .aeroidx-page-item__delete:focus {
	color: var(--ax-on-accent);
	background: var(--ax-wp-error);
	border-color: var(--ax-wp-error);
}

.aeroidx-page-notice {
	margin: 0 0 16px;
	padding: 12px 16px;
	border: 1px solid var(--ax-border-soft);
	border-radius: var(--ax-radius-card);
	font-size: 13px;
	line-height: 1.5;
}

.aeroidx-page-notice--ok {
	background: var(--ax-notice-success-bg);
	border-color: var(--ax-notice-success-edge);
	color: var(--ax-notice-success-ink);
}

.aeroidx-page-notice--warn {
	background: var(--ax-warning-wash);
	border-color: var(--ax-warning-edge);
	color: var(--ax-warning-ink);
}

.aeroidx-page-notice--info {
	background: var(--ax-selected);
	color: var(--ax-secondary);
}

/* A save that was refused. Distinct from --warn, which means "it worked but
   something else needs your attention". */
.aeroidx-page-notice--error {
	background: var(--ax-danger-wash);
	border-color: var(--ax-danger-edge);
	color: var(--ax-danger);
}

/* Widgets authorized for another address (SettingsPage::renderAuthorizationBanner).
   Hidden on Home, whose "Authorize this site" step already says it. */
.aeroidx-authorization-banner {
	display: flex;
	align-items: center;
	gap: 12px;
}

.aeroidx-authorization-banner p {
	flex: 1;
	margin: 0;
}

.aeroidx-authorization-banner p a {
	color: inherit;
	font-weight: 600;
}

/* The dismiss is a link (admin_post, no JS) wearing the toast's close button. */
.aeroidx-settings .aeroidx-authorization-banner .aeroidx-toast__close {
	text-decoration: none;
}

.aeroidx-settings[data-active-screen="home"] .aeroidx-authorization-banner {
	display: none;
}

/* AeroIDX moved the widgets to this site by itself (SettingsPage::renderAutoAuthorizedBanner).
   Same shape as the banner above, but shown on Home too. */
.aeroidx-auto-authorized-banner,
.aeroidx-moving-banner {
	display: flex;
	align-items: center;
	gap: 12px;
}

.aeroidx-auto-authorized-banner p,
.aeroidx-moving-banner p {
	flex: 1;
	margin: 0;
}

/* AeroIDX is about to move the widgets here (SettingsPage::renderMovingBanner).
   Violet like the "found" pill: nothing is in the way and nothing needs
   deciding. Shown on Home too, unlike .aeroidx-authorization-banner. */
.aeroidx-moving-banner {
	background: var(--ax-violet-wash);
	border-color: var(--ax-violet-wash);
}

.aeroidx-settings .aeroidx-auto-authorized-banner .aeroidx-toast__close {
	text-decoration: none;
}

/*
 * TOASTS. admin.js moves every .aeroidx-page-notice[data-aeroidx-toast] into
 * this corner; the rules above are what those notices look like without it.
 *
 * Bottom right, clear of the admin bar and of core's own notices at the top,
 * and under the confirm dialog (z-index 100000) so a toast never sits on top
 * of a question being asked. The stack ignores the pointer and each toast
 * takes it back, so the empty corner does not swallow clicks.
 */
.aeroidx-toasts {
	position: fixed;
	right: 24px;
	bottom: 24px;
	z-index: 99998;
	display: flex;
	flex-direction: column;
	align-items: flex-end;
	gap: 8px;
	width: min(400px, calc(100vw - 32px));
	pointer-events: none;
}

.aeroidx-toast {
	pointer-events: auto;
	display: flex;
	align-items: flex-start;
	gap: 12px;
	width: 100%;
	box-sizing: border-box;
	padding: 12px 8px 12px 16px;
	border: 1px solid var(--ax-border-soft);
	border-radius: var(--ax-radius-card);
	background: var(--ax-card);
	color: var(--ax-secondary);
	font-size: 13px;
	line-height: 1.5;
	box-shadow: 0 12px 28px rgba(17, 24, 39, 0.14);
	animation: aeroidx-toast-in 200ms var(--ax-ease);
}

.aeroidx-toast.is-leaving {
	animation: aeroidx-toast-out 150ms var(--ax-ease) forwards;
}

/* Same palette as the inline notices, so a message reads the same wherever
 * it lands. Info keeps the card's white: its inline fill is not opaque, and a
 * toast floats over content. */
.aeroidx-toast--ok {
	background: var(--ax-notice-success-bg);
	border-color: var(--ax-notice-success-edge);
	color: var(--ax-notice-success-ink);
}

.aeroidx-toast--warn {
	background: var(--ax-warning-wash);
	border-color: var(--ax-warning-edge);
	color: var(--ax-warning-ink);
}

.aeroidx-toast--error {
	background: var(--ax-danger-wash);
	border-color: var(--ax-danger-edge);
	color: var(--ax-danger);
}

.aeroidx-toast__text {
	flex: 1;
	min-width: 0;
	padding-top: 2px;
}

.aeroidx-settings .aeroidx-toast__close {
	flex: none;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 28px;
	height: 28px;
	padding: 0;
	border: 0;
	border-radius: var(--ax-radius-input);
	background: transparent;
	color: inherit;
	font-size: 18px;
	line-height: 1;
	opacity: 0.7;
	cursor: pointer;
}

.aeroidx-settings .aeroidx-toast__close:hover {
	opacity: 1;
	background: rgba(17, 24, 39, 0.06);
}

.aeroidx-settings .aeroidx-toast__close:focus-visible {
	opacity: 1;
	outline: 2px solid var(--ax-violet-500);
	outline-offset: 1px;
}

@keyframes aeroidx-toast-in {
	from {
		opacity: 0;
		transform: translateY(8px);
	}
}

@keyframes aeroidx-toast-out {
	to {
		opacity: 0;
		transform: translateY(8px);
	}
}

@media (prefers-reduced-motion: reduce) {
	.aeroidx-toast,
	.aeroidx-toast.is-leaving {
		animation: none;
	}
}

@media (max-width: 600px) {
	.aeroidx-toasts {
		right: 16px;
		bottom: 16px;
	}
}

/*
 * The .aeroidx-notice rules that lived here are gone with the markup that used
 * them: Admin\PanelState replaced renderPanelNotice()'s inline card, so nothing
 * in src/ emits those classes any more. Their replacement is
 * `.aeroidx-panelstate` in the "Panel empty / connect / error state" section
 * above — the centred component shared by Home and all six panels.
 */

/* Embedded widget builder (Widgets tab, "Flow Y"). */
.aeroidx-builder__bar {
	display: flex;
	flex-wrap: wrap;
	align-items: flex-start;
	justify-content: space-between;
	gap: 12px;
}

.aeroidx-builder__intro {
	min-width: 0;
}

/* Type picker + open button. */
.aeroidx-builder__picker {
	margin-top: 16px;
}

/* ---- Widget type cards ------------------------------------------------- */
/* Each card is a <button>: clicking one opens the builder for that type. They
   are actions, not a selection, so nothing is pre-selected and there is no
   confirm step. Native buttons carry Tab focus and Enter/Space activation. */
.aeroidx-type-grid {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
	gap: 14px;
	margin: 0;
	padding: 0;
	border: 0;
}

.aeroidx-type-card {
	position: relative;
	display: flex;
	flex-direction: column;
	padding: 0;
	overflow: hidden;
	font: inherit;
	text-align: left;
	background: var(--ax-card);
	border: 1px solid var(--ax-border-soft);
	border-radius: var(--ax-radius-card);
	cursor: pointer;
	transition: border-color 150ms var(--ax-ease), box-shadow 150ms var(--ax-ease),
		transform 150ms var(--ax-ease);
}

.aeroidx-type-card:hover:not(:disabled) {
	border-color: var(--ax-grad-from);
	box-shadow: 0 2px 10px rgba(139, 92, 246, 0.14);
	transform: translateY(-1px);
}

.aeroidx-type-card:focus-visible {
	outline: 2px solid var(--ax-grad-to);
	outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
	.aeroidx-type-card {
		transition: none;
	}

	.aeroidx-type-card:hover {
		transform: none;
	}
}

.aeroidx-type-card__preview {
	position: relative;
	display: block;
	overflow: hidden;
	border-bottom: 1px solid var(--ax-border-soft);
}

.aeroidx-type-card__body {
	display: flex;
	align-items: flex-start;
	gap: 10px;
	padding: 14px;
}

.aeroidx-type-card__icon {
	flex: 0 0 auto;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 36px;
	height: 36px;
	color: var(--ax-grad-from);
	background: var(--ax-violet-wash);
	border-radius: var(--ax-radius-input);
}

.aeroidx-type-card__glyph {
	width: 22px;
	height: 22px;
}

.aeroidx-type-card__text {
	display: flex;
	flex-direction: column;
	gap: 4px;
	min-width: 0;
}

.aeroidx-type-card__name {
	font-weight: 600;
	color: var(--ax-ink);
}

.aeroidx-type-card__desc {
	font-size: 12px;
	line-height: 1.5;
	color: var(--ax-muted);
	/* Two lines max, like the arrowidx picker (line-clamp-2), so a long
	   description can't stretch its card taller than the rest of the row. */
	display: -webkit-box;
	-webkit-box-orient: vertical;
	-webkit-line-clamp: 2;
	line-clamp: 2;
	overflow: hidden;
}

/* ---- Type preview skeletons -------------------------------------------- */
/* Abstract shapes standing in for each widget's real layout, copied element for
   element from arrowidx's WidgetSkeleton.vue. Tailwind does not exist in
   wp-admin, so every utility is translated to its px / percent value and each
   rule says which utilities it came from. Colors use Tailwind's real purple
   ramp as channel tokens, so a rule reads like the utility it replaces:
   bg-purple-300/70 -> rgb(var(--skel-purple-300) / 0.7).
   `dark:*` variants are left out: wp-admin has no dark mode.

   Both preview banners (picker card, saved-widget card) carry the tokens too:
   the banner gradient needs them and the skeleton inherits them from there. */
.aeroidx-type-card__preview,
.aeroidx-widget-item__preview,
.aeroidx-skel {
	--skel-purple-50: 250 245 255;
	--skel-purple-100: 243 232 255;
	--skel-purple-200: 233 213 255;
	--skel-purple-300: 216 180 254;
	--skel-purple-400: 192 132 252;
	--skel-purple-500: 168 85 247;
	--skel-purple-600: 147 51 234;
}

/* The banner the skeleton is drawn on: h-32 bg-gradient-to-br from-purple-50
   via-purple-100/60 to-purple-50, with the 1px bottom border inside the height
   (Tailwind boxes are border-box). */
.aeroidx-type-card__preview,
.aeroidx-widget-item__preview {
	box-sizing: border-box;
	height: 128px;
	background: linear-gradient(
		to bottom right,
		rgb(var(--skel-purple-50)),
		rgb(var(--skel-purple-100) / 0.6),
		rgb(var(--skel-purple-50))
	);
}

/* absolute inset-0. Every type sets its own layout below. Tailwind's preflight
   is also reproduced: border-box sizing everywhere, and block-level spans and
   svgs (zero specificity, so a type's own `display` always wins). */
.aeroidx-skel {
	position: absolute;
	inset: 0;
}

.aeroidx-skel,
.aeroidx-skel * {
	box-sizing: border-box;
}

:where(.aeroidx-skel) span,
:where(.aeroidx-skel) svg {
	display: block;
}

/* gallery: p-4 grid grid-cols-3 gap-2 items-stretch. */
.aeroidx-skel--gallery {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: 8px;
	align-items: stretch;
	padding: 16px;
}

.aeroidx-skel__tile {
	background: rgb(var(--skel-purple-200) / 0.7);
	border-radius: 4px;
}

.aeroidx-skel__tile:nth-child(2) {
	background: rgb(var(--skel-purple-300) / 0.6);
}

.aeroidx-skel__tile:nth-child(3) {
	background: rgb(var(--skel-purple-200) / 0.6);
}

/* carousel: flex items-center justify-center gap-1.5 px-4. Dimmed arrows
   (h-12 w-6) flanking the taller, more opaque active slide (h-[4.5rem] w-32). */
.aeroidx-skel--carousel {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 6px;
	padding: 0 16px;
}

.aeroidx-skel__nav {
	display: flex;
	flex-shrink: 0;
	align-items: center;
	justify-content: center;
	width: 24px;
	height: 48px;
	background: rgb(var(--skel-purple-200) / 0.2);
	border-radius: 4px;
}

.aeroidx-skel__nav svg {
	width: 14px;
	height: 14px;
	color: rgb(var(--skel-purple-400) / 0.8);
}

.aeroidx-skel__slide {
	width: 128px;
	height: 72px;
	background: rgb(var(--skel-purple-200) / 0.9);
	border-radius: 4px;
	box-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);
}

/* showcase_slider: p-4 grid grid-cols-5 gap-2 items-stretch. A hero image
   (col-span-3) beside a copy panel (col-span-2: flex-col justify-center gap-2
   px-2) holding a title, a subtitle and a button pill. */
.aeroidx-skel--showcase-slider {
	display: grid;
	grid-template-columns: repeat(5, minmax(0, 1fr));
	gap: 8px;
	align-items: stretch;
	padding: 16px;
}

.aeroidx-skel__showcase-hero {
	grid-column: span 3 / span 3;
	background: rgb(var(--skel-purple-200) / 0.8);
	border-radius: 4px;
}

.aeroidx-skel__showcase-copy {
	display: flex;
	grid-column: span 2 / span 2;
	flex-direction: column;
	justify-content: center;
	gap: 8px;
	padding: 0 8px;
}

.aeroidx-skel__showcase-title {
	width: 75%;
	height: 12px;
	background: rgb(var(--skel-purple-300) / 0.7);
	border-radius: 4px;
}

.aeroidx-skel__showcase-sub {
	width: 50%;
	height: 10px;
	background: rgb(var(--skel-purple-200) / 0.6);
	border-radius: 4px;
}

.aeroidx-skel__showcase-cta {
	width: 40%;
	height: 24px;
	margin-top: 8px;
	background: rgb(var(--skel-purple-300) / 0.6);
	border-radius: 999px;
}

/* search: flex-col items-center justify-center px-6 gap-2.5. */
.aeroidx-skel--search {
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 10px;
	padding: 0 24px;
}

/* search / ai_search bar: h-8 rounded-full bg-white/80 border
   border-purple-300/50 flex items-center px-3 gap-2. search adds w-full;
   ai_search stretches inside its own p-4 flex-col. */
.aeroidx-skel__bar {
	display: flex;
	align-items: center;
	gap: 8px;
	width: 100%;
	height: 32px;
	padding: 0 12px;
	background: rgb(255 255 255 / 0.8);
	border: 1px solid rgb(var(--skel-purple-300) / 0.5);
	border-radius: 999px;
}

.aeroidx-skel__bar-line {
	width: 50%;
	height: 8px;
	background: rgb(var(--skel-purple-200) / 0.8);
	border-radius: 999px;
}

/* Bar glyphs: size-3.5 shrink-0. Magnifier text-purple-400, sparkle text-purple-500. */
.aeroidx-skel__glyph {
	flex-shrink: 0;
	width: 14px;
	height: 14px;
	color: rgb(var(--skel-purple-500));
}

.aeroidx-skel__glyph--search {
	color: rgb(var(--skel-purple-400));
}

/* market_areas: p-4 grid grid-cols-2 gap-2. One big tile beside two stacked
   tiles that together match its height. */
.aeroidx-skel--market-areas {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: 8px;
	padding: 16px;
}

.aeroidx-skel__area-feature,
.aeroidx-skel__area-tile {
	border: 1px solid rgb(var(--skel-purple-300) / 0.4);
	border-radius: 4px;
}

.aeroidx-skel__area-feature {
	display: flex;
	align-items: center;
	justify-content: center;
	background: rgb(var(--skel-purple-200) / 0.7);
}

.aeroidx-skel__area-stack {
	display: flex;
	flex-direction: column;
	gap: 8px;
}

.aeroidx-skel__area-tile {
	flex: 1 1 0%;
	background: rgb(var(--skel-purple-300) / 0.6);
}

.aeroidx-skel__area-tile:nth-child(2) {
	background: rgb(var(--skel-purple-200) / 0.6);
}

/* market_stats: p-4 flex-col gap-2. Stat tiles, trend chart, subscribe pill. */
.aeroidx-skel--market-stats {
	display: flex;
	flex-direction: column;
	align-items: stretch;
	justify-content: flex-start;
	gap: 8px;
	padding: 16px;
}

.aeroidx-skel__stats {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: 8px;
}

.aeroidx-skel__stat {
	position: relative;
	padding: 6px;
	background: rgb(var(--skel-purple-200) / 0.7);
	border: 1px solid rgb(var(--skel-purple-300) / 0.4);
	border-radius: 4px;
}

.aeroidx-skel__stat:nth-child(2) {
	background: rgb(var(--skel-purple-200) / 0.6);
}

.aeroidx-skel__stat-dot {
	position: absolute;
	top: 4px;
	right: 4px;
	width: 6px;
	height: 6px;
	background: rgb(var(--skel-purple-400) / 0.6);
	border-radius: 999px;
}

.aeroidx-skel__stat-line {
	display: block;
	width: 66.6667%;
	height: 8px;
	background: rgb(var(--skel-purple-300) / 0.7);
	border-radius: 999px;
}

.aeroidx-skel__trend {
	display: flex;
	flex: 1 1 0;
	align-items: flex-end;
	gap: 4px;
	min-height: 0;
	padding: 6px;
	background: rgb(255 255 255 / 0.55);
	border: 1px solid rgb(var(--skel-purple-200) / 0.5);
	border-radius: 4px;
}

.aeroidx-skel__trend-bar {
	flex: 1 1 0;
	background: rgb(var(--skel-purple-300) / 0.55);
	border-radius: 2px;
}

.aeroidx-skel__trend-bar--mid {
	background: rgb(var(--skel-purple-300) / 0.65);
}

.aeroidx-skel__trend-bar--peak {
	background: rgb(var(--skel-purple-500) / 0.7);
}

.aeroidx-skel__subscribe {
	align-self: flex-end;
	width: 64px;
	height: 10px;
	background: rgb(var(--skel-purple-300) / 0.7);
	border-radius: 999px;
}

/* map_widget: a rounded, ruled 16px grid on bg-purple-50/90 with three
   teardrop pins. Pins are absolute at top/left percentages (inline) and only
   shifted by -translate-x-1/2, as upstream does; the large and middle one carry
   drop-shadow-sm. The pin glyph is also the marker inside a market_areas tile
   (size-5, text-purple-500/60). */
.aeroidx-skel__grid {
	position: relative;
	width: 100%;
	height: 100%;
	overflow: hidden;
	background-color: rgb(var(--skel-purple-50) / 0.9);
	background-image: linear-gradient(to right, rgba(167, 139, 250, 0.22) 1px, transparent 1px),
		linear-gradient(to bottom, rgba(167, 139, 250, 0.22) 1px, transparent 1px);
	background-size: 16px 16px;
	border-radius: 4px;
}

.aeroidx-skel__pin {
	width: 20px;
	height: 20px;
}

.aeroidx-skel__grid .aeroidx-skel__pin {
	position: absolute;
	transform: translateX(-50%);
}

.aeroidx-skel__pin--lg {
	color: rgb(var(--skel-purple-500));
	filter: drop-shadow(0 1px 1px rgb(0 0 0 / 0.05));
}

.aeroidx-skel__pin--md {
	width: 16px;
	height: 16px;
	color: rgb(var(--skel-purple-600) / 0.8);
	filter: drop-shadow(0 1px 1px rgb(0 0 0 / 0.05));
}

.aeroidx-skel__pin--sm {
	width: 14px;
	height: 14px;
	color: rgb(var(--skel-purple-400) / 0.7);
}

.aeroidx-skel__pin--area {
	color: rgb(var(--skel-purple-500) / 0.6);
}

/* ai_search: p-4 flex-col justify-center gap-2.5 around the shared bar. */
.aeroidx-skel--ai-search {
	display: flex;
	flex-direction: column;
	justify-content: center;
	gap: 10px;
	padding: 16px;
}

/* ai_search_drawer: a panel absolute top-3 bottom-3 right-3 w-[52%] rounded
   bg-white/85 border border-purple-300/50 p-2 flex-col gap-1.5, with a sparkle
   and title row over two copy lines. */
.aeroidx-skel__drawer {
	position: absolute;
	top: 12px;
	right: 12px;
	bottom: 12px;
	display: flex;
	flex-direction: column;
	gap: 6px;
	width: 52%;
	padding: 8px;
	background: rgb(255 255 255 / 0.85);
	border: 1px solid rgb(var(--skel-purple-300) / 0.5);
	border-radius: 4px;
}

.aeroidx-skel__drawer-head {
	display: flex;
	align-items: center;
	gap: 6px;
}

.aeroidx-skel__drawer-glyph {
	flex-shrink: 0;
	width: 12px;
	height: 12px;
	color: rgb(var(--skel-purple-500));
}

.aeroidx-skel__drawer-title {
	width: 50%;
	height: 8px;
	background: rgb(var(--skel-purple-300) / 0.6);
	border-radius: 999px;
}

.aeroidx-skel__drawer-line {
	width: 100%;
	height: 8px;
	background: rgb(var(--skel-purple-200) / 0.7);
	border-radius: 999px;
}

.aeroidx-skel__drawer-line--short {
	width: 75%;
	background: rgb(var(--skel-purple-200) / 0.6);
}

/* testimonials: flex items-center justify-center gap-3 px-6. A size-9 portrait
   beside three quote lines (w-32 / w-24 / w-16) and the carousel's pagination
   dots (size-1.5, gap-1, mt-1). */
.aeroidx-skel--testimonials {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 12px;
	padding: 0 24px;
}

.aeroidx-skel__avatar {
	flex-shrink: 0;
	width: 36px;
	height: 36px;
	background: rgb(var(--skel-purple-300) / 0.7);
	border: 1px solid rgb(var(--skel-purple-300) / 0.5);
	border-radius: 999px;
}

.aeroidx-skel__quote {
	display: flex;
	flex-direction: column;
	gap: 6px;
}

.aeroidx-skel__quote-line {
	width: 128px;
	height: 8px;
	background: rgb(var(--skel-purple-200) / 0.8);
	border-radius: 999px;
}

.aeroidx-skel__quote-line--mid {
	width: 96px;
	background: rgb(var(--skel-purple-200) / 0.7);
}

.aeroidx-skel__quote-line--short {
	width: 64px;
	background: rgb(var(--skel-purple-200) / 0.6);
}

.aeroidx-skel__dots {
	display: flex;
	align-items: center;
	gap: 4px;
	margin-top: 4px;
}

.aeroidx-skel__dot {
	width: 6px;
	height: 6px;
	background: rgb(var(--skel-purple-300) / 0.4);
	border-radius: 999px;
}

.aeroidx-skel__dot--active {
	background: rgb(var(--skel-purple-400) / 0.7);
}

/* contact_form: px-5 py-3 flex-col justify-center gap-1.5. A label over a rule
   per field, never a filled box. */
.aeroidx-skel--contact-form {
	display: flex;
	flex-direction: column;
	align-items: stretch;
	justify-content: center;
	gap: 6px;
	padding: 12px 20px;
}

.aeroidx-skel__eyebrow {
	display: flex;
	align-items: center;
	gap: 6px;
}

.aeroidx-skel__eyebrow-rule {
	flex: 0 0 auto;
	width: 16px;
	height: 2px;
	background: rgb(var(--skel-purple-400) / 0.7);
}

.aeroidx-skel__eyebrow-label {
	width: 36px;
	height: 6px;
	background: rgb(var(--skel-purple-300) / 0.7);
	border-radius: 999px;
}

.aeroidx-skel__heading {
	width: 66.6667%;
	height: 12px;
	background: rgb(var(--skel-purple-300) / 0.8);
	border-radius: 4px;
}

.aeroidx-skel__fields {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: 12px;
	margin-top: 2px;
}

.aeroidx-skel__field {
	display: flex;
	flex-direction: column;
	gap: 4px;
}

.aeroidx-skel__field-label {
	height: 6px;
	background: rgb(var(--skel-purple-200) / 0.8);
	border-radius: 999px;
}

.aeroidx-skel__field-rule {
	width: 100%;
	height: 2px;
	background: rgb(var(--skel-purple-300) / 0.6);
}

.aeroidx-skel__submit {
	width: 100%;
	height: 20px;
	margin-top: 4px;
	background: rgb(var(--skel-purple-400) / 0.8);
	border-radius: 2px;
}

/* mortgage_calculator: p-4 grid-cols-5 gap-3 items-center. Input rows (3 cols)
   beside the payment donut (2 cols). */
.aeroidx-skel--mortgage-calculator {
	display: grid;
	grid-template-columns: repeat(5, minmax(0, 1fr));
	gap: 12px;
	align-items: center;
	padding: 16px;
}

.aeroidx-skel__inputs {
	display: flex;
	grid-column: span 3 / span 3;
	flex-direction: column;
	gap: 8px;
}

.aeroidx-skel__input {
	display: flex;
	align-items: center;
	gap: 6px;
	height: 24px;
	padding: 0 8px;
	background: rgb(255 255 255 / 0.75);
	border: 1px solid rgb(var(--skel-purple-300) / 0.45);
	border-radius: 4px;
}

.aeroidx-skel__input-label {
	flex: 0 0 auto;
	width: 28px;
	height: 6px;
	background: rgb(var(--skel-purple-300) / 0.7);
	border-radius: 999px;
}

.aeroidx-skel__input-value {
	flex: 1 1 0;
	height: 6px;
	background: rgb(var(--skel-purple-200) / 0.7);
	border-radius: 999px;
}

.aeroidx-skel__donut-cell {
	display: flex;
	grid-column: span 2 / span 2;
	align-items: center;
	justify-content: center;
}

/* -rotate-90 starts the first arc at 12 o'clock, where the widget starts its ring. */
.aeroidx-skel__donut {
	width: 64px;
	height: 64px;
	transform: rotate(-90deg);
}

.aeroidx-skel__donut-track {
	stroke: rgb(var(--skel-purple-200) / 0.4);
}

.aeroidx-skel__donut-arc--principal {
	stroke: rgb(var(--skel-purple-500) / 0.8);
}

.aeroidx-skel__donut-arc--taxes {
	stroke: rgb(var(--skel-purple-400) / 0.85);
}

.aeroidx-skel__donut-arc--hoa {
	stroke: rgb(var(--skel-purple-300) / 0.95);
}

/* sign_in: flex centered, gap-4, no padding. Signed-out pill beside the
   signed-in avatar and menu caret. */
.aeroidx-skel--sign-in {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 16px;
}

.aeroidx-skel__signin-button {
	display: flex;
	align-items: center;
	justify-content: center;
	height: 32px;
	padding: 0 16px;
	background: rgb(var(--skel-purple-300) / 0.7);
	border: 1px solid rgb(var(--skel-purple-300) / 0.5);
	border-radius: 999px;
}

.aeroidx-skel__signin-label {
	width: 48px;
	height: 8px;
	background: rgb(255 255 255 / 0.7);
	border-radius: 999px;
}

.aeroidx-skel__signin-account {
	display: flex;
	align-items: center;
	gap: 4px;
}

.aeroidx-skel__signin-avatar {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 32px;
	height: 32px;
	background: rgb(var(--skel-purple-200) / 0.8);
	border: 1px solid rgb(var(--skel-purple-300) / 0.5);
	border-radius: 999px;
}

.aeroidx-skel__signin-avatar svg {
	width: 16px;
	height: 16px;
	color: rgb(var(--skel-purple-500) / 0.7);
}

.aeroidx-skel__signin-caret {
	width: 12px;
	height: 12px;
	color: rgb(var(--skel-purple-400) / 0.8);
}

/* Generic preview for a type known only from the remote registry. No upstream
   skeleton exists, so it reuses the showcase composition (p-4 grid grid-cols-5
   gap-2) from the same tokens: a block beside a title line and a shorter one. */
.aeroidx-skel--generic {
	display: grid;
	grid-template-columns: repeat(5, minmax(0, 1fr));
	gap: 8px;
	align-items: stretch;
	justify-content: normal;
	padding: 16px;
}

.aeroidx-skel__hero {
	grid-column: span 3 / span 3;
	background: rgb(var(--skel-purple-200) / 0.8);
	border-radius: 4px;
}

.aeroidx-skel__lines {
	display: flex;
	grid-column: span 2 / span 2;
	flex-direction: column;
	justify-content: center;
	gap: 8px;
	padding: 0 8px;
}

.aeroidx-skel__line {
	width: 75%;
	height: 12px;
	background: rgb(var(--skel-purple-300) / 0.7);
	border-radius: 4px;
}

.aeroidx-skel__line--short {
	width: 50%;
	height: 10px;
	background: rgb(var(--skel-purple-200) / 0.6);
}

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

/*
 * Shared confirm-before-you-act dialog, rendered once per screen and driven by
 * data attributes on whatever button opened it (see admin.js). It knows nothing
 * about pages, widgets or anything else, so a second destructive action wires
 * itself up by adding attributes rather than by adding another dialog.
 *
 * Ported from the widget-builder branch and re-expressed in tokens on the way:
 * the original carried seventeen literal colours, radii and easings from before
 * the token layer existed, including greys from the Gray ramp the rest of this
 * admin no longer uses.
 */
.aeroidx-modal {
	position: fixed;
	inset: 0;
	z-index: 100000;
	display: flex;
	align-items: center;
	justify-content: center;
	padding: 20px;
}

/* Author display beats the browser's [hidden] rule, so restore it. */
.aeroidx-modal[hidden] {
	display: none;
}

.aeroidx-modal__backdrop {
	position: absolute;
	inset: 0;
	background: var(--ax-scrim);
}

.aeroidx-modal__dialog {
	position: relative;
	width: 100%;
	max-width: 460px;
	padding: 24px;
	background: var(--ax-card);
	border-radius: var(--ax-radius-overlay);
	box-shadow: var(--ax-shadow-overlay);
	animation: aeroidx-modal-in 150ms var(--ax-ease);
}

@keyframes aeroidx-modal-in {
	from {
		opacity: 0;
		transform: translateY(8px) scale(0.98);
	}
	to {
		opacity: 1;
		transform: none;
	}
}

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

.aeroidx-modal__close {
	position: absolute;
	top: 14px;
	right: 14px;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 30px;
	height: 30px;
	padding: 0;
	color: var(--ax-muted);
	background: none;
	border: 0;
	border-radius: var(--ax-radius-tile);
	cursor: pointer;
	transition: background 150ms var(--ax-ease), color 150ms var(--ax-ease);
}

.aeroidx-modal__close:hover {
	color: var(--ax-ink);
	background: var(--ax-locked);
}

.aeroidx-modal__close:focus-visible {
	outline: none;
	box-shadow: 0 0 0 2px var(--ax-violet-500);
}

.aeroidx-modal__head {
	display: flex;
	align-items: flex-start;
	gap: 14px;
	padding-right: 28px;
}

.aeroidx-modal__icon {
	flex: 0 0 auto;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 44px;
	height: 44px;
	color: var(--ax-danger-solid);
	background: var(--ax-danger-tint);
	border-radius: 50%;
}

/*
 * Tones. The red circle above is the DELETE register, and it was the only one
 * this dialog could speak in. A path collision is a decision with more than one
 * right answer and nothing gets destroyed by any of them, so it takes amber;
 * dressing it in red would teach admins that red here does not mean what it
 * means two rows up on the same screen.
 */
.aeroidx-modal__icon.is-warning {
	color: var(--ax-warning-ink);
	background: var(--ax-warning-edge);
}

/*
 * There was an `is-neutral` here too, violet, for the dialogs that report a page
 * the plugin had lost track of. It is gone rather than left unused: those
 * dialogs are amber now, so the rule had no consumer, and a tone nobody asks for
 * is the kind of thing that gets re-adopted years later by someone who assumes
 * it was load-bearing.
 */

.aeroidx-modal__title {
	margin: 0;
	font-size: 17px;
	font-weight: 700;
	line-height: 1.3;
	color: var(--ax-ink);
}

.aeroidx-modal__subtitle {
	margin: 2px 0 0;
	font-size: 13px;
	color: var(--ax-muted);
}

.aeroidx-modal__body {
	margin-top: 16px;
}

.aeroidx-modal__question {
	margin: 0;
	font-size: 14px;
	line-height: 1.5;
	color: var(--ax-secondary);
}

.aeroidx-modal__question strong {
	font-weight: 700;
	word-break: break-word;
}

.aeroidx-modal__note {
	margin: 8px 0 0;
	font-size: 13px;
	line-height: 1.5;
	color: var(--ax-muted);
}

.aeroidx-modal__actions {
	display: flex;
	justify-content: flex-end;
	gap: 10px;
	margin-top: 24px;
}

.aeroidx-modal__cancel.button,
.aeroidx-modal__confirm.button {
	height: auto;
	min-height: 38px;
	padding: 0 18px;
	font-weight: 600;
	border-radius: var(--ax-radius-tile);
}

/* Neutral secondary action; it must never pick up the violet primary styling. */
.aeroidx-modal__cancel.button,
.aeroidx-modal__cancel.button:hover,
.aeroidx-modal__cancel.button:focus {
	color: var(--ax-secondary);
	background: var(--ax-card);
	border-color: var(--ax-border-soft);
}

.aeroidx-modal__cancel.button:hover {
	background: var(--ax-locked);
	border-color: var(--ax-border);
	color: var(--ax-ink);
}

/*
 * Filled destructive action. Hover goes lighter, not darker: that is what the
 * Design System's Buttons page specifies for DangerButton (red-600 at rest,
 * red-500 on hover), and the branch this came from had it inverted.
 */
.aeroidx-modal__confirm.button,
.aeroidx-modal__confirm.button:hover,
.aeroidx-modal__confirm.button:focus {
	color: var(--ax-on-accent);
	background: var(--ax-danger-solid);
	border-color: var(--ax-danger-solid);
	box-shadow: none;
}

.aeroidx-modal__confirm.button:hover {
	background: var(--ax-danger-solid-hover);
	border-color: var(--ax-danger-solid-hover);
}

/* No dimming: the spinner and the "…ing" label (button.is-busy) say it is
 * working, and a faded button reads as a disabled one. */
.aeroidx-modal__confirm.button[aria-busy="true"] {
	pointer-events: none;
}

.aeroidx-modal__confirm.button:focus-visible,
.aeroidx-modal__alt.button:focus-visible,
.aeroidx-modal__cancel.button:focus-visible {
	outline: none;
	box-shadow: 0 0 0 2px var(--ax-card), 0 0 0 4px var(--ax-violet-500);
}

/* ─────────────────────────────────────────────────────────────────────────
 * PATH COLLISIONS
 *
 * Everything below turns the shared confirm dialog into something that can
 * also ask a question with more than one right answer. See
 * SettingsPage::renderConfirmDialog() for why this extends the one dialog
 * instead of standing a second one up beside it.
 * ───────────────────────────────────────────────────────────────────────── */

/*
 * The wider box, opted into per invocation. The 460px default was sized for a
 * delete: two short paragraphs and two buttons. A collision carries a found-page
 * card or a list plus a radio set, and three buttons that do not fit on one row
 * at 460 in any language.
 */
.aeroidx-modal__dialog.is-wide {
	max-width: 560px;
}

/*
 * The third action. Outlined and neutral, deliberately NOT the filled
 * treatment: with two real choices on screen, filling one of them is the
 * screen picking for the admin, and the whole point here is that the plugin
 * cannot know which page they meant.
 */
.aeroidx-modal__alt.button,
.aeroidx-modal__alt.button:hover,
.aeroidx-modal__alt.button:focus {
	height: auto;
	min-height: 38px;
	padding: 0 18px;
	font-weight: 600;
	color: var(--ax-secondary);
	background: var(--ax-card);
	border-color: var(--ax-border);
	border-radius: var(--ax-radius-tile);
	box-shadow: none;
}

.aeroidx-modal__alt.button:hover {
	color: var(--ax-ink);
	background: var(--ax-locked);
}

/* No dimming: the spinner and the "…ing" label (button.is-busy) say it is
 * working, and a faded button reads as a disabled one. */
.aeroidx-modal__alt.button[aria-busy="true"] {
	pointer-events: none;
}

/*
 * `hidden` has to WIN here, and it does not on its own: .button carries
 * display:inline-block from WordPress core, an author declaration, and an author
 * declaration beats the UA stylesheet's `[hidden] { display: none }`. Without
 * this the dialogs that declare no third action still render it — an empty
 * button, 38px of nothing between Cancel and the confirm, and a nameless stop in
 * the tab order for anybody on a keyboard.
 *
 * That is the sixth instance of this exact trap in this file. See
 * .aeroidx-modal[hidden], .aeroidx-market-card[hidden] and the three around the
 * widgets list.
 */
.aeroidx-modal__alt.button[hidden] {
	display: none;
}

/*
 * Filled violet. For a dialog whose action BUILDS something, the delete red was
 * not merely the wrong hue — it told the admin that pressing "Create all pages"
 * would remove something.
 */
.aeroidx-modal__confirm.button.is-primary,
.aeroidx-modal__confirm.button.is-primary:hover,
.aeroidx-modal__confirm.button.is-primary:focus {
	color: var(--ax-on-accent);
	background: var(--ax-violet-700);
	border-color: var(--ax-violet-700);
}

.aeroidx-modal__confirm.button.is-primary:hover {
	background: var(--ax-violet-500);
	border-color: var(--ax-violet-500);
}

/* Same reasoning as __alt: the accept button drops the filled red when the
 * dialog is a choice rather than a confirmation. */
.aeroidx-modal__confirm.button.is-neutral,
.aeroidx-modal__confirm.button.is-neutral:hover,
.aeroidx-modal__confirm.button.is-neutral:focus {
	color: var(--ax-secondary);
	background: var(--ax-card);
	border-color: var(--ax-border);
}

.aeroidx-modal__confirm.button.is-neutral:hover {
	color: var(--ax-ink);
	background: var(--ax-locked);
}

/*
 * Three buttons plus a gap do not fit at 460px, and at 560px they fit in
 * English and stop fitting in German. Rather than pick a width and hope, the
 * row wraps: on a narrow viewport the buttons stack full width, which is the
 * layout that holds in every language.
 */
.aeroidx-modal__actions {
	flex-wrap: wrap;
}

@media (max-width: 600px) {
	.aeroidx-modal__actions {
		flex-direction: column-reverse;
		align-items: stretch;
	}

	.aeroidx-modal__actions .button {
		width: 100%;
	}
}

.aeroidx-modal__extra[hidden] {
	display: none;
}

/* The page found sitting on the path. */
.aeroidx-modal__found {
	display: flex;
	align-items: center;
	gap: 11px;
	margin-top: 14px;
	padding: 11px 13px;
	background: var(--ax-locked);
	border: 1px solid var(--ax-border-soft);
	border-radius: var(--ax-radius-tile);
}

.aeroidx-modal__found-icon {
	flex: 0 0 auto;
	display: flex;
	color: var(--ax-muted);
}

/*
 * flex:1 is what pushes the badge and the View link to the right edge. Without
 * it this column sizes to its content and the two of them bunch up against the
 * date, reading as part of the same sentence rather than as the row's controls.
 *
 * min-width:0 is load-bearing too: without it the ellipsis below never triggers,
 * because a flex item refuses to shrink past its content.
 */
.aeroidx-modal__found-main {
	display: flex;
	flex: 1 1 auto;
	flex-direction: column;
	min-width: 0;
}

.aeroidx-modal__found-title {
	overflow: hidden;
	font-size: 13.5px;
	font-weight: 600;
	color: var(--ax-ink);
	white-space: nowrap;
	text-overflow: ellipsis;
}

.aeroidx-modal__found-meta {
	margin-top: 1px;
	font-family: var(--ax-font-mono);
	font-size: 11.5px;
	color: var(--ax-muted);
}

.aeroidx-modal__found-badge {
	flex: 0 0 auto;
	padding: 1px 8px;
	font-size: 10.5px;
	font-weight: 600;
	color: var(--ax-warning-ink);
	background: var(--ax-warning-wash);
	border: 1px solid var(--ax-warning-edge);
	border-radius: var(--ax-radius-pill);
}

.aeroidx-modal__found-link {
	flex: 0 0 auto;
	font-size: 12.5px;
	font-weight: 600;
	color: var(--ax-violet-700);
	text-decoration: none;
}

.aeroidx-modal__found-link:hover,
.aeroidx-modal__found-link:focus {
	color: var(--ax-violet-700);
	text-decoration: underline;
}

/*
 * The bulk dialog's list of what is in the way.
 *
 * A flex column, not a plain block list, and that is not decoration: wp-admin
 * gives `li` a bottom margin, and inside a bordered container with
 * overflow:hidden that margin showed as a strip of the card's white sitting
 * under the amber row, reading like a second row that had failed to render.
 * A flex container makes the rows' spacing explicit, and it is the shape
 * .aeroidx-page-list already uses one screen over for the same reason.
 */
.aeroidx-modal__list {
	display: flex;
	flex-direction: column;
	margin: 14px 0 0;
	padding: 0;
	overflow: hidden;
	list-style: none;
	border: 1px solid var(--ax-border-soft);
	border-radius: var(--ax-radius-tile);
}

.aeroidx-modal__list li {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	gap: 4px 10px;
	margin: 0;
	padding: 8px 12px;
	font-size: 13px;
	background: var(--ax-warning-wash);
	border-bottom: 1px solid var(--ax-warning-edge);
}

.aeroidx-modal__list li:last-child {
	border-bottom: 0;
}

/*
 * The recovered-pages list in the bulk dialog once painted itself violet, to set
 * it apart from the addresses-in-the-way list above it. Both are amber now: one
 * dialog carries one register, and a header saying "we lost track of these"
 * above a list saying "relax, this is fine" was the dialog disagreeing with
 * itself.
 *
 * The two lists are still told apart, by the thing that actually carries the
 * difference — each row says what it is, and each list sits under its own
 * legend and its own radio set. Colour was never doing that work.
 */
.aeroidx-modal__list--found .aeroidx-modal__list-holder {
	color: var(--ax-warning-ink);
}

.aeroidx-modal__list-name {
	font-weight: 600;
	color: var(--ax-ink);
}

.aeroidx-modal__list-slug {
	font-family: var(--ax-font-mono);
	font-size: 12px;
	color: var(--ax-warning-ink);
}

.aeroidx-modal__list-holder {
	margin-left: auto;
	overflow: hidden;
	font-size: 12px;
	color: var(--ax-muted);
	white-space: nowrap;
	text-overflow: ellipsis;
}

/* The one choice that applies to every address in the way. */
.aeroidx-modal__choice {
	display: flex;
	flex-direction: column;
	gap: 6px;
	margin: 16px 0 0;
	padding: 0;
	border: 0;
}

.aeroidx-modal__choice-legend {
	padding: 0;
	margin-bottom: 4px;
	font-size: 12.5px;
	font-weight: 600;
	color: var(--ax-ink);
}

.aeroidx-modal__choice label {
	display: flex;
	align-items: flex-start;
	gap: 9px;
	padding: 9px 11px;
	font-size: 13px;
	line-height: 1.4;
	color: var(--ax-secondary);
	cursor: pointer;
	border: 1px solid var(--ax-border-soft);
	border-radius: var(--ax-radius-tile);
}

.aeroidx-modal__choice label:hover {
	border-color: var(--ax-border);
}

.aeroidx-modal__choice label:has(input:checked) {
	color: var(--ax-ink);
	background: var(--ax-violet-wash);
	border-color: var(--ax-violet-500);
}

.aeroidx-modal__choice label:has(input:focus-visible) {
	outline: 2px solid var(--ax-violet-500);
	outline-offset: 2px;
}

/*
 * The radio, repainted in the plugin's violet.
 *
 * accent-color alone does nothing here, and it is worth knowing why before
 * anybody deletes these rules as redundant: wp-admin sets `appearance: none` on
 * its radios and draws the dot itself, as a ::before filled with core's blue
 * (#3582c4). accent-color only reaches a control the browser is still painting,
 * so on this screen it was styling nothing at all.
 *
 * The attribute selector is deliberate. `.aeroidx-modal__choice input` and
 * core's `input[type=radio]` both score (0,1,1), which leaves the winner to be
 * decided by whichever stylesheet happens to load second. Adding [type="radio"]
 * takes it to (0,2,1) and settles it on specificity instead of on enqueue order.
 */
.aeroidx-modal__choice input[type="radio"] {
	flex: 0 0 auto;
	margin: 3px 0 0;
	background: var(--ax-card);
	border-color: var(--ax-border);
	accent-color: var(--ax-violet-700);
}

.aeroidx-modal__choice input[type="radio"]:checked {
	border-color: var(--ax-violet-700);
}

.aeroidx-modal__choice input[type="radio"]:checked::before {
	background-color: var(--ax-violet-700);
}

/*
 * Core's focus ring is the same blue, and it is REMOVED rather than recoloured.
 * The whole row already draws an outline when the radio inside it takes focus
 * (see the label:has(input:focus-visible) rule above), and keeping both would
 * put two rings around one control — the row's, and a second one hugging a
 * 16px circle inside it.
 */
.aeroidx-modal__choice input[type="radio"]:focus {
	border-color: var(--ax-violet-700);
	box-shadow: none;
}

.aeroidx-modal__choice-hint {
	display: block;
	margin-top: 2px;
	font-size: 12px;
	font-weight: 400;
	color: var(--ax-muted);
}

/*
 * The row pill for a catalog page whose address is taken. Amber rather than the
 * neutral "Not created" grey, because this is the one state in the list that is
 * waiting on the admin instead of on a click.
 */
.aeroidx-market-status--taken {
	color: var(--ax-warning-ink);
	background: var(--ax-warning-wash);
	border-color: var(--ax-warning-edge);
}

/*
 * A page of ours that already exists and that the plugin had lost the pointer
 * to. Violet rather than amber: nothing is in the way and nothing needs
 * deciding, the row is reporting good news that happens to need one click. Amber
 * here would put it in the same register as a real obstruction.
 */
.aeroidx-market-status--found {
	color: var(--ax-violet-700);
	background: var(--ax-violet-wash);
	border-color: var(--ax-violet-500);
}

/*
 * Home's Account tile while AeroIDX moves the authorization here on its own.
 * Same violet as --found, for the same reason, and a slow pulse on the dot
 * so it reads as in progress rather than done.
 */
.aeroidx-market-status--moving {
	color: var(--ax-violet-700);
	background: var(--ax-violet-wash);
	border-color: var(--ax-violet-500);
}

.aeroidx-market-status--moving::before {
	animation: aeroidx-moving-pulse 1.2s ease-in-out infinite;
}

@keyframes aeroidx-moving-pulse {
	50% {
		opacity: 0.25;
	}
}

@media (prefers-reduced-motion: reduce) {
	.aeroidx-market-status--moving::before {
		animation: none;
	}
}

/* ─────────────────────────────────────────────────────────────────────────
 * WEBSITE DESIGN PICKER
 *
 * A radio group that does not look like one. The input is the state and the
 * label is the whole target, so the card IS the control rather than a card
 * with a control in it, and the row stays reachable by keyboard because the
 * input is still there being focused.
 *
 * The input is hidden with `position: absolute; opacity: 0` rather than
 * `display: none`. A display-none radio is removed from the accessibility tree
 * and from tab order, which would turn a keyboard-operable group into a set of
 * unreachable cards.
 *
 * THE VISIBLE MARK IS DRAWN, NOT REUSED. Styling the native radio would be
 * less code and would also put a wp-admin default circle at whatever size the
 * browser picks, in the browser accent colour, next to a violet card. The
 * `__mark` span is decoration for the input beside it, `aria-hidden`, and the
 * only thing that says "this one" at a glance.
 * ───────────────────────────────────────────────────────────────────────── */

/*
 * Section headings inside the Designs card.
 *
 * The card already has an h2. These are h3 and deliberately quieter than it:
 * the reader is not choosing between three equal sections, they are reading one
 * picker with two notes about it. Sized level with the card's own body text
 * rather than stepped down from the h2, because a heading smaller than the
 * paragraph under it reads as a caption for the wrong block.
 */
.aeroidx-settings .aeroidx-designs__heading {
	margin: 28px 0 0;
	font-size: 15px;
	font-weight: 600;
	color: var(--ax-ink);
}

.aeroidx-settings .aeroidx-designs__heading + .aeroidx-designs__heading-note {
	margin: 4px 0 0;
	font-size: 13px;
	line-height: 1.5;
	color: var(--ax-muted);
}

/* The heading owns the gap above the grid, so the grid does not add a second. */
.aeroidx-settings .aeroidx-designs__heading + .aeroidx-designs__set,
.aeroidx-settings .aeroidx-designs__heading-note + .aeroidx-designs__set {
	margin-top: 14px;
}

/*
 * "Your agency's theme is live on these pages", above the picker it qualifies.
 *
 * ABOVE AND NOT BESIDE. The cards below answer "which design do I want"; this
 * answers "which pages is that question even about". Read second it explains
 * nothing, because by then the reader has already tried to reconcile a picker
 * whose choice does not cover their whole site.
 *
 * Violet, not amber: nothing is wrong and nothing failed. It is the same wash
 * the applied card uses, saying the same thing — this part is spoken for.
 */
.aeroidx-settings .aeroidx-designs__live {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: 12px;
	margin: 12px 0 0;
	padding: 16px 18px;
	border: 1px solid var(--ax-violet-a38);
	border-radius: var(--ax-radius-sm);
	background: var(--ax-violet-wash);
}

.aeroidx-settings .aeroidx-designs__live-text {
	display: flex;
	min-width: 0;
	flex-direction: column;
	gap: 2px;
}

.aeroidx-settings .aeroidx-designs__live-name {
	font-size: 15px;
	font-weight: 600;
	color: var(--ax-ink);
}

.aeroidx-settings .aeroidx-designs__live-note {
	font-size: 13px;
	line-height: 1.5;
	color: var(--ax-muted);
}

/*
 * The pages as separate pills rather than a comma-joined sentence.
 *
 * A page name here can itself contain a separator — "Search / Map" — so a
 * comma-joined list reads as one more item than it holds. Each on its own
 * ground is unambiguous at any length, and is what the AeroIDX screen this
 * mirrors already draws.
 */
.aeroidx-settings .aeroidx-designs__live-pages {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
	margin: 0;
	padding: 0;
	list-style: none;
}

.aeroidx-settings .aeroidx-designs__live-page {
	margin: 0;
	padding: 4px 10px;
	border-radius: 999px;
	background: var(--ax-violet-a12);
	font-size: 12px;
	font-weight: 600;
	color: var(--ax-violet-700);
}

/*
 * A card the account may not switch to.
 *
 * NOT `display: none`. The theme is real, the client can see it named in the
 * AeroIDX dashboard, and a card that vanishes reads as a bug rather than as a
 * rule — the same call the app makes on its own screen. It is dimmed and inert
 * instead, and `cursor: default` is what stops the label promising a click that
 * the disabled input will not deliver.
 *
 * The opacity sits on the LABEL and not on the wrapper, so the "Applied" badge
 * on a locked card keeps its contrast: that badge is the one thing on it the
 * reader still needs to be able to read.
 */
.aeroidx-settings .aeroidx-design.is-locked .aeroidx-design__label {
	opacity: 0.6;
	cursor: default;
}

/*
 * THE CIRCLE STAYS ON A LOCKED CARD, and hiding it was a mistake worth naming.
 *
 * It looked like tidiness — the control cannot be chosen, so why draw its
 * mark — and it cost the row its shape: three cards in a grid where the others
 * have a mark and these do not read as a different KIND of thing, not as the
 * same thing unavailable. The app draws the empty circle here, and the empty
 * circle is the sentence: this is an option, and it is not selected.
 */

/*
 * AT MOST THREE COLUMNS, AND THE SAME THREE FOR BOTH SETS.
 *
 * This was repeat(auto-fit, minmax(260px, 1fr)). auto-fit collapses the
 * tracks nobody fills, so the three built-in designs took a third of the row
 * each while an agency set of two took HALF each, and with the figure locked
 * to 432/300 the wider card came out taller too. Two sets of the same card at
 * two sizes, one above the other.
 *
 * auto-fill keeps the empty tracks, so a card is the same width however many
 * share its row. The track minimum is the larger of 260px and a third of the
 * row, which caps the count at three (auto-fill alone would fit four at this
 * width and shrink the built-ins) and still drops to two, then one, when the
 * panel narrows. 2 * gap is taken off before dividing, since three columns
 * have two gaps between them.
 */
.aeroidx-settings .aeroidx-designs__set {
	--aeroidx-designs-gap: 20px;
	display: grid;
	gap: var(--aeroidx-designs-gap);
	grid-template-columns: repeat(
		auto-fill,
		minmax(max(260px, calc((100% - 2 * var(--aeroidx-designs-gap)) / 3)), 1fr)
	);
	margin: 20px 0 0;
	padding: 0;
	border: 0;
}

/*
 * The sitemap scope's four cards only — a deliberate breakpoint layout
 * rather than `auto-fit`'s "however many fit", which on this screen's column
 * width would settle on 2 across at every size and never reach 4. Scoped to
 * this one set with a modifier class rather than changed on
 * .aeroidx-designs__set itself, which the website Design picker (a different
 * number of cards, sized for its own thumbnails) also uses.
 */
.aeroidx-settings .aeroidx-designs__set--sitemap-scope {
	grid-template-columns: repeat(2, minmax(0, 1fr));
}

@media (min-width: 900px) {
	.aeroidx-settings .aeroidx-designs__set--sitemap-scope {
		grid-template-columns: repeat(4, minmax(0, 1fr));
	}
}

@media (max-width: 599px) {
	.aeroidx-settings .aeroidx-designs__set--sitemap-scope {
		grid-template-columns: 1fr;
	}
}

.aeroidx-settings .aeroidx-design {
	position: relative;
	display: flex;
}

/*
 * The real radio: focusable, in the tab order, and never painted.
 *
 * THE FULL VISUALLY-HIDDEN RECIPE AND NOT JUST `opacity: 0`, because wp-admin
 * styles `input[type=radio]` hard — its own size, border, background and a
 * ::before for the dot — and this control sits inside its stylesheet, not
 * beside it. Pinning the box to a clipped 1px with `appearance: none` leaves
 * core nothing to draw, rather than drawing something transparent and trusting
 * that no rule anywhere puts the paint back.
 *
 * top/left are set explicitly: absolute with neither leaves it at its static
 * position, which moves whenever the label's layout does.
 */
.aeroidx-settings .aeroidx-design__input {
	position: absolute;
	top: 0;
	left: 0;
	width: 1px;
	height: 1px;
	min-width: 0;
	min-height: 0;
	padding: 0;
	margin: 0;
	border: 0;
	background: none;
	box-shadow: none;
	appearance: none;
	-webkit-appearance: none;
	overflow: hidden;
	clip-path: inset(50%);
	opacity: 0;
	pointer-events: none;
}

.aeroidx-settings .aeroidx-design__input::before,
.aeroidx-settings .aeroidx-design__input::after {
	content: none;
}

.aeroidx-settings .aeroidx-design__label {
	display: flex;
	flex-direction: column;
	flex: 1;
	/*
	 * The thumbnail is INSET rather than bled to the card edge: the reference
	 * shows the card's white around the composition, which is what separates a
	 * preview from a header image. 14px against a ~330px card is the same
	 * proportion as the reference's p-4 against its wider one.
	 */
	padding: 14px;
	overflow: hidden;
	border: 1px solid var(--ax-border-soft);
	border-radius: var(--ax-radius-lg);
	background: var(--ax-card);
	cursor: pointer;
	transition: border-color 120ms ease, box-shadow 120ms ease;
}

.aeroidx-settings .aeroidx-design__label:hover {
	border-color: var(--ax-border);
}

/*
 * The checked ring is an inset box-shadow rather than a thicker border. A 1px
 * to 2px border swap reflows the card by a pixel on every selection change,
 * which reads as a twitch under the pointer.
 */
.aeroidx-settings .aeroidx-design__input:checked + .aeroidx-design__label {
	border-color: var(--ax-violet-500);
	box-shadow: inset 0 0 0 1px var(--ax-violet-500);
}

/*
 * Focus lands on the hidden input, so the ring has to be drawn on the label it
 * controls or the keyboard user gets no visible focus at all.
 */
.aeroidx-settings .aeroidx-design__input:focus-visible + .aeroidx-design__label {
	outline: 2px solid var(--ax-violet-500);
	outline-offset: 2px;
}

/* ── The thumbnail, and the badge that floats on it ─────────────────────── */

.aeroidx-settings .aeroidx-design__figure {
	position: relative;
	display: block;
	/*
	 * 432 x 300 is the collage canvas AeroIDX authors against (ThemeCollage.vue
	 * declares it as DESIGN_WIDTH/DESIGN_HEIGHT). Matching the ratio here means
	 * a capture fills the frame with nothing cropped, and the three cards keep
	 * one height whatever is inside them.
	 */
	aspect-ratio: 432 / 300;
	overflow: hidden;
	border-radius: var(--ax-radius-card);
	/*
	 * NO PADDING AND NO GRADIENT, and undoing those was the fix for a card that
	 * read as a box inside a box.
	 *
	 * The frame was designed when the picture was a cropped hero — a bare
	 * screenshot that needed a backdrop to sit on. The captured collage already
	 * IS a composition on its own backdrop, 432x300 of it, so framing it again
	 * drew a second border and a second inset around something that came with
	 * both. The reference card has the composition meeting the card's own
	 * padding and nothing between.
	 *
	 * The colour below is a placeholder for the moment before the file lands,
	 * not a surface the picture sits on.
	 */
	background: var(--ax-zebra);
}

/*
 * Fills the frame. `cover` crops nothing here because the frame's ratio IS the
 * capture's canvas; it is chosen over `contain` so that a capture which ever
 * arrives at a slightly different shape fills the card rather than opening
 * placeholder bars along two edges.
 *
 * No radius and no shadow of its own: the frame clips the corners, and a
 * picture that already contains its own depth does not need more.
 */
.aeroidx-settings .aeroidx-design__shot {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: center;
}

/*
 * What a card draws when it has no picture: the design's name on a brand wash.
 *
 * AGENCY BUNDLES ARE THE PERMANENT CASE, not an edge one. There is no fixed
 * composition to photograph because the bundle IS the design, so `preview_url`
 * is null for them by design and always will be. Before this, the figure was
 * skipped entirely and the card collapsed to roughly half the height of the
 * three beside it — a row that read as a rendering failure rather than as a
 * design without a photo. A built-in added upstream after this release lands
 * here too, for as long as its capture has not shipped.
 *
 * The frame above already supplies the ratio, the radius and the clipping, so
 * this only has to fill it and centre one line.
 */
.aeroidx-settings .aeroidx-design__placeholder {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 100%;
	height: 100%;
	padding: 0 16px;
	box-sizing: border-box;
	text-align: center;
	/*
	 * Matches the name below it in weight and tracking but not in size: this is
	 * standing in for a picture, so it reads as the subject of the frame rather
	 * than as a second title.
	 */
	font-size: 20px;
	font-weight: 700;
	letter-spacing: -0.01em;
	line-height: 1.2;
	color: var(--ax-ink);
	/*
	 * Diagonal, matching the agency card on the AeroIDX side. `to bottom right`
	 * rather than a degree value so it stays a diagonal at any card width.
	 */
	background: linear-gradient(
		to bottom right,
		var(--ax-violet-a15),
		var(--ax-violet-deep-a15),
		var(--ax-magenta-a15)
	);
	/* Long agency names wrap rather than overflow the frame they are centred in. */
	overflow-wrap: anywhere;
}

.aeroidx-settings .aeroidx-design__applied {
	display: inline-flex;
	align-items: center;
	gap: 4px;
	font-size: 11px;
	font-weight: 600;
	letter-spacing: 0.02em;
	padding: 3px 9px;
	border-radius: var(--ax-radius-pill);
	color: var(--ax-on-accent);
	background: linear-gradient(141deg, var(--ax-violet-500), var(--ax-violet-deep));
	white-space: nowrap;
}

/*
 * Floating on the picture, so it needs to survive whatever is underneath it.
 * The shadow is what separates it from a light sky or a white façade; without
 * one the pill disappears into roughly half the listing photos.
 */
.aeroidx-settings .aeroidx-design__applied--over {
	position: absolute;
	top: 12px;
	right: 12px;
	box-shadow: 0 1px 3px var(--ax-shadow-a12), 0 2px 8px var(--ax-shadow-a12);
}

/* ── The body: mark, name, description ──────────────────────────────────── */

.aeroidx-settings .aeroidx-design__body {
	display: flex;
	/*
	 * Centred against the title AND the description together. Aligned to the
	 * start instead, the circle pins itself to the title and the card looks
	 * top-heavy next to a two-line description, which is every card here.
	 */
	align-items: center;
	gap: 12px;
	padding: 14px 6px 6px;
}

/*
 * A choice card with no picture (the Settings screen's sitemap options). The
 * body's top padding exists to clear a figure; without one it only pushes the
 * text off centre.
 *
 * MARK AND TITLE ON ONE LINE, DESCRIPTION UNDER BOTH. The Designs card gives
 * the mark a column of its own, centred against the title and description
 * together, which suits a card with a picture above it. Four text-only cards
 * in a row are narrow, and that column took width from every line of the
 * description. Here the mark sits beside the title and the description starts
 * at the mark's edge, so it gets the card's full width.
 *
 * __text is dissolved with `display: contents` so the name and the description
 * become grid items of the body directly; the markup stays the same as the
 * Designs card's.
 */
.aeroidx-settings .aeroidx-design--compact .aeroidx-design__body {
	display: grid;
	grid-template-columns: auto 1fr;
	align-items: center;
	column-gap: 10px;
	row-gap: 6px;
	padding: 6px;
}

.aeroidx-settings .aeroidx-design--compact .aeroidx-design__text {
	display: contents;
}

.aeroidx-settings .aeroidx-design--compact .aeroidx-design__mark {
	margin-top: 0;
}

.aeroidx-settings .aeroidx-design--compact .aeroidx-design__name {
	grid-column: 2;
}

.aeroidx-settings .aeroidx-design--compact .aeroidx-design__desc {
	grid-column: 1 / -1;
}

/*
 * The chosen compact card is filled as well as ringed: with no picture to tell
 * three cards of text apart, the ring alone is a thin signal. A violet wash,
 * not --ax-selected, which is a neutral grey and reads as "disabled" on white.
 * Not on the Designs cards, whose white frame is what sets a preview apart
 * from its surroundings.
 */
.aeroidx-settings .aeroidx-design--compact .aeroidx-design__input:checked + .aeroidx-design__label {
	background: var(--ax-violet-a07);
}

.aeroidx-settings .aeroidx-design__mark {
	flex: none;
	width: 20px;
	height: 20px;
	margin-top: 1px;
	border: 1px solid var(--ax-border);
	border-radius: 50%;
	background: var(--ax-card);
	display: flex;
	align-items: center;
	justify-content: center;
	transition: background-color 120ms ease, border-color 120ms ease;
}

/*
 * The tick is drawn from a rotated corner rather than shipped as an SVG,
 * because it is one shape that only ever appears in one size and one colour.
 * It is present at all times and revealed by opacity, so the circle does not
 * change size when it appears.
 */
.aeroidx-settings .aeroidx-design__mark::after {
	content: "";
	width: 5px;
	height: 9px;
	margin-top: -2px;
	border: solid var(--ax-on-accent);
	border-width: 0 2px 2px 0;
	transform: rotate(45deg);
	opacity: 0;
	transition: opacity 120ms ease;
}

.aeroidx-settings .aeroidx-design__input:checked + .aeroidx-design__label .aeroidx-design__mark {
	border-color: var(--ax-violet-500);
	background: var(--ax-violet-500);
}

.aeroidx-settings .aeroidx-design__input:checked + .aeroidx-design__label .aeroidx-design__mark::after {
	opacity: 1;
}

.aeroidx-settings .aeroidx-design__text {
	display: flex;
	flex-direction: column;
	gap: 4px;
	min-width: 0;
}

.aeroidx-settings .aeroidx-design__head {
	display: flex;
	align-items: center;
	flex-wrap: wrap;
	gap: 8px;
}

.aeroidx-settings .aeroidx-design__name {
	font-weight: 700;
	font-size: 17px;
	letter-spacing: -0.01em;
	color: var(--ax-ink);
}

.aeroidx-settings .aeroidx-design__desc {
	font-size: 13px;
	line-height: 1.45;
	color: var(--ax-secondary);
}

/*
 * Where a design came from is a fact, not an action, so it stays quiet and
 * does not borrow the Applied badge's fill.
 */
/*
 * "BY YOUR AGENCY" — violet, not grey.
 *
 * Grey on grey was the neutral choice and the wrong one: this tag is the only
 * thing on the card that says where the design came from, and on a locked card
 * it is the only thing that is not dimmed into the background. It is the same
 * violet the app gives it, and the same violet the applied-theme block uses,
 * because both are saying "your agency" about the same account.
 */
.aeroidx-settings .aeroidx-design__tag {
	font-size: 11px;
	font-weight: 600;
	letter-spacing: 0.02em;
	text-transform: uppercase;
	padding: 2px 8px;
	border-radius: var(--ax-radius-pill);
	color: var(--ax-violet-700);
	background: var(--ax-violet-a12);
}

/* ── The action row ─────────────────────────────────────────────────────── */

.aeroidx-settings .aeroidx-designs__actions {
	display: flex;
	align-items: center;
	flex-wrap: wrap;
	gap: 12px;
	margin: 16px 0 0;
}

.aeroidx-settings .aeroidx-designs__unavailable {
	font-size: 13px;
	color: var(--ax-muted);
}

/*
 * The applied-design sentence sits beside the button and answers the question
 * the reader standing at a disabled Apply is actually asking: which design is
 * live, and therefore why is there nothing to press.
 */
.aeroidx-settings .aeroidx-designs__current {
	font-size: 13px;
	color: var(--ax-secondary);
}

.aeroidx-settings .aeroidx-designs__current strong {
	font-weight: 600;
	color: var(--ax-ink);
}


.aeroidx-settings .aeroidx-designs__unavailable {
	margin: 16px 0 0;
}

/*
 * "This list may be out of date", above the cards it is about.
 *
 * LOUDER THAN __unavailable, WHICH READS AS BACKWARDS UNTIL YOU SEE WHY. That
 * one replaces the whole picker, so the empty space carries the message and the
 * text only has to name it. This one sits above six perfectly normal-looking
 * cards, one of which is wearing an Applied badge that may be a lie. Muted grey
 * beside them would be read as a footnote and skipped, which leaves the reader
 * trusting the badge — the exact outcome the line exists to prevent.
 */
.aeroidx-settings .aeroidx-designs__stale {
	margin: 16px 0 0;
	padding: 10px 12px;
	border-left: 2px solid var(--ax-warning-edge);
	border-radius: 0 var(--ax-radius-sm) var(--ax-radius-sm) 0;
	background: var(--ax-warning-wash);
	font-size: 13px;
	line-height: 1.5;
	color: var(--ax-warning-ink);
}

/*
 * The notice is rendered inside the card, so it needs the margins core gives
 * it at the top of an admin page and does not otherwise get here.
 */
/* Inside the card now, between the intro and the grid, so it needs air on
 * both sides rather than only above. */
.aeroidx-settings .aeroidx-designs__notice {
	margin: 16px 0;
}

/*
 * A DISABLED PRIMARY BUTTON THAT STILL LOOKS ENABLED.
 *
 * `.button.button-primary` paints a violet gradient, and a gradient is a
 * background-image: wp-admin's disabled rule sets background-color and loses.
 * So Apply sat there in full brand violet while being inert, which is the one
 * state a button must never be in. Muted here, on the plugin's own class, so
 * nothing else in the admin changes.
 */
.aeroidx-settings .button.aeroidx-designs__apply[disabled],
.aeroidx-settings .button.aeroidx-designs__apply:disabled {
	opacity: 0.5;
	box-shadow: none;
	filter: none;
	cursor: not-allowed;
}

/* ─────────────────────────────────────────────────────────────────────────
 * THE CSS SELECTOR REFERENCE, FOLDED
 *
 * A <details> wearing the card's own skin, so opening it does not look like
 * a different kind of surface arriving. See SettingsPage::renderThemePanel()
 * for why documentation is folded and the picker above it is not.
 * ───────────────────────────────────────────────────────────────────────── */

.aeroidx-settings .aeroidx-hooks-disclosure {
	/*
	 * The card's padding belongs to the summary and the body separately, or a
	 * closed disclosure carries the full padding of an open one and reads as a
	 * strangely tall empty box.
	 */
	padding: 0;
	overflow: hidden;
}

.aeroidx-settings .aeroidx-hooks-disclosure__summary {
	display: flex;
	flex-wrap: wrap;
	/*
	 * CENTRED, not baseline-aligned. Three things share this row and only two
	 * of them are text; a baseline is something the chevron does not have, so
	 * aligning on one left it hanging below the title it belongs to. Centring
	 * also reads better for a large title beside a small hint.
	 */
	align-items: center;
	gap: 4px 12px;
	padding: 18px 20px;
	cursor: pointer;
	/*
	 * The default triangle is replaced by nothing: `list-style: none` here and
	 * the ::-webkit-details-marker rule below cover both engines, and the row
	 * gets its own marker so the affordance is not a 7px glyph in the corner.
	 */
	list-style: none;
	border-radius: var(--ax-radius-card);
}

.aeroidx-settings .aeroidx-hooks-disclosure__summary::-webkit-details-marker {
	display: none;
}

.aeroidx-settings .aeroidx-hooks-disclosure__summary:hover {
	background: var(--ax-zebra);
}

.aeroidx-settings .aeroidx-hooks-disclosure__summary:focus-visible {
	outline: 2px solid var(--ax-violet-500);
	outline-offset: -2px;
}

/*
 * `display: flex` on the wrapper is what centres the glyph: an inline <svg>
 * sits on the text baseline by default and would hang low next to the title,
 * which is the same misalignment the rotated border box had by another route.
 *
 * margin-left: auto pushes it to the far edge. See renderThemePanel() for why
 * it trails the row: leading it indented this heading past every other card's.
 */
.aeroidx-settings .aeroidx-hooks-disclosure__mark {
	display: flex;
	align-items: center;
	justify-content: center;
	flex: none;
	margin-left: auto;
	color: var(--ax-muted);
	transition: transform 140ms var(--ax-ease), color 140ms var(--ax-ease);
}

/*
 * .aeroidx-field__title is a card <h2>'s class and carries `margin: 0 0 6px`
 * for the paragraph that normally follows it. Nothing follows it here, and in
 * a centred flex row that bottom margin pushes the text up off centre and
 * makes the row taller than its contents. Reset where it is borrowed.
 */
.aeroidx-settings .aeroidx-hooks-disclosure__summary .aeroidx-field__title {
	margin: 0;
}

.aeroidx-settings .aeroidx-hooks-disclosure[open] .aeroidx-hooks-disclosure__mark {
	transform: rotate(90deg);
}

.aeroidx-settings .aeroidx-hooks-disclosure__summary:hover .aeroidx-hooks-disclosure__mark {
	color: var(--ax-ink);
}

.aeroidx-settings .aeroidx-hooks-disclosure__hint {
	font-size: 13px;
	color: var(--ax-muted);
}

/*
 * Everything after the summary carries the padding the card would have had.
 * Scoped to direct children so the table's own rules are untouched.
 */
.aeroidx-settings .aeroidx-hooks-disclosure > *:not(.aeroidx-hooks-disclosure__summary) {
	margin-inline: 20px;
}

.aeroidx-settings .aeroidx-hooks-disclosure > *:last-child {
	margin-bottom: 20px;
}

/* --- Sitemap listing filters panel -------------------------------------- */
/*
 * Inside the Sitemap card, shown only under the "Selected areas" choice card.
 * Every field here is a plain .aeroidx-field__input that already posts a
 * value SitemapFilters::sanitize() understands on its own — the combo boxes
 * below are JS drawn OVER that same input (assets/js/admin.js), never a
 * replacement for it, which is why nothing here assumes JavaScript ran.
 */
.aeroidx-sitemap-filters {
	display: flex;
	flex-direction: column;
	gap: 12px;
	margin-top: 20px;
	padding-top: 20px;
	border-top: 1px solid var(--ax-border-soft);
}

/*
 * admin.js ties the panel's `hidden` attribute to the "Selected areas" radio.
 * Setting `display: flex` above is an author rule and beats the UA
 * stylesheet's `[hidden] { display: none }` on origin alone, regardless of
 * source order — so without this, toggling `.hidden` in JS would do nothing
 * and the panel would stay visible under every scope. See
 * .aeroidx-field__error[hidden] for the same pattern elsewhere in this file.
 */
.aeroidx-sitemap-filters[hidden] {
	display: none;
}

/*
 * The empty-areas hint ("Choose at least one area, or the whole MLS is
 * published"). Violet, not amber: choosing "Selected areas" and saving
 * before picking one is not a mistake, just an in-progress state — the same
 * "nothing failed" register .aeroidx-designs__live uses, scaled down to one
 * line rather than a full banner.
 */
.aeroidx-sitemap-filters__hint {
	color: var(--ax-violet-700);
}

.aeroidx-sitemap-filters__subheading {
	margin: 4px 0 0;
	font-size: 13px;
	font-weight: 600;
	color: var(--ax-ink);
}

.aeroidx-sitemap-filters__grid {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
	gap: 16px;
}

.aeroidx-sitemap-filters__label {
	font-size: 13px;
	font-weight: 600;
	color: var(--ax-ink);
}

/*
 * ONE BOX, NOT TWO. The combo sits where the plain-text input was; admin.js
 * hides that input (never removes it — it is still what posts) the moment it
 * draws this over it. `position: relative` anchors the suggestions dropdown
 * below it (see __options). Without JS this stays `hidden` and the input is
 * what the admin edits directly, comma-separated — see the [hidden] rule
 * below for why that requires its own override.
 */
.aeroidx-sitemap-filters__combo {
	position: relative;
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 6px;
	box-sizing: border-box;
	/*
	 * Same box as .aeroidx-field__input: 14px text at line-height 1.4, 9px of
	 * vertical padding and a 1px border give that field its height. The
	 * vertical padding here is smaller because the search input below carries
	 * the difference, so an empty combo lines up with the ZIP and price fields
	 * beside it.
	 */
	min-height: calc(14px * 1.4 + 20px);
	padding: 5px 12px;
	background: var(--ax-input);
	border: 1px solid var(--ax-border);
	border-radius: var(--ax-radius-input);
	transition: border-color 150ms var(--ax-ease),
		box-shadow 150ms var(--ax-ease), background 150ms var(--ax-ease);
}

/* The focus treatment of .aeroidx-field__input, on the box instead of the input. */
.aeroidx-sitemap-filters__combo:focus-within {
	background: var(--ax-input-focus);
	border-color: var(--ax-violet-500);
	box-shadow: 0 0 0 1px var(--ax-violet-500);
	outline: 2px solid transparent; /* preserved for forced-colors mode */
}

/*
 * The chips wrap inline with the search input (below), inside the combo's
 * own flex row — no border or background of its own, or the "one box" the
 * combo above provides would read as two again.
 */
.aeroidx-sitemap-filters__chips {
	display: contents;
}

/*
 * Setting `display` above is an author rule, which beats the UA stylesheet's
 * `[hidden] { display: none }` regardless of source order (origin, not
 * specificity, decides that contest) — so this needs its OWN [hidden] rule,
 * the same defensive pattern .aeroidx-field__error[hidden] already uses.
 * Without it, the server-rendered `hidden` attribute this ships with before
 * admin.js runs would be silently ignored and the combo would show even with
 * JavaScript disabled.
 */
.aeroidx-sitemap-filters__combo[hidden] {
	display: none;
}

.aeroidx-chip {
	display: inline-flex;
	align-items: center;
	gap: 4px;
	padding: 4px 6px 4px 10px;
	background: var(--ax-card);
	border: 1px solid var(--ax-border-soft);
	border-radius: var(--ax-radius-pill);
	font-size: 12px;
	line-height: 1.4;
	color: var(--ax-ink);
}

.aeroidx-chip__label {
	max-width: 220px;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.aeroidx-chip__remove {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 18px;
	height: 18px;
	padding: 0;
	background: transparent;
	border: 0;
	border-radius: var(--ax-radius-full);
	color: var(--ax-secondary);
	font-size: 14px;
	line-height: 1;
	cursor: pointer;
}

.aeroidx-chip__remove:hover {
	background: var(--ax-border-soft);
	color: var(--ax-ink);
}

.aeroidx-chip__remove:focus-visible {
	outline: 2px solid var(--ax-violet-500);
	outline-offset: 1px;
}

/*
 * A saved chip whose value has 0 matches (or has vanished entirely) in the
 * fetched values, per the design's zero-match decision — the same warning
 * treatment .aeroidx-conn--warning uses, applied to one chip rather than a
 * whole banner.
 */
.aeroidx-chip.is-zero-match {
	background: var(--ax-warning-wash);
	border-color: var(--ax-warning-edge);
	color: var(--ax-warning-ink);
}

/*
 * The search cursor itself: no border or background of its own — it reads as
 * the combo's own text cursor, not a second field — and grows to fill
 * whatever room the chips have left.
 *
 * THE SELECTOR IS LONG ON PURPOSE. wp-admin styles `input[type=text]` with a
 * border, a white background, a min-height and a blue focus shadow, and that
 * selector outranks a single class. Losing to it drew a white box inside the
 * grey one, which read as two fields.
 */
.aeroidx-settings .aeroidx-sitemap-filters__combo input.aeroidx-sitemap-filters__search-input,
.aeroidx-settings .aeroidx-sitemap-filters__combo input.aeroidx-sitemap-filters__search-input:focus {
	flex: 1 1 80px;
	min-width: 80px;
	min-height: 0;
	height: auto;
	margin: 0;
	padding: 4px 0;
	background: transparent;
	border: 0;
	border-radius: 0;
	box-shadow: none;
	outline: 0;
	font-size: 14px;
	line-height: 1.4;
	color: var(--ax-ink);
}

.aeroidx-settings .aeroidx-sitemap-filters__combo input.aeroidx-sitemap-filters__search-input::placeholder {
	color: var(--ax-muted-on-fill);
	opacity: 1;
}

/*
 * The suggestions dropdown. COLLAPSED BY DEFAULT (the `hidden` attribute
 * admin.js toggles on focus/typing, one field at a time — see
 * buildChipField()'s openOptions()/closeOptions()) and positioned as a
 * floating overlay OUTSIDE the combo's own box model: `position: absolute`
 * off the combo (not the page's normal flow) means it can never be clipped
 * by the card, which has no overflow:hidden of its own, and never pushes a
 * sibling field down the grid while open. `z-index` is set well above the
 * grid's own stacking so it draws over a sibling field's combo rather than
 * being tucked behind it, and `max-height` plus its own scrollbar keeps a
 * long list from growing past a sane height on the page.
 */
.aeroidx-sitemap-filters__options {
	position: absolute;
	z-index: 20;
	inset-inline: 0;
	top: 100%;
	margin: 4px 0 0;
	padding: 4px;
	list-style: none;
	max-height: 240px;
	overflow-y: auto;
	background: var(--ax-card);
	border: 1px solid var(--ax-border);
	border-radius: var(--ax-radius-input);
	box-shadow: 0 1px 3px var(--ax-shadow-a12), 0 2px 8px var(--ax-shadow-a12);
}

.aeroidx-sitemap-filters__options[hidden] {
	display: none;
}

.aeroidx-sitemap-filters__options:empty {
	display: none;
}

.aeroidx-sitemap-filters__option {
	display: block;
	width: 100%;
	padding: 8px 10px;
	background: transparent;
	border: 0;
	border-radius: var(--ax-radius-xs);
	text-align: left;
	font-size: 13px;
	color: var(--ax-ink);
	cursor: pointer;
}

.aeroidx-sitemap-filters__option:hover,
.aeroidx-sitemap-filters__option:focus-visible {
	background: var(--ax-violet-a07);
}

.aeroidx-sitemap-filters__option:focus-visible {
	outline: 2px solid var(--ax-violet-500);
	outline-offset: -2px;
}

.aeroidx-settings .aeroidx-sitemap-filters__field .aeroidx-field__input:disabled {
	background: var(--ax-locked);
	color: var(--ax-muted);
	cursor: not-allowed;
}

/*
 * The min/max price "money" inputs (SettingsPage::renderSitemapFilters(),
 * mockup https://claude.ai/artifact/Ezu2h6wQxpVke4u5EKjtkM's `.money`
 * fields): a `$` glyph anchored inside a plain `type="text"` input, same
 * positioning technique as .aeroidx-sitemap-filters__search-icon above.
 */
.aeroidx-sitemap-filters__price {
	position: relative;
}

.aeroidx-sitemap-filters__price-prefix {
	position: absolute;
	left: 12px;
	top: 50%;
	transform: translateY(-50%);
	color: var(--ax-muted-on-fill);
	pointer-events: none;
}

/*
 * Room for the "$" glyph above, and tabular numerals so the digits don't
 * jitter in width as they're typed and reformatted. Same specificity
 * tie-break as .aeroidx-sitemap-filters__location-input's own padding rule
 * just below (`.aeroidx-settings` plus one class beats the bare
 * .aeroidx-field__input rule on source order).
 */
.aeroidx-settings .aeroidx-sitemap-filters__price-input {
	padding-left: 24px;
	font-variant-numeric: tabular-nums;
}

/* --- Location combobox (county/city/ZIP, one search bar) ---------------- */
/*
 * See sdd/sitemap-listing-filters/design-or: the backend now expresses a
 * county/city + ZIP mix as a real OR, so the three separate v1 fields become
 * one search bar with chips below it — SettingsPage::renderLocationField()
 * on the server, buildLocationBar() in admin.js on the client. Spans the
 * full width of the primary grid row rather than sitting in one ~220px
 * column: a search bar and a wrapping chip list both want the room.
 */
.aeroidx-sitemap-filters__field--location {
	grid-column: 1 / -1;
}

/*
 * The no-JS fallback: three plain fields, stacked. admin.js hides this the
 * moment it draws the combo below over it — see .aeroidx-sitemap-filters__
 * location-combo[hidden] just below for why an element with its own
 * `display` rule needs its own `[hidden]` override too.
 */
.aeroidx-sitemap-filters__location-plain {
	display: flex;
	flex-direction: column;
	gap: 16px;
}

.aeroidx-sitemap-filters__location-plain[hidden] {
	display: none;
}

.aeroidx-sitemap-filters__location-combo {
	display: flex;
	flex-direction: column;
	gap: 10px;
}

.aeroidx-sitemap-filters__location-combo[hidden] {
	display: none;
}

/*
 * Anchors the suggestions listbox (position: absolute, below). The search
 * input itself is a plain .aeroidx-field__input — reusing that class, rather
 * than inventing a second highly-specific override, is what already beats
 * wp-admin's `input[type=text]` rule on this screen (see
 * .aeroidx-settings .aeroidx-field__input above).
 */
.aeroidx-sitemap-filters__search {
	position: relative;
}

/*
 * The magnifier icon inside the location search input — decorative only
 * (aria-hidden; the input's own placeholder and aria-label already say what
 * it's for), positioned the same way as the approved mockup's `.search svg`.
 */
.aeroidx-sitemap-filters__search-icon {
	position: absolute;
	left: 12px;
	top: 50%;
	transform: translateY(-50%);
	width: 16px;
	height: 16px;
	color: var(--ax-muted-on-fill);
	pointer-events: none;
}

/*
 * Room for the icon above. SAME SPECIFICITY as .aeroidx-field__input's own
 * padding rule (`.aeroidx-settings` plus one class — see that rule higher up
 * this file): this wins on source order alone, the same tie-break already
 * used throughout this section (e.g. .aeroidx-sitemap-filters__chips--location
 * over the base .aeroidx-sitemap-filters__chips).
 */
.aeroidx-settings .aeroidx-sitemap-filters__location-input {
	padding-left: 36px;
}

/*
 * The grouped suggestions dropdown. Same floating-overlay treatment as
 * .aeroidx-sitemap-filters__options (positioned OUTSIDE the field's own box
 * model so it is never clipped by the card and never pushes anything down),
 * with its own `[hidden]` rule for the same reason given there: an author
 * rule touching this selector would otherwise beat the UA stylesheet's
 * `[hidden] { display: none }` on origin alone.
 */
.aeroidx-sitemap-filters__listbox {
	position: absolute;
	z-index: 20;
	inset-inline: 0;
	top: calc(100% + 4px);
	margin: 0;
	padding: 4px;
	list-style: none;
	max-height: 280px;
	overflow-y: auto;
	background: var(--ax-card);
	border: 1px solid var(--ax-border);
	border-radius: var(--ax-radius-input);
	box-shadow: 0 1px 3px var(--ax-shadow-a12), 0 2px 8px var(--ax-shadow-a12);
}

.aeroidx-sitemap-filters__listbox[hidden] {
	display: none;
}

.aeroidx-sitemap-filters__listbox:empty {
	display: none;
}

.aeroidx-sitemap-filters__listbox-heading {
	padding: 8px 10px 4px;
	font-size: 11.5px;
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: 0.02em;
	color: var(--ax-muted-on-fill);
}

.aeroidx-sitemap-filters__listbox-group {
	list-style: none;
	margin: 0;
	padding: 0;
}

.aeroidx-sitemap-filters__listbox-option {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 12px;
	padding: 8px 10px;
	border-radius: var(--ax-radius-xs);
	font-size: 13px;
	color: var(--ax-ink);
	cursor: pointer;
}

.aeroidx-sitemap-filters__listbox-option:hover,
.aeroidx-sitemap-filters__listbox-option.is-active {
	background: var(--ax-violet-a07);
}

.aeroidx-sitemap-filters__listbox-option.is-active {
	box-shadow: inset 0 0 0 1px var(--ax-violet-a38);
}

.aeroidx-sitemap-filters__listbox-meta {
	flex: none;
	color: var(--ax-muted-on-fill);
	font-size: 12px;
	font-variant-numeric: tabular-nums;
}

.aeroidx-sitemap-filters__listbox-empty {
	padding: 8px 10px;
	color: var(--ax-muted-on-fill);
	font-size: 13px;
}

/*
 * Chips BELOW the search bar, not inline inside it (decisions-ui / the
 * approved mockup). The base .aeroidx-sitemap-filters__chips rule sets
 * `display: contents` for the OTHER combo shape, where chips flow inside the
 * same box as the search cursor — this modifier overrides it back to a
 * normal wrapping row, and wins on source order (both are single-class
 * selectors, and this rule is declared later in the file).
 */
.aeroidx-sitemap-filters__chips--location {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
	margin: 0;
	padding: 0;
	list-style: none;
}

/*
 * A touch taller than the shared .aeroidx-chip, which is sized for the
 * dense chip fields elsewhere in this panel. This one carries three things
 * (kind, name, count) plus a remove button and sits alone under a 40px
 * search box, so it was reading as cramped next to it. Padding only — the
 * base class keeps owning the colours, border and radius.
 */
.aeroidx-sitemap-filters__location-chip {
	padding: 7px 8px 7px 8px;
	font-size: 13px;
}

.aeroidx-sitemap-filters__location-chip-type {
	padding: 4px 9px;
	border-radius: var(--ax-radius-pill);
	background: var(--ax-violet-a07);
	color: var(--ax-violet-700);
	font-size: 11px;
	font-weight: 600;
	line-height: 1.4;
}

/*
 * The chip's listing count — server pre-rendered when the filter-values
 * transient is warm (SettingsPage::cachedChipCount()), filled in by
 * admin.js otherwise. Same treatment as the approved mockup's `.chip .n`.
 * Omitted entirely, chip and all, when the count is unknown — see
 * renderLocationChip()'s docblock — so there is nothing to style for that
 * case.
 */
.aeroidx-sitemap-filters__location-chip-count {
	color: var(--ax-muted-on-fill);
	font-size: 11px;
	font-variant-numeric: tabular-nums;
}

/*
 * The row under the chips: the estimate on the left, "Clear all" on the
 * right, matching the approved mockup's `.under`.
 */
.aeroidx-sitemap-filters__location-under {
	display: flex;
	flex-wrap: wrap;
	justify-content: space-between;
	align-items: baseline;
	gap: 4px 16px;
}

/* "Clear all", a text link rather than a bordered button — a low-stakes,
 * reversible action (every chip is still one click to re-add) next to a
 * list it only ever empties. */
.aeroidx-sitemap-filters__clear {
	display: inline-flex;
	align-self: flex-start;
	border: 0;
	background: none;
	padding: 0;
	font: inherit;
	font-size: 12px;
	font-weight: 500;
	color: var(--ax-violet-700);
	cursor: pointer;
	text-decoration: underline;
	text-underline-offset: 2px;
}

.aeroidx-sitemap-filters__clear:hover {
	color: var(--ax-violet-700);
}

.aeroidx-sitemap-filters__clear:focus-visible {
	outline: 2px solid var(--ax-violet-500);
	outline-offset: 2px;
	border-radius: var(--ax-radius-xs);
}

.aeroidx-sitemap-filters__clear[hidden] {
	display: none;
}

/* --- Sale type / Property type checkbox groups --------------------------- */
/*
 * See sdd/sitemap-listing-filters/design-pt: the old free-text property_type
 * field becomes a checkbox card grid over the account's resolved catalog
 * (SettingsPage::renderPropertyTypeField()), and a new Sale type field gets
 * two plain checkboxes (renderListingTypeField()) — both matching the
 * approved mockup's `.checks`/`.check` treatment.
 */
.aeroidx-sitemap-filters__field--types,
.aeroidx-sitemap-filters__field--listing-type {
	grid-column: 1 / -1;
}

.aeroidx-sitemap-filters__toolbar {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 6px 12px;
}

.aeroidx-sitemap-filters__toolbar .aeroidx-sitemap-filters__label {
	margin-right: auto;
}

.aeroidx-sitemap-filters__summary {
	font-size: 12px;
	color: var(--ax-muted-on-fill);
	font-variant-numeric: tabular-nums;
}

/*
 * THREE COLUMNS, NOT AS MANY AS FIT. auto-fill gave five on a wide screen,
 * and with the card gone each count ended up at its own column edge, an
 * arm's length from the name it belongs to — it read as a table of numbers
 * rather than as one option per row. Three keeps a name and its count close
 * enough to be read as one thing, and eight types still fit in three short
 * rows. Two below the wp-admin 1200px breakpoint, one on a phone.
 */
.aeroidx-sitemap-filters__checks {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: 10px 24px;
	margin: 8px 0 0;
}

@media screen and (max-width: 1200px) {
	.aeroidx-sitemap-filters__checks {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}

@media screen and (max-width: 782px) {
	.aeroidx-sitemap-filters__checks {
		grid-template-columns: 1fr;
	}
}

/*
 * "Sale type" is two boxes only, so it uses the intrinsic-width layout
 * (matching the mockup's `.checks.two`) rather than the auto-fill grid a
 * whole catalog needs.
 */
.aeroidx-sitemap-filters__checks--two {
	grid-template-columns: repeat(2, max-content);
	gap: 10px 28px;
}

/*
 * One checkbox card. Built on the SAME `.aeroidx-field__*` tokens as the
 * rest of this panel (the input box, the border, the radius) rather than
 * inventing a second visual language for one field.
 */
/*
 * NO CARD AROUND THE CHECK. This was a bordered, filled card; Edwin took
 * the fill off and then the border too (2026-09-22), which lands where the
 * approved mockup had it all along: a checkbox, a name and a count, with the
 * grid's own gap doing the separating. Checked state reads from the box
 * itself, so the row needs no outline of its own — and the flagged states
 * below moved to label colour for the same reason.
 */
.aeroidx-sitemap-filters__check {
	display: flex;
	align-items: center;
	gap: 8px;
	min-width: 0;
	padding: 4px 0;
	background: transparent;
	border: 0;
	font-size: 13px;
	color: var(--ax-ink);
	cursor: pointer;
}

/*
 * NO FILL, BORDER ONLY. These cards sit in a grid of eight-plus, and eight
 * violet washes side by side turned the panel into a block of color with
 * nothing to look at — Edwin asked for the fill to go on 2026-09-22. The
 * checked state now reads from the border and the mark alone, which is also
 * what keeps the two flagged states below legible without a wash of their
 * own.
 */


.aeroidx-sitemap-filters__check:has(input:focus-visible) {
	outline: 2px solid var(--ax-violet-500);
	outline-offset: 2px;
}

/*
 * The checkbox itself, repainted in the plugin's violet. Attribute selector
 * for the same reason `.aeroidx-modal__choice input[type="radio"]` uses one
 * (see that rule's docblock): `.aeroidx-sitemap-filters__check input` and
 * core's `input[type=checkbox]` both score (0,1,1) and the winner would be
 * decided by enqueue order alone; adding [type="checkbox"] takes this
 * selector to (0,2,1) and settles it on specificity instead.
 */
.aeroidx-sitemap-filters__check input[type="checkbox"] {
	flex: none;
	width: 18px;
	height: 18px;
	margin: 0;
	padding: 0;
	-webkit-appearance: none;
	appearance: none;
	background: var(--ax-card);
	border: 1px solid var(--ax-border);
	border-radius: var(--ax-radius-xs);
	box-shadow: none;
	cursor: pointer;
	transition: background 150ms var(--ax-ease), border-color 150ms var(--ax-ease);
}

/*
 * The tick, drawn rather than typed: core paints its own ✓ through
 * `input[type=checkbox]:checked::before` with a dashicons-ish content string
 * and its own color, so `appearance: none` alone leaves a stray blue glyph
 * behind. Overriding ::before with a rotated border box replaces it outright
 * and keeps the mark in our own violet.
 */
.aeroidx-sitemap-filters__check input[type="checkbox"]:checked {
	background: var(--ax-violet-700);
	border-color: var(--ax-violet-700);
}

.aeroidx-sitemap-filters__check input[type="checkbox"]::before {
	content: "";
	display: block;
	width: 5px;
	height: 9px;
	margin: 1px 0 0 5px;
	border: solid var(--ax-on-accent);
	border-width: 0 2px 2px 0;
	transform: rotate(45deg);
	opacity: 0;
	transition: opacity 150ms var(--ax-ease);
}

.aeroidx-sitemap-filters__check input[type="checkbox"]:checked::before {
	opacity: 1;
}

/*
 * break-word, not anywhere: "Manufactured Home" was being split mid-word
 * ("ManufacturedHo / me") when the column got tight. This breaks at the
 * space first and only inside a word when a single word genuinely cannot
 * fit.
 */
.aeroidx-sitemap-filters__check-label {
	overflow-wrap: break-word;
}

/*
 * The count sits right after the name it counts, not pushed to the far edge
 * by `margin-left: auto` — once the card border went, that gap left every
 * number floating between two options with nothing saying which one it
 * belonged to.
 */
.aeroidx-sitemap-filters__check-count {
	flex: none;
	color: var(--ax-muted-on-fill);
	font-size: 12px;
	font-variant-numeric: tabular-nums;
}

/*
 * A saved id no longer offered by the account's catalog (D4/D9): flagged,
 * never silently dropped, and kept checked until the owner unchecks it
 * themselves. The same warning register as .aeroidx-chip.is-zero-match,
 * applied to a checkbox card instead of a chip.
 */
.aeroidx-sitemap-filters__check--stale .aeroidx-sitemap-filters__check-label {
	color: var(--ax-warning-ink);
}

.aeroidx-sitemap-filters__check-count--warning {
	color: var(--ax-warning-ink);
}

/*
 * Zero-count styling reused from the chip fields (admin.js applies the same
 * `.is-zero-match` class here) — same warning treatment as
 * .aeroidx-chip.is-zero-match, on a checkbox card instead of a chip.
 *
 * COLOR, NOT JUST BACKGROUND. .aeroidx-chip.is-zero-match also sets `color`
 * (see that rule above), which is what actually reads as "this one is
 * different" — background/border alone left the label the same dark
 * .aeroidx-sitemap-filters__check-label ink as every other card, so a
 * zero-match card that happened to be checked (the "all selected" default —
 * see renderPropertyTypeField()) looked identical to the rest at a glance.
 * `--ax-muted-on-fill` rather than the chip's `--ax-warning-ink`: this is a
 * checkbox grid an owner scans quickly for what's checked, not a single
 * standalone banner, so a quieter "this one doesn't matter" reads better
 * than a louder warning color that competes with the violet checked wash.
 * No layout change — color and background-only, same box model as every
 * other .aeroidx-sitemap-filters__check card.
 */
.aeroidx-sitemap-filters__check.is-zero-match {
	color: var(--ax-muted-on-fill);
}

.aeroidx-sitemap-filters__check.is-zero-match .aeroidx-sitemap-filters__check-label {
	color: var(--ax-muted-on-fill);
}

/* ── Listing details: "Your own content" ─────────────────────────────────── */

/* The Page tab's fields stack with the same rhythm as the siblings above. */
.aeroidx-extra {
	margin-top: 4px;
}

.aeroidx-extra__intro {
	margin: 0 0 12px;
}

.aeroidx-extra__field {
	margin: 0 0 16px;
}

/* Help on the left, "Edit in Elementor ↗" on the right of the same line. */
.aeroidx-extra__help {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	justify-content: space-between;
	gap: 4px 16px;
}

.aeroidx-settings .aeroidx-extra__edit {
	flex: none;
	display: inline-flex;
	align-items: center;
	gap: 4px;
	font-weight: 600;
	color: var(--ax-violet-700);
	text-decoration: none;
}

.aeroidx-settings .aeroidx-extra__edit:hover {
	text-decoration: underline;
}

.aeroidx-extra__edit[hidden],
.aeroidx-extra__warning[hidden] {
	display: none;
}

/* The same amber as the sheet's unsaved-changes chip, as a block: a saved page
 * that is gone is something to act on, not a hint. */
.aeroidx-extra__warning {
	margin-top: 8px;
	padding: 8px 10px;
	border: 1px solid var(--ax-warning-edge);
	border-radius: var(--ax-radius-input);
	background: var(--ax-warning-wash);
	color: var(--ax-warning-ink);
}

/* ── Details / Agent sheet: the page address on top of Search & sharing ──── */

.aeroidx-seo-sheet__address {
	display: block;
	margin: 0 0 24px;
	padding: 0 0 24px;
	border-bottom: 1px solid var(--ax-hairline);
}

.aeroidx-page-config__label.aeroidx-address__label {
	margin-bottom: 8px;
	font-size: 15px;
}

/* An address, not code: the site and the example read in the body face,
 * which also keeps the row on one line beside the input. */
.aeroidx-seo-sheet .aeroidx-address .aeroidx-page-config__permalink--pattern {
	font-family: var(--ax-font-body);
}

/* A long domain must not push the example onto its own line: it keeps the
 * row and trims its tail ("/123-main-st-spri…"). */
.aeroidx-seo-sheet .aeroidx-address .aeroidx-page-config__permalink--pattern {
	flex-wrap: nowrap;
}

.aeroidx-seo-sheet .aeroidx-address .aeroidx-page-config__permalink--pattern .aeroidx-page-config__permalink-base {
	flex: none;
}

.aeroidx-seo-sheet .aeroidx-address .aeroidx-page-config__permalink--pattern .aeroidx-page-config__permalink-suffix {
	display: block; /* text-overflow does nothing on a flex container */
	flex: 1 1 0;
	min-width: 0;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.aeroidx-address .aeroidx-page-config__permalink-base,
.aeroidx-address .aeroidx-page-config__permalink-suffix {
	font-family: var(--ax-font-body);
	font-size: 14px;
	color: var(--ax-muted-on-fill);
}

/* Every page moves when this word changes: said once it does. */
.aeroidx-address__notice {
	margin: 10px 0 0;
	padding: 10px 12px;
	border: 1px solid var(--ax-violet-a10);
	border-radius: var(--ax-radius-sm);
	background: var(--ax-violet-wash);
	color: var(--ax-violet-700);
	font-size: 13px;
	line-height: 1.45;
}

.aeroidx-address__notice[hidden] {
	display: none;
}

/* ── Page Layout tab: sections ─────────────────────────────────────────────── */

.aeroidx-layout__section {
	grid-column: 1 / -1;
	margin: 0;
	padding: 0 0 20px;
	border-bottom: 1px solid var(--ax-hairline);
}

/* The section above already draws the rule. */
.aeroidx-layout__section + .aeroidx-page-config__more {
	border-top: 0;
}

.aeroidx-layout__heading {
	margin: 0 0 12px;
	font-size: 16px;
	font-weight: 600;
	color: var(--ax-ink);
}

/* ── Details sheet: Page Layout tab ───────────────────────────────────────── */

/* The section heading reads as one: bigger than the field labels under it,
 * which used to share its exact size and weight. */
.aeroidx-extra__legend {
	float: left;
	width: 100%;
	margin: 0 0 4px;
	padding: 0;
	font-size: 16px;
	font-weight: 600;
	color: var(--ax-ink);
}

.aeroidx-extra .aeroidx-extra__intro {
	clear: both;
	margin: 0 0 24px;
	font-size: 14px;
	color: var(--ax-ink);
}

.aeroidx-extra__field {
	margin: 0 0 28px;
}

.aeroidx-page-config__label.aeroidx-extra__label {
	margin-bottom: 8px;
	font-size: 15px;
}

/* The element to paste, whole and copyable: it used to wrap mid-tag. */
.aeroidx-extra__code {
	display: flex;
	align-items: center;
	gap: 8px;
	margin-top: 8px;
	padding: 6px 6px 6px 12px;
	border: 1px solid var(--ax-border);
	border-radius: var(--ax-radius-sm);
	background: var(--ax-fill-zebra);
}

.aeroidx-extra__code code {
	flex: 1;
	min-width: 0;
	padding: 0;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
	background: transparent;
	font-size: 13px;
	color: var(--ax-ink);
	user-select: all;
}

.aeroidx-settings .aeroidx-extra__copy {
	flex: none;
	display: inline-flex;
	align-items: center;
	gap: 6px;
	min-height: 32px;
}

.aeroidx-extra__copied-icon,
.aeroidx-extra__copy.is-copied .aeroidx-extra__copy-icon {
	display: none;
}

.aeroidx-extra__copy.is-copied .aeroidx-extra__copied-icon {
	display: block;
	color: var(--ax-success-ink);
}

.aeroidx-extra__copy[hidden] {
	display: none;
}

.aeroidx-extra__footnote {
	padding-top: 16px;
	border-top: 1px solid var(--ax-hairline);
}

.aeroidx-settings .aeroidx-extra__refresh {
	padding: 0;
	border: 0;
	background: none;
	color: var(--ax-violet-700);
	font: inherit;
	font-weight: 600;
	text-decoration: underline;
	cursor: pointer;
}

.aeroidx-settings .aeroidx-extra__refresh:disabled {
	color: var(--ax-muted-on-fill);
	cursor: progress;
}

.aeroidx-extra__refresh-status:empty {
	display: none;
}

.aeroidx-extra__refresh-status {
	display: block;
	margin-top: 4px;
}

/* General tab: theme plumbing folded under "Theme compatibility". */
.aeroidx-page-config__more {
	grid-column: 1 / -1;
	padding-top: 8px;
	border-top: 1px solid var(--ax-hairline);
}

.aeroidx-page-config__more-summary {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	gap: 4px 10px;
	min-height: 44px;
	padding: 10px 0;
	box-sizing: border-box;
	cursor: pointer;
	list-style: none;
}

.aeroidx-page-config__more-summary::-webkit-details-marker {
	display: none;
}

.aeroidx-page-config__more-summary::before {
	content: "";
	align-self: center;
	width: 7px;
	height: 7px;
	margin: 0 4px 0 2px;
	border-right: 2px solid var(--ax-muted-on-fill);
	border-bottom: 2px solid var(--ax-muted-on-fill);
	transform: rotate(-45deg);
	transition: transform 150ms var(--ax-ease);
}

.aeroidx-page-config__more[open] > .aeroidx-page-config__more-summary::before {
	transform: rotate(45deg);
}

.aeroidx-page-config__more-summary:focus-visible {
	outline: 2px solid var(--ax-violet-500);
	outline-offset: 2px;
}

.aeroidx-page-config__more-title {
	font-weight: 600;
	color: var(--ax-ink);
}

.aeroidx-page-config__more-value {
	font-size: 13px;
	color: var(--ax-muted-on-fill);
}

.aeroidx-page-config__more > .aeroidx-page-config__field {
	margin-top: 4px;
}

@media (prefers-reduced-motion: reduce) {
	.aeroidx-page-config__more-summary::before {
		transition: none;
	}
}

/* ── Listing details: searchable picker over the content selects ─────────── */

/* The native select stays in the form as the value; the picker drives it. */
.aeroidx-picker__native[hidden] {
	display: none !important;
}

.aeroidx-picker {
	position: relative;
}

/* Reads like the select it replaces: same field box, title then kind. */
.aeroidx-settings .aeroidx-picker__trigger {
	display: flex;
	align-items: center;
	gap: 10px;
	min-height: 44px;
	text-align: left;
	cursor: pointer;
}

.aeroidx-settings .aeroidx-picker.is-open .aeroidx-picker__trigger {
	border-color: var(--ax-violet-500);
	box-shadow: 0 0 0 1px var(--ax-violet-500);
}

.aeroidx-picker__value {
	flex: 1;
	min-width: 0;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.aeroidx-picker__kind {
	flex: none;
	font-size: 12px;
	color: var(--ax-muted-on-fill);
}

.aeroidx-picker__trigger.is-missing .aeroidx-picker__value {
	color: var(--ax-warning-ink);
}

.aeroidx-picker__chevron {
	flex: none;
	color: var(--ax-muted-on-fill);
	transition: transform 150ms var(--ax-ease);
}

.aeroidx-picker.is-open .aeroidx-picker__chevron {
	transform: rotate(180deg);
}

/* Fixed, placed by seo-sheet.js from the button's position: inside the
 * scrolling column it grew the column and scrolled it on every open. */
.aeroidx-picker__pop {
	position: fixed;
	z-index: 30;
	display: flex;
	flex-direction: column;
	background: var(--ax-card);
	border: 1px solid var(--ax-border);
	border-radius: 10px;
	box-shadow: 0 12px 32px -8px var(--ax-shadow-a12), 0 2px 6px var(--ax-shadow-a06);
	overflow: hidden;
}

.aeroidx-picker__pop[hidden] {
	display: none;
}

.aeroidx-picker__search {
	display: flex;
	align-items: center;
	gap: 8px;
	margin: 10px;
	padding: 0 12px;
	min-height: 40px;
	border: 1px solid var(--ax-border);
	border-radius: var(--ax-radius-input);
	background: var(--ax-card);
}

.aeroidx-picker__search:focus-within {
	border-color: var(--ax-violet-500);
	box-shadow: 0 0 0 1px var(--ax-violet-500);
}

.aeroidx-picker__search-icon {
	flex: none;
	color: var(--ax-muted-on-fill);
}

.aeroidx-settings .aeroidx-picker__input,
.aeroidx-settings .aeroidx-picker__input:focus {
	flex: 1;
	min-width: 0;
	min-height: 38px;
	margin: 0;
	padding: 0;
	border: 0;
	background: transparent;
	box-shadow: none;
	outline: none;
	font-size: 14px;
	color: var(--ax-ink);
}

/* The native WebKit clear button: blue, and missing in Firefox. Ours replaces it. */
.aeroidx-picker__input::-webkit-search-cancel-button,
.aeroidx-picker__input::-webkit-search-decoration {
	-webkit-appearance: none;
	appearance: none;
}

.aeroidx-settings .aeroidx-picker__clear {
	flex: none;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 28px;
	height: 28px;
	margin-right: -6px;
	padding: 0;
	border: 0;
	border-radius: 6px;
	background: transparent;
	color: var(--ax-muted-on-fill);
	cursor: pointer;
	transition: color 150ms var(--ax-ease), background 150ms var(--ax-ease);
}

.aeroidx-settings .aeroidx-picker__clear:hover {
	color: var(--ax-violet-700);
	background: var(--ax-violet-wash);
}

.aeroidx-settings .aeroidx-picker__clear:focus-visible {
	outline: 2px solid var(--ax-violet-500);
	outline-offset: 1px;
}

.aeroidx-picker__clear[hidden] {
	display: none;
}

.aeroidx-picker__input::placeholder {
	color: var(--ax-muted-on-fill);
	opacity: 1;
}

.aeroidx-picker__list {
	position: relative;
	max-height: 300px;
	overflow-y: auto;
	padding: 0 0 6px;
	border-top: 1px solid var(--ax-hairline);
}

.aeroidx-picker__group[hidden],
.aeroidx-picker__option[hidden],
.aeroidx-picker__empty[hidden] {
	display: none;
}

.aeroidx-picker__group-label {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: 12px;
	padding: 10px 14px 4px;
	font-size: 11px;
	font-weight: 600;
	letter-spacing: 0.04em;
	text-transform: uppercase;
	color: var(--ax-muted-on-fill);
}

.aeroidx-picker__group-count {
	font-weight: 500;
	letter-spacing: 0;
	text-transform: none;
}

.aeroidx-picker__option {
	display: flex;
	align-items: center;
	gap: 10px;
	min-height: 40px;
	padding: 8px 14px;
	box-sizing: border-box;
	font-size: 14px;
	color: var(--ax-ink);
	cursor: pointer;
}

.aeroidx-picker__option.is-active {
	background: var(--ax-violet-wash);
}

.aeroidx-picker__option.is-missing {
	color: var(--ax-warning-ink);
}

.aeroidx-picker__text {
	flex: 1;
	min-width: 0;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.aeroidx-picker__hit {
	font-weight: 700;
	color: var(--ax-violet-700);
}

.aeroidx-picker__check {
	flex: none;
	visibility: hidden;
	color: var(--ax-violet-700);
}

.aeroidx-picker__option.is-selected .aeroidx-picker__check {
	visibility: visible;
}

.aeroidx-picker__empty {
	display: flex;
	flex-direction: column;
	gap: 4px;
	padding: 18px 14px;
	border-top: 1px solid var(--ax-hairline);
	font-size: 13px;
	color: var(--ax-muted-on-fill);
}

.aeroidx-picker__empty-title {
	font-weight: 600;
	color: var(--ax-ink);
}

.aeroidx-picker__foot {
	display: flex;
	flex-wrap: wrap;
	justify-content: space-between;
	gap: 4px 12px;
	padding: 8px 14px;
	border-top: 1px solid var(--ax-hairline);
	font-size: 12px;
	color: var(--ax-muted-on-fill);
}

/* Short window: the list keeps the room, the footer goes. */
.aeroidx-picker__pop.is-compact .aeroidx-picker__foot {
	display: none;
}

/* Phones have no arrow keys to hint at. */
@media (hover: none) {
	.aeroidx-picker__keys {
		display: none;
	}
}

/* ── Listing details: "Where it shows" schematic (top of the aside) ───────── */

.aeroidx-where {
	display: flex;
	flex-direction: column;
	gap: 10px;
	/* Alone in the aside: the SEO preview it used to sit above is hidden on
	 * the Page Layout tab, so no margin pushes the column into a scroll. */
	margin: 0;
}

.aeroidx-where[hidden] {
	display: none;
}

.aeroidx-where__bar {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: 12px;
}

.aeroidx-where__heading {
	margin: 0;
	font-size: 14px;
	font-weight: 600;
	color: var(--ax-ink);
}

.aeroidx-where__scope {
	font-size: 12px;
	color: var(--ax-muted);
}

.aeroidx-where__box {
	display: flex;
	flex-direction: column;
	gap: 8px;
	padding: 12px;
	border: 1px solid var(--ax-border);
	border-radius: 10px;
	background: var(--ax-card);
}

.aeroidx-where__chrome {
	padding: 6px 10px;
	border-radius: 6px;
	background: var(--ax-hairline);
	color: var(--ax-muted-on-fill);
	font-size: 12px;
	text-align: center;
}

.aeroidx-where__slot {
	display: flex;
	flex-direction: column;
	gap: 2px;
	padding: 10px 12px;
	border: 2px dashed var(--ax-border);
	border-radius: 8px;
	background: transparent;
	color: var(--ax-muted-on-fill);
	font-size: 12px;
}

.aeroidx-where__slot-title {
	font-size: 13px;
	font-weight: 600;
}

.aeroidx-where__slot.is-filled {
	border: 2px solid var(--ax-violet-700);
	background: var(--ax-violet-wash);
}

.aeroidx-where__slot.is-filled .aeroidx-where__slot-title {
	color: var(--ax-ink);
	font-weight: 700;
}

.aeroidx-where__listing {
	display: flex;
	flex-direction: column;
	gap: 8px;
	padding: 10px 12px;
	border-radius: 8px;
	background: var(--ax-zebra);
}

.aeroidx-where__shapes {
	display: grid;
	grid-template-columns: 2fr 1fr;
	gap: 6px;
}

.aeroidx-where__shape {
	display: block;
	height: 14px;
	border-radius: 4px;
	background: var(--ax-hairline);
}

.aeroidx-where__shape--photo {
	grid-column: 1 / -1;
	height: 44px;
	background: var(--ax-violet-wash);
}

.aeroidx-where__shape--map {
	grid-column: 1 / -1;
	height: 28px;
}

.aeroidx-where__caption {
	font-size: 12px;
	color: var(--ax-muted-on-fill);
	text-align: center;
}

/* ── Details sheet: "Where it shows" on short windows ─────────────────────
 * Last in the file on purpose: these override the schematic's base sizes. */

/* Short windows (side by side, under ~820px tall): the schematic tightens
 * so the aside fits without a scrollbar. Same drawing, smaller blocks. */
@media (min-width: 961px) and (max-height: 820px) {
	.aeroidx-where {
		gap: 8px;
	}

	.aeroidx-where__box {
		gap: 6px;
		padding: 10px;
	}

	.aeroidx-where__chrome {
		padding: 4px 10px;
	}

	.aeroidx-where__listing {
		padding: 8px 12px;
	}

	.aeroidx-where__shape--photo {
		height: 28px;
	}

	.aeroidx-where__shape--map {
		height: 16px;
	}

	.aeroidx-where__slot {
		padding: 8px 12px;
	}
}

/* Laptop-short (under ~780px): the closing note goes too; the drawing says it. */
@media (min-width: 961px) and (max-height: 780px) {
	.aeroidx-where > .aeroidx-field__help {
		display: none;
	}

	.aeroidx-where__shape--photo {
		height: 20px;
	}

	.aeroidx-where__box {
		gap: 4px;
	}
}

/*
 * AI crawlers card (AiCrawlersCard). The notices reuse .aeroidx-page-notice;
 * these only lay out the icon beside the text and the pasted rules.
 */
.aeroidx-settings .aeroidx-ai-crawlers__notice,
.aeroidx-settings .aeroidx-llms-txt__notice {
	display: flex;
	gap: 10px;
	margin: 16px 0 0;
}

.aeroidx-settings .aeroidx-ai-crawlers__notice svg,
.aeroidx-settings .aeroidx-llms-txt__notice svg {
	flex: none;
	margin-top: 2px;
}

.aeroidx-settings .aeroidx-ai-crawlers__rules,
.aeroidx-settings .aeroidx-llms-txt__rules {
	margin: 12px 0 0;
	padding: 12px 14px;
	border: 1px solid var(--ax-border-soft);
	border-radius: var(--ax-radius-card);
	background: var(--ax-fill-locked);
	font-size: 12.5px;
	line-height: 1.6;
	white-space: pre-wrap;
}

.aeroidx-settings .aeroidx-ai-crawlers__copy,
.aeroidx-settings .aeroidx-llms-txt__copy {
	margin: 12px 0 0;
}

/*
 * llms.txt "What it includes" (LlmsTxtCard::renderSections()): the section
 * switches beside a preview of the file, from the approved canvas. The two
 * columns stack below 960px. A disabled fieldset (llms.txt off) dims the
 * switches but leaves their text readable.
 */
.aeroidx-settings .aeroidx-llms-txt__body {
	display: grid;
	grid-template-columns: minmax(0, 1fr);
	gap: 24px;
	margin: 20px 0 0;
	padding: 20px 0 0;
	border-top: 1px solid var(--ax-border-soft);
}

@media (min-width: 961px) {
	.aeroidx-settings .aeroidx-llms-txt__body--preview {
		grid-template-columns: minmax(0, 1fr) minmax(0, 420px);
		align-items: start;
	}
}

.aeroidx-settings .aeroidx-llms-txt__sections {
	min-width: 0;
	margin: 0;
	padding: 0;
	border: 0;
}

.aeroidx-settings .aeroidx-llms-txt__legend {
	padding: 0;
	font-size: 14px;
	font-weight: 600;
	color: var(--ax-ink);
}

.aeroidx-settings .aeroidx-llms-txt__hint {
	margin: 6px 0 0;
}

.aeroidx-settings .aeroidx-llms-txt__group {
	margin: 20px 0 0;
}

.aeroidx-settings .aeroidx-llms-txt__group-title {
	margin: 0 0 4px;
	font-size: 11px;
	font-weight: 600;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--ax-secondary);
}

.aeroidx-settings .aeroidx-llms-txt__row {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 16px;
	padding: 12px 0;
	border-bottom: 1px solid var(--ax-border-soft);
}

.aeroidx-settings .aeroidx-llms-txt__group .aeroidx-llms-txt__row:last-child {
	border-bottom: 0;
}

.aeroidx-settings .aeroidx-llms-txt__row-text {
	display: flex;
	flex-direction: column;
	gap: 2px;
	min-width: 0;
}

.aeroidx-settings .aeroidx-llms-txt__row-label {
	font-size: 13px;
	font-weight: 500;
	color: var(--ax-ink);
}

.aeroidx-settings .aeroidx-llms-txt__row-help {
	font-size: 12px;
	line-height: 1.5;
	color: var(--ax-secondary);
}

.aeroidx-settings .aeroidx-llms-txt__sections:disabled .aeroidx-switch {
	opacity: 0.45;
	cursor: not-allowed;
}

.aeroidx-settings .aeroidx-llms-txt__sections:disabled .aeroidx-llms-txt__row-label {
	cursor: not-allowed;
}

.aeroidx-settings .aeroidx-llms-txt__preview {
	min-width: 0;
	padding: 16px;
	border: 1px solid var(--ax-border-soft);
	border-radius: var(--ax-radius-card);
}

.aeroidx-settings .aeroidx-llms-txt__preview-head {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: 12px;
}

.aeroidx-settings .aeroidx-llms-txt__preview-title {
	margin: 0;
	font-size: 14px;
	font-weight: 600;
	color: var(--ax-ink);
}

.aeroidx-settings .aeroidx-llms-txt__preview-path {
	font-size: 12px;
	color: var(--ax-secondary);
}

.aeroidx-settings .aeroidx-llms-txt__preview-body {
	max-height: 560px;
	overflow: auto;
	font-size: 11.5px;
	word-break: break-word;
}

.aeroidx-settings .aeroidx-llms-txt__preview-empty {
	margin: 12px 0 0;
	padding: 28px 16px;
	border-radius: var(--ax-radius-card);
	background: var(--ax-fill-locked);
	text-align: center;
}

.aeroidx-settings .aeroidx-llms-txt__preview-empty-title {
	margin: 0;
	font-size: 13px;
	font-weight: 500;
	color: var(--ax-ink);
}

.aeroidx-settings .aeroidx-llms-txt__preview-empty-text {
	margin: 4px 0 0;
	font-size: 12px;
	line-height: 1.5;
	color: var(--ax-secondary);
}

/*
 * The robots.txt file panel on the AI crawlers card, when the host serves its
 * own file (AiCrawlersCard::renderFilePanel()). Four tones from the approved
 * canvas: violet (add the rules), green (they are in), amber (they went, or
 * the file is locked). The green and amber panels colour all their text with
 * the tone's ink; the violet one sets its own on the neutral ramp.
 */
.aeroidx-settings .aeroidx-robots {
	display: flex;
	gap: 14px;
	margin: 16px 0 0;
	padding: 20px;
	border: 1px solid var(--ax-border-soft);
	border-radius: var(--ax-radius-card);
}

.aeroidx-settings .aeroidx-robots--violet {
	background: var(--ax-violet-a07);
	border-color: var(--ax-violet-edge);
	color: var(--ax-neutral-700);
}

.aeroidx-settings .aeroidx-robots--violet .aeroidx-robots__icon {
	color: var(--ax-violet-700);
}

.aeroidx-settings .aeroidx-robots--violet .aeroidx-robots__title {
	color: var(--ax-neutral-850);
}

.aeroidx-settings .aeroidx-robots--violet .aeroidx-robots__note {
	color: var(--ax-neutral-600);
}

.aeroidx-settings .aeroidx-robots--warn {
	background: var(--ax-warning-wash);
	border-color: var(--ax-warning-edge);
	color: var(--ax-warning-ink);
}

.aeroidx-settings .aeroidx-robots__icon {
	flex: none;
	margin-top: 1px;
}

.aeroidx-settings .aeroidx-robots__body {
	display: flex;
	flex: 1;
	flex-direction: column;
	gap: 14px;
	min-width: 0;
}

.aeroidx-settings .aeroidx-robots__text {
	display: flex;
	flex-direction: column;
	gap: 4px;
}

.aeroidx-settings .aeroidx-robots__title,
.aeroidx-settings .aeroidx-robots__copy,
.aeroidx-settings .aeroidx-robots__note {
	margin: 0;
}

.aeroidx-settings .aeroidx-robots__title {
	font-size: 15px;
	font-weight: 600;
}

.aeroidx-settings .aeroidx-robots__copy {
	font-size: 14px;
	line-height: 1.6;
}

.aeroidx-settings .aeroidx-robots__note {
	font-size: 13px;
}

.aeroidx-settings .aeroidx-robots__row {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 16px;
	font-size: 14px;
}

.aeroidx-settings .aeroidx-robots__lines summary {
	font-weight: 500;
	color: var(--ax-violet-700);
	cursor: pointer;
}

/* Under the actions, on a row of its own: the lines are the detail a few want
 * to check, not a second action beside the button. */
.aeroidx-settings .aeroidx-robots__lines {
	font-size: 14px;
}

.aeroidx-settings .aeroidx-robots__lead {
	margin: 10px 0 8px;
	font-size: 13px;
	line-height: 1.6;
	color: var(--ax-neutral-600);
}

.aeroidx-settings .aeroidx-robots__lines .aeroidx-ai-crawlers__rules,
.aeroidx-settings .aeroidx-robots__message {
	background: var(--ax-card);
	color: var(--ax-neutral-850);
	font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}

.aeroidx-settings .aeroidx-robots__message {
	margin: 0;
	padding: 16px 18px;
	font-size: 13px;
	line-height: 1.7;
}

.aeroidx-settings .aeroidx-robots__lead {
	margin: 10px 0 8px;
	font-size: 13px;
	line-height: 1.6;
	color: var(--ax-neutral-600);
}

/*
 * The AI crawlers switch row (AiCrawlersCard::renderSwitch): the copy on the
 * left and the switch on the right, flat in the card like the llms.txt card's
 * title row (the "AI search copy" canvas dropped the box around it).
 * The "Saving…" indicator admin.js inserts sits left of the switch.
 */
.aeroidx-settings .aeroidx-ai-crawlers__policy {
	display: flex;
	align-items: flex-start;
	gap: 16px;
	margin: 20px 0 0;
}

.aeroidx-settings .aeroidx-ai-crawlers__policy-text {
	display: flex;
	flex: 1;
	flex-direction: column;
	gap: 6px;
	min-width: 0;
}

.aeroidx-settings .aeroidx-ai-crawlers__policy-title,
.aeroidx-settings .aeroidx-ai-crawlers__policy-copy,
.aeroidx-settings .aeroidx-ai-crawlers__shield {
	margin: 0;
}

/*
 * One step under the card's own 16px/600 title (.aeroidx-field__title), so
 * "Who can read your site" reads as the heading and this as the setting.
 */
.aeroidx-settings .aeroidx-ai-crawlers__policy-title {
	font-size: 15px;
	font-weight: 500;
	color: var(--ax-neutral-850);
}

.aeroidx-settings .aeroidx-ai-crawlers__policy-copy {
	font-size: 14px;
	line-height: 1.6;
	color: var(--ax-neutral-700);
}

.aeroidx-settings .aeroidx-ai-crawlers__shield {
	display: flex;
	align-items: center;
	gap: 8px;
	margin-top: 4px;
	font-size: 13px;
	color: var(--ax-neutral-600);
}

.aeroidx-settings .aeroidx-ai-crawlers__shield svg {
	flex: none;
}

.aeroidx-settings .aeroidx-ai-crawlers__policy-control {
	display: flex;
	align-items: center;
	gap: 12px;
}

.aeroidx-settings .aeroidx-saving {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	font-size: 13px;
	color: var(--ax-neutral-600);
}

.aeroidx-settings .aeroidx-saving__ring {
	display: inline-block;
	box-sizing: border-box;
	width: 14px;
	height: 14px;
	border: 2px solid var(--ax-violet-a15);
	border-top-color: var(--ax-violet-700);
	border-radius: var(--ax-radius-pill);
	animation: aeroidx-saving-spin 0.8s linear infinite;
}

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

@media (prefers-reduced-motion: reduce) {
	.aeroidx-settings .aeroidx-saving__ring {
		animation-duration: 2.4s;
	}
}

/* A switch whose request is out: not clickable, not disabled (a disabled input
 * is not posted; see admin.js, "Autosaving switches"). */
.aeroidx-settings .aeroidx-switch[aria-busy="true"] {
	pointer-events: none;
	opacity: 0.6;
	cursor: progress;
}

/*
 * llms.txt card (LlmsTxtCard). The notice, the pasted section and its copy
 * button share the AI crawlers card's rules above; this adds the title row with
 * the switch beside it, as the canvas draws it.
 */
.aeroidx-settings .aeroidx-llms-txt__head {
	display: flex;
	align-items: flex-start;
	gap: 16px;
}

.aeroidx-settings .aeroidx-llms-txt__text {
	flex: 1;
	min-width: 0;
}

.aeroidx-settings .aeroidx-llms-txt__paste {
	margin: 12px 0 0;
}

/*
 * "AI search" (SettingsPage::renderAiSearchHeading): the heading over the AI
 * crawlers and llms.txt cards. Not a card, so it sits on the page background.
 */
.aeroidx-settings .aeroidx-ai-search-head {
	margin: 36px 4px 16px;
}

.aeroidx-settings .aeroidx-ai-search-head__title {
	margin: 0 0 6px;
	padding: 0;
	font-size: 22px;
	font-weight: 600;
	color: var(--ax-ink);
}

.aeroidx-settings .aeroidx-ai-search-head__copy {
	max-width: 680px;
	margin: 0;
	font-size: 14px;
	line-height: 1.6;
	color: var(--ax-neutral-600);
}

/* "View your robots.txt ↗" / "View your llms.txt ↗", under each card's switch. */
.aeroidx-settings .aeroidx-ai-file-link {
	margin: 16px 0 0;
	font-size: 14px;
}

.aeroidx-settings .aeroidx-ai-file-link a {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	font-weight: 500;
	color: var(--ax-violet-700);
}

.aeroidx-settings .aeroidx-ai-file-link a:hover,
.aeroidx-settings .aeroidx-ai-file-link a:focus {
	color: var(--ax-violet-800);
}

/* The "on" note on the llms.txt card: a violet wash with no edge, as the
   canvas draws it. --info is grey in this admin, so it gets its own tone. */
.aeroidx-settings .aeroidx-page-notice--violet {
	border-color: transparent;
	background: var(--ax-violet-a07);
	color: var(--ax-violet-900);
}

/* The "off" note on the llms.txt card: grey, nothing for the owner to fix. */
.aeroidx-settings .aeroidx-page-notice--neutral {
	background: var(--ax-fill-locked);
	color: var(--ax-secondary);
}

/*
 * "Customize what's included" (LlmsTxtCard::renderSections): a full-width row
 * with the chevron trailing it, as on the "Styling AeroIDX pages" disclosure,
 * closed by default. Its body keeps the rules of .aeroidx-llms-txt__body.
 */
.aeroidx-settings .aeroidx-llms-txt__more {
	margin: 16px 0 0;
	padding: 8px 0 0;
	border-top: 1px solid var(--ax-border-soft);
}

.aeroidx-settings .aeroidx-llms-txt__more-summary {
	display: flex;
	align-items: center;
	gap: 12px;
	min-height: 44px;
	cursor: pointer;
	list-style: none;
}

.aeroidx-settings .aeroidx-llms-txt__more-summary::-webkit-details-marker {
	display: none;
}

.aeroidx-settings .aeroidx-llms-txt__more-summary:focus-visible {
	outline: 2px solid var(--ax-violet-500);
	outline-offset: 2px;
	border-radius: var(--ax-radius-card);
}

.aeroidx-settings .aeroidx-llms-txt__more-text {
	display: flex;
	flex: 1;
	flex-wrap: wrap;
	align-items: baseline;
	gap: 2px 12px;
	min-width: 0;
}

/* The same step under the card title as the AI crawlers switch title. */
.aeroidx-settings .aeroidx-llms-txt__more-title {
	font-size: 15px;
	font-weight: 500;
	color: var(--ax-ink);
}

.aeroidx-settings .aeroidx-llms-txt__more-hint {
	font-size: 13px;
	color: var(--ax-neutral-600);
}

.aeroidx-settings .aeroidx-llms-txt__more-mark {
	display: flex;
	flex: none;
	color: var(--ax-muted);
	transition: transform 140ms var(--ax-ease), color 140ms var(--ax-ease);
}

.aeroidx-settings .aeroidx-llms-txt__more[open] .aeroidx-llms-txt__more-mark {
	transform: rotate(90deg);
}

.aeroidx-settings .aeroidx-llms-txt__more-summary:hover .aeroidx-llms-txt__more-mark {
	color: var(--ax-ink);
}

/* Inside the disclosure the summary row is the divider; the body's own top
   border and padding would draw a second one. */
.aeroidx-settings .aeroidx-llms-txt__more .aeroidx-llms-txt__body {
	margin-top: 12px;
	padding-top: 0;
	border-top: 0;
}

@media (prefers-reduced-motion: reduce) {
	.aeroidx-settings .aeroidx-llms-txt__more-mark {
		transition: none;
	}
}

/*
 * The switch: a checkbox with role="switch", drawn as a 40 x 24 pill with a
 * round knob (the canvas's .ax-switch). wp-admin's own checkbox look is
 * switched off for it. Locked, it greys out the way the locked option cards do.
 */
.aeroidx-settings .aeroidx-switch {
	appearance: none;
	-webkit-appearance: none;
	position: relative;
	flex: none;
	width: 40px;
	height: 24px;
	min-width: 40px;
	margin: 0;
	border: 0;
	border-radius: var(--ax-radius-pill);
	background: var(--ax-border-control);
	cursor: pointer;
	transition: background-color 0.15s ease;
}

/*
 * wp-admin draws a checkmark on every checked checkbox with
 * `input[type=checkbox]:checked::before`, specificity (0,2,2). The plain
 * ::before rule (0,2,1) loses to it, so the "✓" showed on the switch only
 * while it was on. The :checked rule (0,3,1) outranks core's.
 */
.aeroidx-settings .aeroidx-switch::before,
.aeroidx-settings .aeroidx-switch:checked::before {
	content: none;
	display: none;
}

.aeroidx-settings .aeroidx-switch::after {
	content: "";
	position: absolute;
	top: 3px;
	left: 3px;
	width: 18px;
	height: 18px;
	border-radius: 50%;
	background: var(--ax-on-accent);
	transition: left 0.15s ease;
}

.aeroidx-settings .aeroidx-switch:checked {
	background: var(--ax-violet-700);
}

.aeroidx-settings .aeroidx-switch:checked::after {
	left: 19px;
}

.aeroidx-settings .aeroidx-switch:focus {
	box-shadow: none;
}

.aeroidx-settings .aeroidx-switch:focus-visible {
	outline: 2px solid var(--ax-violet-500);
	outline-offset: 2px;
}

.aeroidx-settings .aeroidx-switch:disabled {
	opacity: 0.6;
	cursor: not-allowed;
}

@media (prefers-reduced-motion: reduce) {
	.aeroidx-settings .aeroidx-switch,
	.aeroidx-settings .aeroidx-switch::after {
		transition: none;
	}
}
