/* Customer presentation only. Standard Swift layouts and scheme variables remain authoritative. */
.hewitt-home-hero figure::after { content: ""; position: absolute; inset: 0; background: linear-gradient(90deg, rgba(0,0,0,.78), rgba(0,0,0,.36) 62%, rgba(0,0,0,.12)); }
.hewitt-home-hero [data-swift-text] { max-width: 42rem; }
.hewitt-home-hero h1 { max-width: 18ch; }
.hewitt-category-card .card-img-top { aspect-ratio: 16 / 10; object-fit: cover; }
header[data-swift-page-header] img { max-width: 100%; height: auto; }
@media (max-width: 767.98px) { .hewitt-home-hero figure::after { background: rgba(0,0,0,.55); } }

/* Keep the desktop dropdown reachable while the pointer crosses Swift's Popper gap.
   Swift marks the top item position-static for the full-width panel. The shared
   affordance bridge is item-anchored, so give only customer dropdown items a
   containing block and keep the panel viewport-wide. */
@media (min-width: 992px) {
  .megamenu-wrapper > nav > .nav-item.dropdown { position: relative !important; }
  .megamenu-wrapper > nav > .nav-item.dropdown > .dropdown-menu,
  .megamenu-wrapper > nav > .nav-item.dropdown > .megamenu {
    position: fixed !important;
    inset: 0 auto auto 0 !important;
    width: 100vw !important;
  }
}

/* Hewitt informative swatches keep their source aspect ratio and labels. */
main [data-dw-itemtype="swift-v2_image"] figure:has(> img[src*="vinyl-colors2.jpg"]),
main [data-dw-itemtype="swift-v2_image"] figure:has(> img[src*="defender-colors.jpg"]),
main [data-dw-itemtype="swift-v2_image"] figure:has(> img[src*="trim.jpg"]) {
  aspect-ratio: auto;
  max-height: none;
  overflow: visible;
}
main [data-dw-itemtype="swift-v2_image"] figure > img[src*="vinyl-colors2.jpg"],
main [data-dw-itemtype="swift-v2_image"] figure > img[src*="defender-colors.jpg"],
main [data-dw-itemtype="swift-v2_image"] figure > img[src*="trim.jpg"] {
  width: 100%;
  height: auto;
  max-height: none;
  object-fit: contain;
}
/* The compact trim sample stays legible without filling a desktop-width row. */
main [data-dw-itemtype="swift-v2_image"] figure > img[src*="trim.jpg"] {
  max-width: 32rem;
}

/* Preserve useful empty-search feedback hidden by the generic reference theme. */
main [data-dw-itemtype="swift-v2_productlistitemrepeater"] .product-list > .alert.alert-dark {
  display: block !important;
}

/* Native public form labels wrap within the customer content column. */
main form[id^="dw-form-"] .form-label {
  white-space: normal;
  overflow-wrap: anywhere;
  max-width: 100%;
}

/* == w1-tokens == */
/* Consumes the native colour-scheme custom tokens --dw-color-heading and --dw-color-link
   (HewittRAD scheme group "hewitt", #003965 on light schemes). The Style-asset generator
   emits both variables but no stock rule reads them, so the navy heading/link colour of the
   live CVI cannot be reached by configuration alone. Falls back to inherit, so the BoatLifter
   scheme group, which declares neither token, is unaffected.
   Retire when the colour-scheme model gains dedicated heading/link fields. */
h1, h2, h3, h4, h5, h6,
.dw-h1, .dw-h2, .dw-h3, .dw-h4, .dw-h5, .dw-h6 {
  color: var(--dw-color-heading, inherit);
}
main a:not([data-dw-button]):not(.btn):not(.nav-link):not(.dropdown-item):not(.stretched-link) {
  color: var(--dw-color-link, inherit);
}

/* == w1-header == */
/* Wave 1 chrome, HewittRAD header bands and mega menu.
   Native configuration carries the three bands (brand bar = grid row 1882 / scheme lightgrey2,
   logo band = row 289 / scheme primary, nav band = row 290 / scheme dark) and the four mega-menu
   columns (product-group navigation flags). Only the items below have no configuration surface in
   Swift 2.4 and are therefore presentation-only rules. Area 4 and area 5 both load this file; each
   rule is scoped to the header so no page body is affected. */

/* 1. The live CVI sets the catalog bar in uppercase. Swift has no per-navigation case setting. */
@media (min-width: 992px) {
  header[data-swift-page-header] section[data-dw-colorscheme="dark"] .nav-wrapper > nav > .nav-item > .nav-link,
  header[data-swift-page-header] section[data-dw-colorscheme="dark"] .nav-wrapper > nav > .nav > .nav-item > .nav-link {
    text-transform: uppercase;
    letter-spacing: .02em;
    font-weight: 600;
  }
}

/* 2. The brand bar reads as a thin secondary strip, not a second main menu. */
header[data-swift-page-header] section[data-dw-colorscheme="lightgrey2"] .nav-link {
  font-size: .875rem;
  padding-top: .25rem;
  padding-bottom: .25rem;
}

/* 3. The catalog menu and the information menu belong together on the left of the nav band;
      only the search field takes the remaining width. Swift's flex columns otherwise share
      the row evenly, which pushes the information links into the middle of the bar. */
@media (min-width: 992px) {
  header[data-swift-page-header] section[data-swift-gridrow="3ColumnsFlex"] > [data-swift-container] > [data-swift-gridcolumn]:nth-child(1),
  header[data-swift-page-header] section[data-swift-gridrow="3ColumnsFlex"] > [data-swift-container] > [data-swift-gridcolumn]:nth-child(2) {
    flex: 0 0 auto !important;
  }
  header[data-swift-page-header] section[data-swift-gridrow="3ColumnsFlex"] > [data-swift-container] > [data-swift-gridcolumn]:nth-child(3) {
    flex: 1 1 auto !important;
    max-width: 28rem;
    margin-left: auto;
  }
}

/* 4. Mega-menu panel theme. Swift-v2_MenuRelatedContent/Menu.cshtml hard-codes
      data-dw-colorscheme="light" on the panel, so the Hewitt panel grey and the navy column
      heading of the live CVI cannot be reached through the colour-scheme configuration.
      Retire when the menu component exposes a panel colour scheme. */
