/* .container-catalog-results (post 61 node 101, wraps the whole sidebar+results row)
   has a native "Image" background enabled at the Tablet Portrait breakpoint
   (breakpoint_tablet_portrait, <=1023px) with no image ever actually picked — confirmed via
   get-css-selectors, the backgrounds array has {type:"image",disabled:false} but no
   image.id/url. Renders as a broken-image placeholder SVG tiled across the entire results
   column (the "strange grey background" behind the product grid on every mobile catalog
   page). Cleared via specificity override rather than editing the Selector Library entry
   directly — the class also carries breakpoint_base layout/size properties that a raw
   insert-stylesheet rewrite would silently wipe if not restated in full (see the
   div-catalog-sidebar z-index fix above for why). Confirmed 2026-07-30. */
@media (max-width: 1023px) {
  body.breakdance .container-catalog-results {
    background-image: none;
  }
}

/* .section-shop-search-results (post 61 node 100, the outer Section wrapping the whole
   sidebar+results row, parent of .container-catalog-results above) carries the exact same
   unset "Image" background bug as its child, independently — confirmed via raw Selector
   Library read: breakpoint_tablet_portrait.background.backgrounds = [{"type":"image"}], no
   "image" key at all, no "disabled" key (defaults to enabled). Oxygen compiles this to a
   literal data: URI of its own placeholder/empty-state SVG, rendering as a light-grey box
   with faint lettering behind the whole catalog content area on any <=1023px viewport --
   reported again 2026-08-04 (iPad width) after the child-element fix above was mistaken for
   covering both. Same fix, same reasoning (avoid insert-stylesheet wiping this classs other
   breakpoint properties -- it has real padding/flex_shrink/flex_direction data to preserve). */
@media (max-width: 1023px) {
  body.breakdance .section-shop-search-results {
    background-image: none;
  }
}

/* .pl-banner (catalog archive hero, OxyDance-ported) has 0 left/right padding baked into
   its own class, and its child .section-container is display:contents (Selector Library
   custom CSS on the class itself), so section-container's own padding can never apply
   either — net effect, the hero eyebrow/H1/subhead sit flush against the viewport edge on
   every category archive (/plastic-pallets/, /wood-pallets/, /containers/, /wood-crates/).
   Confirmed 2026-07-30. Restore the same horizontal inset every other hero in the design
   system uses, without touching the Selector Library entry (avoids risking its existing
   display:contents mechanism). */
body.breakdance .pl-banner {
  padding-left: clamp(20px, 4vw, 24px);
  padding-right: clamp(20px, 4vw, 24px);
}

/* Constrained width (default) — aligns catalog grid to the standard site container so it
   matches the header. Un-toggling to "wide" removes this class and falls back to Oxygen's
   own full-width section default (--bde-section-width: 100%, set in post-61.css). */
body.nelson-catalog-constrained .bde-section-61-100 .section-container {
  --bde-section-width: var(--container);
}

/* Minimal card view (data-npc-view="minimal", .npc-view-minimal on .post-loop-product-cards) —
   regression fix. Originally added 2026-05-26 scoped to the old .npc component (hid
   .npc__specs + .npc__glance) but never ported to the .pc BEM component that replaced it on
   2026-07-08 (see nelson-product-card.css "Nelson Product Card v2" header), so the toggle was
   wired in JS with zero matching CSS. Restored here against the current .pc__* class names —
   hides the specs table and the "At a glance" tag row (label + pills) only, collapsing card
   height. Ribbons and the condition pill stay visible — confirmed 2026-09-10, an earlier pass
   also hid .pc__ribbons/.pc__cond, which was wrong.
   .pc__tags needs !important: it's also a registered Oxygen Selector Library class with
   `display:flex!important` baked in (Oxygen's Layout panel auto-compiles !important on flex
   properties, confirmed via selectors.css) — the documented equal-specificity-tie exception
   where !important is the correct fix, not the body.breakdance-prefix pattern used elsewhere
   in this file. */
.npc-view-minimal .pc__specs,
.npc-view-minimal .pc__glance-lbl {
  display: none;
}
.npc-view-minimal .pc__tags {
  display: none !important;
}

