:root {
    --psv2-teal: #00999a;
    --psv2-header-bg: #f0f0f0;
    --psv2-border: #b5b5b5;
    --psv2-text-muted: #969696;
    --psv2-part-col-width: 220px;
    --psv2-slider-col-width: 95px;
    --psv2-highlight: #d4ecec;
    --psv2-highlight-hover: #c2e4e4;
    --psv2-highlight: #f3f3f3;
    --psv2-highlight-hover: #f0f0f0;
}

/* Shared with v1 where useful — table header labels */
.psv2-root .param-header {
    display: block;
    background: transparent;
    color: #000;
    font-weight: 600;
    text-transform: uppercase;
    font-size: 12px;
    line-height: 1.2;
    padding: 10px 12px;
    min-height: 44px;
    border-bottom: none;
}

.psv2-root {
    position: relative;
    width: 100%;
    margin-top: 0;
    padding-top: 0;
}

/* full_width="yes" (table) / toolbar_full_width="yes" (toolbar) — breaks whichever
   element carries this class out of a Bootstrap .container (or any ancestor, however
   deeply nested) to span the full viewport width. Reusable rather than scoped to
   .psv2-root: applied to .psv2-table-panel by default (the table only) and, separately,
   to .psv2-controls when toolbar_full_width="yes" — the two are independent so the
   toolbar can stay container-constrained while the table goes full width, or vice versa.
   Uses --psv2-vw (set by JS in parametric-search-v2.js from document.documentElement.
   clientWidth, the true visible content width) instead of the raw 100vw unit: 100vw is
   measured against the full viewport INCLUDING any vertical scrollbar's width, so on any
   page with a scrollbar the plain-CSS version overshoots by the scrollbar's width — which
   isn't just cosmetic, it makes the whole PAGE overflow horizontally, producing a stray
   page-level scrollbar and throwing off anything (like the widget's own dummy scrollbar)
   that measures the true viewport width. --psv2-vw sidesteps that by measuring the actual
   rendered width directly. Falls back to 100vw only if that JS hasn't run yet.
   Requires no ancestor has overflow:hidden. */
.psv2-full-width {
    /* Bootstrap's ".row > *" sets max-width:100% on every row child, .psv2-controls
       included (it's itself a .row); max-width caps the used width independently of the
       width property below (browsers resolve used width as min(width, max-width)
       regardless of which rule "wins" the cascade for each property individually), so
       without this override the element was still capped to its row's constrained
       width.
       !important on width/margins: this class is applied to elements (.psv2-table-panel,
       .psv2-controls) that also have their own plain "width: 100%" base rule defined
       LATER in this same file — same specificity (one class each), so without
       !important the later rule silently won regardless of which one a reader would
       expect to take precedence, and full_width quietly stopped doing anything. */
    max-width: none !important;
    width: var(--psv2-vw, 100vw) !important;
    margin-left: calc(50% - var(--psv2-vw, 100vw) / 2) !important;
    margin-right: calc(50% - var(--psv2-vw, 100vw) / 2) !important;
    padding-left: 1.5rem;
    padding-right: 1.5rem;
    box-sizing: border-box;
}

body {
    padding-top: 7.2rem;
}

section#parametric-search .container .row {
    padding-top: 0;
}

/* This page's breadcrumb (common/_breadcrumb.html) renders a plain <section
   class="breadcrumb">, which picks up Bootstrap's own default .breadcrumb background
   (a pale gray/blue) since nothing here overrides it. The reference to match is a page
   showing the parametric table under a specific sub-platform (e.g.
   /products/power-management/boost-converters) — that uses "wrapper-breadcrumb
   sub-cats-breadcrumb" with NO "bg-white", which resolves to $sierra-gray (#ededed) per
   docroot/assets/sass/pages/_common.scss's ".wrapper-breadcrumb { background-color:
   $sierra-gray; }" — matching that color here without touching the shared breadcrumb
   component itself (swapping it broke the breadcrumb outright the first time this was
   tried). */
body.design-support.parametric-search-v2 .breadcrumb,
body.design-support.parametric-search .breadcrumb {
    background-color: #ededed;
}

/* Full-page v2: no page header, keep toolbar tight under breadcrumb */
body.design-support.parametric-search-v2 #content,
.psv2-page {
    margin-top: 0 !important;
    padding-top: 0 !important;
}

.psv2-page > .container {
    padding-top: 0;
}

.psv2-controls {
    flex-wrap: wrap;
    align-items: flex-end;
    /* width: 100%; */
    margin-top: 0;
    margin-bottom: 0.75rem !important;
}

.psv2-controls > .psv2-toolbar-item.psv2-toolbar-place-right-start {
    margin-left: auto !important;
}

.psv2-controls > .psv2-toolbar-item.psv2-toolbar-place-left {
    margin-left: 0 !important;
}

/* CSS-only default matching TOOLBAR_DEFAULT_RIGHT_ITEMS in parametric-search-v2.js:
   applyToolbarPlacement() only adds .psv2-toolbar-place-right-start (the actual
   margin-left:auto, above) once its JS has run — until then .psv2-toolbar-actions sits
   wherever plain DOM order puts it, which is the left, causing a flash of left-aligned
   buttons before JS repositions them. This bakes in the common-case default so it's
   already right-aligned on first paint; JS's own !important rules above still win for
   toolbar_place="actions:left" or any other explicit override. */
.psv2-controls > .psv2-toolbar-actions {
    margin-left: auto;
}

.psv2-toolbar-btn-wrap .psv2-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