header[data-swift-page-header] .megamenu-wrapper .megamenu.dropdown-menu,
header[data-swift-page-header] .megamenu-wrapper .dropdown-menu.dropdown-menu-shadow {
  background-color: #ECEDEE;
}
header[data-swift-page-header] .megamenu-wrapper .megamenu .megamenu-col > .nav-link:first-child {
  background-color: #13315F;
  color: #FFFFFF;
  padding: .4rem .75rem;
  margin-bottom: .5rem;
  line-height: 1.3;
}
header[data-swift-page-header] .megamenu-wrapper .megamenu .megamenu-col > .nav-link:first-child strong {
  font-weight: 600;
}
header[data-swift-page-header] .megamenu-wrapper .megamenu .megamenu-col > .nav-link:not(:first-child) {
  color: #232020;
}

/* 5. Utility labels in the navy band stay on one line next to their icons. */
header[data-swift-page-header] section[data-dw-colorscheme="primary"] .nav-link {
  white-space: nowrap;
}

/* 6. Below the desktop breakpoint the brand strip and the quick-add link are dropped rather than
      wrapped: they are desktop chrome, and the phone header is owned by the mobile header page and
      the off-canvas pass. Native HideForPhones is device-detection based and does not fire on a
      narrow desktop viewport, so the breakpoint rule lives here. */
@media (max-width: 991.98px) {
  header[data-swift-page-header] section[data-dw-colorscheme="lightgrey2"],
  header[data-swift-page-header] section[data-dw-colorscheme="primary"] [data-swift-gridcolumn][data-dw-itemtype="swift-v2_navigation"] {
    display: none !important;
  }
}

/* == w1-footer == */
/* Footer chrome for the tan (secondary) band and the near-black copyright strip.
   Everything structural is native: grid rows 286/287 (page 191) and 291-294 (page 192) carry the
   colour schemes, the columns are Swift-v2_Navigation / Swift-v2_Text / Swift-v2_Logo paragraphs.
   The rules below cover the three things the components do not expose. */

/* 1. Swift-v2_Navigation renders its Title as a bare text node directly in the grid column, so the
      column heading can only be reached through the column itself. Restore the body font inside the
      link list. */
footer[data-swift-page-footer] [data-swift-gridcolumn][data-dw-itemtype="swift-v2_navigation"] {
  font-family: var(--swift-foundation-headings-font-family, Oswald), sans-serif;
  font-size: .95rem;
  letter-spacing: .04em;
  text-transform: uppercase;
}
footer[data-swift-page-footer] [data-swift-gridcolumn][data-dw-itemtype="swift-v2_navigation"] .nav-wrapper {
  font-family: var(--swift-foundation-body-font-family, Titillium), sans-serif;
  font-size: 1rem;
  letter-spacing: normal;
  text-transform: none;
  margin-top: .5rem;
}
/* The extra-links column (REVIEWS / CUSTOM MANUFACTURING) is a title-less navigation whose items are
   the headings themselves, so it keeps the heading treatment on its links. */
footer[data-swift-page-footer] [data-swift-gridcolumn][data-dw-itemtype="swift-v2_navigation"] .nav-link {
  padding-left: 0;
  padding-right: 0;
  white-space: normal;
}

/* 2. Social column: the live CVI shows icons only. Swift-v2_Navigation always emits the node name
      next to the page Icon, so the label is hidden here rather than removed from the page. */
footer[data-swift-page-footer] [data-swift-gridcolumn][data-dw-itemtype="swift-v2_navigation"] .nav-link .icon-3 + span {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
}
footer[data-swift-page-footer] [data-swift-gridcolumn][data-dw-itemtype="swift-v2_navigation"] .nav-link .icon-3 {
  width: 1.75rem;
  height: 1.75rem;
}
footer[data-swift-page-footer] [data-swift-gridcolumn][data-dw-itemtype="swift-v2_navigation"] .nav.flex-nowrap:not(.flex-column) {
  flex-wrap: wrap !important;
  gap: .25rem;
}

/* 3. NColumnsFlex rows keep every column on one line at every viewport. The footer band has six
      columns, so it is forced to wrap below the desktop breakpoint and the contact column is given a
      usable minimum measure. */
footer[data-swift-page-footer] [data-swift-gridrow] > [data-swift-container] {
  flex-wrap: wrap;
}
footer[data-swift-page-footer] [data-swift-gridcolumn] {
  min-width: 12rem;
}
@media (max-width: 991.98px) {
  footer[data-swift-page-footer] [data-swift-gridcolumn] {
    flex: 1 1 14rem !important;
  }
}
@media (max-width: 575.98px) {
  footer[data-swift-page-footer] [data-swift-gridcolumn] {
    flex: 1 1 100% !important;
    min-width: 0;
  }
}
footer[data-swift-page-footer] [data-swift-gridcolumn][data-dw-itemtype="swift-v2_logo"] img {
  max-width: 100%;
  height: auto;
}

/* == w1-mobile == */
/* The phone document is the Mobile Header (page 190) + Mobile Footer (page 192), selected server-side
   by user agent, so the off-canvas burger, the logo, the search field, the account link and the cart
   are all native paragraphs there. These rules only handle what a narrow *desktop-UA* viewport sees,
   where Dynamicweb still serves the desktop header, and the phone search field's own measure. */
@media (max-width: 991.98px) {
  header[data-swift-page-header] [data-swift-gridcolumn][data-dw-itemtype="swift-v2_searchfield"] {
    min-width: 0;
  }
  header[data-swift-page-header] [data-swift-gridcolumn][data-dw-itemtype="swift-v2_logo"] img {
    max-width: 150px;
    height: auto;
  }
}
/* Long catalog labels in the off-canvas tree wrap instead of widening the panel. */
.offcanvas .offcanvas-navigation .nav-link {
  white-space: normal;
}

/* A narrow desktop-UA viewport still receives the desktop header (Dynamicweb picks the header page by
   user agent, not by width). Its utility row is min-content ~435px, so below the desktop breakpoint the
   row is allowed to wrap and the favourites link is dropped - the phone header (page 190) does not
   carry one either. */
@media (max-width: 991.98px) {
  header[data-swift-page-header] [data-swift-gridrow] > [data-swift-container] {
    flex-wrap: wrap;
  }
  header[data-swift-page-header] [data-swift-gridcolumn] {
    min-width: 0;
  }
  header[data-swift-page-header] [data-swift-gridcolumn][data-dw-itemtype="swift-v2_favorites"] {
    display: none !important;
  }
}