/* SEO landing page template (_template-seo-landing, post 4721) results section ships
   full-bleed (--bde-section-width:100%, set in post-4721.css) by default — unlike the main
   catalog page above, it has no width-toggle button, so it always ran edge-to-edge under
   the already-constrained hero/banner directly above it (--container, 1440px), overrunning
   the page's established content width by ~212px on desktop. Confirmed 2026-09-09 across
   all 45 landing pages (shared template, one fix point). Always constrained, no toggle. */
body.breakdance .bde-section-4721-100 .section-container {
  --bde-section-width: var(--container);
}

/* =====================================================================
   Catalog filter sidebar + results toolbar — real Phox Facets markup.
   Do not invent new facet markup; these are the actual classes Phox
   Facets renders (see design-system/AGENTS.md "Phox Facets + WooCommerce
   markup"). Product card (.npc) is a separate component, styled in
   nelson-product-card.css — not touched here.
   ===================================================================== */

/* ── Sidebar shell ───────────────────────────────────────────────── */
.div-catalog-sidebar {
  display: flex;
  flex-direction: column;
}

/* Below 1024px the sidebar's own static box must collapse to nothing —
   but NOT via display:none, which also hides its position:fixed
   OffCanvasPanel child (post 61 node 145): a display:none ancestor hides
   fixed descendants too, that's what silently broke the mobile filter
   drawer (confirmed 2026-07-16, div-catalog-sidebar selector had a stale
   breakpoint_tablet_portrait display:none left over from before the
   OffCanvasPanel existed). width/overflow collapses the static box's own
   content while a position:fixed child is unaffected (fixed positioning
   escapes the ancestor's box model entirely, clipping only applies to
   normal-flow content within it). */
@media (max-width: 1023px) {
  /* body.breakdance bumps specificity so this reliably beats the compiled
     div-catalog-sidebar selector's own breakpoint_base flex-basis:200px
     (same selector, same specificity — a plain tie is decided by load
     order, and oxy-selectors.css loads after this file). Currently
     invisible in practice since the OffCanvasPanel drawer (z-index 1000)
     sits on top of this collapsed box either way, but a real fix, not a
     load-order accident, per this project's standing no-!important
     convention. */
  body.breakdance .div-catalog-sidebar {
    width: 0;
    height: 0;
    overflow: hidden;
    padding: 0;
    flex-basis: 0;
  }
}

/* .div-catalog-search-results (post 61 node 103, the results column sibling of the sidebar
   above) carries its own padding-left/right:20px at all breakpoints — a gutter between it
   and the sidebar box on desktop. Below 1023px the sidebar collapses to zero width (fix
   above), so that gutter has nothing left to separate from and just reads as an extra
   20px indent stacked on top of .section-container's own 24px page margin (44px total left
   inset vs. every other section on the page). Confirmed 2026-09-10 (86e379c4t) on
   /wood-pallets/ — the "Request a Match" card sat 20px right of the H1/logo above it. */
@media (max-width: 1023px) {
  body.breakdance .div-catalog-search-results {
    padding-left: 0;
    padding-right: 0;
  }
}

/* .div-catalog-search-results is a flex item of .container-catalog-results (sidebar's
   flex row sibling) with no min-width set — a flex item's default min-width is "auto"
   (its content's min-content size), not 0, so it refused to shrink below the grid's own
   min-content width (~550px) even after the sidebar collapses to 0 on mobile. That kept
   the results column — and the product grid inside it — wider than the viewport on every
   phone, which is also why the PostsLoop's native "one item at Phone Portrait" setting
   (post 61 node 134, --bde-posts-per-row:1 below 479px) never visibly took effect: the
   grid still had ~550px of box to lay out in, so its own grid-template-columns (Selector
   Library "post-loop-product-cards" > .bde-loop, auto-fill/minmax(min(260px,100%),1fr))
   kept fitting 2 columns regardless of viewport width. Confirmed 2026-09-20 (Jackie:
   "category pages not responsive on mobile, cards not in one column") via live DOM
   measurement at a real 390px viewport — results column stayed 550px wide, grid rendered
   273.5px x 2; adding min-width:0 alone dropped it to a single ~342px column, matching
   the viewport. */
body.breakdance .div-catalog-search-results {
  min-width: 0;
}

