:where(.spf-filter-area) {
  color: var(--spf-text-color, var(--bde-body-text-color, #1f2937));
}

:where(.spf-options) {
  display: grid;
  gap: var(--spf-gap, 0.625rem);
}

:where(.spf-filter-area button, .spf-filter-area input, .spf-filter-area select, .spf-filter-area a):focus-visible {
  outline: var(--spf-focus-width, 2px) solid var(--spf-focus-color, #2563eb);
  outline-offset: 2px;
}

/* Hierarchical checkbox tree (Checkbox 'hierarchical' option, Render\FacetRenderer's
   renderHierarchicalCheckbox()): a nested <ul class="spf-choice-children" data-depth="n">
   under each parent's own <li class="spf-choice-item">. Only the browser's native list box
   model (markers, default margin/padding) is reset here; the actual indent rhythm is a
   preset concern, exactly like .spf-options' own display/gap default just above. Flat mode
   (the default) never emits any of these classes, so this rule never touches it. */
:where(.spf-choice-tree),
:where(.spf-choice-children) {
  list-style: none;
  margin: 0;
  padding: 0;
}

:where(.spf-choice-children) {
  display: grid;
  gap: var(--spf-gap, 0.625rem);
  margin-top: var(--spf-gap, 0.625rem);
  padding-left: var(--spf-choice-indent, 1.25rem);
}

:where(.spf-choice-item) {
  display: block;
}


/* Active-filter chips (Render\UtilityShortcodes::activeFilters, filled by sf-chips.js).
   Structural only: shape and spacing so a chip reads as a removable tag rather than as a line
   of text with a stray cross after it. The container and its items carry list ROLES instead of
   list elements, so no theme bullet can render in front of them; see the shortcode's own
   comment. Presets restyle colour on top through the same classes. */
.spf-active-filters {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
}

.spf-active-filters .spf-chip {
  display: inline-flex;
  align-items: center;
  margin: 0;
  padding: 0;
}

.spf-active-filters .spf-chip button {
  display: inline-flex;
  align-items: center;
  gap: 0.4375rem;
  min-height: 2rem;
  padding: 0 0.75rem;
  border: 1px solid var(--spf-card-border, rgba(15, 23, 42, 0.12));
  border-radius: 999px;
  background: var(--spf-chip-bg, rgba(15, 23, 42, 0.04));
  color: inherit;
  font-size: 0.8125rem;
  font-weight: 600;
  line-height: 1;
  cursor: pointer;
}

.spf-active-filters .spf-chip button:hover {
  border-color: var(--spf-choice-accent, #2563eb);
  color: var(--spf-choice-accent, #2563eb);
}

.spf-active-filters .spf-chip button:focus-visible {
  outline: 2px solid var(--spf-focus-color, var(--spf-choice-accent, #2563eb));
  outline-offset: 2px;
}

/* An empty state is a note, not a control. */
.spf-active-filters .spf-active-filters-empty {
  display: inline-flex;
  align-items: center;
  opacity: 0.65;
  font-size: 0.8125rem;
}


/* Product colour swatches ([spf_product_swatches], Woo\ProductSwatchShortcode): links to the
   sibling products that are the same item in another colour. Only the browser's own list box
   model is reset here, exactly like .spf-choice-tree above; the swatch circle itself reuses the
   .spf-swatch class the colour-swatch FACET already renders, so a preset styles both at once and
   skeleton mode keeps its promise of shipping no looks of its own. */
/* NOT wrapped in :where() here, unlike the facet rules above, and that difference is the whole
   point. :where() has specificity 0, which is right for rules a preset should be able to
   override, but useless against a THEME: `ul { list-style: disc }` and `li { margin }` are
   element selectors that beat 0 every time. Rendered inside a real shop theme this list showed
   three of the theme's own bullets and no swatches at all, because the reset lost and the
   circles had no size of their own.

   So the product-swatch block carries plain class specificity: it has to win against whatever
   the theme does to lists, on any site, without a priority override. */
.spf-product-swatches {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--spf-gap, 0.625rem);
}

.spf-product-swatches .spf-product-swatch {
  list-style: none;
  margin: 0;
  padding: 0;
}

.spf-product-swatch-link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  text-decoration: none;
  border: 0;
}

/* The circle needs a size of its own. Until now .spf-swatch was sized ONLY by the four preset
   stylesheets, so anywhere a preset does not reach (skeleton mode, or a product page rendered
   before one loads) it was an empty span with no dimensions and rendered as nothing at all.
   An invisible swatch is not a styling preference, it is a control you cannot see or click,
   which is why this belongs in the always-loaded sheet next to .spf-visually-hidden rather than
   in the presets.

   Single class on purpose, matching the presets' own `.spf-swatch` weight exactly: equal
   specificity is resolved by source order, and spf-base.css is always enqueued BEFORE a preset
   (PresetAssets lists it as the preset's dependency), so a preset still wins every property it
   sets. This is a floor, not a ceiling, and it fixes the facet swatches on a skeleton site in
   the same stroke. */
.spf-swatch {
  display: block;
  width: var(--spf-swatch-size, 1.5rem);
  height: var(--spf-swatch-size, 1.5rem);
  border-radius: var(--spf-swatch-radius, 999px);
  border: 1px solid var(--spf-swatch-border, rgba(15, 23, 42, 0.15));
  background-size: cover;
  background-position: center;
}

/* The colour being viewed. A ring rather than a colour change: the swatch already carries a
   colour, so the active state has to read as a shape. Same selector the presets use, so they
   override it rather than drawing a second ring next to this one. */
.spf-product-swatch.is-current .spf-product-swatch-link {
  box-shadow: 0 0 0 2px #fff, 0 0 0 4px var(--spf-choice-accent, #2563eb);
  border-radius: var(--spf-swatch-radius, 999px);
  cursor: default;
}


/* Regular WooCommerce variable products. The real select remains in the form and is hidden
   only after the companion script is alive; without JavaScript the custom UI stays hidden and
   WooCommerce's original dropdown remains completely usable. */
.spf-variable-control {
  --spf-variable-accent: var(--spf-choice-accent, #2563eb);
  --spf-variable-ink: var(--spf-text-color, currentColor);
  --spf-variable-line: var(--spf-card-border, rgba(15, 23, 42, 0.15));
  --spf-variable-surface: var(--spf-card-bg, #fff);
  position: relative;
  width: 100%;
  max-width: 34rem;
  color: var(--spf-variable-ink);
}

.spf-variable-control:not([data-spf-ready="1"]) > .spf-variable-options,
.spf-variable-control:not([data-spf-ready="1"]) > .spf-variable-dropdown {
  display: none;
}

.spf-variable-control[data-spf-ready="1"] > [data-spf-native-variation-select] {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.spf-variable-options {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.625rem;
}

.spf-variable-control .spf-variable-option {
  position: relative;
  appearance: none;
  -webkit-appearance: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  min-width: 2.75rem;
  min-height: 2.75rem;
  margin: 0;
  padding: 0.375rem;
  border: 1px solid var(--spf-variable-line);
  border-radius: 999px;
  background: var(--spf-variable-surface);
  color: inherit;
  font: inherit;
  line-height: 1;
  box-shadow: 0 1px 2px rgba(15, 23, 42, 0.04);
  cursor: pointer;
  transition: border-color 160ms ease, box-shadow 160ms ease, transform 160ms ease;
}

.spf-variable-control .spf-variable-swatch-option {
  padding: 0.3125rem;
}

.spf-variable-control .spf-variable-swatch-option:has(.spf-variable-swatch-label) {
  padding-right: 0.875rem;
}

.spf-variable-control .spf-variable-option .spf-swatch {
  flex: 0 0 auto;
  width: 2rem;
  height: 2rem;
  border-color: rgba(15, 23, 42, 0.18);
}

.spf-variable-swatch-label,
.spf-variable-badge-label {
  display: inline-flex;
  align-items: center;
  padding: 0 0.25rem;
  font-size: 0.875rem;
  font-weight: 650;
  line-height: 1.15;
}

.spf-variable-control .spf-variable-badge-option {
  min-width: 3rem;
  padding: 0.6875rem 1rem;
  border-radius: 0.75rem;
}

.spf-variable-control .spf-variable-option:hover:not(:disabled),
.spf-variable-control .spf-variable-option:focus-visible {
  border-color: var(--spf-variable-accent);
  transform: translateY(-1px);
}

.spf-variable-control .spf-variable-option:focus-visible,
.spf-variable-dropdown-trigger:focus-visible,
.spf-variable-dropdown-option:focus-visible {
  outline: 2px solid var(--spf-variable-accent);
  outline-offset: 2px;
}

.spf-variable-control .spf-variable-option.is-selected {
  border-color: var(--spf-variable-accent);
  box-shadow: 0 0 0 1px var(--spf-variable-accent), 0 5px 14px rgba(15, 23, 42, 0.1);
}

.spf-variable-option-check {
  display: none;
}

.spf-variable-control .spf-variable-option.is-unavailable,
.spf-variable-control .spf-variable-option:disabled,
.spf-variable-dropdown-option.is-unavailable,
.spf-variable-dropdown-option:disabled {
  opacity: 0.38;
  cursor: not-allowed;
  filter: saturate(0.45);
  transform: none;
}

.spf-variable-control .spf-variable-option.is-unavailable::after,
.spf-variable-control .spf-variable-option:disabled::after {
  content: "";
  position: absolute;
  inset: 50% 0.3125rem auto;
  height: 1px;
  background: currentColor;
  transform: rotate(-35deg);
  transform-origin: center;
}

.spf-variable-dropdown {
  position: relative;
  width: min(100%, 25rem);
}

.spf-variable-dropdown-trigger {
  appearance: none;
  -webkit-appearance: none;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: 1rem;
  width: 100%;
  min-height: 3.25rem;
  margin: 0;
  padding: 0.75rem 1rem 0.75rem 1.125rem;
  border: 1px solid var(--spf-variable-line);
  border-radius: 0.875rem;
  background:
    linear-gradient(180deg, rgba(255, 255, 255, 0.72), rgba(248, 250, 252, 0.44)),
    var(--spf-variable-surface);
  color: inherit;
  font: inherit;
  text-align: left;
  box-shadow: 0 8px 24px rgba(15, 23, 42, 0.06), inset 0 1px 0 rgba(255, 255, 255, 0.75);
  cursor: pointer;
  transition: border-color 160ms ease, box-shadow 160ms ease;
}

.spf-variable-dropdown-value {
  min-width: 0;
  overflow: hidden;
  font-size: 0.9375rem;
  font-weight: 650;
  line-height: 1.25;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.spf-variable-dropdown-chevron {
  width: 0.625rem;
  height: 0.625rem;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  opacity: 0.65;
  transform: rotate(45deg) translateY(-0.125rem);
  transition: transform 160ms ease;
}

.spf-variable-control.is-open .spf-variable-dropdown-trigger {
  border-color: var(--spf-variable-accent);
  box-shadow: 0 0 0 1px var(--spf-variable-accent), 0 12px 32px rgba(15, 23, 42, 0.1);
}

.spf-variable-control.is-open .spf-variable-dropdown-chevron {
  transform: rotate(225deg) translate(-0.125rem, -0.125rem);
}

.spf-variable-control .spf-variable-dropdown-menu {
  position: absolute;
  z-index: 1000;
  top: calc(100% + 0.5rem);
  right: 0;
  left: 0;
  display: grid;
  gap: 0.25rem;
  max-height: min(20rem, 55vh);
  margin: 0;
  padding: 0.4375rem;
  overflow-y: auto;
  border: 1px solid var(--spf-variable-line);
  border-radius: 0.875rem;
  background: var(--spf-variable-surface);
  box-shadow: 0 24px 56px rgba(15, 23, 42, 0.16), 0 4px 12px rgba(15, 23, 42, 0.08);
}

.spf-variable-control .spf-variable-dropdown-menu[hidden] {
  display: none;
}

.spf-variable-dropdown-option {
  appearance: none;
  -webkit-appearance: none;
  display: grid;
  grid-template-columns: minmax(0, 1fr) 1.25rem;
  align-items: center;
  gap: 0.75rem;
  width: 100%;
  min-height: 2.75rem;
  margin: 0;
  padding: 0.625rem 0.75rem;
  border: 0;
  border-radius: 0.625rem;
  background: transparent;
  color: inherit;
  font: inherit;
  font-size: 0.9375rem;
  line-height: 1.25;
  text-align: left;
  cursor: pointer;
}

.spf-variable-dropdown-option:hover:not(:disabled),
.spf-variable-dropdown-option:focus-visible {
  background: color-mix(in srgb, var(--spf-variable-accent) 8%, transparent);
}

.spf-variable-dropdown-option.is-selected {
  background: color-mix(in srgb, var(--spf-variable-accent) 11%, transparent);
  color: var(--spf-variable-accent);
  font-weight: 700;
}

.spf-variable-dropdown-option.is-selected .spf-variable-option-check {
  display: block;
  width: 0.75rem;
  height: 0.4rem;
  margin-top: -0.125rem;
  border-bottom: 2px solid currentColor;
  border-left: 2px solid currentColor;
  transform: rotate(-45deg);
}

@media (max-width: 480px) {
  .spf-variable-control,
  .spf-variable-dropdown {
    max-width: none;
  }

  .spf-variable-control .spf-variable-badge-option {
    min-height: 2.875rem;
  }
}

@media (prefers-reduced-motion: reduce) {
  .spf-variable-control .spf-variable-option,
  .spf-variable-dropdown-trigger,
  .spf-variable-dropdown-chevron {
    transition: none;
  }
}



/* LAYOUT INSIDE AN OPEN DRAWER.
   The panel does not render the filters, it BORROWS them from the page (sf-drawer.js adopt()),
   so whatever those elements were given in a wide builder row travels with them: horizontal
   flow, fixed column widths, side-by-side option lists. Dropped into a 22rem off-canvas panel
   that reads as a broken layout, with option labels running off the right edge and count badges
   crammed against the next checkbox.

   The panel therefore imposes a single-column, full-width layout on everything it holds. Scoped
   to .spf-drawer-active so none of it can touch the desktop layout the filters came from, and
   written with enough specificity to beat the preset and theme rules that produced the original
   arrangement, without a priority override. */
[data-sf-drawer-enabled="1"].spf-drawer-active .spf-facet,
[data-sf-drawer-enabled="1"].spf-drawer-active .spf-filter-group,
[data-sf-drawer-enabled="1"].spf-drawer-active .spf-options,
[data-sf-drawer-enabled="1"].spf-drawer-active .spf-choice-tree {
  width: 100%;
  max-width: 100%;
  min-width: 0;
  float: none;
}

[data-sf-drawer-enabled="1"].spf-drawer-active .spf-facet {
  margin: 0 0 1.5rem;
}

/* One option per row, always. */
[data-sf-drawer-enabled="1"].spf-drawer-active .spf-options,
[data-sf-drawer-enabled="1"].spf-drawer-active .spf-choice-tree,
[data-sf-drawer-enabled="1"].spf-drawer-active .spf-choice-children {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0.625rem;
}

/* Label left, count hard right, and a label long enough to wrap does so instead of pushing the
   count off the panel. */
[data-sf-drawer-enabled="1"].spf-drawer-active .spf-option {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  width: 100%;
  min-width: 0;
}

[data-sf-drawer-enabled="1"].spf-drawer-active .spf-option .spf-option-label {
  flex: 1 1 auto;
  min-width: 0;
  overflow-wrap: anywhere;
}

[data-sf-drawer-enabled="1"].spf-drawer-active .spf-option .spf-count {
  flex: 0 0 auto;
  margin-left: auto;
}

[data-sf-drawer-enabled="1"].spf-drawer-active .spf-option input[type="checkbox"],
[data-sf-drawer-enabled="1"].spf-drawer-active .spf-option input[type="radio"] {
  flex: 0 0 auto;
}

/* Swatches stay a wrapping row: they are the one control that reads better side by side. */
[data-sf-drawer-enabled="1"].spf-drawer-active .spf-swatches {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}

/* Buttons in a drawer are full-width blocks, not free-floating blobs sized by their own text. */
[data-sf-drawer-enabled="1"].spf-drawer-active .spf-reset,
[data-sf-drawer-enabled="1"].spf-drawer-active .spf-apply,
[data-sf-drawer-enabled="1"].spf-drawer-active button[data-sf-reset] {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: auto;
  min-height: 2.5rem;
  padding: 0 1.25rem;
  border-radius: 999px;
  line-height: 1;
}

/* The price slider and any range control must not push the panel wider than the viewport. */
[data-sf-drawer-enabled="1"].spf-drawer-active .spf-range,
[data-sf-drawer-enabled="1"].spf-drawer-active input[type="range"] {
  width: 100%;
  max-width: 100%;
}

/* Nothing inside may introduce a horizontal scrollbar. */
[data-sf-drawer-enabled="1"].spf-drawer-active * {
  max-width: 100%;
}

/* Mobile drawer MECHANICS, shared by every preset AND skeleton mode, on the same argument
   .spf-visually-hidden below is here for: assets/sf-drawer.js only ever toggles classes, so
   whatever turns those classes into an off-canvas panel has to exist unconditionally.

   Until this block existed the mechanics lived exclusively in
   adapters/breakdance/bd-elements/SPF_Filter_Area/default.css, which only Breakdance loads.
   The four presets carry the drawer's LOOK with builder-neutral selectors, but none of them
   carries these four rules: the toggle's hidden/shown state, the desktop hiding of the drawer
   chrome, and the body scroll lock. A Divi or [spf_filter_area] drawer therefore rendered a
   permanently visible toggle plus an inline close header and apply bar on desktop, with a
   scrollable background while open, on EVERY preset and not only on skeleton.

   Everything here is wrapped in :where() (specificity 0) so both the presets and the existing
   Breakdance sheet keep winning wherever they define the same property. This block is the
   floor, never the ceiling: adding it changes nothing on a Breakdance page.

   Breakpoint ownership stays with the script (see sf-drawer.js's own docblock): these rules
   hang off the .spf-drawer-active class it sets, and never restate a width themselves. */
:where(.spf-drawer-toggle) {
  display: none;
}

/* The toggle is a FLOATING control, not a block in the content flow.
   It used to be a plain inline-block sitting wherever the panel happened to be in the page,
   which on a real shop meant it scrolled away with the header and, unstyled, read as a stray
   line of text rather than a button. A filter button you have to scroll back up to find is a
   filter button nobody presses, so position and appearance are BOTH part of the mechanism here
   and not a preset's decoration. Presets still win on colour, radius and typography, because
   every rule below is specificity 0. */
/* GEOMETRY AND STACKING: real class specificity, not :where().
   These are the properties that decide whether the button can be seen and hit at all, so a
   preset must not be able to undercut them by accident. It did: every preset styles
   `.spf-drawer-toggle` with a compact desktop padding and font size, which at specificity 0-1-0
   beat the :where() version of this rule and shrank the floating button back below a usable
   touch target. The z-index was likewise too low to clear a theme's product cards, so the
   button rendered behind them.

   Colour and shape stay in the :where() block below, where presets are still meant to win. */
.spf-drawer-toggle.spf-drawer-active {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  position: fixed;
  left: 50%;
  transform: translateX(-50%);
  bottom: calc(var(--spf-drawer-toggle-offset, 1.25rem) + env(safe-area-inset-bottom, 0px));
  /* Above the drawer's own backdrop and panel is wrong (the button hides while open), but it
     must clear whatever the THEME stacks: product cards, sticky headers, add-to-cart bars.
     Deliberately far above the plugin's own 1000/1001 rather than one step above it. */
  z-index: var(--spf-drawer-toggle-z, 99998);
  /* WCAG 2.5.5: at least a 44px target, and comfortably more on a phone where this is the one
     control standing between a shopper and the filters. */
  min-height: 3.25rem;
  padding: 0 2rem;
  font-size: 1.0625rem;
  line-height: 1;
  /* Never wider than the viewport on a small phone. */
  max-width: calc(100vw - 2rem);
}

/* PLACED BY THE AUTHOR, not floating. [spf_drawer_toggle] renders this modifier, and
   sf-drawer.js:211 adopts that button instead of building its own -- so a page either has a
   floating button or one where the author put it, never both.

   Everything the .spf-drawer-active rule above sets for FLOATING is handed back here; what
   stays is the part that is not about position: the display switch that reveals the button
   below the breakpoint, and the touch target. Same specificity as the rule it answers
   (0-2-0), and it comes later, so it wins on order alone -- no priority override. */
.spf-drawer-toggle--inline.spf-drawer-active {
  position: static;
  left: auto;
  bottom: auto;
  transform: none;
  z-index: auto;
  max-width: none;
}

/* While the drawer is open the button would sit under the panel; hiding it stops it showing
   through and stops it being a tab stop inside the focus trap. */
.spf-drawer-toggle.spf-drawer-active[aria-expanded="true"],
/* Scrolled past the results this button filters. It is fixed to the viewport, so without this
   it would hover over the header, the footer and every unrelated section of the page. */
.spf-drawer-toggle.spf-drawer-active.spf-drawer-toggle-away {
  display: none;
}

/* APPEARANCE: presets override all of this. */
:where(.spf-drawer-toggle.spf-drawer-active) {
  border: 0;
  border-radius: 999px;
  background: var(--spf-choice-accent, #2563eb);
  color: #fff;
  font-weight: 700;
  cursor: pointer;
  box-shadow: 0 8px 24px rgba(15, 23, 42, 0.28);
}

/* The open drawer has to clear the same theme chrome the button does. The panel and its
   backdrop sat at 1001/1000, chosen before anyone had put this in front of a real shop theme;
   a product grid stacking above that would have left the drawer opening BEHIND the page it is
   supposed to cover. Stacking only, on real specificity, so presets keep every other property
   including the panel's own width, colour and radius. */
[data-sf-drawer-enabled="1"].spf-drawer-active {
  z-index: var(--spf-drawer-panel-z, 100000);
}

.spf-drawer-backdrop {
  z-index: var(--spf-drawer-backdrop-z, 99999);
}

:where([data-sf-drawer-enabled="1"].spf-drawer-active) {
  position: fixed;
  inset: 0 0 0 auto;
  width: min(90vw, 22rem);
  max-width: 100vw;
  overflow-y: auto;
  background: var(--spf-drawer-bg, #fff);
  transform: translateX(100%);
  transition: transform 0.2s ease;
  /* Stacking lives in its own rule above, on real specificity; keeping a second value here
     would be a preset-overridable copy of a number that must not be overridable. */
  padding: 1rem;
  /* A closed drawer sits off-canvas; visibility keeps it out of the tab order too. */
  visibility: hidden;
}

:where([data-sf-drawer-enabled="1"].spf-drawer-active.spf-drawer-open) {
  transform: translateX(0);
  visibility: visible;
}

:where(.spf-drawer-backdrop) {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.4);
}

/* Above the breakpoint the panel is a normal in-flow block again, so the chrome the script
   injected into it (close header, sticky apply bar) must not show up inside the page layout. */
:where([data-sf-drawer-enabled="1"]:not(.spf-drawer-active) .spf-drawer-header),
:where([data-sf-drawer-enabled="1"]:not(.spf-drawer-active) .spf-drawer-sticky) {
  display: none;
}

:where(.spf-drawer-header) {
  display: flex;
  justify-content: flex-end;
}

:where(.spf-drawer-sticky) {
  position: sticky;
  bottom: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  background: var(--spf-drawer-bg, #fff);
}

:where(.spf-drawer-close),
:where(.spf-drawer-apply) {
  cursor: pointer;
}

html:where(.spf-drawer-lock) {
  overflow: hidden;
}


/* IN-FLIGHT FEEDBACK, shared by every preset AND skeleton mode, for the same reason
   .spf-visually-hidden below is here: assets/sf-runtime.js only ever flips an attribute, so
   whatever turns that attribute into something a shopper can see has to exist unconditionally.

   Selector shape is dictated by the runtime, not by taste. Scope.prototype.setBusy()
   (assets/sf-runtime.js:632-634) writes aria-busy on THIS.ROOT, and this.root is the
   `[data-sf-area="<scopeId>"]` element when the route emits one, or document.body when it does
   not (SF.init(), assets/sf-runtime.js:655 -- the Divi results-connector route deliberately
   emits data-sf-scope and no data-sf-area, see src/Render/DrawerAttributes.php:28-42). Both
   roots are ANCESTORS of the results fragment, never the fragment itself, so this needs a
   descendant selector and both roots need naming: a `[data-sf-fragment][aria-busy]` rule would
   match nothing at all, and dropping the body variant would silently skip every Divi and
   shortcode scope. Real class/attribute specificity, no :where(): a preset must not be able to
   undercut the one signal that a click was registered.

   Until this existed aria-busy was screen-reader-only. On a slow host a click left the old,
   now-wrong result set fully lit and fully clickable for the whole request, so the page read
   as frozen and a second click landed on a card that was about to be replaced. */
[data-sf-area][aria-busy="true"] [data-sf-fragment="results"],
body[aria-busy="true"] [data-sf-fragment="results"] {
  opacity: var(--spf-busy-opacity, 0.45);
  pointer-events: none;
  /* Declared inside the busy rule and NOT on the fragment itself, so the dim fades in over
     the request while the finished result set appears at full opacity immediately: new
     results should never have to wait out a fade to be readable. */
  transition: opacity var(--spf-busy-fade, 120ms) ease;
}

/* Facets deliberately stay fully interactive while a request is in flight. Locking them out
   was tried and reverted: the runtime ABORTS the in-flight request on the next interaction
   (assets/sf-runtime.js, Scope.prototype.request) precisely so a shopper can tick three boxes
   in a row without waiting, and on a slow host that request is seconds long -- a lock would
   swallow those clicks and read as an unresponsive filter panel, which is the exact complaint
   this whole in-flight treatment exists to answer. Only the RESULTS dim, because only the
   results are the thing that is briefly out of date. */

/* The dim itself is the information, so it stays; only the animation goes. */
@media (prefers-reduced-motion: reduce) {
  [data-sf-area][aria-busy="true"] [data-sf-fragment="results"],
  body[aria-busy="true"] [data-sf-fragment="results"] {
    transition: none;
  }
}


/* Screen-reader-only, shared by every preset AND skeleton mode. The color-swatch widget
   hides its real checkbox and its accessible label text with this class (FacetRenderer),
   so it must exist even when no preset stylesheet is active, or the checkbox and label
   text render visibly on a skeleton site (launch audit). */
.spf-visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}


/* A container the drawer emptied by adopting every filter out of it (assets/sf-drawer.js sets
   this class, and removes it before handing the filters back). Adoption moves the elements, so
   without this the sidebar they came from keeps its full width holding nothing: with the drawer
   active on desktop that is a 225px empty gutter beside the product grid.

   In spf-base.css rather than in a preset because the drawer is available with no preset at all.
   The class is repeated to reach specificity (0,2,0) so it outranks the page builder's own
   single-class column rules. This file deliberately carries no priority overrides at all -- the
   drawer suite asserts their absence -- so a preset, or a shop's own stylesheet, can always
   answer back. Only ever applied to a container with nothing left in it: sf-drawer.js checks
   that before adding the class, so this can never hide content the drawer did not take. */
.spf-drawer-vacated.spf-drawer-vacated {
  display: none;
}