/* At desktop the six footer columns sit on one row, as on the live CVI; the wrap above is the
   below-lg behaviour only. */
@media (min-width: 992px) {
  footer[data-swift-page-footer] [data-swift-gridrow="6ColumnsFlex"] > [data-swift-container] {
    flex-wrap: nowrap;
  }
  footer[data-swift-page-footer] [data-swift-gridrow="6ColumnsFlex"] [data-swift-gridcolumn] {
    min-width: 0;
  }
}

/* == w3b-pdp == */
/* The product detail page stacks one section per grid row: a Swift-v2_Text heading row
   followed by the row that carries the data component. A Swift grid column renders exactly
   one paragraph, so a heading and its component cannot share a row, and none of the stock
   product components offers "hide my heading when I have no data". These rules drop the
   pair when the component produced nothing, so no product shows a bare section heading.

   Three mechanics worth keeping in mind here:
   - every relation is a DIRECT-CHILD path (section > container > column); a descendant
     match would also select the outer section the product detail rows are nested in and
     blank the whole page;
   - emptiness is expressed as "no element child", in a SEPARATE :not(:has(...)), because
     the column always carries the template's own whitespace (so :empty never matches) and
     because :has() inside :has() is invalid - the browser drops the whole rule;
   - the selectors are anchored on a swift-v2_product* item type, AND the whole block is
     scoped by `main:has([data-dw-itemtype="swift-v2_productcomponentselector"])`, the buy-box
     component that only a product DETAIL page renders. Without that scope rule 2 also matched
     a product LIST row standing in front of an empty swift-v2_productlistinfo row, which is
     exactly the shape of /boatlifter/shop - the entire grid was hidden (QA defect 1). */

/* 1. Component rendered nothing at all (ProductMediaTable, ProductBom): its own row ... */
main:has([data-dw-itemtype="swift-v2_productcomponentselector"]) section[data-swift-gridrow]:has(> [data-swift-container] > [data-swift-gridcolumn]:only-child[data-dw-itemtype^="swift-v2_product"]):not(:has(> [data-swift-container] > [data-swift-gridcolumn] > *)) {
  display: none;
}
/* ... and the heading row immediately in front of it. The SUBJECT must itself be a
      Swift-v2_Text heading row (fix round C). Without that qualifier the rule also fired
      inside the BUY BOX, where the component source page stacks nine 1ColumnFlex product
      rows: ProductPriceTable, ProductVariantSelector and ProductMediaTable render nothing
      on most products, so the rule hid whatever row stood in front of them - the PRICE row
      (in front of the empty price table) and the ADD TO CART row (in front of the empty
      media table) - on every product detail page in both areas. That is the "buy box is
      title and SKU only, ~60% whitespace" half of QA defect 9; it was masked while the
      shop-wide anonymous price gate was on, because the gate's own lock chip sat in the
      same hidden row. */
main:has([data-dw-itemtype="swift-v2_productcomponentselector"]) section[data-swift-gridrow]:has(> [data-swift-container] > [data-swift-gridcolumn]:only-child[data-dw-itemtype="swift-v2_text"]):has(+ section[data-swift-gridrow] > [data-swift-container] > [data-swift-gridcolumn]:only-child[data-dw-itemtype^="swift-v2_product"]):not(:has(+ section[data-swift-gridrow] > [data-swift-container] > [data-swift-gridcolumn] > *)) {
  display: none;
}

/* 2. ProductFieldDisplayGroups always renders its wrapper and an empty <table> when the
      product has no values in the bound display group (hewitt_specs). */
main:has([data-dw-itemtype="swift-v2_productcomponentselector"]) section[data-swift-gridrow]:has(> [data-swift-container] > [data-swift-gridcolumn]:only-child[data-dw-itemtype="swift-v2_productfielddisplaygroups"]):not(:has(.item_swift-v2_productfielddisplaygroups tbody tr)) {
  display: none;
}
main:has([data-dw-itemtype="swift-v2_productcomponentselector"]) section[data-swift-gridrow]:has(> [data-swift-container] > [data-swift-gridcolumn]:only-child[data-dw-itemtype="swift-v2_text"]):has(+ section[data-swift-gridrow] > [data-swift-container] > [data-swift-gridcolumn]:only-child[data-dw-itemtype="swift-v2_productfielddisplaygroups"]):not(:has(+ section[data-swift-gridrow] .item_swift-v2_productfielddisplaygroups tbody tr)) {
  display: none;
}

/* == w2b-home == */
/* Hewitt homepage (area 4, page 106) rework. Every rule below covers something the
   native Swift 2.4 components do not expose as a setting. Scoped to <main> so the
   header/footer chrome (w1-*) and BoatLifter (area 5, which never renders these
   structures on its home page) are untouched. */

/* 1. Hero slider height. Stock Swift-v2_Slider/CardCoverFull.cshtml hard-codes
      min-height:55vh inline on the slide card; there is no height field on
      Swift-v2_Slider or Swift-v2_Slider_Item. Retire when the slider item type
      grows a height setting. */
/* The hero height does not come from the template's inline min-height:55vh but from the
   Distribution theme layer (`Custom/default_custom.css`, "CardCoverFull hero"), which sets
   `min-height: 55vh !important` on exactly this card. default_custom.css is
   Distribution-owned and stays byte-identical, so the override below repeats that selector
   with a `main` prefix to win on specificity among the !important declarations. Retire when
   Swift-v2_Slider grows a slide-height setting or the theme layer exposes a token. */
main [data-dw-itemtype="swift-v2_slider"] .swiffy-slider .slider-container[style*="--swiffy-slider-item-width: 100%"] > li > .card {
  min-height: 560px !important;
}
@media (max-width: 991.98px) {
  main [data-dw-itemtype="swift-v2_slider"] .swiffy-slider .slider-container[style*="--swiffy-slider-item-width: 100%"] > li > .card {
    min-height: 440px !important;
  }
}

/* 2. Hero overlay typography. Title/Subtitle are rich-text fields rendered raw by the
      stock template, so the headline classes below are authored in the field value;
      the component has no font-size setting for slide text. */