/* ── Search facet ────────────────────────────────────────────────── */
.div-catalog-sidebar .phox-facet-search {
  padding-bottom: 18px;
  margin-bottom: 4px;
  border-bottom: 1px solid var(--border-subtle);
}
.div-catalog-sidebar .phox-facet-search__form {
  display: flex;
  align-items: center;
  gap: 10px;
  position: relative;
  background: var(--nelson-white);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 0 14px;
  height: 46px;
  box-shadow: var(--shadow-1);
}
.div-catalog-sidebar .phox-facet-search__input {
  flex: 1;
  order: 2;
  border: 0;
  outline: none;
  background: transparent;
  height: 100%;
  font-family: var(--font-sans);
  font-size: 14px;
  color: var(--fg);
}
.div-catalog-sidebar .phox-facet-search__icon {
  order: 1;
  display: flex;
  color: var(--fg-muted);
}
.div-catalog-sidebar .phox-facet-search__icon svg { width: 16px; height: 16px; }
.div-catalog-sidebar .phox-facet-search__clear {
  order: 3;
  border: 0;
  background: none;
  cursor: pointer;
  font-size: 18px;
  line-height: 1;
  color: var(--fg-muted);
}
.div-catalog-sidebar .phox-facet-search__clear:hover { color: var(--nelson-maroon); }

/* ── Facet accordion group (checkbox + range facets share this) ───
   Padding matches the tokenized hi-fi: design-system/handoff-070726/
   plastic-pallets-landing/plastic-pallets-landing.css `.pl-facet__head
   {padding:11px 2px}` / `.pl-facet__body{padding:0 2px 14px}`.
   Border-top is real — confirmed 2026-07-16 in the RAW (untokenized)
   monolith, incoming/Nelson-Handoff-070726/styles.css:315:
   `.nc-acc, .pl-facet, .nc-features { border-top: 1px solid var(--border-subtle); }`
   — a shared component rule that lived outside the page-scoped block and
   was dropped when plastic-pallets-landing.css was split out during
   intake (design-system/handoff-070726/README.md gap, not a value
   mismatch). It's border-TOP, not -bottom — every facet gets a divider
   above it, including the first (right under the search box). The
   earlier "no border at all" read (2026-07-16, same day) was wrong —
   that comparison only checked the already-incomplete tokenized file. */
.div-catalog-sidebar .phox-facet {
  padding: 0 2px 14px;
}
/* Oxygen compiles a per-node `border:none!important` onto every facet's
   .phox-facet (post-61.css, e.g. .oxy-phox-facetcheckbox-61-123 .phox-facet
   — from the Card panel's show_card:false), which beats a plain border-top
   outright regardless of specificity ties. body.breakdance bumps real
   specificity (0-3-1 vs the compiled rule's 0-2-0) and matches its
   !important so this actually wins. */
body.breakdance .div-catalog-sidebar .phox-facet {
  border-top: 1px solid var(--border-subtle) !important;
}
/* Toggle facets (Best Sellers/New Arrivals/Clearance/One-Piece, elements
   160/161/146/163 on post 61) don't want the accordion divider above —
   they're standalone switches, not part of the checkbox/range accordion
   group. Higher specificity (0-4-1 vs 0-3-1) wins outright over the rule
   above regardless of source order. Ticket 86e381fbz, 2026-09-11. */
body.breakdance .div-catalog-sidebar .oxy-phox-facettoggle .phox-facet {
  border-top: none !important;
}
/* Toggle facets (same 4) default to Phox's vendor purple checked-state
   color (Facet_Toggle/default.css: `background: var(--phox-toggle-track-active,
   #7c3aed)`) — override the variable itself rather than fighting the
   selector, matches brand green. Ticket 86e32m8yr. */
:root {
  --phox-toggle-track-active: var(--nelson-green);
}
/* Mobile filter panel sticky footer (Clear All + Show Results, ticket
   86e3823ce) — same divider bug as the toggles above, showing as a stray
   horizontal line across the "Show N Results" button. */
body.breakdance .div-catalog-sidebar .pf-panel-footer .phox-facet {
  border-top: none !important;
}
/* Mobile filter panel footer Clear All button (86e38tekm) — vendor Phox
   default.css styles .phox-facet-reset as a bordered/filled pill button
   (background, border, padding). Zach wants plain red text, no pill.
   Descendant selector (0-2-0) beats the vendor's bare class (0-1-0). */