.psv2-root.psv2-filters-disabled .psv2-filter-row,
.psv2-root.psv2-filters-disabled .psv2-filter-toggle-wrap {
    display: none !important;
}

.psv2-controls > .form-group,
.psv2-controls > [class*="col-"] {
    margin-bottom: 0;
}

.psv2-controls .psv2-control-label {
    display: block;
    font-size: 0.85rem;
    line-height: 1.2;
    min-height: 1.05rem;
    margin-bottom: 0.25rem;
}

.psv2-controls .form-control-sm,
.psv2-controls .btn-sm,
.psv2-controls .psv2-btn,
.psv2-controls .psv2-toolbar-btn-row {
    height: 31px;
}

.psv2-controls .form-control-sm {
    line-height: 1.5;
    padding-top: 0.25rem;
    padding-bottom: 0.25rem;
}

.psv2-controls #searchButton.btn-sm {
    font-size: .875rem;
}

.psv2-controls .psv2-btn,
.psv2-controls #searchButton.btn-sm {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding-top: 0;
    padding-bottom: 0;
    line-height: 1;
    border-radius: 4px;
}

.psv2-toolbar-length .d-flex {
    align-items: center;
    height: 31px;
}

.psv2-toolbar-actions .psv2-toolbar-btn-row {
    align-items: center;
}

@media (min-width: 1200px) {
    .psv2-controls {
        flex-wrap: nowrap;
    }
}

.psv2-toolbar-search .psv2-global-search {
    width: 200px;
    min-width: 160px;
}

.psv2-toolbar-actions .d-flex {
    flex-wrap: nowrap;
}

.psv2-label {
    font-size: 0.85rem;
    margin-right: 0.35rem;
    margin-bottom: 0.25rem;
    display: inline-block;
}

.psv2-label-suffix {
    font-size: 0.85rem;
}

.psv2-btn {
    border: 1px solid var(--psv2-border);
    background: #000;
    color: #fff;
    font-size: 0.7rem;
    font-weight: 600;
    letter-spacing: 0.02em;
    padding: 0.45rem 0.65rem;
    line-height: 1.2;
    cursor: pointer;
    white-space: nowrap;
}

.psv2-btn:hover,
.psv2-btn:focus {
    background: #222;
    color: #fff;
}

.psv2-btn.is-active {
    background: var(--psv2-teal);
    border-color: var(--psv2-teal);
}

.psv2-scroll-wrapper {
    position: relative;
    overflow-x: auto;
    /* NOT "visible" — per the CSS Overflow spec, overflow-y:visible paired with a
       non-visible overflow-x (here "auto") gets silently force-converted to "auto" by
       the browser. Since the table needs horizontal scroll, its native horizontal
       scrollbar reserves height at the bottom of this box; the forced overflow-y:auto
       then ALSO shows a vertical scrollbar to let you scroll into that self-reserved
       space, leaving a visible blank gap the height of the scrollbar. "hidden" is a
       valid explicit pairing with "auto" (no forced conversion, since it's already
       non-visible), so it avoids the phantom scrollbar/gap without needing height:auto
       math to work around it. */
    overflow-y: hidden;
    width: 100%;
    -webkit-overflow-scrolling: touch;
    border-left: 1px solid var(--psv2-border);
    border-right: 1px solid var(--psv2-border);
    border-top: 1px solid var(--psv2-border);
    border-bottom: 1px solid var(--psv2-border);
}

.psv2-scroll-wrapper::-webkit-scrollbar-thumb {
    background: #888;
    border-radius: 6px;
}

.psv2-scroll-wrapper::-webkit-scrollbar-track {
    background: #f0f0f0;
}

/* Floating chevron buttons hinting the table is horizontally scrollable, and letting a
   click scroll it. position:fixed and vertically centered on the VIEWPORT (not the
   table panel), so they stay put on screen regardless of how tall the table is or how
   far the page has scrolled. Reparented to <body> via JS while visible — .psv2-root and
   .psv2-table-panel are both position:relative, which would otherwise hijack the
   containing block for position:fixed and throw off the computed left/right (same issue
   worked around for the dummy scrollbar elsewhere in this file). Shown/hidden and
   enabled/disabled via JS based on actual scroll position and table visibility. */
.psv2-scroll-nav-btn {
    position: fixed;
    top: 50%;
    transform: translateY(-50%);
    z-index: 1001;
    width: 32px;
    height: 32px;
    padding: 0;
    border: 1px solid var(--psv2-border);
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.9);
    cursor: pointer;
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);
    transition: background-color 0.1s ease, transform 0.1s ease;
    display: flex;
    align-items: center;
    justify-content: center;
}

.psv2-scroll-nav-btn:hover {
    background: #fff;
}

.psv2-scroll-nav-btn:active {
    transform: translateY(-50%) scale(0.9);
    background: #eee;
}

.psv2-scroll-nav-btn[hidden] {
    display: none;
}

.psv2-scroll-nav-btn:disabled {
    opacity: 0.35;
    cursor: default;
}

/* CSS-drawn triangle rather than a text glyph — a unicode chevron's visual weight
   sits off-center inside its own font metrics (varies by font/OS), so it never looks
   truly centered in a circular button no matter how the text is aligned. */
.psv2-scroll-nav-btn::before {
    content: "";
    display: block;
    width: 0;
    height: 0;
    border-top: 6px solid transparent;
    border-bottom: 6px solid transparent;
}

.psv2-scroll-nav-left::before {
    border-right: 7px solid #444;
    margin-right: 2px;
}

.psv2-scroll-nav-right::before {
    border-left: 7px solid #444;
    margin-left: 2px;
}