main .swiffy-slider .hewitt-hero-kicker {
  font-family: var(--dw-font-heading, inherit);
  text-transform: uppercase;
  letter-spacing: .12em;
  font-size: clamp(.75rem, .6rem + .4vw, 1rem);
  margin: 0 0 .25rem;
  opacity: .95;
}
main .swiffy-slider .hewitt-hero-headline {
  text-transform: uppercase;
  font-size: clamp(2rem, 1rem + 4.2vw, 4.5rem);
  line-height: 1.02;
  margin: 0 0 1rem;
  max-width: 18ch;
}

/* 3. Section headings (WHAT'S NEW / FEATURED ITEMS / CUSTOMER PHOTOS) get the live
      site's left-aligned uppercase label plus hairline rule. Swift-v2_Text has no
      "rule under heading" setting. */
main .hewitt-section-heading {
  text-transform: uppercase;
  border-bottom: 1px solid rgba(0, 0, 0, .18);
  padding-bottom: .5rem;
  margin-bottom: 0;
  width: 100%;
}

/* 4. Homepage product strips: hide the "N out of N products" counter that
      Swift-v2_ProductListItemRepeater always renders inside #ProductListLoadMore.
      The component exposes no setting for it. Scoped structurally to the compact
      homepage card component (image + name only, no price paragraph), so the real
      PLP keeps its counter and Load-more. Retire when the repeater gets a
      "hide result count" field. */
main .product-list:has(article.js-product [data-dw-itemtype="swift-v2_productheader"]):not(:has([data-dw-itemtype="swift-v2_productprice"])) #ProductListLoadMore {
  display: none;
}
/* Same scope: keep the four cards on one row and give the name room. */
main .product-list:not(:has([data-dw-itemtype="swift-v2_productprice"])) article.js-product {
  padding: 0 .5rem;
}

/* 5. Customer photos strip. NColumnsFlex columns are flex-fill and never wrap
      (same trap as the w1-footer band), and Swift-v2_Image has no crop setting, so
      six source photos of different aspect ratios would draw six different heights. */
main section[data-swift-gridrow="6ColumnsFlex"] > [data-swift-container]:has(> [data-dw-itemtype="swift-v2_image"]) {
  flex-wrap: wrap;
}
main section[data-swift-gridrow="6ColumnsFlex"] > [data-swift-container] > [data-dw-itemtype="swift-v2_image"] {
  /* !important beats Bootstrap's .flex-fill (flex: 1 1 auto !important); without a fixed
     basis the loaded 1920px photos blow the flex basis up and each lands on its own row. */
  flex: 0 0 calc((100% - 5 * 1rem) / 6) !important;
  min-width: 0;
}
main section[data-swift-gridrow="6ColumnsFlex"] > [data-swift-container] > [data-dw-itemtype="swift-v2_image"] img {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
}
@media (max-width: 991.98px) {
  main section[data-swift-gridrow="6ColumnsFlex"] > [data-swift-container] > [data-dw-itemtype="swift-v2_image"] {
    flex: 0 0 calc((100% - 2 * 1rem) / 3) !important;
  }
}
@media (max-width: 575.98px) {
  main section[data-swift-gridrow="6ColumnsFlex"] > [data-swift-container] > [data-dw-itemtype="swift-v2_image"] {
    flex: 0 0 calc((100% - 1rem) / 2) !important;
  }
}

/* 6. Swift-v2_Card image-beside-text layouts (CardImageLeft/CardImageRight) hard-code
      `grid grid-2` with `--bs-columns:2 !important` at every viewport, so the Docks and
      Lifts bands keep two columns on a phone and the copy column becomes unreadably
      narrow. The card exposes no responsive setting. */
@media (max-width: 767.98px) {
  main [data-dw-itemtype="swift-v2_card"] .card.grid.grid-2 {
    --bs-columns: 1 !important;
  }
  main [data-dw-itemtype="swift-v2_card"] .card.grid.grid-2 > figure > img {
    aspect-ratio: 16 / 10;
  }
}

/* 7. The "Follow us" social row is a Swift-v2_Navigation rendered with
      `ul.nav.flex-nowrap`, which cannot wrap, so five icon links overflow the phone
      canvas. Same component trap the w1-footer block fixes inside <footer>. */
main [data-dw-itemtype="swift-v2_navigation"] .nav.flex-nowrap:not(.flex-column) {
  flex-wrap: wrap !important;
  justify-content: center;
}

/* == fixA == */
/* Fix round A (2026-09-17), QA defects 3b, 4, 6 and 7. Every rule here covers something
   the native Swift 2.4 components do not expose as a setting; the facet rail, the card
   anatomy, the H1 duplication and the BoatLifter/bumper images were all fixed by
   configuration and carry no CSS. */

/* 1. No-image fallback (defect 3b). Swift-v2_ProductDefaultImage.cshtml renders NOTHING
      at all when the product resolves no image - not a placeholder, not a wrapper - so
      the card's image column collapses to zero height. That is what made the PLP grid
      ragged (cards with and without an image had different heights) and drew blank white
      squares. No stock setting exists: the item type has ImageAspectRatio / Width /
      ImageObjectFit but no default-image field, and neither the shop model
      (ShopSave: ImageFolder / ImagePatternMain / ImagePatternVariant) nor the Ecommerce
      settings surface has a "image not found" file. So the empty column keeps the card's
      4:3 slot and paints the archive's own no-image file as a background.
      Retire when Swift-v2_ProductDefaultImage grows a fallback-image field. */
main .product-list [data-swift-gridcolumn][data-dw-itemtype="swift-v2_productdefaultimage"]:not(:has(figure)) {
  aspect-ratio: 4 / 3;
  background-image: url("/Files/Images/Hewitt/no-image-file.jpg");
  background-repeat: no-repeat;
  background-position: center center;
  background-size: contain;
  opacity: .55;
}

/* 2. Shop-root H1 (defect 6). Swift-v2_ProductListInfo emits the page H1 from the current
      product GROUP; on the shop root there is no group, so it emits nothing and the page
      had no H1 and no heading at all. The item type has no fallback-title setting (Title
      is the paragraph header, the template never reads it). Paragraph 2413 on page 167
      supplies a static "Shop" H1; this rule removes it again on every listing where
      ProductListInfo did render its own H1 (a group page or a search result), so exactly
      one H1 is on the page in all three states. Retire when ProductListInfo grows a
      "title when there is no group" field. */
main:has(.item_swift-v2_productlistinfo) .hewitt-plp-fallback-title {
  display: none;
}