.pf-panel-footer .phox-facet-reset {
  background: none;
  border: none;
  padding: 0;
  color: var(--nelson-maroon);
}
.pf-panel-footer .phox-facet-reset:hover {
  background: none;
  border-color: transparent;
  color: var(--nelson-maroon);
  text-decoration: underline;
}

/* Vendor phox-facets.css sets .phox-facet-results/__count color directly on
   that literal class name (not the per-instance wrapper the Design panel's
   Typography/Count controls actually target), so the Show-Results button's
   native color fields render inert — fix at the class the color really
   lives on. Descendant selector (0-2-0) already beats the vendor's bare
   0-1-0 rule without !important. */
.pf-panel-footer__show .phox-facet-results,
.pf-panel-footer__show .phox-facet-results__count {
  color: #fff;
}
.div-catalog-sidebar .phox-facet__title-row {
  padding: 11px 0;
  display: flex;
  align-items: center;
  gap: 8px;
  font-family: var(--font-sans);
  font-weight: 700;
  font-size: 13px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--fg-strong);
}
/* Phox's own .phox-facet__title already ships display:flex + justify-content:
   space-between + cursor:pointer (phox-facets.css) and is the only element its
   click-delegation checks (never the row) — stretch it to fill the row instead
   of building a second arrow + handler, so the far-right arrow is the real,
   already-wired-up toggle target. */
.div-catalog-sidebar .phox-facet__title-row .phox-facet__title {
  flex: 1 1 auto;
  width: 100%;
}
.div-catalog-sidebar .phox-facet.is-collapsible > .phox-facet__title-row .phox-facet__title::after,
.div-catalog-sidebar .phox-facet.is-collapsible > .phox-facet__title::after {
  content: '';
  border: none;
  width: 16px;
  height: 16px;
  background: currentColor;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E") center/contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E") center/contain no-repeat;
  color: var(--fg-muted);
  opacity: 1;
  margin-left: 0;
  transform: none;
  transition: transform var(--dur-fast) var(--ease);
}
.div-catalog-sidebar .phox-facet.is-collapsible:not(.is-collapsed) > .phox-facet__title-row .phox-facet__title::after,
.div-catalog-sidebar .phox-facet.is-collapsible:not(.is-collapsed) > .phox-facet__title::after {
  transform: rotate(180deg);
}
/* phox-facets.css ships its own border-arrow (border-right+border-bottom,
   rotate(45deg) open / rotate(-45deg) collapsed) and its .is-collapsed-
   specific rule ties our collapsed-state selector on class count (0-5-1
   each) — whichever stylesheet loads second wins the tied `transform`,
   which was phox-facets.css, pointing our mask-chevron sideways instead of
   down at rest. Explicit .is-collapsed selector (adds a class, 0-6-1) beats
   the tie outright regardless of load order, same technique as the
   :not(.is-collapsed) rule above. */
.div-catalog-sidebar .phox-facet.is-collapsible.is-collapsed > .phox-facet__title-row .phox-facet__title::after,
.div-catalog-sidebar .phox-facet.is-collapsible.is-collapsed > .phox-facet__title::after {
  transform: none;
  border: none;
}
.div-catalog-sidebar .phox-facet.is-collapsible.is-collapsed .phox-facet__list,
.div-catalog-sidebar .phox-facet.is-collapsible.is-collapsed .phox-facet__search,
.div-catalog-sidebar .phox-facet.is-collapsible.is-collapsed .phox-facet-range__slider,
.div-catalog-sidebar .phox-facet.is-collapsible.is-collapsed .phox-facet-range__inputs {
  display: none;
}

/* ── Checkbox facet list ─────────────────────────────────────────── */
.div-catalog-sidebar .phox-facet__list {
  list-style: none;
  margin: 0;
  padding: 0;
}
.div-catalog-sidebar .phox-facet__item { padding: 0; }
.div-catalog-sidebar .phox-facet__item label {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 5px 0;
  font-family: var(--font-sans);
  font-size: 14px;
  font-weight: 400;
  color: var(--fg);
  cursor: pointer;
}
.div-catalog-sidebar .phox-facet__item input[type="checkbox"] {
  width: 16px;
  height: 16px;
  flex: none;
  accent-color: var(--nelson-bright-blue);
  cursor: pointer;
}
.div-catalog-sidebar .phox-facet__count {
  margin-left: auto;
  font-size: 13px;
  color: var(--fg-subtle);
}
.div-catalog-sidebar .phox-facet__label { line-height: 1.25; }