/* v1-style dummy horizontal scrollbar — fixed to viewport bottom while table extends below fold */
.psv2-dummy-scrollbar {
    height: 14px;
    margin-top: 8px;
    overflow-x: auto;
    overflow-y: hidden;
    background: #f0f0f0;
    border-top: 1px solid #ddd;
    display: none;
    /* "auto" matches the thicker/more visible option used for the real scrollbar above
       (and its own ::-webkit-scrollbar height below) — was "thin", working against
       wanting this more noticeable, and also a mismatch (11px container vs. the
       webkit-scrollbar rule's own 15px) that clipped part of the scrollbar in
       webkit browsers; now both this box and the scrollbar it contains agree on 14px. */
    scrollbar-width: auto;
    scrollbar-color: #888 #f0f0f0;
}

.psv2-dummy-scrollbar.is-fixed {
    margin-top: 0;
    z-index: 999;
    box-shadow: 0 -2px 5px rgba(0, 0, 0, 0.08);
}

.psv2-dummy-content {
    height: 1px;
}

.psv2-dummy-scrollbar::-webkit-scrollbar {
    height: 14px;
}

.psv2-dummy-scrollbar::-webkit-scrollbar-thumb {
    background: #888;
    border-radius: 6px;
}

.psv2-dummy-scrollbar::-webkit-scrollbar-track {
    background: #f0f0f0;
}

.psv2-table.psv2-col-layout {
    table-layout: fixed;
}

.psv2-table.table {
    /* width: max-content !important; */
    margin-bottom: 0;
}

.psv2-table {
    border-collapse: separate;
    border-spacing: 0;
    visibility: hidden;
    /* Do NOT add transform/filter/perspective/will-change:transform here — the
       header-fixed mode positions .psv2-table's own <thead> with position:fixed via JS
       (applyFixedHeaderPosition), which requires the viewport as its containing block.
       Any of those properties on an ancestor (this element included) gives fixed
       descendants a new containing block instead, breaking "stays put while scrolling"
       entirely. A translateZ(0) was tried here to smooth a sub-pixel border-flicker
       rendering artifact and had to be reverted for exactly this reason. */
}

.psv2-table.psv2-ready,
.psv2-root:not(.is-loading) .psv2-table {
    visibility: visible;
}

/*
 * border-right stays present (transparent by default) rather than being omitted —
 * an actually-absent border shifts the cell's box-sizing:border-box content width by
 * that 1px, which previously drifted header/body column widths apart. Only the color
 * changes below, per row type, never the border's presence.
 */
.psv2-table thead th,
.psv2-table tbody td {
    border-right: 1px solid transparent;
    border-bottom: 1px solid var(--psv2-border);
    padding: 0;
    vertical-align: top;
    white-space: nowrap;
    font-size: 14px;
    box-sizing: border-box;
}

/* Header keeps a visible divider between every column; body only shows one after the
   first (part) column — see the psv2-part-col rule further below. */
.psv2-table thead th {
    border-right-color: var(--psv2-border);
}

/* Outer left edge — travels with the sticky part column on horizontal scroll.
   Right edge uses box-shadow rather than the border-right every other column gets
   (border-right-color stays transparent, from the base rule above) — an actual border
   on a sticky element re-creates the double-border-on-scroll family of bugs a real
   border caused elsewhere in this file. A single bare "1px 0 0 var(--border)" value (no
   blur, no companion shadow) didn't render at all — built the same way as the thead's
   own box-shadow further down (which does work): a blurred component alongside the
   hard-edge line, not the hard-edge alone. */
.psv2-table thead th.psv2-part-col,
.psv2-table tbody td.psv2-part-col {
    border-left: 1px solid var(--psv2-border);
    box-shadow:
        2px 0 6px rgba(0, 0, 0, 0.15),
        1px 0 0 var(--psv2-border);
}

/* Needed in addition to the rule above: "thead th" (higher up, plain visible
   border-right-color for every header cell) has lower specificity but nothing here
   overrides it back to transparent now that this rule no longer does — without this,
   the header's part-col would get a real visible border-right from that general rule
   again, stacking with the box-shadow above into the exact double-line this was meant
   to avoid. tbody needs no equivalent: its own base rule already defaults to
   transparent, untouched by anything more specific. */
.psv2-table thead th.psv2-part-col {
    border-right-color: transparent;
}

/*
 * .psv2-scroll-wrapper now supplies its own left/right border, so the first/last
 * column no longer need one — without this they'd double up into a 2px seam.
 * Placed after the .psv2-part-col rule above (same specificity as :first-child) so
 * this wins the cascade on source order and actually removes the border-left.
 */
.psv2-table thead th:first-child,
.psv2-table tbody td:first-child {
    border-left: none;
}

/* The wrapper's own border-right (and, in header-fixed mode, the detached header's own
   box-shadow border-replacement) already sits at the true last-column edge — a visible
   border-right on that same column doubles it into a 2px seam. :not(:has(...)) finds the
   last cell with no further non-hidden sibling after it, i.e. the true visually-last
   column, regardless of how many .psv2-col-hidden ones trail it in the DOM. Transparent,
   not "none": the border must stay present for box-sizing (see the base rule above) —
   only its color changes. Higher specificity than the plain "thead th" color rule above
   (via the :not()/:has() clauses) is what makes this win regardless of source order. */
.psv2-table thead th:not(.psv2-col-hidden):not(:has(~ th:not(.psv2-col-hidden))),
.psv2-table tbody td:not(.psv2-col-hidden):not(:has(~ td:not(.psv2-col-hidden))) {
    border-right-color: transparent;
}