/* 3. Phone overflow on the PLP (defect 4). The anonymous price gate draws the theme
      layer's .td-price-lock chip; the chip itself wraps (default_custom.css sets
      flex-wrap:wrap), but its anchor is a .btn, and Bootstrap buttons do not wrap their
      label, so "Sign in for account pricing" set a min-width wider than a 2-column card
      and pushed the canvas to 492px at 390. default_custom.css is Distribution-owned and
      stays byte-identical, so the wrap is granted here instead. */
@media (max-width: 991.98px) {
  main .product-list .td-price-lock {
    max-width: 100%;
  }
  main .product-list .td-price-lock__action {
    white-space: normal;
    max-width: 100%;
    text-align: left;
  }
  main .product-list .td-price-lock__label {
    white-space: normal;
  }
}

/* 4. Related-products table on the phone (defect 7). Hewitt_RelatedProductsList renders
      `table table-sm table-striped align-middle text-nowrap` inside a .table-responsive.
      Bootstrap's .text-nowrap is `white-space: nowrap !important`, so at 390 the table
      measured 611-803px and scrolled inside its wrapper with the Product column cut off.
      The template's list layout is a copied template already in the ledger; rather than
      editing it again, the phone breakpoint is allowed to wrap the cells. */
@media (max-width: 767.98px) {
  main .table-responsive > table.text-nowrap,
  main .table-responsive > table.text-nowrap td,
  main .table-responsive > table.text-nowrap th {
    white-space: normal !important;
  }
}

/* == fixB == */
/* Fix round B defect 11, applied in fix round C (the CSS owner's round).
   Docks/Lifts landing tiles: "normalise tile aspect through the stock card image ratio
   setting" has no native equivalent in this Swift 2.4 build. Confirmed by direct source
   read of Paragraph/Swift-v2_Card/CardImageTop.cshtml (bare <img class="card-img-top">,
   no ratio/crop attribute or setting) and by get_row_definitions(areaId:4) on
   "4ColumnsFlex" (columnCount/columnWidths/widthType/spacing/gap/background flags only,
   no image-ratio flag). Scoped to the two family-landing pages only through the page-id
   data attribute Swift-v2_Page.cshtml already emits on <body> (data-dw-page-id), so no
   other Card usage on the site is affected. Retire when the Card item type or the row
   definition grows an image-ratio field. Source: notes/build/fixB-pending.css. */
/* Selector correction made in fix round C: CardImageTop.cshtml emits the card wrapper as
   [data-dw-itemtype="swift-v2_card"], NOT the .item_swift-v2_card class the pending draft
   assumed; the drafted class matched nothing on either landing page. */
body[data-dw-page-id="589"] [data-dw-itemtype="swift-v2_card"] .card-img-top,
body[data-dw-page-id="590"] [data-dw-itemtype="swift-v2_card"] .card-img-top {
  aspect-ratio: 4 / 3;
  object-fit: cover;
  width: 100%;
}

/* == fixD == */
/* Fix round D, cosmetic items 13-19 and N3-N5. hewitt_custom.css owned by this round.
   Native config did the header account swap (N4), the off-canvas close-button contrast
   (N5), the empty grid rows (N3, delete_grid_rows on the paragraph-less BoatLifter rows),
   the About Us / Contact Us row width and the BoatLifter hero row scheme (17, 19), and the
   homepage row-spacing reduction (16). What is left needs CSS because no stock field
   reaches it; each rule says why. */

/* 13a. Heading colour (w1-tokens gap). Swift's own .h1-.h6 utility classes
        (color: var(--bs-heading-color), class specificity 0,1,0) outrank the w1-tokens
        element selector (h1..h6, specificity 0,0,1), so a heading that carries a size
        utility (About Us H1 "h1 mb-2") stayed Bootstrap black while a bare heading
        (Find a Dealer, Docks) rendered the intended navy. Repeating the utility classes
        in the selector matches the utility rule's own specificity; declaration order
        (this rule is later in the cascade) settles the tie in the token's favour.
        Retire together with w1-tokens when the colour-scheme model gains heading/link
        fields. */
h1, h2, h3, h4, h5, h6,
.h1, .h2, .h3, .h4, .h5, .h6,
.dw-h1, .dw-h2, .dw-h3, .dw-h4, .dw-h5, .dw-h6 {
  color: var(--dw-color-heading, inherit);
}

/* 13b. Body text (w1-tokens gap). The light-scheme foregroundColor is #0D0D0D
        (Files/System/Styles/ColorSchemes/hewitt.css: --dw-color-foreground) but stock
        swift.css sets `body{color:var(--bs-body-color)}`, a Bootstrap variable no DW
        surface ever points at the scheme foreground, so body text renders Bootstrap's
        own default rgb(33,37,41). Bridging the two variables (not hard-coding the hex)
        keeps BoatLifter's own scheme group in charge of its own body colour. */
body {
  --bs-body-color: var(--dw-color-foreground, var(--bs-body-color));
}

/* N3. Empty grid rows left by product components that render a wrapper but no content.
   Scoped like w3b-pdp: only inside the buy-box-bearing product detail page. */

/* Short description: Swift-v2_ProductShortDescription always renders its wrapper div
   (class item_swift-v2_productshortdescription), even with no description text, so the
   existing w3b-pdp "no element children" test never matches it (the wrapper IS a child
   element, just an empty one). Target the wrapper's own emptiness instead. */
main:has([data-dw-itemtype="swift-v2_productcomponentselector"]) section[data-swift-gridrow]:has(> [data-swift-container] > [data-swift-gridcolumn]:only-child > .item_swift-v2_productshortdescription:empty) {
  display: none;
}

/* Kit Includes / Parts Breakdown: Hewitt_RelatedProductsGroupList (paragraphs 2398/2399,
   2423/2424 dealer-only mirror) renders nothing at all for a product with no rows in that
   relation group - by design, see its own file header. The w3b-pdp rule only matches an
   itemtype starting "swift-v2_product"; RelatedProductsList's itemtype is
   "swift-v2_relatedproductslist" and never matched, so the 48px empty row stayed. */
main:has([data-dw-itemtype="swift-v2_productcomponentselector"]) section[data-swift-gridrow]:has(> [data-swift-container] > [data-swift-gridcolumn]:only-child[data-dw-itemtype="swift-v2_relatedproductslist"]):not(:has(> [data-swift-container] > [data-swift-gridcolumn] > *)) {
  display: none;
}

