/**
 * Plain Query Filters — defensive invariants. DELIBERATELY UNLAYERED.
 *
 * DO NOT ADD AN `@layer` WRAPPER TO THIS FILE. scripts/wrap-css-layer.js lists
 * `defense.css` in UNLAYERED_SHEETS and will step over it; wrapping it by hand
 * would silently undo every rule below without changing a single byte of the
 * rules themselves — the exact failure mode this file exists to end.
 *
 * THE CONTRACT
 * ------------
 * Since 0.32 every other shipped stylesheet is wrapped in `@layer pqf-neutral`,
 * so a consuming theme's unlayered CSS beats ours by ORIGIN: at any specificity,
 * in any load order, with neither side having to reason about selector weights
 * again. That is the correct default for a plugin that ships neutral structure
 * and expects the theme to own the paint, and it is a large part of why this
 * plugin can be sold onto sites it has never seen.
 *
 * It is the wrong default for one narrow class of rule, and the original
 * justification for applying it everywhere was subtly the wrong shape. It read:
 * layering is safe because "no shipped rule targets a bare element". The premise
 * is true; the conclusion does not follow. The collision was never about what OUR
 * selectors target — it is about the bare elements this plugin RENDERS. A
 * <select>, a <label>, <option> rows, three kinds of <input>, three <button>s and
 * about a dozen <a>s go out inside our markup, and every generic `label {}` /
 * `input {}` / `a {}` rule already sitting on the consuming page reaches straight
 * into them. Class-scoping our own selectors does nothing about that. Layered, we
 * lose to all of it, at every specificity, and nothing anywhere warns you.
 *
 * Three confirmed defects came out of that gap:
 *   1. a WooCommerce store was measured lifting the sort <label> 5.3px off its
 *      own control, via nothing more exotic than
 *      `.woocommerce-page label { margin-bottom: .7em }` (0,1,1);
 *   2. the <select> font defect had to be worked around in a consuming THEME,
 *      because the plugin was not able to defend itself;
 *   3. filter-popover's own comment records every popover on every site
 *      reopening with the wrong row gap, continuously, from 0.32 onward.
 *
 * So the split is BY CONTRACT — not by block, not by file size, not by taste:
 *
 *   layered   (assets/css/controls.css, src/<block>/style.css) = DEFAULTS.
 *             "A theme MAY repaint this." Paint, sizing, decoration, preference.
 *   unlayered (this file)                                      = INVARIANTS.
 *             "This MUST survive foreign CSS on elements we render."
 *
 * Keep this file small and keep the bar high. Every declaration added here is a
 * right taken away from the consuming site, so it belongs here only if a generic
 * element rule on somebody else's stylesheet would otherwise BREAK the control —
 * not merely restyle it in a way we did not choose. Restyling is the theme's
 * prerogative and the layer exists to grant it.
 *
 * NO `!important` IN THIS FILE. EVER.
 * ------------------------------------
 * Specificity is sufficient here, and being sufficient is the entire point. Our
 * (0,2,0) already beats `.woocommerce-page label` at (0,1,1) and a bare `label`
 * at (0,0,1) — the two selector shapes behind the incidents above — while still
 * leaving a consuming theme a clean, ordinary escape one step up at (0,2,1) or
 * (0,3,0). `!important` would take that escape away entirely: an `!important`
 * author declaration also beats the theme's OWN `!important`, and for a plugin
 * sold onto other people's sites that is a right we do not own and cannot ask
 * for. If a rule here genuinely cannot win on specificity, that is a signal the
 * rule is in the wrong file or aimed at the wrong element — raise it, do not
 * reach for `!important`.
 *
 * THE DOUBLED CLASS
 * -----------------
 * `.pqf-control.pqf-control` is not a typo or a paste error. It is the
 * specificity-only idiom: identical matching, (0,2,0) instead of (0,1,0), no
 * `!important`, and no dependence on markup structure we might later change.
 * (0,1,0) would beat a bare `select {}` but LOSE to `.woocommerce-page select` —
 * which is exactly the rule shape that broke us. Anything added to this file
 * should carry the same weight for the same reason.
 *
 * Load order is irrelevant here. Unlayered author CSS beats layered author CSS by
 * origin, so `pqf-defense` wins against `pqf-controls` whichever order WordPress
 * happens to print the two <link> tags in — this file must never be made to
 * depend on being enqueued last.
 */