/* Same reasoning for the wrapper's new top/bottom border: the last body row no longer
   needs its own bottom edge, and the label row's border-top (removed here) is likewise
   redundant with the wrapper's top edge — except in fixed-header mode, handled below. */
.psv2-table tbody tr:last-child td {
    border-bottom: none;
}

/*
 * Fixed-header mode detaches <thead> (position:fixed, opaque background, z-index above
 * everything) from .psv2-scroll-wrapper. It needs its own top/left/right border back:
 * getScrollClipBox() lines its box up flush with the wrapper's edges, but being
 * position:fixed it now paints in front of the wrapper's own border on that same screen
 * line rather than beside it, so the wrapper's border is simply covered, not visible
 * through/around the header — it needs to carry the line itself. (Vertically this was
 * already true regardless of alignment: getStickyTop() pins it near the top of the
 * viewport, nowhere near the wrapper's now-scrolled-past top edge.)
 *
 * box-shadow, not border: an actual border on the thead (or its first/last th) adds to
 * that element's own box width/height, which then has to be subtracted back out
 * everywhere else that measures against the wrapper's or header's dimensions (columns,
 * colgroup, row width, clip box) to keep them all in agreement — three separate rounds
 * of "double border" / "row is short" / "columns misaligned" bugs all traced back to
 * some piece of that arithmetic being inconsistent with another. box-shadow (non-inset)
 * draws outside the box entirely without changing its dimensions, so it can't ever throw
 * that off — the header's width/height can just equal the wrapper's exactly, always.
 */
/* box-shadow itself lives on the later .psv2-table.psv2-header-fixed thead rule below
   (box-shadow doesn't merge across separate rules for the same selector — whichever
   declaration comes last in the file wins outright — so it has to be one declaration). */

/*
 * Override v1 parametric-search globals (th { min-width: 220px !important }) loaded
 * on the same page. Data columns shrink to content; only the part column keeps a min-width.
 */
.psv2-table thead th.psv2-data-col:not(.slider-column),
.psv2-table tbody td.psv2-data-col:not(.slider-column) {
    min-width: 0 !important;
    max-width: none !important;
}

/* Fixed header: beat v1 global th { min-width: 220px !important } on detached thead rows */
.psv2-root .psv2-table.psv2-header-fixed thead tr th.psv2-data-col:not(.slider-column) {
    min-width: 0 !important;
    max-width: none !important;
}

/* Range-slider columns — fixed width in every mode so stick/unstick stays consistent */
.psv2-table thead th.slider-column,
.psv2-table tbody td.slider-column,
.psv2-root .psv2-table.psv2-header-fixed thead tr th.slider-column {
    width: var(--psv2-slider-col-width) !important;
    min-width: var(--psv2-slider-col-width) !important;
    max-width: var(--psv2-slider-col-width) !important;
    box-sizing: border-box;
}

.psv2-table thead th.slider-column:has(.range-slider-container),
.psv2-root .psv2-table.psv2-header-fixed thead tr th.slider-column:has(.range-slider-container) {
    vertical-align: middle;
}

.psv2-label-row th.slider-column .param-header {
}

.psv2-table tbody td.slider-column {
    text-align: center;
}

.psv2-part-cell {
    min-height: 48px;
    position: relative;
    overflow: visible;
}

.psv2-root .part-number-container .compare-checkbox,
.psv2-root td.psv2-part-col input.compare-checkbox {
    position: absolute;
    margin: 0;
    top: 50%;
    left: 3px;
    transform: translateY(-50%);
    width: 14px;
    height: 14px;
    cursor: pointer;
    pointer-events: auto;
    overflow: visible;
    display: inline-block;
    vertical-align: middle;
}

.psv2-table tbody td.psv2-part-col,
.psv2-table:not(.psv2-header-fixed) thead th.psv2-part-col {
    text-align: left;
    width: var(--psv2-part-col-width) !important;
    min-width: var(--psv2-part-col-width) !important;
    max-width: var(--psv2-part-col-width) !important;
    position: sticky;
    left: 0;
}

.psv2-table.psv2-header-fixed thead th.psv2-part-col,
.psv2-table.psv2-header-fixed tbody td.psv2-part-col {
    width: var(--psv2-part-col-width) !important;
    min-width: var(--psv2-part-col-width) !important;
    max-width: var(--psv2-part-col-width) !important;
}

.psv2-table.psv2-header-fixed thead th.psv2-part-col {
    position: relative;
    left: auto;
}

.psv2-table tbody td.psv2-part-col {
    z-index: 3;
    /* Sticky positioning + z-index only controls stacking ORDER, not opacity — without
       an actual background this cell stays visually transparent, so scrolled-behind
       columns' content (in normal flow at that same screen position once scrolled) was
       showing through/around it instead of being hidden underneath. */
    background: #fff;
}

.psv2-table thead th:not(.psv2-part-col) {
    z-index: 1;
    background: var(--psv2-header-bg);
}

/*
 * Label row must stack above the filter row. The part column is position: sticky,
 * so it composites on its own layer; during vertical scroll the filter-row cell can
 * bleed a pixel or two over the label-row cell. Keeping the (opaque) label row on top
 * hides that bleed and preserves the crisp row-divider border.
 */
.psv2-table thead .psv2-label-row th {
    background: var(--psv2-header-bg);
    z-index: 2;
}

.psv2-table thead .psv2-filter-row th:not(.psv2-part-col) {
    background: #f0f0f0;
    z-index: 1;
}

