/* The @layer wrapper below is applied in place by scripts/wrap-css-layer.js.
   Edit the rules freely — just leave the wrapper alone (re-running is a no-op).
   Everything below is inside @layer pqf-neutral, so ANY unlayered CSS
   (a consuming theme's) wins regardless of specificity or load order. */
@layer pqf-neutral {
	.pqf-load-more {
		flex-wrap: wrap;
	}

	.pqf-load-more__link {
		display: inline-flex;
		align-items: center;
		justify-content: center;
		min-block-size: 44px;
		padding-inline: 1em;
		border: 1px solid currentcolor;
		border-radius: 0.35em;
		text-decoration: none;
	}

	.pqf-load-more__error {
		flex-basis: 100%;
		text-align: center;
	}
	/**
 * Plain Query Filters — shared control language (the LAYERED half).
 *
 * ONE neutral recipe for every interactive control surface (popover trigger,
 * sort <select>, map-toggle button). Colorless by construction: every tone is
 * derived from currentColor via color-mix(), so the defaults are correct on any
 * palette — light, dark, or otherwise — without the plugin shipping a hex.
 *
 * SPLIT BY CONTRACT. Everything in this file is layered, which means it is a
 * DEFAULT: "a theme may repaint this". Paint, sizing, decoration, preference.
 * The recipe's other half — the neutralisers that must survive a foreign
 * `select {}` / `label {}` / `input {}` rule on someone else's site — is
 * deliberately UNLAYERED and lives in assets/css/defense.css (handle
 * `pqf-defense`). `.pqf-control` therefore spans two files: box-sizing, color,
 * font and line-height are over there; min-height, background, border, radius,
 * padding and cursor are here. Read that file's header before moving a
 * declaration in either direction — the boundary is a contract, not a
 * convenience.
 *
 * Theme override surface: the --pqf-control-* custom properties, or the
 * .pqf-control class itself. Browsers without color-mix() drop the invalid
 * border-color and fall back to the plain currentColor declaration above it —
 * a stronger but still correct border.
 *
 * THE SCALE TOKENS (canonical list — this is their documentation)
 * --------------------------------------------------------------
 * Space, radius, type and motion for the chrome the plugin RENDERS, read the
 * same way paint is: a --pqf-* hook first, a neutral literal behind it.
 *
 *   --pqf-space-xs / -sm / -md          gaps and padding inside plugin chrome
 *   --pqf-radius-sm / -md / -full       control, card and pill corners
 *   --pqf-font-size-2xs / -xs / -sm     chrome type (badges, tips, labels)
 *   --pqf-transition / --pqf-transition-slow   hover/state motion
 *   --pqf-focus-color / -width / -offset      focus paint and standalone offset
 *
 * Focus defaults to currentColor, 2px width and a 2px outward offset. Known
 * scrollports use the private --pqf-internal-focus-inset flag to keep the stroke inset.
 *
 * Defaults follow the active theme's merged Global Styles via pqf-theme:
 * blockGap supplies the spacing rhythm (including named/fluid presets), and
 * the theme's background/text pair supplies opaque floating surfaces. The
 * WordPress Style Engine resolves preset notation on both front end and editor.
 * Public --pqf-* hooks still override these private fallbacks. No theme-specific
 * preset slug is assumed or written permanently into post content.
 * Control padding stays relative to inherited typography; block support styles
 * and authored core blocks remain the native customization surface.
 *
 * QUERY FEEDBACK
 * --------------
 * Shared navigation acknowledgement and reserved content status also live here.
 * Blocks need this sheet when they render one of its classes or bind a shared
 * navigation action. Native Interactivity bindings derive transient state from
 * the shared transaction; no inline spinner changes a control's dimensions.
 */
	.pqf-control {
		/* Controls own their box math: this shared min-height floor keeps the whole
	   control row uniform even though a native <select> and an icon-bearing
	   button reach different natural heights. It only means the same thing on
	   both because of the border-box half of that box math, which is an
	   invariant and lives unlayered in assets/css/defense.css. */
		min-height: var(--pqf-control-min-height, 2.4em);
		background: var(--pqf-control-bg, transparent);
		border: 1px solid currentcolor; /* color-mix fallback */
		border-color: var(
			--pqf-control-border,
			color-mix(in srgb, currentColor 28%, transparent)
		);
		border-radius: var(--pqf-control-radius, 4px);
		cursor: pointer;
		padding: var(--pqf-control-padding, 0.4em 0.75em);
	}

	/* Optical centering: flexbox centers the label's LINE BOX, but text ink sits
   mostly above the baseline inside it, so geometrically centered text reads
   ~1px high next to icon/chevron glyphs. text-box trims the box to the ink —
   and the symmetric padding immediately gives the trimmed leading back, so:
   (a) what flexbox centers is the INK (padding is symmetric),
   (b) the label's layout height stays exactly 1lh — control heights remain
       uniform across trigger/select/toggle and width-ghost siblings, and
   (c) the padding doubles as descender headroom if a theme clips the label
       with overflow:hidden for ellipsis truncation (clipping happens at the
       padding box, so g/y descenders keep painting).
   Browsers without text-box/lh/cap keep plain line-box centering. */
	@supports (text-box: trim-both cap alphabetic) and
		(padding: calc((1lh - 1cap) / 2)) {
		.pqf-control__label {
			text-box: trim-both cap alphabetic;
			padding-block: calc((1lh - 1cap) / 2);
		}
	}

	/* Text-entry fields (typeahead search, range number inputs) share the control
   recipe but are typed into, not clicked: text cursor, and no hover wash — a
   `background` shorthand on hover would also wipe a theme's background-image
   (e.g. a magnifier icon) and a field's affordance is its caret, not a wash.
   :where() keeps the exclusion at the base (0,2,0) specificity. That's no
   longer what lets a theme's hover override win — this file is layered, so
   an unlayered theme rule wins regardless of specificity — but the low
   specificity is kept anyway so other layered rules can still out-specify it
   without a fight. */
	.pqf-control--field {
		cursor: text;
	}

	@media (hover: hover) {
		.pqf-control:hover:where(:not(.pqf-control--field)) {
			/* Two-tier naming, most- to least-specific:
		   1. --pqf-hover-bg — per-instance var written inline by render.php
		      (filter-popover / active-filters) for a single control;
		   2. --pqf-control-hover-bg — theme-facing override for all controls;
		   3. the color-mix() derivation — colorless default fallback. */
			background: var(
				--pqf-hover-bg,
				var(
					--pqf-control-hover-bg,
					color-mix(in srgb, currentColor 7%, transparent)
				)
			);
		}
	}

	/* Focus paint is themeable. Its structural width/style/placement live in
	   defense.css so a generic theme focus rule cannot split that geometry.
	   Authored core-block content retains WordPress/theme focus styles. */
	.pqf-control:focus-visible,
	.pqf-state-control:focus-visible,
	.pqf-option:has(> .pqf-option__checkbox:focus-visible),
	.wp-block-plainplugins-taxonomy-filter__item:focus-visible,
	.wp-block-plainplugins-meta-filter__item:focus-visible,
	.wp-block-plainplugins-post-type-filter__item:focus-visible,
	.wp-block-plainplugins-meta-toggle__item:focus-visible,
	.wp-block-plainplugins-query-views__tab:focus-visible {
		outline-color: var(
			--pqf-focus-color,
			var(--pqf-internal-focus-color, currentcolor)
		);
	}

	@media (forced-colors: active) {
		.pqf-control:focus-visible,
		.pqf-state-control:focus-visible,
		.pqf-option:has(> .pqf-option__checkbox:focus-visible),
		.wp-block-plainplugins-taxonomy-filter__item:focus-visible,
		.wp-block-plainplugins-meta-filter__item:focus-visible,
		.wp-block-plainplugins-post-type-filter__item:focus-visible,
		.wp-block-plainplugins-meta-toggle__item:focus-visible,
		.wp-block-plainplugins-query-views__tab:focus-visible {
			outline-color: var(--pqf-internal-focus-color, CanvasText);
		}
	}

	/* Customizable Select — shared STRUCTURE for the sort <select>'s open picker.
 *
 * The sort <select> carries `.pqf-control` (render.php), so its trigger box —
 * border, radius, background, padding, cursor, focus ring from the recipe above,
 * plus font/color/box-sizing/line-height from the unlayered defensive half in
 * assets/css/defense.css — is already fully described. In browsers with
 * `appearance: base-select` the
 * <select> button AND its dropdown picker become real styleable boxes; the rules
 * below give that picker the SAME neutral structure the filter-popover panel
 * ships (src/filter-popover/style.css), driven by the SAME `--pqf-panel-*` hooks
 * with the SAME defaults — so the open sort menu matches the popover panel with
 * zero theme CSS (e.g. the naked QA harness). STRUCTURE only lives here; every
 * color / tint / shadow accent is the consuming theme's to paint. Browsers
 * without base-select keep the native widget (nothing below applies). The
 * block's own chevron / leading-icon masks + field-sizing stay in the block's
 * style.css — this section deliberately does not restate them. */
	@supports (appearance: base-select) {
		.wp-block-plainplugins-sort-dropdown__select,
		.wp-block-plainplugins-sort-dropdown__select::picker(select) {
			appearance: base-select;
		}

		/* Trigger — minimal structure; the box paint comes from `.pqf-control`,
	   whose `font: inherit` is already declared UNLAYERED in
	   assets/css/defense.css. Restating it here bought nothing: the select
	   carries `.pqf-control` (render.php), and a layered restatement could never
	   win anything the unlayered original did not already win. */
		.wp-block-plainplugins-sort-dropdown__select {
			display: inline-flex;
			align-items: center;
			gap: 0.4em;
			cursor: pointer;
		}

		/* Open picker — same var-based default paint as the filter-popover panel, on
	   the SAME `--pqf-panel-*` hooks with the SAME neutral defaults, so a theme
	   that maps the panel once covers both dropdowns. */
		.wp-block-plainplugins-sort-dropdown__select::picker(select) {
			margin-top: 6px;

			/* The UA ships ::picker(select) with a visible 1px border the popover
		   panel doesn't have — reset it to the shared hook (default none) so the
		   two panels' chrome can't drift. */
			border: var(--pqf-panel-border, none);

			/* The picker is the options' inheritance parent and the UA paints it
		   canvastext (pure black) — inherit from the select so option text
		   matches the trigger / filter items (option's own color:inherit below
		   resolves through THIS box, not the select). */
			color: inherit;
			background: var(
				--pqf-panel-bg,
				var(--pqf-internal-surface-bg, Canvas)
			);
			border-radius: var(--pqf-panel-radius, 4px);
			box-shadow: var(--pqf-panel-shadow, 0 4px 12px rgba(0, 0, 0, 0.15));

			/* Block axis only — MENU-ROW PARITY with the popover panel, which moved
		   its inline inset onto the rows so the hover wash paints edge to edge
		   (see filter-popover/style.css). The option rows below carry the inline
		   half from the same token. */
			padding: var(
					--pqf-panel-padding,
					var(--pqf-space-sm, var(--pqf-internal-space-sm, 12px))
				)
				0;
		}

		/* Option rows — flex so the native ::checkmark can sit at the row end as a
	   single-select affordance. MENU-ROW PARITY: padding, line-height, hover wash
	   and the bold active cue below all mirror the popover panel's filter rows
	   (the popover half lives in filter-popover/style.css via the
	   --pqf-panel-item-* defaults), so both open menus read identically on an
	   unthemed install. The line-height re-widens the rows from the trigger's
	   compact 1.2 (inherited via .pqf-control — declared in the unlayered
	   assets/css/defense.css, not in this file) to the list leading the filter
	   items use. */
		.wp-block-plainplugins-sort-dropdown__select option {
			display: flex;
			align-items: center;
			gap: 0.5em;

			/* Inline half = the panel padding token, mirroring the popover's
		   `--pqf-panel-item-padding` default — the row runs wall to wall and
		   carries the inset itself, so its hover wash does too. */
			padding: 0.35em
				var(
					--pqf-panel-padding,
					var(--pqf-space-sm, var(--pqf-internal-space-sm, 12px))
				);
			font: inherit;

			/* The UA paints options canvastext (pure black) instead of inheriting —
		   inherit so option rows match the filter items' text color exactly. */
			color: inherit;
			line-height: 1.4;
			cursor: pointer;
		}

		/* The native picker is a separate scrollport, so its options need their
		   own placement. Keep focus independent of :checked/checkmark selection.
		   :focus also preserves the browser's pointer-open active-option cue. */
		.wp-block-plainplugins-sort-dropdown__select option:focus {
			outline-color: var(--pqf-focus-color, currentcolor);
		}

		@media (forced-colors: active) {
			.wp-block-plainplugins-sort-dropdown__select option:focus {
				color: CanvasText;
				background: Canvas;
				outline-color: CanvasText;
			}
		}

		/* Hover wash — the same var chain as .pqf-control:hover, so an unthemed
	   install gets the same faint currentColor mix the popover's rows default to,
	   and a theme's --pqf-control-hover-bg covers this too. The UA's own
	   base-select hover paint (browser-specific) is replaced so the two menus
	   can't drift. */
		@media (hover: hover) {
			.wp-block-plainplugins-sort-dropdown__select option:hover {
				background: var(
					--pqf-hover-bg,
					var(
						--pqf-control-hover-bg,
						color-mix(in srgb, currentColor 7%, transparent)
					)
				);
			}
		}

		/* Selected row — the same shape cue (not color-only, WCAG 1.4.1) the filter
	   blocks put on __item--active; the ::checkmark below is the select-specific
	   bonus affordance. */
		.wp-block-plainplugins-sort-dropdown__select option:checked {
			font-weight: 600;
		}

		/* Native checkmark — pushed to the row end (single-select affordance),
	   colorless (currentColor); themes tint it. */
		.wp-block-plainplugins-sort-dropdown__select option::checkmark {
			order: 1;
			margin-inline-start: auto;
		}
	}

	/* Feedback belongs to content. Filter controls retain their exact dimensions,
	   including the active tab underline, while the canonical result set loads. */
	.pqf-is-loading {
		opacity: 0.7;
	}

	.wp-block-plainplugins-result-count,
	.wp-block-plainplugins-query-map-cards__header {
		display: flex;
		align-items: baseline;
		justify-content: space-between;
		flex-wrap: wrap;
		gap: 0.5em 1em;
	}

	.pqf-query-status {
		display: inline-grid;
		box-sizing: border-box;
		grid-template-areas: "status";
		align-items: center;
		position: relative;
		font-size: 0.875em;
		font-weight: 400;
		line-height: 1.5;
		white-space: normal;
		min-inline-size: 0;
		max-inline-size: 100%;
		overflow-wrap: anywhere;
	}
	.pqf-query-status__measure,
	.pqf-query-status__message {
		grid-area: status;
		padding-inline-start: 1.4em;
	}
	.pqf-query-status__measure {
		visibility: hidden;
	}
	.pqf-query-status::before {
		content: "";
		position: absolute;
		inset-inline-start: 0;
		box-sizing: border-box;
		width: 0.8em;
		height: 0.8em;
		border: 2px solid currentcolor;
		border-top-color: transparent;
		border-radius: 50%;
		visibility: hidden;
	}
	.pqf-query-status[data-loading="true"]::before {
		visibility: visible;
		animation: pqf-spin 0.8s linear infinite;
	}
	/* Persistent maps are outside router regions. Their status is an authored
	   sibling of the SDK canvas, so a router swap never replaces map-owned DOM. */
	.pqf-query-status--map {
		position: absolute;
		inset-block-start: 0.75em;
		inset-inline-end: 0.75em;
		max-inline-size: calc(100% - 1.5em);
		z-index: 1000;
		padding: 0.45em 0.75em;
		border-radius: var(--pqf-radius-sm, 4px);
		background: var(--pqf-map-chrome, #fff);
		color: var(--pqf-map-ink, #1f2937);
		box-shadow: 0 1px 4px rgb(0 0 0 / 15%);
		pointer-events: none;
		visibility: hidden;
	}
	.pqf-query-status--map::before {
		inset-inline-start: 0.75em;
	}
	.pqf-query-status--map[data-loading="true"] {
		visibility: visible;
	}

	@keyframes pqf-spin {
		to {
			transform: rotate(360deg);
		}
	}
	@media (prefers-reduced-motion: reduce) {
		.pqf-query-status[data-loading="true"]::before {
			animation: none;
		}
	}

	/* List-filter block style variants — shared NEUTRAL structure.
 *
 * The three list-type filter blocks (taxonomy-filter, meta-filter,
 * post-type-filter) expose WP-native block styles (block.json `styles`): Text
 * (default, plain link rows — untouched here), Pills, Buttons, Underline. This
 * section gives each __item its per-variant SHAPE only — inline box, radius,
 * separator underline — with zero paint: every tone is a currentColor mix so the
 * defaults read on any palette and a consuming theme repaints wholesale. The
 * global active cue (font-weight, in each block's style.css) still applies.
 *
 * Selectors name the three blocks explicitly (no [class*=] matching); the
 * is-style-* class lands on the block root in BOTH the front end and the editor
 * canvas, so these rules cover both. Specificity is kept at (0,3,0) via an
 * :is(.is-style-pills, .is-style-buttons) group on the root — enough to sit
 * above the block's own neutral base. A theme doesn't need it kept low to
 * override: this whole file is layered, so any unlayered theme rule wins
 * regardless of specificity. */

	/* Pills + Buttons — an inline bordered chip. Buttons differ only in radius.
   The `text-decoration: none` these two variant rules used to restate now comes
   once from `.pqf-link` in assets/css/defense.css, unlayered — every __item is
   an anchor and carries that class. */
	.wp-block-plainplugins-taxonomy-filter:is(
			.is-style-pills,
			.is-style-buttons
		)
		.wp-block-plainplugins-taxonomy-filter__item,
	.wp-block-plainplugins-meta-filter:is(.is-style-pills, .is-style-buttons)
		.wp-block-plainplugins-meta-filter__item,
	.wp-block-plainplugins-post-type-filter:is(
			.is-style-pills,
			.is-style-buttons
		)
		.wp-block-plainplugins-post-type-filter__item {
		display: inline-flex;
		align-items: center;
		padding: 0.35em 0.9em;
		border: 1px solid color-mix(in srgb, currentcolor 25%, transparent);
		border-radius: 999px;
	}

	.wp-block-plainplugins-taxonomy-filter.is-style-buttons
		.wp-block-plainplugins-taxonomy-filter__item,
	.wp-block-plainplugins-meta-filter.is-style-buttons
		.wp-block-plainplugins-meta-filter__item,
	.wp-block-plainplugins-post-type-filter.is-style-buttons
		.wp-block-plainplugins-post-type-filter__item {
		border-radius: 2px;
	}

	/* Active chip — faint currentColor wash + a solid-currentColor border. */
	.wp-block-plainplugins-taxonomy-filter:is(
			.is-style-pills,
			.is-style-buttons
		)
		.wp-block-plainplugins-taxonomy-filter__item--active,
	.wp-block-plainplugins-meta-filter:is(.is-style-pills, .is-style-buttons)
		.wp-block-plainplugins-meta-filter__item--active,
	.wp-block-plainplugins-post-type-filter:is(
			.is-style-pills,
			.is-style-buttons
		)
		.wp-block-plainplugins-post-type-filter__item--active {
		background: color-mix(in srgb, currentcolor 10%, transparent);
		border-color: currentcolor;
	}

	/* Underline — a text row with a transparent 2px rule that fills when active. */
	.wp-block-plainplugins-taxonomy-filter.is-style-underline
		.wp-block-plainplugins-taxonomy-filter__item,
	.wp-block-plainplugins-meta-filter.is-style-underline
		.wp-block-plainplugins-meta-filter__item,
	.wp-block-plainplugins-post-type-filter.is-style-underline
		.wp-block-plainplugins-post-type-filter__item {
		padding: 0.15em 0;
		border-bottom: 2px solid transparent;
	}

	.wp-block-plainplugins-taxonomy-filter.is-style-underline
		.wp-block-plainplugins-taxonomy-filter__item--active,
	.wp-block-plainplugins-meta-filter.is-style-underline
		.wp-block-plainplugins-meta-filter__item--active,
	.wp-block-plainplugins-post-type-filter.is-style-underline
		.wp-block-plainplugins-post-type-filter__item--active {
		border-bottom-color: currentcolor;
	}

	/* Segmented — the options joined into one control: a rounded track with
   rounded segments inside it. Shape only; the one-row structure is in
   assets/css/defense.css. Active is a currentColor wash, like the chips; a
   theme paints the selected segment solid. */
	.wp-block-plainplugins-taxonomy-filter.is-style-segmented,
	.wp-block-plainplugins-meta-filter.is-style-segmented,
	.wp-block-plainplugins-post-type-filter.is-style-segmented {
		box-sizing: border-box;
		padding: 3px;
		border: 1px solid color-mix(in srgb, currentcolor 25%, transparent);
		border-radius: 999px;
	}

	.wp-block-plainplugins-taxonomy-filter.is-style-segmented
		.wp-block-plainplugins-taxonomy-filter__item,
	.wp-block-plainplugins-meta-filter.is-style-segmented
		.wp-block-plainplugins-meta-filter__item,
	.wp-block-plainplugins-post-type-filter.is-style-segmented
		.wp-block-plainplugins-post-type-filter__item {
		display: inline-flex;
		flex: 1 1 auto;
		align-items: center;
		justify-content: center;
		gap: 0.35em;
		padding: 0.45em 0.9em;
		border-radius: 999px;
		white-space: nowrap;
	}

	.wp-block-plainplugins-taxonomy-filter.is-style-segmented
		.wp-block-plainplugins-taxonomy-filter__item--active,
	.wp-block-plainplugins-meta-filter.is-style-segmented
		.wp-block-plainplugins-meta-filter__item--active,
	.wp-block-plainplugins-post-type-filter.is-style-segmented
		.wp-block-plainplugins-post-type-filter__item--active {
		background: color-mix(in srgb, currentcolor 12%, transparent);
	}

	/* The chip-variant wrap gap moved to assets/css/defense.css (handle
   `pqf-defense`). It HAD to: it re-declares the block's base gap rule with a
   variant class added, and that base rule is now unlayered — so a layered
   variant rule would lose to it by ORIGIN no matter that it carries one more
   class, and every pills/buttons list would silently take the roomier base gap.
   The two have to sit on the same side of the layer boundary to be ordered by
   specificity at all. */

	/* ── Results in a View Transition ─────────────────────────────────────
   shared/view-transition.js names each Query Loop result `pqf-post-{id}`,
   class `pqf-item`, for exactly as long as one of this plugin's transitions
   runs: a filter, sort or page change (`pqf-vt--results`) or the map toggle
   (`pqf-vt--map`). A result in both pictures MOVES from its old place to its
   new one; one that only the new page has fades and grows in, one that only
   the old page had fades and shrinks out. Everything unnamed cross-fades.
   Here, in the shared sheet, because every filter control can start one.

   Theme hooks, on the root (the transition pseudo-elements inherit from
   <html>): --pqf-vt-duration (300ms) and --pqf-vt-easing. A theme styles the
   results further with `::view-transition-group(*.pqf-item)`. Reduced motion
   never starts a transition, so nothing here needs a media guard. */
	.pqf-vt::view-transition-group(*) {
		animation-duration: var(--pqf-vt-duration, 300ms);
		animation-timing-function: var(
			--pqf-vt-easing,
			cubic-bezier(0.2, 0, 0, 1)
		);
	}

	.pqf-vt::view-transition-new(*.pqf-item):only-child {
		animation: pqf-vt-item-in var(--pqf-vt-duration, 300ms)
			var(--pqf-vt-easing, cubic-bezier(0.2, 0, 0, 1)) both;
	}

	.pqf-vt::view-transition-old(*.pqf-item):only-child {
		animation: pqf-vt-item-out var(--pqf-vt-duration, 300ms)
			var(--pqf-vt-easing, cubic-bezier(0.2, 0, 0, 1)) both;
	}

	@keyframes pqf-vt-item-in {
		from {
			opacity: 0;
			scale: 0.96;
		}
	}

	@keyframes pqf-vt-item-out {
		to {
			opacity: 0;
			scale: 0.96;
		}
	}
}

@layer pqf-neutral {
	/* Native state controls keep the existing filter presentation. */
	.pqf-control-form {
		display: contents;
	}
	.pqf-control-form:has(> .pqf-option) {
		display: inline-flex;
	}
	.pqf-state-control {
		appearance: none;
		background: transparent;
		border: 0;
		border-radius: 0;
		padding: 0;
		min-height: 24px;
		min-width: 24px;
		text-align: inherit;
		cursor: pointer;
	}
	.pqf-option {
		position: relative;
		display: flex;
		align-items: center;
		width: 100%;
		min-height: 24px;
		cursor: pointer;
	}
	.pqf-option__checkbox {
		position: absolute;
		width: 100%;
		height: 100%;
		inset: 0;
		opacity: 0;
		cursor: pointer;
	}
	.pqf-option__content {
		display: flex;
		align-items: center;
		gap: inherit;
		column-gap: var(--pqf-count-gap, 0.375em);
	}
	.pqf-option__fallback {
		width: 100%;
		cursor: pointer;
	}
}

@layer pqf-neutral {
	/* Tabs — a SEGMENTED CONTROL, which is a different object from the other three
   variants and not just another chip shape. Pills/Buttons/Underline decorate
   items that stay in a wrapping list; Tabs makes the list itself one surface:
   square cells butted edge to edge with no gap, divided by a hairline, on a
   single line that SCROLLS instead of wrapping.
 *
 * WHY A NEW VARIANT AND NOT A PILLS TWEAK. `is-style-pills` is a published
 * block style — it is in three block.json `styles` arrays, so every install of
 * this plugin offers "Pills" in the editor's Styles panel and an unknown number
 * of sites have chosen it. Repainting it would be a silent breaking change on
 * every one of them. Adding a style is additive and reversible; that is the
 * whole reason this section exists rather than a diff to the rule above.
 *
 * THE THREE SHAPE DECISIONS, none of which are optional for a tab strip:
 *
 *   1. The row is SHRINK-TO-FIT and self-centring (`width: fit-content` +
 *      `margin-inline: auto`) rather than a full-width flex row that centres its
 *      items. Those two look identical until the tabs stop fitting, and then
 *      they diverge badly: a full-width row with `justify-content: center`
 *      overflows in BOTH directions, so the first tab sits at a negative offset
 *      and no amount of scrolling can reach it. A fit-content row clamped by
 *      `max-width: 100%` starts its content at the inline start and scrolls
 *      cleanly to the end. The matching `justify-content: flex-start` guard is
 *      unlayered in assets/css/defense.css — see that file for why it cannot
 *      live here.
 *   2. `scrollbar-width: none`. A classic scrollbar under a tab strip adds ~15px
 *      of chrome to a control whose whole job is to be one crisp band, and it
 *      only appears on the desktop widths where the tabs already fit. The tabs
 *      remain scrollable by touch, wheel, and keyboard focus.
 *   3. The divider hangs off the INLINE-START of every item after the first
 *      (`__item + __item`) rather than the inline-end of every item but the
 *      last. `:last-child` is wrong here: with `searchable` the block also
 *      renders a no-results row after the items, so the last ITEM is not the
 *      last CHILD and the trailing divider would survive. The adjacent-sibling
 *      form cannot be fooled by anything rendered before or after the list.
 *
 * PAINT. Same contract as the rest of this file — these are DEFAULTS. The
 * elevation and the divider are the two the variant cannot do without (a
 * segmented card with neither reads as loose text on desktop backgrounds), so
 * they ship with neutral literals behind `--pqf-tabs-shadow` / `--pqf-tabs-
 * divider`, exactly as `--pqf-panel-shadow` / `--pqf-panel-bg` already do for
 * the popover. Everything else — the surface colour, the outer radius, the
 * label weight — is deliberately NOT set here: those arrive per-instance from
 * the block's own color / border / typography supports, which WordPress
 * serialises inline onto the wrapper and which therefore beat this file
 * whatever it said. */
	.wp-block-plainplugins-taxonomy-filter.is-style-tabs,
	.wp-block-plainplugins-meta-filter.is-style-tabs,
	.wp-block-plainplugins-post-type-filter.is-style-tabs {
		width: fit-content;
		max-width: 100%;
		margin-inline: auto;
		overflow-x: auto;
		overflow-y: hidden;
		scrollbar-width: none;

		/* The shared scale token, not a `--pqf-tabs-radius` of its own: this is a
		   card corner, which is exactly what `--pqf-radius-sm` is documented to be
		   (see THE SCALE TOKENS at the top of this file), and query-views'
		   `__toggle` — the plugin's other segmented control — already reads it. */
		border-radius: var(--pqf-radius-sm, 4px);
		box-shadow: var(
			--pqf-tabs-shadow,
			0 1px 3px rgb(0 0 0 / 10%),
			0 1px 2px rgb(0 0 0 / 6%)
		);
	}

	/* The cell. `flex: none` keeps every tab at its natural width inside the
   scroller — without it the flex items shrink to fit and the strip silently
   stops being scrollable at all. `position: relative` is the active bar's
   containing block. */
	.wp-block-plainplugins-taxonomy-filter.is-style-tabs
		.wp-block-plainplugins-taxonomy-filter__item,
	.wp-block-plainplugins-meta-filter.is-style-tabs
		.wp-block-plainplugins-meta-filter__item,
	.wp-block-plainplugins-post-type-filter.is-style-tabs
		.wp-block-plainplugins-post-type-filter__item {
		position: relative;
		display: inline-flex;
		flex: none;
		align-items: center;
		justify-content: center;
		white-space: nowrap;
		border-radius: 0;
		padding: var(--pqf-tabs-padding, 1em 2.5em);
		/* The underline identifies selection. A weight change would resize the
		   tab after the response commits, even without an inline spinner. */
		font-weight: inherit;

		/* The block's own base rule sets 1.4 so wrapped term lists breathe. A tab
		   never wraps, so it takes control leading instead — and this is what makes
		   the strip a predictable height: 1em padding + 1em padding + 1.15lh. */
		line-height: var(--pqf-tabs-line-height, 1.15);
	}

	.wp-block-plainplugins-taxonomy-filter.is-style-tabs
		.wp-block-plainplugins-taxonomy-filter__item
		+ .wp-block-plainplugins-taxonomy-filter__item,
	.wp-block-plainplugins-meta-filter.is-style-tabs
		.wp-block-plainplugins-meta-filter__item
		+ .wp-block-plainplugins-meta-filter__item,
	.wp-block-plainplugins-post-type-filter.is-style-tabs
		.wp-block-plainplugins-post-type-filter__item
		+ .wp-block-plainplugins-post-type-filter__item,
	.wp-block-plainplugins-taxonomy-filter[class~="is-style-tabs"]
		> .pqf-control-form
		+ .pqf-control-form
		.wp-block-plainplugins-taxonomy-filter__item,
	.wp-block-plainplugins-meta-filter[class~="is-style-tabs"]
		> .pqf-control-form
		+ .pqf-control-form
		.wp-block-plainplugins-meta-filter__item,
	.wp-block-plainplugins-post-type-filter[class~="is-style-tabs"]
		> .pqf-control-form
		+ .pqf-control-form
		.wp-block-plainplugins-post-type-filter__item {
		border-inline-start: 1px solid
			var(
				--pqf-tabs-divider,
				color-mix(in srgb, currentcolor 12%, transparent)
			);
	}

	/* Active tab — a bar along the bottom edge. A SHAPE cue, not a colour-only one
   (WCAG 1.4.1), for the same reason `__item--active` ships a font-weight bump:
   the variant has to read correctly before a theme paints anything. Sized and
   coloured through `--pqf-tabs-indicator*` so a theme can tint it without
   restating the geometry. */
	.wp-block-plainplugins-taxonomy-filter.is-style-tabs
		.wp-block-plainplugins-taxonomy-filter__item--active::after,
	.wp-block-plainplugins-meta-filter.is-style-tabs
		.wp-block-plainplugins-meta-filter__item--active::after,
	.wp-block-plainplugins-post-type-filter.is-style-tabs
		.wp-block-plainplugins-post-type-filter__item--active::after {
		content: "";
		position: absolute;
		inset-inline: 0;
		bottom: 0;
		height: var(--pqf-tabs-indicator-size, 2px);
		background: var(--pqf-tabs-indicator, currentcolor);
	}
}