/* Scrollable long facet lists (Footprint, Material, Product Type) */
.div-catalog-sidebar .phox-facet-checkbox.is-searchable .phox-facet__list {
  max-height: 300px;
  overflow-y: auto;
}
.div-catalog-sidebar .phox-facet__search { margin-bottom: 8px; }
.div-catalog-sidebar .phox-facet__search-input {
  width: 100%;
  height: 36px;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 0 12px;
  font-family: var(--font-sans);
  font-size: 13px;
  color: var(--fg);
  background: var(--nelson-white);
}

/* ── Range facet slider ──────────────────────────────────────────── */
.div-catalog-sidebar .phox-facet-range__slider {
  position: relative;
  height: 4px;
  margin: 18px 8px 22px;
}
.div-catalog-sidebar .phox-facet-range__track {
  position: absolute;
  inset: 0;
  background: var(--border-subtle);
  border-radius: 999px;
}
.div-catalog-sidebar .phox-facet-range__fill {
  position: absolute;
  height: 100%;
  background: var(--nelson-bright-blue);
  border-radius: 999px;
}
.div-catalog-sidebar .phox-facet-range__handle {
  position: absolute;
  top: 50%;
  left: 0;
  width: 100%;
  margin: 0;
  -webkit-appearance: none;
  appearance: none;
  background: transparent;
  pointer-events: none;
  transform: translateY(-50%);
}
.div-catalog-sidebar .phox-facet-range__handle::-webkit-slider-thumb {
  -webkit-appearance: none;
  pointer-events: auto;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: var(--nelson-white);
  border: 2px solid var(--nelson-bright-blue);
  cursor: pointer;
}
.div-catalog-sidebar .phox-facet-range__handle::-moz-range-thumb {
  pointer-events: auto;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: var(--nelson-white);
  border: 2px solid var(--nelson-bright-blue);
  cursor: pointer;
  box-sizing: border-box;
}
.div-catalog-sidebar .phox-facet-range__inputs {
  display: flex;
  align-items: center;
  gap: 10px;
}
.div-catalog-sidebar .phox-facet-range__input {
  width: 100%;
  height: 40px;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 0 12px;
  font-family: var(--font-sans);
  font-size: 14px;
  font-weight: 600;
  color: var(--fg-strong);
  background: var(--nelson-white);
}
.div-catalog-sidebar .phox-facet-range__separator { color: var(--fg-muted); }
.div-catalog-sidebar .phox-facet-range__suffix { font-size: 13px; color: var(--fg-muted); font-weight: 400; }

/* ── Results toolbar ─────────────────────────────────────────────── */
.div-results-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 16px;
  margin-bottom: 20px;
}
.div-results-toolbar .phox-facet-results {
  font-family: var(--font-sans);
  font-size: 15px;
  color: var(--fg-muted);
}
.div-results-toolbar .phox-facet-results__count { color: var(--nelson-blue); font-weight: 700; }

/* Active filter chips — moved out of .div-results-toolbar into its own row
   (2026-07-08), so these are unscoped from that ancestor rather than nested under it. */
.phox-facet-active {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px;
}
.phox-facet-active.is-hidden { display: none; }
.phox-facet-active__list {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  list-style: none;
  margin: 0;
  padding: 0;
}
/* !important — phox-facets.css has an equal-specificity .phox-facet-active__item
   rule that wins on source order otherwise; same pattern as facet-swatches.css. */
.phox-facet-active__item {
  display: inline-flex !important;
  align-items: center !important;
  gap: 8px !important;
  font-family: var(--font-sans) !important;
  font-size: 13px !important;
  font-weight: 600 !important;
  color: var(--nelson-blue) !important;
  background: var(--nelson-blue-95) !important;
  border: 1px solid var(--nelson-blue-90) !important;
  border-radius: 999px !important;
  padding: 6px 12px !important;
}
.phox-facet-active__remove {
  border: 0;
  background: none;
  cursor: pointer;
  font-size: 14px;
  line-height: 1;
  color: var(--nelson-blue);
}
.phox-facet-active__remove:hover { color: var(--nelson-maroon); }
.phox-facet-active__clear-all {
  border: 0;
  background: none;
  cursor: pointer;
  font-family: var(--font-sans);
  font-size: 13px;
  color: var(--fg-muted);
}
.phox-facet-active__clear-all:hover { color: var(--nelson-maroon); text-decoration: underline; text-underline-offset: 4px; }