/**
 * The defensive half of `.pqf-control` — the shared recipe stamped onto FIVE
 * bare form controls (the sort <select>, the popover trigger <button>, the
 * map-toggle <button>, <input type=search>, <input type=number>). The paint half
 * — min-height, background, border, radius, padding, cursor — stays layered in
 * assets/css/controls.css, where a theme can still take it.
 *
 * All four declarations below are neutralisers: they say "whatever the page has
 * already done to this element, undo it", which is the one thing a theme cannot
 * be allowed to win by accident.
 */
.pqf-control.pqf-control {
	/* Controls own their box math: border-box is what makes the shared
	   min-height floor (layered, in controls.css) mean the same thing on a
	   native <select> and on an icon-bearing button, whose natural heights
	   differ. A `* { box-sizing: content-box }` or a framework reset on the
	   consuming site silently changes what every padding and min-height in this
	   plugin computes to. */
	box-sizing: border-box;

	/* THE HOOK IS NOT DECORATION — same contract as --pqf-control-line-height
	   below, and it exists for the same reason that one does.
	   `color: inherit` is what stops a consuming site's `select { color: … }` or
	   `input { color: … }` from tinting a control. But unlayered at (0,2,0) it
	   ALSO outranks a theme's own considered `color` on its own control at
	   (0,1,0) — and until this hook existed a theme had no way to win except
	   `!important` or a specificity arms race, which is precisely the taking of
	   control the layer split exists to give back. Found in the wild: a consuming
	   theme setting `color` on this plugin's search input and popover trigger,
	   silently overruled. `inherit` remains the default, so nothing changes for
	   an install that does not set the property. */
	color: var(--pqf-control-color, inherit);

	/* `font` STAYS A SHORTHAND, and stays first. It is the only declaration that
	   can defeat a consuming site's `select { font: … }` wholesale, and it resets
	   line-height to the inherited value — which is why the line-height below
	   must come after it. The two longhands that follow re-open the parts a
	   theme legitimately owns WITHOUT weakening that reset: neither
	   `font-family` nor `font-size` resets line-height, so the ordering
	   requirement is unaffected, and both default to `inherit` — exactly what
	   the shorthand alone produced. An install that sets neither property
	   renders identically to before these hooks existed.

	   WHY font-size NEEDED A HOOK. A theme's form-field scale is not decoration:
	   a consuming theme was found setting its field size to `max(1rem, 16px)`
	   deliberately, because iOS Safari zooms the viewport when a focused input
	   is under 16px. Inheriting a 14px body size silently reintroduced that zoom
	   on every filter search box on the site. A plugin has no business making
	   that call for a theme. */
	font: inherit;
	font-family: var(--pqf-control-font-family, inherit);
	font-size: var(--pqf-control-font-size, inherit);

	/* MUST stay AFTER `font`, and MUST stay in this file with it. (It used to say
	   "immediately after"; the `font-family` / `font-size` hooks above now sit
	   between the two. That is safe — neither longhand resets line-height, which
	   is the only thing the ordering protects against — but nothing else may be
	   inserted here without checking that same property.)
	   `font` is a shorthand: it resets line-height to the inherited value, so a
	   line-height declared before it is discarded. Splitting the pair across the
	   layer boundary is worse still — `font: inherit` unlayered with
	   `line-height: 1.2` left layered would let any unlayered `select {
	   line-height: 2 }` on the consuming site inflate every control on the page.
	   The value itself: controls use compact, predictable leading — article
	   leading (often 1.6+) inflates the control box and skews icon/text optical
	   alignment.

	   THE HOOK IS NOT DECORATION. Everything else in this file is an invariant no
	   theme has a legitimate reason to change; leading is the exception, because
	   control density is a real design decision and themes DO set it deliberately
	   (a consuming theme was found setting 1.4 on this very select). Unlayered at
	   (0,2,0) this rule outranks that theme's (0,1,0) declaration, so without a
	   channel we would be silently overruling considered design — the same taking
	   of control this whole split exists to give back, wearing a different hat.
	   The custom property is that channel: a theme sets
	   `--pqf-control-line-height` and wins without having to out-specify a plugin,
	   which is the contract the rest of the plugin already offers via
	   --pqf-control-padding, --pqf-control-radius and friends. */
	line-height: var(--pqf-control-line-height, 1.2);
}