/* Orphan row with no paragraph at all (data-dw-itemtype=""), directly above the footer on
   pages 168/607 (the row that inspired defect N3's "232px paragraph-less row" reading -
   the grid row exists on the page but no paragraph was ever bound to its one column). No
   grid-row delete was made here because deleting an ACTIVE row with live top/bottom
   spacing risks taking configuration state that a future paragraph placement would reuse;
   collapsing it visually is the same outcome without losing the row. The matching
   BoatLifter rows (271) had no such ambiguity and were deleted outright (delete_grid_rows,
   see polish-changes.md). */
main:has([data-dw-itemtype="swift-v2_productcomponentselector"]) section[data-swift-gridrow]:has(> [data-swift-container] > [data-swift-gridcolumn]:only-child[data-dw-itemtype=""]):not(:has(> [data-swift-container] > [data-swift-gridcolumn] > *)) {
  display: none;
}

/* 15a. Anchor strip (TC_AnchorNav) lists every main h2[id] on the page, including the
   headings the w3b-pdp/fixD rules above just hid for lacking data (default_custom.js,
   Distribution-owned, has no visibility filter by design - see its own header comment).
   A per-product curated repeater cannot be authored for this: which sections exist varies
   by product, and Swift cannot serialize a repeater's children through this layer either
   (same limitation TC_AnchorNav.cshtml's own header documents). Hidden per the task's own
   fallback ("hide the strip if it cannot be curated") rather than ship a strip that can
   still list a hidden section for a different product than the one QA sampled. */
main:has([data-dw-itemtype="swift-v2_productcomponentselector"]) [data-td-anchornav] {
  display: none;
}

/* 18. Hewitt mobile footer column order. Swift-v2_Row's "2Columns"/"3Columns" (mobile
   footer page 192 rows 292/293) emit Bootstrap CSS-Grid utility classes g-col-6/g-col-4
   with NO responsive variant, so the columns stay side-by-side at 390px instead of
   stacking - the row definition has no "stack below lg" setting (get_row_definitions:
   columnWidths/widthType/enableContainerWidth only). Forcing a flex column stack still
   read out of order (REVIEWS/CUSTOM MANUFACTURING, then CONNECT WITH US, then DEALER
   RESOURCES last) because each column ALSO carries an unconditional Bootstrap
   order-N class alongside its order-lg-N one (e.g. DEALER RESOURCES:
   "order-3 order-lg-1", the extra links column: "order-1 order-lg-2") - order-N with no
   breakpoint applies from xs up, so it was winning below lg too. Resetting order on the
   column at this breakpoint falls through to DOM/paragraph-sort order: Footer contact
   block, SUPPORT, DEALER RESOURCES, the untitled REVIEWS/CUSTOM MANUFACTURING links,
   CONNECT WITH US - contact first, then Support, Dealer resources, Connect, as asked.
   Scoped to the footer element and this row's own grid-row name so the desktop footer
   (6ColumnsFlex, unaffected) and any other 2Columns/3Columns usage elsewhere are
   untouched. */
@media (max-width: 991.98px) {
  footer[data-swift-page-footer] section[data-swift-gridrow="2Columns"] > [data-swift-container],
  footer[data-swift-page-footer] section[data-swift-gridrow="3Columns"] > [data-swift-container] {
    display: flex;
    flex-direction: column;
  }
  footer[data-swift-page-footer] section[data-swift-gridrow="2Columns"] > [data-swift-container] > [data-swift-gridcolumn],
  footer[data-swift-page-footer] section[data-swift-gridrow="3Columns"] > [data-swift-container] > [data-swift-gridcolumn] {
    width: 100%;
    order: initial !important;
    margin-bottom: 1.5rem;
  }
  footer[data-swift-page-footer] section[data-swift-gridrow="2Columns"] > [data-swift-container] > [data-swift-gridcolumn]:last-child,
  footer[data-swift-page-footer] section[data-swift-gridrow="3Columns"] > [data-swift-container] > [data-swift-gridcolumn]:last-child {
    margin-bottom: 0;
  }
}

/* 17. About Us (page 198) / Contact Us (page 193) full-width content column. The row's own
   containerWidth is already the widest non-full-bleed preset (3, page container); the
   remaining narrowing comes from swift.css's sitewide `:where([data-swift-text]){
   max-inline-size:var(--swift-text-width)}` (75ch), a readability clamp with no per-row or
   per-paragraph override field. Retired to the row's own container width on these two
   pages only, via the page-id attribute Swift-v2_Page.cshtml already emits on <body> (the
   same scoping fixB uses), so no other Swift-v2_Text content on the site is affected. */
body[data-dw-page-id="198"] main :where([data-swift-text]),
body[data-dw-page-id="193"] main :where([data-swift-text]) {
  max-inline-size: none;
}

/* == fixF-boatlifter-hero == */
/* Neutralises the Distribution "edge motif" (default_custom.css block 22 /
   default_custom.js block 26, --td-edge-mask) on the BoatLifter homepage hero
   only. Scope hook: body[data-dw-page-id="209"] (page 209, /boatlifter, area
   5) - the same page-id attribute fixB/item-17 already key off elsewhere in
   this file.

   Root cause: block 26's JS finds the first main > section containing a
   Swift poster and tags it .td-edge-bottom (row 452 on /boatlifter). Block
   22's CSS then reserves --td-edge-h (~72px at 1440, ~40px at 390) of
   padding-block-end on that row via --dw-row-space-bottom, filled with the
   row's own dark background colour and a white wave-mask crest painted by a
   ::after pseudo-element - this is the ~106px black band with a wave edge
   under the hero. It overrides the row's own topSpacing/bottomSpacing=0
   because Swift's native [data-dw-row-space-bottom="0"] attribute rule and
   block 22's .td-edge-bottom[data-swift-gridrow] rule share (0,2,0)
   specificity, and block 22 loads after Swift's own sheet.

   Fix: drop the pseudo-element and zero the reserved space, scoped to page
   209 only, so the hero sits directly on the white ground of the next
   section ("Explore the range") with no band. Loads after default_custom.css
   (see HewittHeadInclude.cshtml), so no !important is needed. /hewitt (page
   106) carries no [data-swift-poster] - it was rebuilt with a slider - so
   block 26 never tags a row there and this block does not touch it.

   Retire this block if a future wave wants the crest motif back on
   /boatlifter, or if the hero row's position in main changes so it is no
   longer the first poster row block 26 finds. */