/* Mobile only (86e389474): Zach wants "Clear All" to the left of the filter pills,
   not after them — desktop keeps the original order (list, then clear-all), unchanged.
   .phox-facet-active is already display:flex on both its children (__list, __clear-all),
   so a plain flex `order` swap is enough, no markup change needed. */
@media (max-width: 1024px) {
  .phox-facet-active__clear-all {
    order: -1;
  }
}

/* Sort dropdown (Facet_Sort element — styled ahead of placement) */
.div-results-toolbar .phox-facet-sort { display: flex; align-items: center; gap: 10px; }
.div-results-toolbar .phox-facet-sort .phox-facet__title {
  font-family: var(--font-sans); font-size: 13px; color: var(--fg-muted);
}
.div-results-toolbar .phox-facet__select {
  appearance: none;
  -webkit-appearance: none;
  font-family: var(--font-sans);
  font-size: 14px;
  font-weight: 600;
  color: var(--fg-strong);
  background: var(--nelson-white) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2364748B' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E") no-repeat right 14px center/16px;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 11px 38px 11px 16px;
  cursor: pointer;
  min-width: 180px;
}
.div-results-toolbar .phox-facet__select:focus {
  outline: none;
  border-color: var(--nelson-bright-blue);
  box-shadow: 0 0 0 3px rgba(0,120,189,0.18);
}

/* View / page-width toggle icons */
.div-toolbar-tool-icons {
  display: flex;
  gap: 8px;
  color: var(--fg-muted);
}
.div-toolbar-tool-icons .bde-icon {
  cursor: pointer;
  padding: 6px;
  border-radius: 6px;
  color: inherit;
  transition: color var(--dur-fast) var(--ease), background var(--dur-fast) var(--ease);
}
.div-toolbar-tool-icons .bde-icon svg { width: 20px; height: 20px; fill: currentColor; }
.div-toolbar-tool-icons .bde-icon.is-active,
.div-toolbar-tool-icons .bde-icon:hover {
  color: var(--nelson-blue);
  background: var(--nelson-blue-95);
}

/* ── Mobile filter-drawer toggle — hidden on desktop; icon-filters-toggle
   already has the Oxygen interaction wired (toggles .is-open on
   .div-catalog-sidebar). Label text below matches hi-fi's .pl-filterbtn.
   !important needed — Oxygen's own post-61-defaults.css sets
   `.breakdance .bde-icon { display: flex }`, which beats a plain class
   selector on specificity regardless of source order (see facet-swatches.css
   for the same established pattern on this project). */
.icon-filters-toggle {
  display: none !important;
}
@media (max-width: 1024px) {
  .icon-filters-toggle {
    display: inline-flex !important;
    align-items: center;
    gap: 8px;
    background: var(--nelson-white);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    padding: 9px 16px;
    font-family: var(--font-sans);
    font-weight: 700;
    font-size: 13px;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--nelson-blue);
    cursor: pointer;
  }
  .icon-filters-toggle:hover { border-color: var(--nelson-blue); background: var(--nelson-blue-95); }
  .icon-filters-toggle svg { width: 16px; height: 16px; }
  .icon-filters-toggle::after { content: "Filters"; }
}

/* ── Off Canvas Panel (element 145, wraps the sidebar's 17 Phox Facet
   elements) — single Phox Facets instance reused for both desktop and
   mobile instead of duplicating it. Below 1024px it behaves as the Phox
   plugin intends (fixed, off-canvas, slide-in). At/above 1024px this
   override neutralizes the fixed positioning so the exact same facets
   render as a normal static sidebar column, matching the hi-fi's
   desktop-vs-mobile split without a second facets instance. */

