/* ═══════════════════════════════════════════════════════════════════════════
   COMPONENT: PRODUCT ARCHIVE + FACETS
   Moved verbatim out of main.css (plan T11a). Loaded only where the component
   renders -- see inc/assets-components.php for the predicate and the list of
   surfaces (product archives, search results, Info Center resource archive).

   CASCADE CONTRACT -- read before editing:
   * The layer-order statement below is IDENTICAL to main.css line 28, so the
     layer order is the same whichever file the browser sees first.
   * This file is enqueued with a dependency on `sepadin-styles`, so it prints
     AFTER main.css. Every rule keeps its original layer; the unlayered rules
     stay unlayered because they must beat WordPress / WooCommerce core CSS
     that is itself unlayered (each block says which rule it fights).
   * The WooCommerce `[hidden]` override stays in @layer reset: `!important`
     inverts the layer cascade (see the note above that block).
   * The pagination CONTROLS (.product-archive-pagination-controls/-arrow/
     -numbers) are NOT here: the blog, search and Info Center archives reuse
     them on pages that do not load this file, so they stay in main.css.
   ═══════════════════════════════════════════════════════════════════════════ */
@layer tokens, reset, atoms, molecules, organisms, utilities;

/* ── U1 pagination/readout/empty-state/chips (:root) (from main.css unlayered region) ── */
/* Product archive: breathing room between the product grid and the pagination.
   Must be unlayered for the same reason as the reset above — the pagination is a
   flow child of the Product Collection block, so WordPress's unlayered
   ":root :where(.is-layout-flow) > * { margin-block-start: 0 }" (blockGap is 0
   in theme.json) zeroes anything set from inside @layer.

   Separation from the grid is a SECTION-level break, not the 24px the pagination
   uses between its own rows; reusing the component gap for both made the controls
   read as part of the last product row. section--sm (42px) matches
   .blog-archive-pagination, which does the same job on the blog archive. */
:root .product-archive-pagination {
  margin-block-start: var(--wp--custom--semantic--spacing--section--sm);
}

/* Range-slider readout margin. Unlayered + :root for the same reason as the
   rules below: ":root :where(.is-layout-flow) > * { margin-block-start: 0 }" is
   unlayered and beats anything declared inside @layer, however specific. */
:root .product-archive-range-slider__readout {
  margin-block: var(--wp--custom--semantic--spacing--component--gap-sm, 0.75rem) 0;
}

/* Product archive empty state: the three declarations WordPress would otherwise win.
   MUST be unlayered, and ":root"-prefixed, for exactly the reason the pagination
   rule above documents. Measured 2026-09-07 with a CSSOM walk:
     margin-block-start  lost to  :root :where(.is-layout-flow) > * { 0 }
     text-decoration     lost to  a:where(:not(.wp-element-button)) { none }
     color               lost to  a:where(:not(.wp-element-button)) { ink }
   All three were declared in @layer organisms and silently had no effect -- an
   unlayered rule beats ANY layered rule no matter how specific.

   The clear link is the only way back for a shopper who has filtered into an
   empty result set, so it needs to read as a link rather than as plain text. */
:root .product-archive-no-results {
  margin-block-start: var(--wp--custom--semantic--spacing--section--sm);
}

:root .product-archive-no-results__clear {
  color: var(--wp--preset--color--brand);
  margin-block-start: var(--wp--custom--semantic--spacing--component--gap-sm, 0.75rem);
  text-decoration: underline;
}

:root .product-archive-no-results__clear:hover,
:root .product-archive-no-results__clear:focus-visible {
  color: var(--wp--preset--color--ink);
}

/* Active-filter chips: the two declarations WordPress would otherwise win.
   Same cause as the empty-state rules above -- a:where(:not(.wp-element-button))
   is UNLAYERED and sets both colour and text-decoration on every anchor, so a
   rule in @layer organisms silently has no effect however specific it is.

   A chip must read as a control you can click to remove, not as body text; the
   clear-all link must read as a link. */
:root .product-archive-active-filters__chip {
  color: var(--wp--preset--color--ink);
  text-decoration: none;
}

:root .product-archive-active-filters__chip:hover,
:root .product-archive-active-filters__chip:focus-visible {
  color: var(--wp--preset--color--brand);
}

:root .product-archive-active-filters__clear {
  color: var(--wp--preset--color--brand);
  text-decoration: underline;
}

:root .product-archive-active-filters__clear:hover,
:root .product-archive-active-filters__clear:focus-visible {
  color: var(--wp--preset--color--ink);
}

/* ── U2 facet details content gap (from main.css unlayered region) ── */
/* Same WP zero-margin rule also lands on wp:details (PLP sidebar filter
   panels get an auto-added is-layout-flow class) — without this, the
   filter-list content sits flush against the summary title with no gap. */
.product-archive-filter > :not(summary) {
  margin-block-start: var(--wp--custom--semantic--spacing--stack--sm);
}