.psv2-table thead th.psv2-part-col {
    z-index: 5;
    background: var(--psv2-header-bg);
}

.psv2-table thead .psv2-label-row th.psv2-part-col {
    z-index: 6;
}

.psv2-table thead .psv2-filter-row th.psv2-part-col {
    background: #f0f0f0;
    z-index: 5;
    white-space: nowrap;
}

/* Cart icon tooltip must stack above sticky part column and scrolling data columns */
.psv2-table tbody td.psv2-part-col .carticon {
    position: relative;
    cursor: pointer;
}

.psv2-table tbody td.psv2-part-col:has(.carticon) {
    overflow: visible !important;
}

.psv2-table tbody td.psv2-part-col:has(.carticon:hover) {
    clip-path: none !important;
    z-index: 9990 !important;
    box-shadow: none !important;
}

.psv2-table tbody td.psv2-part-col .carticon .tooltip-pdf {
    z-index: 10001 !important;
    position: absolute;
    left: 100%;
    top: 50%;
    transform: translateY(-50%);
}

.psv2-table tbody td:first-child {
    text-align: left;
}

.psv2-table tbody td {
    padding: 8px 12px;
    background-color: #fff;
}

.psv2-table.table-striped > tbody > tr:nth-of-type(odd) > td,
.psv2-table.table-striped > tbody > tr:nth-of-type(even) > td {
    background-color: #fff;
}

.psv2-col-hidden {
    display: none !important;
}

.psv2-filter-row .psv2-filter-cell {
    background: #f0f0f0;
    vertical-align: top;
    position: relative;
}

.psv2-label-row th.psv2-data-col .param-header {
    white-space: normal;
    text-wrap: balance;
}

.psv2-root.filters-collapsed .psv2-filter-row {
    display: none !important;
}

/* Not scoped to .psv2-part-col — data-filter-toggle-all-columns="yes" puts this wrap on
   every column's label, not just the first (part) one. */
.psv2-label-row th .psv2-filter-toggle-wrap {
    display: block;
    padding: 0 8px 6px;
    text-align: left;
    line-height: 1.2;
}

.psv2-label-row th.psv2-part-col .param-header {
    border-bottom: none;
    min-height: 36px;
    padding-bottom: 4px;
}

/* Icon mode (default): the toggle icon itself reads as a visual close for the label, so
   the wrap doesn't need the text label's bottom padding, and .param-header gets its
   border back — restoring the divider the text-label mode omits (border-bottom: none,
   two rules up) since the wrap's own padding used to serve that visual-separation role. */
.psv2-root:not([data-filter-toggle-icon="no"]) .psv2-label-row th .psv2-filter-toggle-wrap {
    padding-bottom: 2px;
    padding-top: 2px;
    /* display:flex + no align-items override (default stretch) so .psv2-filter-toggle
       fills this wrap's full height:100% — it does its own internal centering — giving
       it the biggest possible click target instead of just its tight icon+text box. */
    display: flex;
    min-height: 24px;
}

.psv2-root:not([data-filter-toggle-icon="no"]) .psv2-label-row th .param-header {
    border-bottom: 1px solid var(--psv2-border);
    /* A fixed height (not min-height) rather than position:absolute on the toggle wrap
       below: absolutely positioning it to the cell's bottom looked correct in theory
       (table cells in the same row share one stretched height) but didn't render
       consistently in practice. Giving every column's own label the SAME height up
       front — big enough for a 2-line label like "VESD CONTACT (KV)" — means the
       toggle wrap below it, left in normal flow, lands at the same position in every
       column without needing to fight the table layout at all. */
    height: 60px;
    min-height: 0;
}

/* NOT a shorter height for .psv2-part-col here — every column's label-row <th> shares
   one row, so the browser stretches them all to the tallest one's total (header + toggle)
   height regardless. Giving the part column a shorter header just left it looking
   top-anchored with blank space below before the shared row-bottom, instead of visually
   matching the other columns' toggle position. */

.psv2-part-filter-tools {
    padding: 6px 8px 6px;
    text-align: left;
    /*
     * NOT position:absolute;inset:0 (as it once was, to pin quick-tips to the bottom of
     * any leftover height when another column's filter — e.g. a 150px slider — made the
     * row taller than this content needs): a table using table-layout:fixed (this table
     * gets that whenever column widths are snapshotted/locked — see snapshotColumnWidths
     * in parametric-search-v2.js) has a real browser quirk where a cell's min-height/
     * height CSS property doesn't grow the row, even though the exact same property
     * resolves correctly in the computed-style panel — confirmed on both a position:
     * sticky cell AND a plain, ordinary one. Actual in-flow content, by contrast,
     * reliably drives row height in every browser regardless of table-layout mode — so
     * on a table with only compact (checkbox) filters and no slider, an absolutely
     * positioned tools block could size itself past the cell's real (short) rendered
     * height with nothing forcing the row to grow to match, spilling its own content
     * over the table rows below. Normal flow trades away the "pin quick-tips to the
     * bottom of extra leftover height" cosmetic nicety for guaranteed-correct sizing.
     */
    box-sizing: border-box;
}

.psv2-header-search-wrap {
    margin-bottom: 6px;
}

.psv2-header-search-wrap .psv2-header-search {
    width: 100%;
    min-width: 0;
    font-size: 12px;
}

section#parametric-search+section {
    margin-top: 0 !important;
}

.psv2-quick-tips-wrap {
    padding: 5px;
    text-align: left;
    font-family: inherit;
    font-size: 12px;
    font-weight: 400;
    line-height: 1.35;
    color: #333;
    -webkit-font-smoothing: auto;
}