/* Phox's own compiled z-index for the drawer (.phoxcanvas: 1000, .blur-overlay:
   999) sits well below the sticky header (.nc-header, z-index 9030, see
   nelson-nav.css) — confirmed 2026-07-30, the mobile filter panel opens
   visually underneath the header with its close button unreachable. Bump
   both above the entire global nav z-index band (9000-9080) so the panel is
   topmost while open. */
@media (max-width: 1024px) {
  body.breakdance .oxy-phox-offcanvaspanel .phoxcanvas {
    z-index: 9090;
  }
  body.breakdance .oxy-phox-offcanvaspanel .blur-overlay {
    z-index: 9089;
  }
}

/* .phoxstuff's own padding-top (56px, post 61 node 145, `.oxy-phox-offcanvaspanel-61-145
   .phoxstuff`) predates the z-index fix directly above (2026-07-30) — it was there to clear
   the sticky .nc-header (72px tall at this same <=1080px breakpoint, nelson-nav.css) so the
   panel's own "Filters" title/close button wouldn't render underneath it. Now that the panel
   sits at z-index 9090, above the header's 9030, the header is fully hidden behind the drawer
   while it's open — that padding is now just blank drawer background above the real content,
   with nothing left to clear. Ticket 86e3823ce, "too much space above Filters and Close
   button." Reduced to match the panel's own bottom padding (.pf-panel-footer, 24px) for a
   symmetrical top/bottom rhythm instead of the stale header-clearance value. */
@media (max-width: 1024px) {
  body.breakdance .oxy-phox-offcanvaspanel .phoxstuff {
    padding-top: 24px;
  }
}

/* .phoxcanvas's own height/max-height (100vh !important, post 61 node 145) is fine in Chrome
   DevTools emulation but is the textbook real-iOS-Safari trap: 100vh there reports the
   LARGEST possible viewport (address bar + bottom toolbar collapsed), not the actually-visible
   height once that chrome is showing -- so the drawer can render taller than what's really on
   screen, pushing the sticky Show-N-Results footer (.pf-panel-footer) off the bottom on a real
   phone even though it looks fine here. Ticket 86e3823ce, "can't get the Show Results button,
   needs more room at the bottom." dvh (dynamic viewport height) tracks the real visible area
   and is supported iOS Safari 15.4+ / Android Chrome 108+; the plain vh declaration stays
   first as the fallback for anything older, since an unrecognized value is ignored rather than
   applied as 0. Not independently reproducible in this Chrome-DevTools-only environment (no
   browser-chrome-eats-space behavior to simulate) -- ships as a safe, standards-based fix for
   the reported symptom regardless. */
@media (max-width: 1024px) {
  body.breakdance .oxy-phox-offcanvaspanel .phoxcanvas {
    height: 100vh !important;
    height: 100dvh !important;
    max-height: 100vh !important;
    max-height: 100dvh !important;
  }
}

/* Backdrop scrim never appears (confirmed 2026-07-30): the elements own
   blur_backgound_when_active field is true and Phoxs compiled base/desktop
   breakpoint rule correctly reads .blur-overlay.active{visibility:visible;
   opacity:1} -- but its per-breakpoint compiled CSS for the SAME selector
   re-declares visibility:hidden;opacity:0 (the fields else-branch value) at
   every responsive breakpoint (max-width:1119/1023/767/479px), i.e. every
   breakpoint the off-canvas panel is actually used at. Not a stale-cache
   issue -- persists after wp oxygen clear_cache; a genuine Phox
   breakpoint-CSS-generation bug for this field. Same equal-specificity class
   count as the native rule (.blur-overlay.active), so body.breakdance alone
   is enough to win without !important. */
@media (max-width: 1119px) {
  body.breakdance .oxy-phox-offcanvaspanel .blur-overlay.active {
    visibility: visible;
    opacity: 1;
  }
}