/* ── U3 facet label margin, overflow fade, WC filter-block restyle, [hidden] reset, show-more (from main.css unlayered region) ── */
/* Facet option labels: WooCommerce's woocommerce-blocktheme.css sets
   `.woocommerce-page label { margin-bottom: .7em }`, unlayered, so it beat the
   layered label rules and added 9.7px under every one of our 380 option labels
   -- rows 39.9px apart against the category list's 30.2px (operator spotted
   it). The list's own `gap` owns the spacing, so the label carries none. */
:root .product-archive-filter-list__item label {
  margin: 0;
}

/* Overflow FADE -- operator: "the gradient on the overflow should be different,
   from full opacity to transparency". Replaces the grey scroll shadows. The
   options themselves dissolve toward an edge that hides more, which a
   background cannot do (backgrounds paint UNDER the text), so it is a mask on
   the scroll box: opaque (visible) through the middle, transparent at the
   edge. The mask sits on the box, not the content, so it stays put while the
   list scrolls.

   main.js sets data-overflow = none | bottom | top | both from the scroll
   position, so an edge fades only when there IS more past it -- at the start
   only the bottom fades, at the end only the top. Without JS there is no fade
   and the list still scrolls; a fade that could cover the last real option
   would be worse than none. Covers our lists and WooCommerce's. */
:root :is( .product-archive-filter-list__items, .product-archive-filter-rail .wc-block-product-filter-checkbox-list__items ) {
  --facet-fade: 2.5rem;
  /* How far the fade goes: 80%, so the option at the very edge keeps 20%
     opacity rather than vanishing (operator: "not 100% opacity, try 80").
     The mask's alpha IS the content's opacity, hence 1 - 0.8 = 0.2 here. */
  --facet-fade-edge: rgb( 0 0 0 / 0.2 );
}