body[data-dw-page-id="209"] main > section.td-edge-bottom::after,
body[data-dw-page-id="209"] main > section.td-edge-bottom.td-edge-alt::after {
  content: none;
  display: none;
}
body[data-dw-page-id="209"] main > section.td-edge-bottom {
  padding-block-end: 0;
}
body[data-dw-page-id="209"] main > section.td-edge-bottom[data-swift-gridrow] {
  --dw-row-space-bottom: 0;
}

/* == fixG-plp-spacing == */
/* Fix G (2026-09-17): excessive vertical whitespace at the top of the product
   list pages (/hewitt/shop, /hewitt/shop/products, group pages, search, and
   their BoatLifter equivalents).

   Root cause confirmed by direct computed-style inspection (not guessed):
   Custom/default_custom.css (Distribution-owned, byte-identical, not edited
   here) carries the rule `main [data-swift-container] { padding-top: 1.25rem;
   padding-bottom: 1.25rem }` - EVERY grid row's inner container gets a fixed
   20px top + 20px bottom floor, on top of whatever the row's own native
   topSpacing/bottomSpacing add. The PLP chrome stacks 4-5 separate rows
   between the header and the product grid (breadcrumb / static "Shop"
   fallback heading / group ProductListInfo heading / facets+grid row), each
   paying that 40px floor, so reducing topSpacing/bottomSpacing on the rows to
   0-1 (done first, see polish-changes.md "Fix G PLP spacing" - rows
   167/261, 270/435, 167/262, 270/436, 167/1927, 270/1928, 156/236, 156/237,
   259/410, 259/411) could not bring the gaps under the acceptance thresholds:
   two adjacent rows' containers always sum to >=40px regardless of their own
   spacing fields. There is no native field that changes
   default_custom.css's per-row floor, so this is CSS, scoped tightly to the
   handful of PLP structural rows via their content's data-dw-itemtype (never
   page-id, since the shared results component - page 156/259 - is reused by
   every PLP route: shop root, group pages and search alike).

   Also two rows in the results column render NOTHING on every PLP route: the
   embedded Swift-v2_ProductListInfo instance backing paragraphs 288 (Hewitt)
   and 503 (BoatLifter) - both HideGroupTitle/HideGroupDescription True per
   Fix round A item 6, so they never have content - and its orphan sibling
   row (no bound paragraph at all). Both still drew their 40px floor before
   this block, which is exactly why the grid started well below the top of
   the facet rail (acceptance item 2). They are hidden outright here rather
   than left at zero spacing, since a zero-height empty row still pays the
   40px container floor.

   All selectors are scoped to `main:has([data-dw-itemtype="swift-v2_productlistfacets"])`
   so only pages that actually carry the facet rail (i.e. product listing
   pages) are touched; PDP and content pages, which also use
   BreadcrumbNavigation and (via Related products) similar markup, are
   unaffected. Retire this block if default_custom.css's per-row container
   padding becomes configurable, or if the PLP row layout changes so these
   itemtype hooks no longer identify the same rows. */
main:has([data-dw-itemtype="swift-v2_productlistfacets"]) [data-swift-container]:has(> [data-dw-itemtype="swift-v2_breadcrumbnavigation"]) {
  padding-top: 0.25rem;
  padding-bottom: 0.5rem;
}
main:has([data-dw-itemtype="swift-v2_productlistfacets"]) [data-swift-container]:has(> [data-dw-itemtype="swift-v2_text"] .hewitt-plp-fallback-title) {
  padding-top: 0.25rem;
  padding-bottom: 0.25rem;
}
/* On a group page or search result the static "Shop" H1 (fallback for the
   shop root) is already hidden by the fixA rule above (main:has(.item_swift-v2_productlistinfo)
   .hewitt-plp-fallback-title{display:none}), but its ROW container still paid
   the reduced padding above - acceptance item 4 requires it add no spacing at
   all when hidden, not just less. Hides the row outright in that state; same
   specificity as the rule above (0,3,1), source order decides so this wins.
   The shop-root state (no .item_swift-v2_productlistinfo, no real group H1)
   is untouched and keeps the row visible at the reduced padding above. */
main:has(.item_swift-v2_productlistinfo) [data-swift-container]:has(> [data-dw-itemtype="swift-v2_text"] .hewitt-plp-fallback-title) {
  display: none;
}
main:has([data-dw-itemtype="swift-v2_productlistfacets"]) [data-swift-container]:has(> [data-dw-itemtype="swift-v2_productlistinfo"]) {
  padding-top: 0;
  padding-bottom: 0.25rem;
}
main:has([data-dw-itemtype="swift-v2_productlistfacets"]) [data-swift-container]:has(> [data-dw-itemtype="swift-v2_productlistfacets"]) {
  padding-top: 0.5rem;
}
/* The results column (Swift-v2_ProductListComponentSelector) embeds its own
   nested page (156 Hewitt / 259 BoatLifter) with its own rows, so the
   repeater row pays the same 20px default_custom.css floor a second time,
   on top of the facets column's row above - this is what left the grid
   starting well below the top of the facet rail (acceptance item 2) even
   after the two always-empty rows above it were hidden. Zeroed here so the
   repeater's own row starts flush with its column, matching the facets
   column's top exactly (both are the row263/437 container, already reduced
   above). */
[data-dw-itemtype="swift-v2_productlistcomponentselector"] [data-swift-container]:has(> [data-dw-itemtype="swift-v2_productlistitemrepeater"]) {
  padding-top: 0;
}
[data-dw-itemtype="swift-v2_productlistcomponentselector"] [data-swift-container]:has(> [data-dw-itemtype="swift-v2_productlistinfo"]),
[data-dw-itemtype="swift-v2_productlistcomponentselector"] [data-swift-container]:has(> [data-dw-itemtype=""]) {
  /* !important: this selector's specificity (0,3,0) otherwise loses to the
     .padding-only rule above (0,3,1), which carries an extra `main` type
     selector and would win on the type tiebreak despite loading first -
     confirmed live via computed style before adding this. */
  display: none !important;
}