/**
 * The defensive half of `.pqf-link` — the shared role class stamped onto every
 * <a> this plugin emits. There are eleven: the taxonomy-, meta- and
 * post-type-filter rows, the meta-toggle switch, active-filters' chip "x" and
 * its "Clear all", the two query-views tabs, no-results' clear link,
 * range-filter's reset, the shared reset link in inc/chips.php, and the
 * filter-popover trigger in its link mode. Same idiom as `.pqf-control` above,
 * for the same reason: a role class on a bare element, defended unlayered.
 *
 * WHY IT EXISTS
 * -------------
 * Those eleven anchors are the plugin's controls — filter rows, tabs, chips,
 * resets. They are not prose. But an anchor is an anchor to a consuming site's
 * stylesheet, and every page this plugin is sold onto already carries some form
 * of `a { color: var(--link); text-decoration: underline }`. Layered, we lose to
 * it at any specificity, and a filter list arrives underlined in link blue —
 * reading as a paragraph of links rather than as a row of controls, and
 * mismatching the sort dropdown's <option> rows beside it, which inherit.
 *
 * It also ends a duplication: the SAME two declarations were copy-pasted across
 * seven block stylesheets (taxonomy-filter, meta-filter, post-type-filter,
 * meta-toggle, active-filters, query-views, plus the chip-variant restatements
 * in assets/css/controls.css), where — being layered — none of them had won
 * anything since 0.32. One rule here replaces all seven, and four anchors that
 * never had the reset at all (`pqf-reset-link`, `no-results__clear`,
 * `range-filter__reset`, and the link-mode `filter-popover__trigger`) gain it:
 * this closes an inconsistency as well as a defect.
 *
 * SPECIFICITY — ours (0,2,0) via the doubled class. Beats a bare `a` (0,0,1) and
 * the scoped element rules that actually ship on consuming sites,
 * `.woocommerce-page a` and `.entry-content a`, both (0,1,1). WINS.
 *
 * THE HOOKS ARE MANDATORY, NOT DECORATION
 * ---------------------------------------
 * Exactly as `--pqf-control-line-height` does for control leading, and for the
 * same reason. "Should this control look like a link?" is a real design
 * decision, and themes make it deliberately: one consuming theme
 * sets `active-filters__clear { text-decoration: underline }` at (0,1,0) — a
 * "clear all filters" affordance a theme quite reasonably wants to read as a
 * link, because that is what it is. Unlayered at (0,2,0) we would outrank that
 * declaration and silently strip it: considered design overruled by a plugin,
 * with nothing anywhere to warn either party. That is the same taking of control
 * this whole split exists to give back, wearing a different hat.
 *
 * `--pqf-link-decoration` and `--pqf-link-color` hand the decision back without a
 * specificity fight — the theme sets a custom property and wins, rather than
 * having to out-specify a plugin it did not write. `inherit` / `none` remain the
 * defaults, so an unthemed install still gets a control that reads as a control.
 */
.pqf-link.pqf-link {
	color: var(--pqf-link-color, inherit);
	text-decoration: var(--pqf-link-decoration, none);
}

/* ===========================================================================
 * The defensive half of six block stylesheets, moved out of
 * `@layer pqf-neutral` (src/sort-dropdown, src/filter-popover,
 * src/taxonomy-filter, src/meta-filter, src/post-type-filter,
 * src/range-filter).
 *
 * Every rule below used to carry `!important` purely to survive the layer, or
 * carried a comment recording that it had silently stopped winning since 0.32.
 * Unlayered, none of them needs it: each states the specificity it wins on and
 * the foreign selector it beats, and each deliberately leaves a consuming theme
 * an escape one class above ours.
 * ======================================================================== */

/* ── Sort Dropdown: label margin reset ─────────────────────────────────────
 * The label is a real <label> (accessible-name association, 0.22.3), so it
 * matches themes' GENERIC form-label rules written for STACKED form fields —
 * `label { margin-bottom: .375rem }`, WooCommerce's
 * `.woocommerce-page label { margin-bottom: .7em }`. In this inline control row
 * that margin knocks the label off the select's centerline. Measured on a live
 * WooCommerce store: the label carried `margin-bottom: 9.8px` (WooCommerce's
 * .7em at the inherited 14px) and lifted "Sort by:" 5.3px above the text inside
 * its own <select>.
 *
 * SPECIFICITY — ours (0,2,0), two classes (the :is() contributes its most
 * specific branch, one class). Beats `.woocommerce-page label` (0,1,1) and a
 * bare `label` (0,0,1). WINS. A theme that genuinely wants a margin here has an
 * escape at (0,2,1) or by restyling the wrapper / retuning `--pqf-label-gap`. */