:root :is( .product-archive-filter-list__items, .product-archive-filter-rail .wc-block-product-filter-checkbox-list__items )[data-overflow="bottom"] {
  -webkit-mask-image: linear-gradient( to bottom, #000 calc( 100% - var( --facet-fade ) ), var( --facet-fade-edge ) );
  mask-image: linear-gradient( to bottom, #000 calc( 100% - var( --facet-fade ) ), var( --facet-fade-edge ) );
}

:root :is( .product-archive-filter-list__items, .product-archive-filter-rail .wc-block-product-filter-checkbox-list__items )[data-overflow="top"] {
  -webkit-mask-image: linear-gradient( to bottom, var( --facet-fade-edge ), #000 var( --facet-fade ) );
  mask-image: linear-gradient( to bottom, var( --facet-fade-edge ), #000 var( --facet-fade ) );
}

:root :is( .product-archive-filter-list__items, .product-archive-filter-rail .wc-block-product-filter-checkbox-list__items )[data-overflow="both"] {
  -webkit-mask-image: linear-gradient( to bottom, var( --facet-fade-edge ), #000 var( --facet-fade ), #000 calc( 100% - var( --facet-fade ) ), var( --facet-fade-edge ) );
  mask-image: linear-gradient( to bottom, var( --facet-fade-edge ), #000 var( --facet-fade ), #000 calc( 100% - var( --facet-fade ) ), var( --facet-fade-edge ) );
}

/* ── WooCommerce filter blocks inside our rail ───────────────────────────────
   When Produse → Filtre is set to "Blocuri WooCommerce", the checkbox facets
   are woocommerce/product-filter-attribute blocks. These rules make them read
   exactly like our own lists: same type size, right-aligned counts, no box,
   and the same 17.5rem cap + scroll shadows (9a7bed5, 8c41f4b).

   UNLAYERED on purpose, like the :root rules above: WooCommerce's
   wc-block-library-style.css is unlayered, and an unlayered rule beats ANY
   @layer rule regardless of specificity -- the trap this file has hit twice.
   Scoped to .product-archive-filter-rail so WooCommerce filters placed anywhere
   else on the site keep WooCommerce's own look. */

/* The browser's default <fieldset> groove, never reset by WooCommerce. The
   wrapper is .wp-block-woocommerce-product-filter-checkbox-list (WordPress's
   block class), NOT the .wc-block-… prefix WooCommerce uses for its inner
   elements -- the first version of this rule targeted the latter and missed. */
:root .product-archive-filter-rail .wp-block-woocommerce-product-filter-checkbox-list fieldset {
  border: 0;
  margin: 0;
  min-inline-size: 0;
  padding: 0;
}

:root .product-archive-filter-rail .wc-block-product-filter-checkbox-list__items {
  display: flex;
  flex-direction: column;
  gap: var(--wp--custom--primitive--space--8);
  max-height: 18rem;
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: thin;
  scrollbar-color: var(--c-border) transparent;
}

:root .product-archive-filter-rail .wc-block-product-filter-checkbox-list__label {
  display: flex;
  inline-size: 100%;
  gap: var(--wp--custom--primitive--space--8);
  font-weight: inherit;
  cursor: pointer;
}

/* WooCommerce shrinks the text to .875em of the label; ours is the label size. */
:root .product-archive-filter-rail .wc-block-product-filter-checkbox-list__text-wrapper {
  display: flex;
  flex: 1;
  gap: var(--wp--custom--primitive--space--8);
  font-size: inherit;
}

:root .product-archive-filter-rail .wc-block-product-filter-checkbox-list__text {
  display: block;
  flex: 1;
}

/* The count is emitted as literal "(" <span>38</span> ")". Zero the wrapper's
   font-size to drop the parentheses, then restore the number at the label size
   -- same right-aligned, muted count as our own lists. */
:root .product-archive-filter-rail .wc-block-product-filter-checkbox-list__count {
  font-size: 0;
  color: var(--wp--custom--semantic--color--component--product-archive-filter-label);
}

:root .product-archive-filter-rail .wc-block-product-filter-checkbox-list__count > span {
  font-size: var(--wp--custom--semantic--typography--body-small--size);
}

/* A plain square like the native checkbox our lists use, not WooCommerce's
   tinted swatch. */
:root .product-archive-filter-rail .wc-block-product-filter-checkbox-list__input-wrapper::before {
  display: none;
}

:root .product-archive-filter-rail input[type=checkbox].wc-block-product-filter-checkbox-list__input {
  block-size: 1em;
  inline-size: 1em;
  margin: 0;
  background: var(--c-bg);
  border: 1px solid var(--c-border);
  border-radius: 2px;
}

:root .product-archive-filter-rail input[type=checkbox].wc-block-product-filter-checkbox-list__input:checked {
  background: currentColor;
  border-color: currentColor;
}

:root .product-archive-filter-rail input[type=checkbox].wc-block-product-filter-checkbox-list__input:checked + .wc-block-product-filter-checkbox-list__mark {
  color: var(--c-bg);
}

/* One overflow mechanism, not two. WooCommerce's list shows 15 then "Arată
   încă N"; the operator retired show-more for a capped scroll box
   ("the show more should be removed and we show a fixed max-height with
   scrollbar"), so every option is shown and the box above scrolls. WooCommerce
   hides the extra items with the `hidden` attribute, and has no in-list search,
   so `hidden` on an item means nothing but "past the first 15" here.

   Why this one rule sits in @layer reset and is !important: the global
   `[hidden] { display: none !important }` it has to beat lives in @layer reset
   (line ~526), and for !important declarations the cascade INVERTS -- every
   layered important declaration beats every unlayered one, and earlier layers
   beat later ones. An unlayered `display: block !important` therefore lost
   (measured: 15 of 23 rendered). Inside the same layer, specificity decides,
   and this selector is far more specific than bare [hidden], so the reset still
   governs everything else -- including our own lists' search. */
/* Mobile: one list open at a time (main.js), so it gets the same generous
   50vh region our own lists get below 768px. */
@media (max-width: 768px) {
  :root .product-archive-filter-rail .wc-block-product-filter-checkbox-list__items {
    max-height: 50vh;
  }
}

@layer reset {
  :root .product-archive-filter-rail .wc-block-product-filter-checkbox-list__item[hidden] {
    display: block !important;
  }
}

:root .product-archive-filter-rail .wc-block-product-filter-checkbox-list__show-more {
  display: none;
}

@layer organisms {

  /* ── O1 hero, listing, layout, rail, filter panels, filter-list, search, range submit, filter-list items ── */
  /* Product archive: section-by-section FSE template for shop/category pages.
     Block markup owns the archive title, filters, product query, CTA, and
     marker sections. CSS only adapts Woo output and the fixed Figma rail/grid. */
  .product-archive-hero,
  .product-archive-listing {
    box-sizing: border-box;
    padding-inline: var(--wp--custom--semantic--spacing--component--product-archive-padding-inline);
    width: 100%;
  }

  .product-archive-hero {
    padding-block-start: var(--wp--custom--semantic--spacing--component--product-archive-hero-padding-block-start);
    padding-block-end: var(--wp--custom--semantic--spacing--component--product-archive-hero-padding-block-end);
  }

  .product-archive-hero__title,
  .product-archive-hero__description {
    margin: 0;
    max-inline-size: var(--wp--custom--semantic--size--component--product-header-summary-measure);
  }

  .product-archive-hero__title {
    color: var(--wp--preset--color--ink);
    font-family: var(--wp--custom--semantic--typography--product-archive-title--family);
    font-size: var(--wp--custom--semantic--typography--product-archive-title--size);
    font-weight: var(--wp--custom--semantic--typography--product-archive-title--weight);
    letter-spacing: var(--wp--custom--semantic--typography--product-archive-title--letter-spacing);
    line-height: var(--wp--custom--semantic--typography--product-archive-title--line-height);
    text-transform: var(--wp--custom--semantic--typography--product-archive-title--text-transform);
  }

  .product-archive-listing {
    padding-block-end: var(--wp--custom--semantic--spacing--component--product-archive-listing-padding-block-end);
  }

  .product-archive-layout.wp-block-columns {
    align-items: stretch;
    margin: 0;
  }

  .product-archive-layout.wp-block-columns.is-layout-flex {
    column-gap: 0;
    gap: 0;
    row-gap: 0;
  }

  .product-archive-filter-rail,
  .product-archive-sidebar {
    border: var(--wp--custom--primitive--border--width-hairline) solid var(--wp--custom--semantic--color--component--product-archive-border);
    box-sizing: border-box;
    flex: 0 0 var(--wp--custom--semantic--size--component--product-archive-filter-rail);
    max-inline-size: var(--wp--custom--semantic--size--component--product-archive-filter-rail);
  }

  .product-archive-results,
  .product-archive-main {
    box-sizing: border-box;
    min-inline-size: 0;
  }

  .product-archive-filter {
    border-block-end: var(--wp--custom--primitive--border--width-hairline) solid var(--wp--custom--semantic--color--component--product-archive-border);
    box-sizing: border-box;
    margin: 0;
    padding:
      var(--wp--custom--semantic--spacing--component--product-archive-filter-padding-block)
      var(--wp--custom--semantic--spacing--component--product-archive-filter-padding-inline);
  }

  .product-archive-filter:last-child {
    border-block-end: 0;
  }

  .product-archive-filter summary {
    color: var(--wp--custom--semantic--color--component--product-archive-filter-label);
    cursor: pointer;
    font-family: var(--wp--custom--semantic--typography--body-mini--family);
    font-size: var(--wp--custom--semantic--typography--body-mini--size);
    font-weight: var(--wp--custom--semantic--typography--body-mini--weight);
    letter-spacing: var(--wp--custom--semantic--typography--body-mini--letter-spacing);
    line-height: var(--wp--custom--semantic--typography--body-mini--line-height);
    list-style: none;
  }

  .product-archive-filter summary::-webkit-details-marker {
    display: none;
  }

  .product-archive-filter summary::after {
    border-block-end: var(--wp--custom--primitive--border--width-hairline) solid currentColor;
    border-inline-end: var(--wp--custom--primitive--border--width-hairline) solid currentColor;
    content: "";
    display: block;
    float: right;
    height: var(--wp--custom--primitive--space--6);
    margin-block-start: var(--wp--custom--primitive--space--4);
    transform: rotate(45deg);
    width: var(--wp--custom--primitive--space--6);
  }

  .product-archive-filter[open] summary::after {
    transform: rotate(225deg);
  }

  /* margin-block-start for the content below the summary lives in the
     unlayered WP-layout-reset section near the top of this file (see
     ":root :where(.is-layout-flow) > *" there) — this rule is @layer
     organisms, and WordPress's own ":root :where(.is-layout-flow) > *
     { margin-block: 0 }" is unlayered, so it always wins here regardless
     of specificity. */

  .product-archive-filter :where(ul, ol) {
    list-style: none;
    margin: 0;
    padding: 0;
  }

  .product-archive-filter :where(a, label, select, input) {
    font-family: var(--wp--custom--semantic--typography--body-small--family);
    font-size: var(--wp--custom--semantic--typography--body-small--size);
    letter-spacing: var(--wp--custom--semantic--typography--body-small--letter-spacing);
    line-height: var(--wp--custom--semantic--typography--body-small--line-height);
  }

  .product-archive-filter a {
    color: inherit;
    text-decoration: none;
  }

  .product-archive-filter :where(.wc-block-components-filter-reset-button, .wc-block-components-checkbox-list) {
    margin-block-start: var(--wp--custom--semantic--spacing--stack--sm);
  }

  .product-archive-filter .wp-block-woocommerce-filter-wrapper {
    margin-block: var(--wp--custom--primitive--space--0);
  }

  .product-archive-filter .wp-block-woocommerce-filter-wrapper h2,
  .product-archive-filter .wp-block-woocommerce-filter-wrapper h3,
  .product-archive-filter .wp-block-woocommerce-filter-wrapper h4,
  .product-archive-filter .wp-block-woocommerce-filter-wrapper h5,
  .product-archive-filter .wp-block-woocommerce-filter-wrapper h6 {
    display: none;
  }

  /* Shared filter-list component — one visual language for every custom
     sidebar widget (Brand, Disponibilitate stoc, Sortează, Familii de
     produse), whether the row is a checkbox, a radio, or a plain link.
     Originally built for Brand (replacing wc:woocommerce/attribute-filter,
     which renders nothing — see the PHP for why); reused everywhere else so
     the sidebar reads as one consistent control, not four different ones. */
  .product-archive-filter-list__search {
    box-sizing: border-box;
    width: 100%;
    padding: var(--wp--custom--primitive--space--8) var(--wp--custom--primitive--space--12);
    border: var(--wp--custom--primitive--border--width-hairline) solid var(--wp--custom--semantic--color--component--product-archive-border);
    border-radius: var(--wp--custom--primitive--radius--control);
    font-family: inherit;
    font-size: inherit;
  }

  .product-archive-filter-list__search + .product-archive-filter-list__items {
    margin-block-start: var(--wp--custom--semantic--spacing--stack--sm);
  }

  /* Filter-rail keyword search. Narrows the current listing instead of leaving
     it: the form carries every active filter forward as hidden inputs. Shares
     the border/radius/spacing tokens with .product-archive-filter-list__search
     above so the rail reads as one control group, not two designs. Lives in
     @layer organisms like its neighbours (the layer spans 2235-7412 and is NOT
     inside a media query - check brace depth, not the nearest @media). */
  .product-archive-search {
    display: flex;
    flex-direction: column;
    gap: var(--wp--custom--primitive--space--8);
    margin-block-end: var(--wp--custom--semantic--spacing--stack--sm);
  }

  .product-archive-search__row {
    align-items: center;
    border: var(--wp--custom--primitive--border--width-hairline) solid var(--wp--custom--semantic--color--component--product-archive-border);
    border-radius: var(--wp--custom--primitive--radius--control);
    box-sizing: border-box;
    display: flex;
    gap: var(--wp--custom--primitive--space--8);
    padding-inline: var(--wp--custom--primitive--space--12);
    width: 100%;
  }

  .product-archive-search__input {
    background: transparent;
    border: 0;
    flex: 1 1 auto;
    font-family: inherit;
    font-size: inherit;
    min-width: 0;
    padding-block: var(--wp--custom--primitive--space--8);
  }

  .product-archive-search__input:focus {
    outline: none;
  }

  .product-archive-search__submit {
    background: none;
    border: 0;
    color: inherit;
    cursor: pointer;
    display: inline-flex;
    padding: 0;
  }

  .product-archive-search__clear {
    font-size: var(--wp--custom--semantic--typography--body-small--size);
  }

  /* Range-filter submit -- .product-archive-search__submit above resets
     background/border/padding to nothing, which is right for that control
     (an icon sitting INSIDE a bordered __row) but wrong here: this button
     has no row of its own to give it an edge, so with only the reset it
     rendered as unstyled 24px text with nothing to click on. Re-establish a
     real button using the SAME tokens .btn--primary uses (see @layer atoms,
     "Buttons" section) rather than inventing a colour -- restated here,
     not overridden there, because @layer atoms is lower priority than this
     @layer organisms and would lose to the reset above regardless of
     specificity or source order.
     Shared with the no-JS facet submit: the SELECTOR is extended, the block is
     not copied. This rule is already the fix for a submit that shipped as
     unstyled 24px text, and a second copy would be a second thing to keep above
     the 44px tap-target floor. */
  .product-archive-range-filter__submit,
  .product-archive-facet-form__submit {
    background-color: var(--wp--preset--color--brand);
    color: var(--wp--preset--color--surface-raised);
    border: var(--wp--custom--primitive--border--width-hairline) solid var(--wp--preset--color--brand);
    border-radius: var(--r-md);
    padding: 0.8125rem 1.5rem;
    /* 44px is the tap-target floor -- do not remove or replace with more
       padding. Padding-derived height moves whenever font-size, line-height,
       or a token changes (measured: .btn's own padding+line-height alone is
       ~43.1px, already under the floor); min-height states the requirement
       directly and survives all of that. */
    min-height: 44px;
    font-family: var(--font-alt);
    font-size: var(--fs-btn);
    font-weight: var(--fw-btn);
    letter-spacing: var(--ls-btn);
    line-height: var(--lh-btn);
    text-transform: uppercase;
    align-self: flex-start;
  }

  .product-archive-range-filter__submit:hover,
  .product-archive-facet-form__submit:hover {
    background-color: var(--wp--preset--color--ink);
    border-color: var(--wp--preset--color--ink);
  }

  .product-archive-range-filter__submit:focus-visible,
  .product-archive-facet-form__submit:focus-visible {
    outline: var(--wp--custom--primitive--border--width-hairline) solid var(--wp--preset--color--brand);
    outline-offset: 2px;
  }

  /* Visual-only "-" between the two range inputs (aria-hidden in the markup;
     the accessible names are the screen-reader-text labels either side of
     it) so a sighted user can tell which value is the lower bound once both
     placeholders are gone. */
  .product-archive-range-filter__separator {
    flex-shrink: 0;
    color: var(--wp--custom--semantic--color--component--product-archive-filter-label);
  }

  .product-archive-filter-list__items {
    display: flex;
    flex-direction: column;
    gap: var(--wp--custom--primitive--space--8);

    /* Fixed cap + scroll, replacing the old show-more toggle. Every option is
       rendered server-side now, so this is also what lets a no-JS visitor reach
       all 130 brands -- the toggle never could. 18rem (288px) shows 9 full rows
       and the 10th option's whole name inside the box, its lower half under the
       fade -- so it reads as roughly 60% visible (operator: "see about 60% of the
       item"). Measured: at 284px 64% of the letters were geometrically inside,
       but that part sat in the densest fade and read as far less; the fade, not
       the box edge, sets how much of the peek is legible. */
    max-height: 18rem;
    overflow-y: auto;

    /* Stop the page from scrolling on when the list hits its end. Matters most
       on touch, where the two scrollers otherwise fight. */
    overscroll-behavior: contain;
    scrollbar-width: thin;
    scrollbar-color: var(--c-border) transparent;
  }

  .product-archive-filter-list__items::-webkit-scrollbar {
    inline-size: 6px;
  }

  .product-archive-filter-list__items::-webkit-scrollbar-thumb {
    background: var(--c-border);
    border-radius: 3px;
  }

  .product-archive-filter-list__items::-webkit-scrollbar-thumb:hover {
    background: var(--c-text-2);
  }

  .product-archive-filter-list__item label,
  .product-archive-filter-list__item .product-archive-filter-list__link {
    display: flex;
    align-items: center;
    gap: var(--wp--custom--primitive--space--8);
    cursor: pointer;
  }

  .product-archive-filter-list__item .product-archive-filter-list__link:hover {
    color: var(--wp--preset--color--accent);
  }

  .product-archive-filter-list__name {
    flex: 1;
  }

  .product-archive-filter-list__count {
    color: var(--wp--custom--semantic--color--component--product-archive-filter-label);
  }

  /* Sortează toolbar — lives above the grid, right-aligned, always visible
     (not behind a collapsible filter like the sidebar widgets), since it
     reorders the current result set rather than narrowing it. */
  /* Toolbar carries the results count (left) and the sort control (right).
     Mobile-first: stacked, count above sort — side-by-side would squeeze the
     sort radio list, which wraps to several lines on a narrow viewport.
     From 800px they sit on one full-width row, count left, sort right. */
  /* ── O2 toolbar, inline list, rail toggle, fieldset, active filters, grid ── */
  .product-archive-toolbar {
    align-items: flex-start;
    display: flex;
    flex-direction: column;
    gap: var(--wp--custom--primitive--space--12);
    margin-block-end: var(--wp--custom--semantic--spacing--stack--sm);
    /* Inset both ends so the count and the sort control do not sit flush
       against the content column. Measured: a product card's box starts at the
       same x as this toolbar, but the card's TEXT is inset 18px -- so bare text
       at 0 reads as touching the edge while the grid does not. Uses the
       archive's own inset token (= inset--sm, 16px) rather than a new value, so
       it tracks the rest of the archive's inline rhythm. */
    padding-inline: var(--wp--custom--semantic--spacing--component--product-archive-filter-padding-inline);
    width: 100%;
  }

  @media (min-width: 800px) {
    .product-archive-toolbar {
      align-items: center;
      flex-direction: row;
      justify-content: space-between;
    }
  }

  .product-archive-filter-list--inline {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: var(--wp--custom--primitive--space--12);
  }

  /* Active-filter chips. Rendered as a SIBLING above .product-archive-toolbar,
     never inside it: at >=800px that toolbar is a flex row with
     space-between, so a third child would sit between the count and the sort
     control instead of forming its own strip.

     Only layout lives here. The chip's colour and underline are in the
     unlayered region -- an anchor loses both to WordPress's unlayered
     a:where(:not(.wp-element-button)) no matter how specific a layered rule is. */
  /* The facet container is a <fieldset> so a screen reader announces which
     filter each checkbox belongs to. A fieldset is NOT a drop-in for a div:
     UA stylesheets give it a border, padding, margin and -- the one that
     actually breaks layout -- min-inline-size: min-content, which stops it
     shrinking inside the flex rail. Reset all four.

     SCOPED TO fieldset ON PURPOSE. Four other elements carry
     .product-archive-filter-list and are still divs (category, stock and sort
     controls in section-product-archive-listing.php, plus the resource panel in
     search-scope.php). border/margin/padding are no-ops on a div, but
     min-inline-size is NOT: on a flex item `auto` means min-content, and the
     sort control is a flex child of .product-archive-toolbar. An unscoped rule
     would silently let it shrink below its content. */
  /* Mobile rail disclosure. The button is CREATED BY JS (see main.js) and is
     display:none until the mobile media query reveals it, so a desktop visitor
     never sees a control they do not need and a no-JS visitor never sees a
     button that cannot work. Applies to all three rails -- product archive,
     search results and Info Center -- because all three carry
     .product-archive-sidebar and all three stack full-width below 768px. */
  .product-archive-rail-toggle {
    display: none;
  }

  fieldset.product-archive-filter-list {
    border: 0;
    margin: 0;
    min-inline-size: 0;
    padding: 0;
  }

  .product-archive-active-filters {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: var(--wp--custom--primitive--space--12);
    margin-block-end: var(--wp--custom--semantic--spacing--stack--sm);
    padding-inline: var(--wp--custom--semantic--spacing--component--product-archive-filter-padding-inline);
    width: 100%;
  }

  .product-archive-active-filters__label {
    color: var(--wp--custom--semantic--color--component--product-archive-filter-label);
    font-size: var(--wp--custom--semantic--typography--body-small--size);
  }

  .product-archive-active-filters__list {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: var(--wp--custom--primitive--space--8, 0.5rem);
    list-style: none;
    margin: 0;
    padding: 0;
  }

  .product-archive-active-filters__chip {
    align-items: center;
    border: var(--wp--custom--primitive--border--width-hairline, 1px) solid
            var(--wp--custom--semantic--color--component--product-archive-border);
    border-radius: 999px;
    display: inline-flex;
    gap: 0.5ch;
    padding-block: 0.25rem;
    padding-inline: 0.75rem;
  }

  .product-archive-active-filters__remove {
    font-size: 1.1em;
    line-height: 1;
  }

  .product-archive-toolbar__label {
    color: var(--wp--custom--semantic--color--component--product-archive-filter-label);
    font-size: var(--wp--custom--semantic--typography--body-small--size);
  }

  .product-archive-filter-list--inline .product-archive-filter-list__items {
    flex-direction: row;
    flex-wrap: wrap;
    gap: var(--wp--custom--primitive--space--12);
  }

  .product-archive-grid.shop-product-grid.wp-block-woocommerce-product-collection {
    --wc-product-grid-columns: 4;
  }

  .product-archive-grid .wc-block-product-template {
    background: transparent;
    gap: var(--wp--custom--primitive--space--0);
  }

  .product-archive-grid .wc-block-product-template > li {
    background: var(--wp--preset--color--surface-raised);
  }

  .product-archive-grid .product-card {
    box-shadow: none;
    height: 100%;
    padding: var(--wp--custom--semantic--spacing--component--product-archive-card-padding);
  }

  /* ── O3 pagination wrapper, range slider, empty state, results count ── */
  .product-archive-pagination {
    gap: var(--wp--custom--semantic--spacing--component--product-archive-pagination-gap);
    /* margin-block-start lives in the unlayered WP-layout-reset section near the
       top of this file — same cascade war the .product-archive-filter comment
       below documents. WordPress's ":root :where(.is-layout-flow) > *
       { margin-block-start: 0 }" is unlayered (blockGap is 0 in theme.json), so
       any @layer rule here loses no matter how specific. */
    text-align: center;
  }

  /* PLP range slider. Progressive enhancement built by main.js from the two
     number inputs the server renders; the form works without any of this.
     The .--slider class is added by JS, so no-JS visitors never get the
     hiding rule below and keep the from/to inputs. */
  .product-archive-range-filter--slider .product-archive-search__row {
    display: none;
  }

  .product-archive-range-slider {
    padding-block: var(--wp--custom--semantic--spacing--component--gap-sm, 0.75rem);
    position: relative;
  }

  .product-archive-range-slider__track {
    background: var(--wp--preset--color--surface-sunken, #e9e7ea);
    border-radius: 999px;
    display: block;
    height: 4px;
    position: relative;
    width: 100%;
  }

  .product-archive-range-slider__fill {
    background: var(--wp--preset--color--brand);
    border-radius: 999px;
    position: absolute;
    inset-block: 0;
  }

  /* Both handles occupy the same row so the two tracks coincide. Only the
     thumbs stay interactive -- pointer-events on the input itself would make
     the upper one swallow every click meant for the lower. */
  .product-archive-range-slider__handle {
    appearance: none;
    -webkit-appearance: none;
    background: none;
    inset-block-start: var(--wp--custom--semantic--spacing--component--gap-sm, 0.75rem);
    inset-inline-start: 0;
    margin: 0;
    pointer-events: none;
    position: absolute;
    width: 100%;
  }

  .product-archive-range-slider__handle::-webkit-slider-thumb {
    appearance: none;
    -webkit-appearance: none;
    background: var(--wp--preset--color--brand);
    border: 2px solid var(--wp--preset--color--surface-raised, #fff);
    border-radius: 50%;
    cursor: grab;
    height: 20px;
    pointer-events: auto;
    width: 20px;
  }

  .product-archive-range-slider__handle::-moz-range-thumb {
    background: var(--wp--preset--color--brand);
    border: 2px solid var(--wp--preset--color--surface-raised, #fff);
    border-radius: 50%;
    cursor: grab;
    height: 20px;
    pointer-events: auto;
    width: 20px;
  }

  .product-archive-range-slider__handle:focus-visible::-webkit-slider-thumb {
    outline: 2px solid var(--wp--preset--color--ink);
    outline-offset: 2px;
  }

  .product-archive-range-slider__handle:focus-visible::-moz-range-thumb {
    outline: 2px solid var(--wp--preset--color--ink);
    outline-offset: 2px;
  }

  .product-archive-range-slider__readout {
    color: var(--wp--custom--semantic--color--component--product-archive-meta);
    font-family: var(--wp--custom--semantic--typography--body-small--family);
    font-size: var(--wp--custom--semantic--typography--body-small--size);
    text-align: center;
  }

  /* Empty state for the archive. Rendered by sepadin_render_no_results() and
     deliberately placed OUTSIDE wp:woocommerce/product-collection, because that
     block emits nothing whatsoever at zero results -- so anything nested in it,
     including wp:query-no-results, never appears. Lives in this unlayered region
     for the same cascade reason the neighbours document. Spacing token matches
     .blog-archive-no-results so the two empty states read as one system. */
  .product-archive-no-results {
    text-align: center;
    /* margin-block-start is set UNLAYERED further down -- see the note there. */
  }

  .product-archive-no-results__message {
    color: var(--wp--custom--semantic--color--component--product-archive-meta);
    font-family: var(--wp--custom--semantic--typography--body--family);
    font-size: var(--wp--custom--semantic--typography--body--size);
    margin: 0;
  }

  /* The escape route, not decoration: a shopper who filtered into a dead end has
     no other way back. Given a bare <a> renders as unstyled text here (the same
     trap the range submit hit), it gets an explicit visible treatment. */
  .product-archive-no-results__clear {
    display: inline-block;
    font-family: var(--wp--custom--semantic--typography--body--family);
    font-size: var(--wp--custom--semantic--typography--body--size);
    text-underline-offset: 0.2em;
    /* colour, text-decoration and margin-block-start are set UNLAYERED further
       down: WordPress's own a:where(:not(.wp-element-button)) rule is unlayered
       and beats anything set from inside @layer, regardless of specificity. */
  }

  /* .product-archive-results-count is our own renderer (the WooCommerce block
     rendered blank on page 1 of a category archive). It joins the SAME rule
     rather than getting its own, so the count keeps one set of typography
     tokens -- adding a second rule is how the two drift apart. The two block
     selectors stay for any surface still emitting the original block. */
  .product-archive-results-count,
  .product-archive-toolbar .wp-block-woocommerce-product-results-count,
  .product-archive-pagination .wp-block-woocommerce-product-results-count {
    color: var(--wp--custom--semantic--color--component--product-archive-meta);
    font-family: var(--wp--custom--semantic--typography--body-small--family);
    font-size: var(--wp--custom--semantic--typography--body-small--size);
    font-weight: var(--wp--custom--semantic--typography--body-small--weight);
    letter-spacing: var(--wp--custom--semantic--typography--body-small--letter-spacing);
    line-height: var(--wp--custom--semantic--typography--body-small--line-height);
    margin: 0;
  }

  .product-archive-pagination .wp-block-query-pagination {
    margin: 0;
  }

  /* ── M mobile (max-width: 768px) archive rules ── */
  @media (max-width: 768px) {
    .product-archive-hero,
    .product-archive-listing {
      padding-inline: var(--wp--custom--semantic--spacing--inset--sm);
    }

    .product-archive-filter-rail,
    .product-archive-sidebar {
      flex-basis: 100%;
      max-inline-size: none;
    }

    /* One facet is open at a time below 768px (main.js closes the rest), so the
       open one can afford a generous scroll region rather than a peephole.
       A taller box also makes it obvious WHICH scroller the finger is on. */
    .product-archive-filter-list__items {
      max-height: 50vh;
    }

    /* Below 768px the rail is full-width and sits above the grid, so a shopper
       scrolls past every facet before the first product. Collapse it behind a
       disclosure. Collapsed IN PLACE rather than as a fixed overlay: the rail is
       already full-width and correctly ordered in the document, so this needs no
       focus trap, no scroll lock and no second escape path. */
    .product-archive-rail-toggle {
      background: none;
      border: var(--wp--custom--primitive--border--width-hairline, 1px) solid
              var(--wp--custom--semantic--color--component--product-archive-border);
      cursor: pointer;
      display: block;
      inline-size: 100%;
      margin-block-end: var(--wp--custom--semantic--spacing--stack--sm);
      padding-block: 0.75rem;
      text-align: start;
      padding-inline: var(--wp--custom--semantic--spacing--component--product-archive-filter-padding-inline);
    }

    /* The class is added by JS, never by the server, so a no-JS visitor keeps an
       open rail -- degraded, not broken. */
    .product-archive-sidebar.is-collapsed {
      display: none;
    }

    .product-archive-grid.shop-product-grid.wp-block-woocommerce-product-collection {
      --wc-product-grid-columns: 2;
    }
  }
}