.psv2-quick-tips-title {
    margin: 0 0 3px;
    font-size: 12px;
    font-weight: 600;
    line-height: 1.2;
    color: #333;
}

.psv2-quick-tips-line {
    margin: 0 0 2px;
    font-size: 12px;
    font-weight: 400;
    line-height: 1.2;
    color: #555;
}

.psv2-root .helpTextHeader {
    font-family: inherit;
    font-size: inherit;
    font-weight: inherit;
}

.psv2-filter-toggle {
    position: relative;
    z-index: 2;
    /* Fills its .psv2-filter-toggle-wrap parent (display:block/flex, width:100%) rather
       than sizing to its own icon+text content — otherwise only that tight content box
       was clickable, and the wrap's own padding around it looked clickable but wasn't. */
    display: flex;
    align-items: center;
    width: 100%;
    height: 100%;
    box-sizing: border-box;
    cursor: pointer;
    font-size: 12px;
    color: #333;
    text-decoration: none;
}

.psv2-filter-toggle:hover {
    text-decoration: underline;
}

.psv2-filter-toggle .filter-icon {
    display: inline-flex;
    align-items: center;
    margin-right: 4px;
    opacity: 0.85;
}

.psv2-filter-toggle .filter-icon svg {
    /* SVGs default to vertical-align:baseline, which leaves room below for a text
       descender that isn't there — throwing the icon a few px low relative to the
       flex-centered text next to it. display:block (already set below) mostly
       handles this, but this belongs on the icon itself, not just its wrapper span,
       for the same reason. */
    vertical-align: middle;
}

.psv2-filter-toggle .psv2-filter-toggle-text {
    line-height: 1;
    font-size: 12px;
}

.psv2-filter-toggle:hover .filter-icon {
    opacity: 1;
}

.psv2-filter-toggle .filter-icon svg {
    display: block;
}

.psv2-checkbox-filter {
    max-height: 180px;
    overflow-y: auto;
    overflow-x: hidden;
    padding: 5px 5px 5px 12px;
    text-align: left;
    box-sizing: border-box;
    max-width: none;
    min-width: 0;
}

.psv2-checkbox-filter label.table-checkbox-inner,
.psv2-root label.table-checkbox-inner {
    display: block;
    overflow: visible !important;
    overflow-y: visible !important;
    max-width: none;
    min-width: 0;
    box-sizing: border-box;
    white-space: nowrap;
}

.psv2-checkbox-filter label {
    font-size: 12px;
    font-weight: normal;
    color: #333;
    margin: 2px 0;
    cursor: pointer;
}

.psv2-range-filter {
    display: flex;
    align-items: center;
    gap: 4px;
    padding: 6px;
}

.psv2-range-filter input {
    width: 72px;
    font-size: 12px;
}

.psv2-sortable {
    cursor: pointer;
    user-select: none;
}

.psv2-sortable:hover {
    background-color: var(--psv2-highlight-hover);
}

.psv2-label-row th.psv2-sortable.sort-asc,
.psv2-label-row th.psv2-sortable.sort-desc,
.psv2-label-row th.psv2-sortable.psv2-sorted-col {
    background-color: var(--psv2-highlight);
}

.psv2-filter-row th.psv2-sorted-col {
    background-color: var(--psv2-highlight) !important;
}

.psv2-table tbody td.psv2-sorted-col {
    background-color: var(--psv2-highlight) !important;
}

.psv2-table tbody tr:hover > td {
    background-color: var(--psv2-highlight-hover) !important;
}

.psv2-table tbody tr:hover > td.psv2-part-col {
    background-color: var(--psv2-highlight-hover) !important;
}

/* Fixed header — thead pinned to viewport once table scrolls up (JS-driven) */
.psv2-table.psv2-header-fixed {
    table-layout: fixed;
}

/* Applies in both modes, not just header-fixed — display:block (which the detached,
   position:fixed header needs to lay out its own row/cell structure) is the only piece
   that stays mode-specific, right below. Drop shadow + top/left/right border-replacement,
   all as one declaration (see the comment further up this file, above the now-empty rule
   this used to live in, for why box-shadow rather than border — box-shadow doesn't merge
   across separate rules for the same selector, so it has to stay one declaration here). */
.psv2-table thead {
    /* display:table-header-group (the default here in non-fixed mode) is a known weak
       spot for box-shadow rendering — some browsers don't paint it at all on internal
       table box types even when the computed style reports the value correctly (as
       confirmed live: getComputedStyle showed the exact box-shadow value, but nothing
       painted). position:relative, with no positioning offset of its own, gets it
       treated as a normally-composited box for shadow-painting purposes instead.
       z-index is required here too, not optional: giving .psv2-table tbody the same
       position:relative fix (for its own part-col shadow) made tbody positioned as
       well, and being later in the DOM with no z-index difference it started painting
       ABOVE thead — its own opaque row backgrounds covered thead's shadow, undoing this
       fix. An explicit z-index keeps thead on top regardless of tbody now being
       positioned too. */
    position: relative;
    z-index: 2;
    background: #fff;
    box-shadow:
        0 2px 6px rgba(0, 0, 0, 0.1),
        -1px 0 0 var(--psv2-border),
        1px 0 0 var(--psv2-border),
        0 -1px 0 var(--psv2-border);
}

.psv2-table.psv2-header-fixed thead {
    display: block;
}

/* Same fix as .psv2-table thead above, same reason: display:table-row-group (tbody's
   default) is the same category of internal table box as table-header-group, and the
   sticky part-col cell's own box-shadow (its right-edge divider) wasn't painting inside
   it either. */