.wp-block-plainplugins-sort-dropdown
	:is(.wp-block-plainplugins-sort-dropdown__label) {
	margin: 0;
}

/* ── Filter Popover: panel row gap ─────────────────────────────────────────
 * A popover panel is a listbox, not article flow: a theme's GLOBAL blockGap
 * (`:root :where(.is-layout-flex) { gap: 16px }`, printed by WordPress from
 * theme.json) otherwise leaks into the option list and makes the dropdown
 * leggy. Rows are contiguous by default (gap 0) because inside a panel each row
 * carries its own padding — see the `--pqf-panel-item-*` defaults, which stay
 * LAYERED in src/filter-popover/style.css because they are paint. Themes and
 * authors retune the gap via `--pqf-panel-item-gap`.
 *
 * This is the rule whose own comment recorded that "from 0.32 until now this
 * rule lost outright and every popover dropdown on every consuming site
 * reopened with 16px between its rows".
 *
 * SPECIFICITY — ours (0,2,0): `.…__panel` plus the :is() branch (one class).
 * Beats `:root :where(.is-layout-flex)` at (0,1,0) — `:root` is a pseudo-class,
 * `:where()` contributes nothing. WINS. */
.wp-block-plainplugins-filter-popover__panel
	:is(
		.wp-block-plainplugins-taxonomy-filter,
		.wp-block-plainplugins-meta-filter,
		.wp-block-plainplugins-post-type-filter
	) {
	gap: var(--pqf-panel-item-gap, 0);
}

/* ── Standalone filter lists: wrap gap ─────────────────────────────────────
 * CANONICAL NOTE for the three twins below (src/taxonomy-filter,
 * src/meta-filter, src/post-type-filter — and the citation target for the
 * chip-variant rule in assets/css/controls.css).
 *
 * A filter list is a control, not article flow: it wants a compact wrap gap,
 * and the same unlayered WordPress global as above
 * (`:root :where(.is-layout-flex){gap:16px}`) otherwise leaks in as 16px+ row
 * gaps. These guards were written as an `:is()` specificity bump, went dead the
 * day `@layer pqf-neutral` shipped (unlayered author CSS beats ALL layered
 * author CSS at any specificity), and were then escalated to `!important` —
 * which also beat a consuming theme's own `!important`, a right this plugin
 * does not own. Unlayered, plain specificity is enough.
 *
 * The `:where(:not(...))` keeps these out of popover panels, where the panel
 * gap rule above (`--pqf-panel-item-gap`) stays in charge. The theme/author
 * override channel is unchanged: `--pqf-list-gap`.
 *
 * SPECIFICITY — ours (0,2,0): the block class plus the `:is(.is-layout-flex)`
 * branch; `:where()` contributes 0. Beats `:root :where(.is-layout-flex)` at
 * (0,1,0). WINS. Theme escape: any (0,3,0) rule, or the var. */
.wp-block-plainplugins-taxonomy-filter:is(.is-layout-flex):where(
		:not(.wp-block-plainplugins-filter-popover__panel *)
	) {
	gap: var(--pqf-list-gap, 0.4em 1em);
}

.wp-block-plainplugins-meta-filter:is(.is-layout-flex):where(
		:not(.wp-block-plainplugins-filter-popover__panel *)
	) {
	gap: var(--pqf-list-gap, 0.4em 1em);
}

.wp-block-plainplugins-post-type-filter:is(.is-layout-flex):where(
		:not(.wp-block-plainplugins-filter-popover__panel *)
	) {
	gap: var(--pqf-list-gap, 0.4em 1em);
}

/* ── Typeahead: a hidden row must actually collapse ────────────────────────
 * FUNCTIONAL, not cosmetic: the opt-in typeahead (`searchable`) filters by
 * setting the bare `hidden` attribute on rows. `hidden` is only a UA-stylesheet
 * `display:none`, so ANY author `display` on the row defeats it — the plugin's
 * own `.…__item { display: inline-flex }` (post-type-filter), the chip/pill
 * variants in assets/css/controls.css, or a consuming theme setting its list
 * rows to flex/grid. If this rule loses, typing in the search box hides nothing
 * and the feature looks broken.
 *
 * SPECIFICITY — ours (0,2,0): one class + one attribute selector. Beats a
 * theme's `.…__item { display: flex }` at (0,1,0) and every element-level rule.
 * WINS. (Kept at the original selector — no bump — so a theme retains a (0,3,0)
 * escape, though there is no legitimate reason to take it.) */