/* == fixH-card == */
/* Fix H (2026-09-17): internal spacing/alignment of the product list card, page
   157 (Hewitt) / 260 (BoatLifter), rebuilt by Fix round A item 5 into five
   stacked `1Column` rows (image / name h2 / SKU / price / add to cart). Route:
   native row spacing was already taken to 0 on all five rows via save_grid_rows
   (2026-09-17); this block is what native config could not reach.

   ROOT CAUSE 1 (spacing). Same floor Fix G found: default_custom.css's
   `main [data-swift-container] { padding-top: 1.25rem; padding-bottom: 1.25rem }`
   (20px, unconditional; 8px under its own max-width:767.98px override) pays on
   every row regardless of the row's own topSpacing/bottomSpacing. With five
   stacked rows per card that put >=40px (desktop) / >=16px (phone) between every
   pair of fields, ten times over. There is no native field that lowers this
   floor, so it is overridden per row container here, scoped to the card
   (`main .product-list article.product`) so no other row on the site is
   touched. Rules are unconditional (no media query) so the same tight figures
   win over BOTH of default_custom.css's tiers, at 1440 and at 390 alike.

   ROOT CAUSE 2 (price alignment). default_custom.css block #10 ("Desktop PLP
   column discipline") and block #14 ("Mobile PLP row consistency") both target
   `[data-dw-itemtype="swift-v2_productprice"]` by itemtype only, written for
   the ORIGINAL list-row card (one `12ColumnsFlex` row, all fields side by
   side) that Fix round A item 5 replaced with the stacked layout. They still
   match by itemtype regardless of the new DOM shape:
     - Desktop (>=992px): `align-items: center` on a column whose flex-direction
       is the Swift grid column default of `column` (not `row`) centers the
       price HORIZONTALLY on the cross axis - confirmed live via
       getComputedStyle + getBoundingClientRect (measured left/right gaps
       132px/132px either side of a 70px-wide price, i.e. dead center) even
       though `justify-content: flex-end` (the vertical/main-axis property in a
       column flex, so invisible here) is also set.
     - Mobile (<=991.98px): explicit `margin-left: auto !important` and
       `text-align: right` right-align it outright.
   Both are neutralized below, scoped the same way and loaded after
   default_custom.css, so normal cascade order alone would suffice - the
   `!important` on the mobile override matches the specific properties the
   source rule also marked `!important`, which cascade order does not beat on
   its own.
   Name (Swift-v2_ProductHeader), SKU (Swift-v2_ProductNumber) and Add to cart
   (Swift-v2_ProductAddToCart) were already left-aligned (checked via
   getBoundingClientRect: their left edge already matched the card's left edge
   at both 1440 and iPhone 13) - their own `HorizontalAlignment` paragraph
   field is "start" and the block/left default already holds because no other
   default_custom.css rule overrides them. Add to cart already renders
   `btn btn-primary` (navy, `data-dw-button="primary"`) hard-coded in
   `Paragraph/Swift-v2_ProductAddToCart.cshtml` - the item type has no button
   style field to set. A grey Add to cart is the button's native `:disabled`
   state on an out-of-stock product (confirmed: `disabled` attribute present,
   class list unchanged) and is untouched here per the "no change in what is
   rendered" rule for dealer/stock gating.

   Retire the spacing rules if default_custom.css's per-row floor becomes
   configurable; retire the price-alignment rules if blocks #10/#14 are scoped
   away from the stacked card layout upstream.

   ROOT CAUSE 3 (2026-09-17, Fix I, placeholder ratio). Added after Fix H:
   the real-image box (Paragraph/Swift-v2_ProductDefaultImage.cshtml,
   ImageAspectRatio 75%) measured 267px tall at 334.66px wide (1440,
   /hewitt/shop) - NOT 4:3 (334.66 * 0.75 = 251px). The extra 16px is
   Bootstrap Reboot's default `figure { margin-bottom: 1rem }` on the
   template's own `<figure>` wrapper, which the template does not reset. The
   fixA rule-1 placeholder (a bare div, no figure) already renders at the
   correct 251px/4:3, so it was the REAL box that was off-ratio, not the
   placeholder - fixing the stray margin brings the real box down to true
   4:3, matching the placeholder exactly with no change to the placeholder
   rule. Scoped to the card only, so the PDP gallery (a different template)
   is untouched. Retire if Swift-v2_ProductDefaultImage.cshtml resets its own
   figure margin.

   ROOT CAUSE 4 (2026-09-17, Fix I, placeholder ratio, phone). The margin
   fix alone left a 3px gap at iPhone 13 width (390): the template's inline
   `style="min-width: 60px"` (emitted whenever the paragraph's Width field is
   "auto", which it is here) is wider than the actual 2-across mobile column
   (measured 56px), so the figure is forced to 60px and the Bootstrap
   `.ratio` box computes its height from that inflated 60px, not the
   column's real 56px - 60 * 0.75 = 45px, not 56 * 0.75 = 42px like the
   placeholder (which has no min-width and sizes from the column itself).
   Overriding the inline min-width (needs !important, inline style
   specificity) makes the figure track the column's real width at every
   breakpoint. Retire together with root cause 3. */
main .product-list article.product [data-dw-itemtype="swift-v2_productdefaultimage"] figure {
  margin: 0;
  min-width: 0 !important;
}
main .product-list article.product [data-swift-container]:has(> [data-dw-itemtype="swift-v2_productdefaultimage"]) {
  padding-top: 0;
  padding-bottom: 10px;
}
main .product-list article.product [data-swift-container]:has(> [data-dw-itemtype="swift-v2_productheader"]) {
  padding-top: 4px;
  padding-bottom: 1px;
}
main .product-list article.product [data-swift-container]:has(> [data-dw-itemtype="swift-v2_productnumber"]) {
  padding-top: 2px;
  padding-bottom: 3px;
}
main .product-list article.product [data-swift-container]:has(> [data-dw-itemtype="swift-v2_productprice"]) {
  padding-top: 4px;
  padding-bottom: 4px;
}
main .product-list article.product [data-swift-container]:has(> [data-dw-itemtype="swift-v2_productaddtocart"]) {
  padding-top: 6px;
  padding-bottom: 12px;
}
main .product-list article.product [data-dw-itemtype="swift-v2_productprice"] {
  align-items: flex-start !important;
  justify-content: flex-start !important;
  margin-left: 0 !important;
  text-align: left !important;
}