.psv2-table tbody {
    position: relative;
}

.psv2-table.psv2-header-fixed thead tr {
    display: table;
    table-layout: fixed;
    margin: 0;
}

.psv2-table.psv2-header-fixed thead tr th {
    display: table-cell;
    vertical-align: top;
    overflow: hidden;
    box-sizing: border-box;
}

.psv2-table.psv2-header-fixed thead .psv2-filter-row th {
    overflow: visible;
}

.psv2-sortable.sort-asc .param-header::after {
    content: ' ▲';
    font-size: 10px;
}

.psv2-sortable.sort-desc .param-header::after {
    content: ' ▼';
    font-size: 10px;
}

/* Part number cell (aligned with v1) */
.psv2-root .part-number-container {
    position: relative;
    display: flex;
    align-items: center;
    width: 100%;
    min-height: 28px;
}

.psv2-root .part-buttons {
    display: block;
    width: 100%;
    padding-left: 21px;
    margin-top: 5px;
    margin-bottom: 5px;
}

.psv2-root .part-buttons > a:not(:last-child)::after {
    content: "|";
    margin: 0 8px;
    color: #ccc;
}

.psv2-root span.part-number {
    display: inline-block;
    flex: 1;
    width: auto;
    margin-bottom: 0;
    padding-left: 21px;
    text-align: left;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.psv2-root span.part-number a {
    text-decoration: none;
    color: #5f5d5d;
    font-weight: 600;
    font-size: 18px;
    pointer-events: auto;
}

.psv2-footer {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    margin: 1rem 0 2rem;
    font-size: 0.85rem;
}

.psv2-pagination {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.25rem;
}

.psv2-page-btn {
    border: 1px solid var(--psv2-border);
    background: #fff;
    min-width: 2rem;
    padding: 0.25rem 0.5rem;
    font-size: 0.8rem;
    line-height: 1.2;
    cursor: pointer;
}

.psv2-page-btn:hover:not(.is-active):not(.is-disabled) {
    background: var(--psv2-highlight-hover);
}

.psv2-page-btn.is-active {
    background: var(--psv2-teal);
    color: #fff;
    border-color: var(--psv2-teal);
}

.psv2-page-nav {
    font-weight: 600;
}

.psv2-page-btn.is-disabled {
    opacity: 0.4;
    cursor: default;
}

.psv2-page-ellipsis {
    min-width: 1.5rem;
    padding: 0.25rem 0.25rem;
    text-align: center;
    color: #777;
    user-select: none;
}

.psv2-table-panel {
    position: relative;
    width: 100%;
    background: #fff;
}

.psv2-root.is-loading .psv2-scroll-wrapper,
.psv2-root.is-loading .psv2-dummy-scrollbar {
    display: none;
}

.psv2-root.is-loading .psv2-footer {
    margin-top: 0;
}

.psv2-root:not(.is-loading) .psv2-loading {
    display: none;
}

.psv2-loading {
    display: block;
    position: relative;
    width: 100%;
    min-height: min(420px, 55vh);
    overflow: hidden;
    border: 1px solid var(--psv2-border);
    background: #fff;
}

.psv2-loading-skeleton {
    display: flex;
    flex-direction: column;
    width: 100%;
    min-height: min(420px, 55vh);
    filter: blur(1px);
    pointer-events: none;
}

.psv2-skeleton-header {
    display: flex;
    flex-shrink: 0;
    background: var(--psv2-header-bg);
    border-bottom: 1px solid var(--psv2-border);
}

.psv2-skeleton-cell {
    flex: 1 1 72px;
    min-width: 56px;
    height: 44px;
    border-right: 1px solid var(--psv2-border);
    background: linear-gradient(90deg, #e8e8e8 0%, #f3f3f3 50%, #e8e8e8 100%);
    background-size: 200% 100%;
    animation: psv2-skeleton-shimmer 1.6s ease-in-out infinite;
}

.psv2-skeleton-cell:last-child {
    border-right: none;
}

.psv2-skeleton-cell--part {
    flex: 0 0 var(--psv2-part-col-width);
    min-width: var(--psv2-part-col-width);
}

.psv2-skeleton-body {
    flex: 1;
    display: flex;
    flex-direction: column;
}

.psv2-skeleton-row {
    flex: 1;
    min-height: 34px;
    border-bottom: 1px solid var(--psv2-border);
    background: linear-gradient(90deg, #fafafa 0%, #fff 50%, #fafafa 100%);
    background-size: 200% 100%;
    animation: psv2-skeleton-shimmer 1.6s ease-in-out infinite;
}

.psv2-skeleton-row:nth-child(even) {
    animation-delay: 0.25s;
}

.psv2-loading-status {
    position: absolute;
    inset: 0;
    z-index: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.75rem;
    padding: 2rem 1rem;
    background: rgba(255, 255, 255, 0.68);
    backdrop-filter: blur(5px);
    -webkit-backdrop-filter: blur(5px);
}

.psv2-loading-text {
    margin: 0;
    font-size: 0.95rem;
    color: #555;
}

.psv2-loading .spinner-border {
    width: 2.75rem;
    height: 2.75rem;
    color: var(--psv2-teal);
    border-width: 0.2em;
}

@keyframes psv2-skeleton-shimmer {
    0% {
        background-position: 200% 0;
    }
    100% {
        background-position: -200% 0;
    }
}

.psv2-error {
    display: none;
    position: relative;
    z-index: 6;
    color: #c0392b;
    padding: 1rem;
    margin: 0;
    background: #fff;
    border-top: 1px solid var(--psv2-border);
}

.psv2-no-results {
    display: none;
    padding: 2rem 1.5rem;
    text-align: center;
    background: #fff;
    border-left: 1px solid var(--psv2-border);
    border-right: 1px solid var(--psv2-border);
    border-bottom: 1px solid var(--psv2-border);
}

.psv2-no-results.is-visible {
    display: block;
}

.psv2-no-results-message {
    margin: 0 0 0.75rem;
    color: #333;
    font-size: 1rem;
}

.psv2-no-results-action {
    margin: 0;
}

.psv2-no-results-link {
    color: var(--psv2-teal);
    font-weight: 600;
    text-decoration: none;
}

.psv2-no-results-link:hover,
.psv2-no-results-link:focus {
    text-decoration: underline;
}

/* Help panel */
.psv2-help-panel {
    display: none;
    position: fixed;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    max-width: 640px;
    width: 92%;
    max-height: 80vh;
    overflow-y: auto;
    background: #fff;
    border: 1px solid var(--psv2-border);
    box-shadow: 0 8px 32px rgba(0, 0, 0, 0.18);
    z-index: 10050;
    padding: 1rem 1rem;
}

.psv2-help-panel h3 {
    font-size: 18px;
    line-height: 1;
}

.psv2-help-panel ul {
    margin-bottom: 0;
}

.psv2-help-panel.is-open {
    display: block;
}

.psv2-help-close {
    position: absolute;
    top: 0.5rem;
    right: 0.75rem;
    border: none;
    background: none;
    font-size: 1.5rem;
    line-height: 1;
    cursor: pointer;
}

/* Column customize dropdown — anchored below the Columns button (v1 style: a live-apply
   checklist dropdown, not a modal overlay with staged Cancel/Apply). */
.psv2-col-dropdown-wrap {
    position: relative;
}

.psv2-col-dropdown {
    display: none;
    position: absolute;
    top: 100%;
    left: 0;
    margin-top: 4px;
    min-width: 220px;
    max-height: 70vh;
    overflow-y: auto;
    background: #fff;
    border: 1px solid var(--psv2-border);
    border-radius: 4px;
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.18);
    padding: 6px;
    z-index: 1000;
}

.psv2-col-dropdown.is-open {
    display: block;
}

.psv2-col-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    border: 1px solid var(--psv2-border);
    border-radius: 4px;
    padding: 6px 10px;
    margin-bottom: 4px;
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.02em;
    cursor: pointer;
    background: #fff;
    color: #333;
}

.psv2-col-item:hover {
    border-color: var(--psv2-teal);
}

.psv2-col-item::after {
    content: '';
    flex: 0 0 auto;
    width: 14px;
    height: 14px;
}

.psv2-col-item.is-checked::after {
    content: '\2713';
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--psv2-teal);
    font-weight: 700;
}