.wp-block-plainplugins-taxonomy-filter__item[hidden] {
	display: none;
}

.wp-block-plainplugins-meta-filter__item[hidden] {
	display: none;
}

.wp-block-plainplugins-post-type-filter__item[hidden] {
	display: none;
}

/* ── Range Filter: the reset link must actually collapse ───────────────────
 * IDENTICAL IN KIND to the three typeahead rules above, and here for the same
 * reason. The store binds `hidden` on the reset <a> whenever the range sits at
 * its full extent, and `hidden` is only a UA-stylesheet `display: none` — any
 * author `display` on that element defeats it. The reset now also carries
 * `.pqf-link`, and a theme styling its links as `inline-flex` (an icon + label
 * row, which is exactly what this element is) would leave a "Reset" control
 * permanently on screen offering to reset nothing.
 *
 * SPECIFICITY — ours (0,2,0): one class plus one attribute selector. Beats a
 * theme's `.…__reset { display: inline-flex }` at (0,1,0) and every
 * element-level rule. WINS. Kept at the original selector — no bump — so a
 * theme retains a (0,3,0) escape, as with the typeahead rules. */
.wp-block-plainplugins-range-filter__reset[hidden] {
	display: none;
}

/* ── Range Filter: the two range <input>s stay unstyled by the UA ──────────
 * FUNCTIONAL, and the bluntest case in this file. The dual-thumb control is two
 * native `<input type=range>`s stacked over one shared `__rail` element, and the
 * whole mechanism rests on the natives being stripped: lose `appearance: none`
 * and the browser restores its own track and thumb outright, so the rail paints
 * behind a second, native track and the block reads as broken rather than
 * restyled. These are bare <input>s inside our markup, so the generic rules
 * every consuming site already ships reach straight into them —
 * `input { margin: 0 0 1em }` (a stacked-form default, which here pushes the
 * upper slider off its own rail) and `.woocommerce-page input { background: #fff }`
 * (which paints an opaque band over the rail and fill beneath).
 *
 * ONLY THE THREE NEUTRALISERS MOVED. The rest of that rule — position, offsets,
 * width, height, pointer-events — is the mechanism's own geometry and stays
 * LAYERED in src/range-filter/style.css, where a theme can still take it. No
 * shorthand is split here (unlike `font` / `line-height` in `.pqf-control`
 * above), and nothing layered re-declares margin, background or appearance on
 * this element, so the split changes no outcome inside the plugin.
 *
 * SPECIFICITY — ours (0,2,0) via the doubled class; the source rule was a single
 * class (0,1,0), which loses to `.woocommerce-page input` (0,1,1). Doubled it
 * beats that and a bare `input` (0,0,1). WINS, with a (0,2,1) escape left open
 * for a theme that genuinely wants the native widget back. */
.wp-block-plainplugins-range-filter__slider.wp-block-plainplugins-range-filter__slider {
	margin: 0;
	background: none;
	-webkit-appearance: none;
	appearance: none;
}

/* ── Item template blocks: zero trapped block-axis margins ─────────────────
 * The item template's blocks (a Paragraph holding {{label}}, a Heading, …)
 * render INSIDE the <a> control row. A theme's article-flow spacing — most
 * often theme.json's `:root :where(p){margin-block-end:…}` — lands on that
 * inner element, and because the anchor is a flex item (its own formatting
 * context) the margin cannot collapse out: it becomes dead space below every
 * row's text, which in wrapped lists reads as bloated leading. Control rows
 * aren't article flow. Inline-axis margins stay authorable.
 *
 * These three were the rules `scripts/validate-contracts.js` allowlisted with
 * "dead since 0.32, needs the same !important fix the matching gap rule already
 * got" — going unlayered is that fix, without the `!important`.
 *
 * SPECIFICITY — ours (0,1,1): one class plus the :is() branch (one element).
 * Beats `:root :where(p)` at (0,1,0) and a bare `p { margin: 0 0 1em }` at
 * (0,0,1). WINS. A theme scoping to our item (e.g. `.…__item p`, also (0,1,1))
 * ties and wins on order — an intentional escape, not a defeat. */
.wp-block-plainplugins-taxonomy-filter__item > :is(p, h1, h2, h3, h4, h5, h6) {
	margin-block: 0;
}

.wp-block-plainplugins-meta-filter__item > :is(p, h1, h2, h3, h4, h5, h6) {
	margin-block: 0;
}