.oxy-phox-offcanvaspanel .blur-overlay {
  background: rgba(15, 23, 42, 0.5) !important;
  backdrop-filter: none !important;
}
@media (min-width: 1025px) {
  /* body.breakdance bumps specificity above post-{id}.css's compiled
     `.oxy-phox-offcanvaspanel-{post}-{node} .phoxcanvas{height:100vh!important}`
     rule (also 2 classes) — a plain equal-specificity !important tie was
     being decided by load order (post CSS loads after this file), so the
     100vh height won on real large-viewport monitors even though this
     override was already here. See nelson-catalog-toolbar.css gap fix,
     2026-07-15. */
  body.breakdance .oxy-phox-offcanvaspanel .phoxcanvas {
    position: static !important;
    transform: none !important;
    width: auto !important;
    height: auto !important;
    padding: 0 !important;
    overflow: visible !important;
  }
  body.breakdance .oxy-phox-offcanvaspanel .phoxstuff {
    height: auto !important;
    width: auto !important;
    overflow: visible !important;
    padding: 0 !important;
  }
  body.breakdance .oxy-phox-offcanvaspanel .close-btn,
  body.breakdance .oxy-phox-offcanvaspanel .blur-overlay {
    display: none !important;
  }
  /* Desktop filters apply live (no explicit submit step), so the mobile
     drawer's sticky Clear All / Show N Results footer (.pf-panel-footer,
     post 61 node 167) is redundant here — hide it same as the drawer chrome
     above. Ticket 86e38aadq. */
  body.breakdance .oxy-phox-offcanvaspanel .pf-panel-footer {
    display: none !important;
  }
}

/* The Active Filters wrapper's global class (`facet-active-filters-1`,
   compiled to `.facet-active-filters-1{flex-grow:1}`) is the only
   flex-grow:1 item in the stretched sidebar row. Phox's own JS only hides
   the inner `.phox-facet-active` markup when there are no active filters —
   it never touches this outer wrapper, so on a page with zero active
   filters the empty wrapper still expands to fill 100% of the row's
   stretched height, pushing the CTA banner/product grid down. Confirmed on
   /wood-crates/ at large-monitor viewport heights, 2026-07-15. */
body.breakdance .oxy-phox-offcanvaspanel .facet-active-filters-1 {
  flex-grow: 0;
}

/* Same mechanism as above, but for the desktop layout: node 132's real
   location is a sibling of the toolbar inside `.div-catalog-search-results`,
   outside the off-canvas panel, so the override above never applied there.
   Confirmed on /plastic-pallets/ at tall-monitor viewport heights,
   2026-09-09. */
body.breakdance .div-catalog-search-results .facet-active-filters-1 {
  flex-grow: 0;
}

/* .pf-panel-header ("Filters" title + circular close button, post 61 node 164) sits at the
   top of the single OffCanvasPanel instance (node 145) shared between mobile and desktop —
   see the "Off Canvas Panel" comment above re: one Phox Facets instance reused for both.
   Below 1024px it's a real overlay drawer, so the title + close button make sense. At/above
   1024px the same panel renders as a normal static sidebar column (never an overlay), where
   a close button is meaningless and the "Filters" heading duplicates the .icon-filters-toggle
   button (hidden on desktop, see above) that opens this panel on mobile — Zach flagged both
   as redundant on desktop (86e3897ma). body.breakdance needed for the same reason as every
   other override in this file: .pf-panel-header is a Selector Library class, ties in
   specificity with its own compiled base rule, and selectors.css loads after this file. */
@media (min-width: 1024px) {
  body.breakdance .pf-panel-header {
    display: none;
  }
}

/* Main catalog PostsLoop (post 61, node 134) — shared by all 4 category archives.
   Plastic Pallets loads all 269 products in one response (no pagination, see FC1 fix
   2026-09-15) and under Lighthouse's default mobile CPU throttling this scored poorly
   (perf 32, TBT 1480ms) — laying out/painting ~3000 DOM nodes blocks the main thread.
   content-visibility:auto skips style/layout/paint for cards not near the viewport,
   deferring that cost until the visitor scrolls to them. Validated 2026-09-19 via an
   isolated static-HTML A/B test (removes backend/network confounds): TBT 1480ms->690ms,
   perf score 32->41, no CLS regression (0 both ways) — see
   project_nelson_category_page_perf_shelved memory for the full test writeup. Harmless
   on the other 3 (much smaller) category archives that share this same node.
   contain-intrinsic-size is a placeholder estimate (self-corrects after first real
   layout via the "auto" keyword) — not yet measured precisely per breakpoint. */
body.breakdance .bde-post-loop-61-134 .bde-loop-item {
  content-visibility: auto;
  contain-intrinsic-size: auto 550px;
}