.psv2-col-dropdown-footer {
    gap: 4px;
    margin-top: 2px;
}

.psv2-col-close-item,
.psv2-col-reset-item {
    flex: 1 1 50%;
    border: none;
    border-radius: 4px;
    padding: 6px 10px;
    font-size: 0.7rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.02em;
    cursor: pointer;
}

.psv2-col-close-item {
    background: #fff;
    color: #333;
    border: 1px solid var(--psv2-border);
}

.psv2-col-close-item:hover {
    border-color: var(--psv2-teal);
}

.psv2-col-reset-item {
    background: #000;
    color: #fff;
}

.psv2-col-reset-item:hover {
    background: #222;
}

/* Embed mode — table-only embeds skip the platform bar via show_platform="no" */
.text-green {
    color: var(--psv2-teal) !important;
}

/* Range sliders (mirrors v1; needed for compact embed without v1 CSS) */
.psv2-root .range-slider-container {
    display: flex;
    flex-direction: column;
    align-items: center;
    margin: 1px 0;
    height: 150px;
    position: relative;
    z-index: 1003;
    background-color: transparent;
    font-weight: normal;
}

.psv2-root .range-slider {
    height: 120px;
    margin: 5px auto;
    max-width: 4px;
}

.psv2-root .ui-slider-vertical {
    width: 8px;
}

.psv2-root .ui-slider-vertical .ui-slider-handle {
    width: 20px !important;
    height: 10px !important;
    border-radius: 6px !important;
    left: 50% !important;
    margin-left: -10px !important;
    background: #5f5d5d !important;
    border: 1px solid #5f5d5d !important;
    cursor: pointer !important;
}

/* A single-value column (e.g. a spec every part shares) can't offer a real range — the
   slider still renders (both handles stacked at the same spot, one hidden behind the
   other) rather than being disabled entirely, so it's grayed out here to read as
   "disabled" instead of looking like a slider missing its min handle. */
.psv2-root .psv2-range-fixed-value .ui-slider-vertical .ui-slider-handle {
    background: #c8c8c8 !important;
    border-color: #c8c8c8 !important;
    cursor: default !important;
}

.psv2-root .psv2-range-fixed-value .ui-slider-vertical.ui-state-disabled {
    opacity: 1;
    background: #e6e6e6;
}

.psv2-root .min-value-display,
.psv2-root .max-value-display {
    margin: 5px 0;
    font-size: 12px;
    text-align: center;
    width: 100%;
}

/* Hidden toolbar items — removed from layout (not visibility:hidden slots) */
.psv2-root .psv2-toolbar-item--hidden {
    display: none !important;
}

.psv2-root .psv2-toolbar-btn-row .psv2-toolbar-item--hidden {
    min-width: 0;
}