.wp-block-plainplugins-post-type-filter__item > :is(p, h1, h2, h3, h4, h5, h6) {
	margin-block: 0;
}

/* ── Chip variants: tighter wrap gap ──────────────────────────────────────
 * Re-declares the base list gap above with a style-variant class added, so the
 * pills/buttons lists sit tighter (0.5em/0.5em) than the default row.
 *
 * IT LIVES HERE BECAUSE ITS BASE RULE DOES. This was the last `!important` in
 * controls.css, carried to beat the theme blockGap global. Unlayered it does not
 * need one — but it also could not have STAYED layered once the base rule moved:
 * layered, it would lose to its own unlayered base by ORIGIN, and the extra
 * class would buy nothing. Two rules that override each other by specificity
 * must sit on the same side of the layer boundary; splitting them silently
 * inverts which one wins.
 *
 * SPECIFICITY — ours (0,3,0): block class + the :is() variant branch + the
 * :is(.is-layout-flex) branch (:where() contributes nothing). Beats the base
 * rule at (0,2,0) and the theme global `:root :where(.is-layout-flex)` at
 * (0,1,0). WINS. Override channel is unchanged: `--pqf-list-gap`. */
.wp-block-plainplugins-taxonomy-filter:is(
		.is-style-pills,
		.is-style-buttons
	):is(.is-layout-flex):where(
		:not(.wp-block-plainplugins-filter-popover__panel *)
	),
.wp-block-plainplugins-meta-filter:is(.is-style-pills, .is-style-buttons):is(
		.is-layout-flex
	):where(:not(.wp-block-plainplugins-filter-popover__panel *)),
.wp-block-plainplugins-post-type-filter:is(
		.is-style-pills,
		.is-style-buttons
	):is(.is-layout-flex):where(
		:not(.wp-block-plainplugins-filter-popover__panel *)
	) {
	gap: var(--pqf-list-gap, 0.5em 0.5em);
}

/* ── Tabs variant: one line, no gap, no centred overflow ───────────────────
 * The three declarations a segmented tab strip cannot be talked out of. Its
 * SHAPE is layered in assets/css/controls.css; these three are here because
 * each of them has to beat unlayered CSS that is already on the page:
 *
 *   flex-wrap      the base list wraps by design, and both the block's own
 *                  block.json layout default and WordPress's flex-layout output
 *                  say `wrap`. A tab strip that wraps is not a tab strip — it is
 *                  a two-row grid of white boxes with a stray divider.
 *   gap            re-declares the base list gap above (and the chip-variant gap
 *                  beside it) with the variant class added. Same reasoning as
 *                  that rule, verbatim: two rules that override each other by
 *                  specificity must sit on the same side of the layer boundary.
 *                  Tabs butt together, so the default is 0, not a tighter wrap.
 *   justify-content  the one that is a BUG guard rather than a style. WordPress
 *                  prints an author's flex justification as
 *                  `.wp-container-<block>-is-layout-<hash>{justify-content:center}`
 *                  — unlayered, so nothing in controls.css can reach it. Left in
 *                  place on an overflowing scroller it centres the negative free
 *                  space: the first tab sits at a NEGATIVE offset, outside the
 *                  scrollable range, and is unreachable at every viewport too
 *                  narrow for the strip. Measured on a 390px viewport with four
 *                  tabs totalling 669px. Centring is not lost — controls.css
 *                  centres the ROW instead (`width: fit-content` +
 *                  `margin-inline: auto`), which is the same result at every
 *                  width where the tabs fit and a working scroller at every
 *                  width where they do not.
 *
 * SPECIFICITY — ours (0,3,0): block class + `.is-style-tabs` + the
 * `:is(.is-layout-flex)` branch. Beats the base gap rule at (0,2,0), the
 * layout-class justification at (0,1,0) and the theme global
 * `:root :where(.is-layout-flex)` at (0,1,0). WINS. Override channels:
 * `--pqf-tabs-gap`, or any (0,4,0) rule for the other two. */
.wp-block-plainplugins-taxonomy-filter.is-style-tabs:is(.is-layout-flex),
.wp-block-plainplugins-meta-filter.is-style-tabs:is(.is-layout-flex),
.wp-block-plainplugins-post-type-filter.is-style-tabs:is(.is-layout-flex) {
	flex-wrap: nowrap;
	gap: var(--pqf-tabs-gap, 0);
	justify-content: flex-start;
}
