/* ING DESIGN LAYER - ingmining.com
   Built 2026-07-30 by build_design4.py. Served from
   wp-content/plugins/my-custom-plugin/ing/ing-design.css and enqueued by
   ing-design.php. EDIT THIS FILE, then `python deploy_design4.py`.

   WHY IT LIVES IN A PLUGIN AND NOT IN THE THEME
   ---------------------------------------------
   These three blocks used to be appended to `themes/woostify/style.css`. On
   2026-07-30 08:38 a Woostify 2.5.4 reinstall rewrote every file in that
   directory and deleted all three, exactly as it deleted the twelve ing-*.php
   files. The PHP was restored into this plugin the same day; the stylesheet was
   not, and nobody measured it, so for the whole of 2026-07-30 the store served
   the raw WooCommerce loop: no card, one product per row on a phone, an
   Add-to-Cart button clipped out of sight on desktop, and unstyled `ing-chip`
   and `ing-shelf` markup on 48 archive URLs.

   `worldpressit-auto-updater` is still installed and will reinstall the theme
   again. wp-content/plugins is out of its reach.

   ORDER MATTERS. Block 2 deliberately wins over block 1 at equal specificity and
   block 3 wins over both; that is why they are concatenated rather than merged.
   The sheet is enqueued with a dependency on `woostify-style` and at
   `wp_enqueue_scripts` priority 11, which puts it in the same place in the
   cascade the appended blocks occupied: after the theme, before Elementor.

   It is presentation only. No markup, no PHP, no product data, and nothing that
   changes what the cart or the checkout DOES.
*/

/* BEGIN ING MOBILE PASS 2026-07-27
   Phone-first store layout for ingmining.com. Appended to the Woostify parent
   stylesheet, so it loads on every page and needs no new plugin or child theme.

   Scope: <=600px only (Woostify's own mobile breakpoint). Desktop and tablet
   rules are untouched - every declaration below lives inside a media query.

   What it changes and why:
   1. The product loop was one product per ~530px of scroll on a phone. It is
      now a 2-up CSS grid, the way every real mobile store does it.
   2. Nothing is hidden from phone users. Same markup, same links, same price,
      same add-to-cart, same wishlist control - laid out tighter.
   3. Touch targets on the store chrome (sort select, pagination, add-to-cart)
      are raised to 44px, which is the Google/WCAG minimum.
*/
@media (max-width: 600px) {

  /* ---- 1. two-column product grid -------------------------------------- */
  /* Woostify lays the loop out with floats + clear:both. Floats and uneven
     card heights do not mix, so switch to grid and neutralise the float rules
     rather than fighting them. !important is deliberate: the theme's own
     `.products.mobile-columns-1 .product` is a 3-class selector. */
  ul.products {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    column-gap: 10px;
    row-gap: 22px;
  }

  /* The theme's clearfix pseudo-element would become a stray grid cell. */
  ul.products::before,
  ul.products::after {
    display: none !important;
  }

  ul.products > li.product {
    width: auto !important;
    max-width: none !important;
    float: none !important;
    clear: none !important;
    margin: 0 !important;
    padding: 0 !important;
  }

  /* Cards in the same row end up different heights (titles wrap differently).
     Make each card a full-height column so the price and the buy button line
     up along the bottom edge of the row instead of floating mid-card. */
  ul.products > li.product > .product-loop-wrapper {
    display: flex;
    flex-direction: column;
    height: 100%;
  }

  /* The theme pads this 25px/15px, which on a 176px-wide card is a third of
     the card spent on whitespace. */
  ul.products > li.product .product-loop-content {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    padding: 10px 0 0;
  }

  ul.products > li.product .product-loop-meta {
    margin-top: auto;
  }

  /* ---- 2. the image ----------------------------------------------------- */
  /* Was a 300px square with 45px of dead gutter either side. Fill the column
     and hold a square box so the grid does not reflow as images decode. */
  ul.products > li.product .product-loop-image-wrapper {
    width: 100%;
  }

  ul.products > li.product .product-loop-image-wrapper img,
  ul.products > li.product img.product-loop-image {
    width: 100% !important;
    max-width: 100% !important;
    height: auto;
    aspect-ratio: 1 / 1;
    object-fit: contain;
    display: block;
  }

  /* ---- 3. title and price, directly under the image --------------------- */
  ul.products > li.product .woocommerce-loop-product__title {
    font-size: 13px;
    line-height: 1.35;
    margin: 0 0 6px;
    text-align: left;
    /* No clamping: the full product name stays readable and selectable. */
  }

  /* Loop titles ship at #8f8f8f on white = 3.2:1, which fails WCAG AA for 14px
     text. At phone size in daylight that is the difference between scannable
     and not. Same grey family, readable weight. */
  ul.products > li.product .woocommerce-loop-product__title a {
    color: #3d3d3d;
  }

  ul.products > li.product .product-loop-content.text-center {
    text-align: left;
  }

  ul.products > li.product .price {
    display: block;
    font-size: 15px;
    font-weight: 600;
    line-height: 1.3;
    margin: 0 0 8px;
  }

  /* Woostify swaps price for the cart button on hover. A phone has no hover,
     so pin both visible and stacked. */
  ul.products > li.product .animated-meta,
  ul.products > li.product .animated-meta .price,
  ul.products > li.product .animated-meta .loop-add-to-cart-btn {
    position: static !important;
    opacity: 1 !important;
    visibility: visible !important;
    transform: none !important;
  }

  /* ---- 4. 44px touch targets ------------------------------------------- */
  ul.products > li.product .loop-add-to-cart-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    width: 100%;
    min-height: 44px;
    padding: 8px 10px;
    font-size: 13px;
    line-height: 1.2;
    text-align: center;
  }

  /* The label ships as #090068 on a #122d31 button - 1.26:1, i.e. the primary
     store CTA is effectively invisible. The cart glyph is worse: the SVG has
     fill="#000000" baked into the path attribute, so it has to be overridden
     explicitly rather than inherited. Background and shape are unchanged. */
  ul.products > li.product .loop-add-to-cart-btn,
  ul.products > li.product .loop-add-to-cart-btn:hover,
  ul.products > li.product .loop-add-to-cart-btn:focus {
    color: #ffffff;
  }

  ul.products > li.product .loop-add-to-cart-btn svg {
    width: 15px;
    height: 15px;
    flex: 0 0 auto;
  }

  ul.products > li.product .loop-add-to-cart-btn svg path {
    fill: currentColor;
  }

  ul.products > li.product .tinvwl_add_to_wishlist_button {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    padding: 6px 2px;
    font-size: 12px;
  }

  /* The hover-reveal action overlay sits on top of the image and cannot be
     triggered by touch; the same wishlist control exists below the button. */
  ul.products > li.product .product-loop-image-wrapper .product-loop-action {
    display: none;
  }

  /* ---- 5. store chrome above the grid ----------------------------------- */
  /* 49px of margin above and below the content area, plus an 89px sorting bar
     holding one 32px select, put the first product 270px down a 844px screen. */
  .site-content {
    margin-top: 18px;
    margin-bottom: 24px;
  }

  .woostify-sorting {
    padding-bottom: 0;
  }

  .woostify-sorting .woostify-toolbar-left {
    margin-bottom: 0;
  }

  /* The theme hides "Showing 1-12 of 145 results" on phones and shows it on
     desktop. With 145 products that line is the only thing telling a buyer how
     big the catalogue is and where they are in it. Put it back. */
  .woostify-sorting .woocommerce-result-count {
    display: block !important;
    margin: 0 0 8px;
    font-size: 13px;
    color: #4a4a4a;
  }

  .woocommerce-ordering {
    margin-bottom: 16px !important;
  }

  .woocommerce-ordering select.orderby,
  .woostify-sorting select {
    min-height: 44px;
    width: 100%;
    max-width: 100%;
    font-size: 14px;
  }

  .woocommerce-ordering {
    width: 100%;
    max-width: 100%;
    float: none;
  }

  /* ---- 6. pagination --------------------------------------------------- */
  /* 13 pages of 29x29px targets in a single 360px row. Let them wrap and give
     each one a real 44px box. */
  .woocommerce-pagination ul.page-numbers {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 6px;
    padding: 0;
    margin: 0;
  }

  .woocommerce-pagination ul.page-numbers li {
    float: none;
    margin: 0;
    width: auto;
    height: auto;
  }

  /* The theme pins these to 29x29 with
     `.woocommerce-pagination ul .page-numbers:not(.prev):not(.next)`, which is
     a higher-specificity selector than a plain descendant chain - so match its
     shape and add one class rather than reaching for !important. */
  .pagination ul.page-numbers li .page-numbers:not(.prev):not(.next),
  .woocommerce-pagination ul.page-numbers li .page-numbers:not(.prev):not(.next),
  .woocommerce-pagination ul.page-numbers li .page-numbers.prev,
  .woocommerce-pagination ul.page-numbers li .page-numbers.next {
    box-sizing: border-box;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: auto;
    min-width: 44px;
    height: 44px;
    padding: 0 8px;
    border-radius: 22px;
  }

  /* Pagination inherits the theme's #8f8f8f (3.2:1). These are navigation
     controls on a 13-page catalogue; they need to be readable. */
  .woocommerce-pagination ul.page-numbers li a.page-numbers {
    color: #3d3d3d;
  }

  /* ---- 7. site chrome: header controls and footer ----------------------- */
  /* The hamburger is the only way into the menu on a phone and ships at 33px. */
  .elementor-menu-toggle {
    min-width: 44px;
    min-height: 44px;
    display: flex !important;
    align-items: center;
    justify-content: center;
  }

  .elementor-menu-cart__toggle_button.elementor-button {
    min-height: 44px;
  }

  /* Product title link: 41px tall, just under the bar. */
  ul.products > li.product .woocommerce-loop-product__title a {
    display: block;
    padding: 3px 0;
    min-height: 44px;
  }

  /* Elementor sizes its social icons from its own stylesheet, which is
     enqueued after the theme's, so a same-specificity rule here would lose. */
  .elementor-location-footer .elementor-social-icon {
    width: 44px !important;
    height: 44px !important;
  }

  .elementor-location-footer .elementor-icon-list-item > a,
  .elementor-location-footer .elementor-heading-title > a {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
  }

  .elementor-location-footer .elementor-field-group .elementor-field,
  .elementor-location-footer .elementor-field-group .elementor-button {
    min-height: 44px !important;
  }

  /* ---- 8. header: one row instead of three ----------------------------- */
  /* The Elementor header container is a flex ROW, but each of its three
     children is set to 100% width, so they wrap onto three lines: logo,
     then the hamburger, then the cart pulled back up by a -37px margin.
     That is 135px of chrome on a 844px screen before any content.
     Letting them sit on one line costs nothing and recovers ~65px on every
     page. The element IDs are Elementor's own and are stable for the life of
     the element; if the header is ever rebuilt these rules simply stop
     matching and the layout returns to what it is today. */
  header.elementor-location-header .elementor-element-91b4dd2 > .e-con-inner {
    flex-wrap: nowrap;
    align-items: center;
    gap: 8px;
  }

  header.elementor-location-header .elementor-element-38e09ac {
    width: auto !important;
    flex: 1 1 auto;
    min-width: 0;
    padding: 0;
  }

  header.elementor-location-header .elementor-element-38e09ac .elementor-widget-theme-site-logo,
  header.elementor-location-header .elementor-element-38e09ac .elementor-widget-theme-site-logo a {
    width: auto;
    max-width: 210px;
  }

  /* On one row the logo link shrinks to the image box (~29px tall). It is the
     home link on every page, so it keeps a 44px target. */
  header.elementor-location-header .elementor-element-38e09ac .elementor-widget-theme-site-logo a {
    display: flex;
    align-items: center;
    min-height: 44px;
  }

  /* Cart before hamburger, the order every phone store uses. */
  header.elementor-location-header .elementor-element-2e6a1fb {
    width: auto !important;
    flex: 0 0 auto;
    order: 1;
    margin-top: 0 !important;
    padding: 0;
    align-items: center;
  }

  header.elementor-location-header .elementor-element-c17f7b7 {
    width: auto !important;
    flex: 0 0 auto;
    order: 2;
    padding: 0;
    align-items: center;
  }

  /* The hamburger widget carries a hand-set `margin-top: -62px` on mobile  -
     the previous workaround for the three-row stack, which yanked the toggle up
     into the logo row out of a zero-height container. On one row that offset
     throws the toggle off the top of the header entirely, so it has to go.
     Without this the phone menu button is invisible: caught in review. */
  header.elementor-location-header .elementor-element-c17f7b7 .elementor-widget-nav-menu > .elementor-widget-container {
    margin-top: 0 !important;
  }

  header.elementor-location-header .elementor-element-c17f7b7 > .elementor-widget-nav-menu {
    width: auto;
  }

  /* Product search lives in the off-canvas menu on a phone - it is the only
     way to search 145 products from a small screen, so it gets real targets. */
  .sidebar-menu .woocommerce-product-search .search-field,
  .sidebar-menu .woocommerce-product-search button,
  .sidebar-menu .search-form .search-field,
  .sidebar-menu .search-form button {
    min-height: 44px;
  }

  .sidebar-menu .woocommerce-product-search button,
  .sidebar-menu .search-form button {
    min-width: 44px;
  }

  /* Carousel dots ship at 6x6px - a standalone control a thumb cannot hit.
     The padding grows the hit area to 44x44 while background-clip keeps the
     dot itself exactly 6px, so nothing looks different. */
  .swiper-pagination-clickable .swiper-pagination-bullet {
    padding: 19px;
    margin: 0 2px !important;
    background-clip: content-box;
    box-sizing: content-box;
  }

  .elementor-post__read-more {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
  }
}

/* Narrow phones: the 30px container gutter costs a lot of a 360px screen. */
@media (max-width: 400px) {
  ul.products {
    column-gap: 8px;
  }

  ul.products > li.product .woocommerce-loop-product__title {
    font-size: 12.5px;
  }
}
/* END ING MOBILE PASS 2026-07-27 */

/* BEGIN ING PREMIUM GRID 2026-07-28
   The product card, rebuilt. Appended to the Woostify parent stylesheet so it
   loads everywhere the WooCommerce loop renders: /all-miners, all 22 category
   archives, and the "Related products" strip on every product page.

   It changes presentation only. No markup, no PHP, no template override, no
   product data, and nothing on cart or checkout. Every selector below starts at
   `ul.products > li.product`, so it cannot reach the single-product summary,
   the cart table or the checkout form.

   Measured before/after on 1440x950 and 390x844.

   What was wrong (all measured on the live site, 2026-07-28):

   1. There was no card. `.product-loop-wrapper` computed to
      `background: transparent; border: 0; border-radius: 0; box-shadow: none`.
      A tile was a floating image with centred grey text under it.
   2. Desktop laid the loop out with `float: left` + `clear`. Any tile shorter
      than its neighbours left a hole in the next row - and 53 of 145 products
      have no photo on disk, so short tiles are common. /product-category/
      used-asic-miners/ had a visible half-row gap.
   3. A missing photo rendered as the browser's broken-image glyph plus the alt
      text in `#090068` link-navy. 10 of the 12 tiles on
      /product-category/new-asic-miners/ page 1 show it.
   4. The desktop Add to Cart label computed to `#090068` on `#122D31` -
      1.26:1. The store's primary CTA was effectively invisible on desktop. The
      2026-07-27 mobile pass fixed this below 600px only.
   5. Loop titles computed to `#8f8f8f` on white - 3.2:1, below WCAG AA. Same
      story: fixed on phones in July, never on desktop.
   6. `.product-loop-meta` was `height: 30px; overflow: hidden` and the buy
      button lived inside it, revealed by sliding the block up 24px on hover.
      What a visitor actually saw was a dark 2px bar under every price, and on
      any touch device the button could not be revealed at all.
   7. The sale badge was a square of `#1346af` - Woostify's stock blue, which
      appears nowhere else in this store's palette.

   Palette is the one already on the site: #122D31 (buttons, set by a human in
   wp-custom-css with !important - deliberately not fought here), #0f3436 (the
   condition-chip and category-shelf ink), #c9a24a gold.
*/

/* ---- 1. the loop is a grid, so rows cannot go ragged ------------------- */
/* Elementor renders "Related products" as `ul.products.elementor-grid` and
   sets its own `grid-template-columns` from widget settings. Card styling
   applies there; column maths does not. */
ul.products:not(.elementor-grid) {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  column-gap: 24px;
  row-gap: 28px;
  margin: 0 0 30px;
  padding: 0;
  list-style: none;
}

/* Woostify's clearfix pseudo-elements would each become a stray grid cell. */
ul.products:not(.elementor-grid)::before,
ul.products:not(.elementor-grid)::after {
  display: none !important;
}

/* 300x300 is the only thumbnail size WooCommerce generated here - there is no
   larger derivative in the srcset. Three columns on a 1370px content area
   gives a 436px tile and a 45% upscale, which is visibly soft on a photograph.
   Four columns gives 324px: an 8% upscale, and 12 products per page becomes
   three clean rows instead of four. */
@media (min-width: 1200px) {
  ul.products:not(.elementor-grid),
  ul.products:not(.elementor-grid).columns-3 {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}

ul.products:not(.elementor-grid).columns-1 { grid-template-columns: minmax(0, 1fr); }
ul.products:not(.elementor-grid).columns-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }

@media (min-width: 1200px) {
  ul.products:not(.elementor-grid).columns-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  ul.products:not(.elementor-grid).columns-5 { grid-template-columns: repeat(5, minmax(0, 1fr)); }
  ul.products:not(.elementor-grid).columns-6 { grid-template-columns: repeat(6, minmax(0, 1fr)); }
}

@media (min-width: 601px) and (max-width: 991px) {
  ul.products:not(.elementor-grid) {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    column-gap: 18px;
    row-gap: 22px;
  }
}

@media (max-width: 600px) {
  ul.products:not(.elementor-grid) {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    column-gap: 12px;
    row-gap: 16px;
    margin-bottom: 22px;
  }
}

/* The float rules and the nth-child clears have to go, or they fight the grid
   and reintroduce the holes. */
ul.products > li.product {
  float: none !important;
  clear: none !important;
  width: auto !important;
  max-width: none !important;
  margin: 0 !important;
  padding: 0 !important;
  list-style: none;
}

/* ---- 2. the card ------------------------------------------------------- */
ul.products > li.product > .product-loop-wrapper {
  display: flex;
  flex-direction: column;
  height: 100%;
  background-color: #ffffff;
  border: 1px solid #e3e7e8;
  border-radius: 14px;
  overflow: hidden;
  transition: border-color 0.18s ease, box-shadow 0.18s ease, transform 0.18s ease;
}

/* Hover lift only where there is a real pointer. A touch device fires :hover
   on tap and the card would stick in the lifted state. */
@media (hover: hover) and (min-width: 992px) {
  ul.products > li.product > .product-loop-wrapper:hover {
    border-color: #c3cfd0;
    box-shadow: 0 14px 30px -16px rgba(15, 52, 54, 0.55);
    transform: translateY(-3px);
  }
}

/* Keyboard users get the same affordance the mouse gets. */
ul.products > li.product > .product-loop-wrapper:focus-within {
  border-color: #122d31;
  box-shadow: 0 0 0 3px rgba(18, 45, 49, 0.16);
}

/* ---- 3. one square image box, so every row lines up -------------------- */
ul.products > li.product .product-loop-image-wrapper {
  position: relative;
  overflow: hidden;
  background-color: #f5f8f8;
  border-bottom: 1px solid #ecf0f0;
  padding: 0;
}

ul.products > li.product .product-loop-image-wrapper > a.woocommerce-loop-product__link {
  display: block;
  position: relative;
  width: 100%;
  aspect-ratio: 1 / 1;
  overflow: hidden;
  text-align: center;
}

/* `contain`, not `cover`: these are photographs of the actual machine being
   sold and a crop can cut off the model badge, the connector or the damage a
   "Need Parts" listing is honest about. Letterboxing onto the neutral panel is
   the safe direction. */
ul.products > li.product img.product-loop-image {
  position: absolute;
  left: 0;
  top: 0;
  width: 100% !important;
  height: 100% !important;
  max-width: 100% !important;
  max-height: 100%;
  object-fit: contain;
  display: block;
  /* Alt text is what Chrome paints inside a broken image. Keeping it out of
     the paint means the placeholder below is the only thing a buyer sees; the
     attribute itself is untouched, so assistive tech and Google still read it. */
  color: transparent;
  font-size: 0;
  transition: transform 0.35s ease;
}

@media (hover: hover) and (min-width: 992px) {
  ul.products > li.product:hover img.product-loop-image {
    transform: scale(1.045);
  }
}

/* ---- 3b. a missing photo should look deliberate, not broken ------------ */
/* 477 of 630 media files were lost in the site migration, so 53 of 145
   products point at a thumbnail that 404s. A replaced element renders its
   pseudo-elements ONLY when the image fails to load - so these two paint over
   the broken glyph and paint nothing at all when the photo is there. No PHP,
   no per-request disk check, and it self-heals the moment a real photograph is
   uploaded.

   The wording is deliberately "No photo yet" and not a promise: the store
   genuinely does not have a picture of these units, and inventing one is
   forbidden. */
ul.products > li.product img.product-loop-image::after {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  right: 0;
  bottom: 0;
  z-index: 1;
  background-color: #eef2f2;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23a4b1b3' stroke-width='1.3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 8.6A1.6 1.6 0 0 1 4.6 7h2.1l1.1-2h8.4l1.1 2h2.1A1.6 1.6 0 0 1 21 8.6v8.8a1.6 1.6 0 0 1-1.6 1.6H4.6A1.6 1.6 0 0 1 3 17.4z'/%3E%3Ccircle cx='12' cy='13' r='3.5'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: center 36%;
  background-size: 38px 38px;
}

ul.products > li.product img.product-loop-image::before {
  content: "No photo yet";
  position: absolute;
  left: 0;
  right: 0;
  top: 58%;
  z-index: 2;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.06em;
  line-height: 1.4;
  text-transform: uppercase;
  text-align: center;
  color: #7d8b8d;
}

@media (max-width: 600px) {
  ul.products > li.product img.product-loop-image::after {
    background-size: 30px 30px;
  }
  ul.products > li.product img.product-loop-image::before {
    font-size: 9.5px;
    letter-spacing: 0.04em;
  }
}

/* ---- 3c. the same placeholder, now that the tile no longer 404s -------- */
/* ing-seo-media.php (2026-07-30) stopped WooCommerce emitting a thumbnail URL
   that 404s for the 53 products whose photograph was lost, so the tile now
   renders wc_placeholder_img() - a file that LOADS. Block 3b above paints only
   while an image FAILS, so it stops firing on exactly the tiles it was written
   for. The PHP marks the image wrapper `ing-no-photo` for those products and the
   same panel is painted on the link box, which is a real element.

   3b is deliberately kept: it still catches an image that breaks for a reason
   nobody has measured, and it costs nothing when there is no such image. */
ul.products > li.product .product-loop-image-wrapper.ing-no-photo > a.woocommerce-loop-product__link::after {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  right: 0;
  bottom: 0;
  z-index: 1;
  background-color: #eef2f2;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23a4b1b3' stroke-width='1.3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 8.6A1.6 1.6 0 0 1 4.6 7h2.1l1.1-2h8.4l1.1 2h2.1A1.6 1.6 0 0 1 21 8.6v8.8a1.6 1.6 0 0 1-1.6 1.6H4.6A1.6 1.6 0 0 1 3 17.4z'/%3E%3Ccircle cx='12' cy='13' r='3.5'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: center 36%;
  background-size: 38px 38px;
}

ul.products > li.product .product-loop-image-wrapper.ing-no-photo > a.woocommerce-loop-product__link::before {
  content: "No photo yet";
  position: absolute;
  left: 0;
  right: 0;
  top: 58%;
  z-index: 2;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.06em;
  line-height: 1.4;
  text-transform: uppercase;
  text-align: center;
  color: #7d8b8d;
}

/* The placeholder graphic itself is WooCommerce's own and says less than the
   panel above it; hidden rather than removed so the <img> keeps its alt text,
   which is what a screen reader and Google read. */
ul.products > li.product .product-loop-image-wrapper.ing-no-photo img.product-loop-image {
  opacity: 0;
}

@media (max-width: 600px) {
  ul.products > li.product .product-loop-image-wrapper.ing-no-photo > a.woocommerce-loop-product__link::after {
    background-size: 30px 30px;
  }
  ul.products > li.product .product-loop-image-wrapper.ing-no-photo > a.woocommerce-loop-product__link::before {
    font-size: 9.5px;
    letter-spacing: 0.04em;
  }
}

/* ---- 4. the sale badge, in the store's own colours --------------------- */
ul.products > li.product .product-loop-image-wrapper .onsale,
ul.products > li.product .product-loop-image-wrapper .woostify-tag-on-sale {
  top: 11px;
  padding: 4px 10px !important;
  border-radius: 999px;
  background-color: #122d31;
  color: #ffffff;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.04em;
  line-height: 1.45;
  box-shadow: 0 2px 8px rgba(18, 45, 49, 0.28);
}

ul.products > li.product .product-loop-image-wrapper .onsale.sale-left {
  left: 11px;
}

/* ---- 5. the text block ------------------------------------------------- */
ul.products > li.product .product-loop-content,
ul.products > li.product .product-loop-content.text-center {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  padding: 14px 14px 16px;
  text-align: left;
}

ul.products > li.product .woocommerce-loop-product__title {
  margin: 0 0 9px;
  font-size: 15px;
  line-height: 1.42;
  font-weight: 600;
  text-align: left;
}

/* Three lines, so the price and the button sit on the same baseline across a
   row. The full name stays in the DOM - this hides nothing from a crawler. */
ul.products > li.product .woocommerce-loop-product__title a {
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
  color: #16292b;
  font-size: inherit;
  font-weight: inherit;
}

ul.products > li.product .woocommerce-loop-product__title a:hover,
ul.products > li.product .woocommerce-loop-product__title a:focus {
  color: #122d31;
  text-decoration: underline;
  text-underline-offset: 2px;
}

/* The condition chip (Used / New / Parts) shipped 2026-07-28. */
ul.products > li.product .ing-chip {
  align-self: flex-start;
  margin: 0 0 10px;
}

/* ---- 6. price and buy button, both visible, at the bottom of the card --- */
/* Woostify clips this to 30px and slides the button into view on hover. On a
   phone that button is unreachable; on desktop the clip shows as a dark bar
   under every price. */
ul.products > li.product .product-loop-meta,
ul.products > li.product .product-loop-meta:not(.no-transform) {
  margin-top: auto;
  height: auto;
  line-height: inherit;
  overflow: visible;
}

ul.products > li.product .product-loop-meta .animated-meta,
ul.products > li.product .product-loop-meta:not(.no-transform) .animated-meta,
ul.products > li.product .product-loop-meta:not(.no-transform) .animated-meta:focus-within,
ul.products .product:hover .product-loop-meta:not(.no-transform) .animated-meta {
  display: block;
  height: auto;
  max-width: none;
  transform: none;
  text-align: left;
}

/* #014609 is not a new colour: it is what the "Related products" cards on all
   145 product pages already compute to, set in the Elementor kit. Elementor's
   rule wins on those cards no matter what is written here, so matching it is
   the only way every product card in the store states its price the same way.
   Archives shipped #2b2b2b before this run, which is why they looked like a
   different component. (The single-product summary uses a third green,
   #2F9C3B at 28px - that is the Elementor product template, a different
   surface, and it is deliberately left alone.) */
ul.products > li.product .product-loop-meta .price {
  display: block;
  margin: 0 0 12px;
  font-size: 18px;
  font-weight: 700;
  line-height: 1.3;
  color: #014609;
}

/* Beats `.woocommerce .product .product-loop-meta .price .woocommerce-Price-amount
   { color:#2b2b2b; font-size:14px }` from the customizer's inline stylesheet. */
ul.products > li.product .product-loop-meta .price .woocommerce-Price-amount {
  font-size: inherit;
  color: inherit;
}

ul.products > li.product .product-loop-meta .price del,
ul.products > li.product .product-loop-meta .price del .woocommerce-Price-amount {
  margin-right: 7px;
  font-size: 14px;
  font-weight: 500;
  color: #8b989a;
  opacity: 1;
  text-decoration: line-through;
}

ul.products > li.product .product-loop-meta .price ins,
ul.products > li.product .product-loop-meta .price ins .woocommerce-Price-amount {
  background-color: transparent;
  text-decoration: none;
  color: #014609;
}

/* 64 of 145 products carry no price. WooCommerce prints no `.price` element at
   all for those and swaps the button label to "Read more", so the card used to
   end with an unexplained gap where every other card states a number. `Price
   on request` is what that state actually is - the phone number and email are
   already on every product page in the trust block. Out-of-stock tiles are
   excluded: they have a price, they just cannot be bought today. */
ul.products > li.product:not(.purchasable):not(.outofstock) .product-loop-meta .animated-meta::before {
  content: "Price on request";
  display: block;
  margin: 0 0 12px;
  font-size: 15px;
  font-weight: 600;
  line-height: 1.3;
  color: #5a6769;
}

/* The button. Background stays #122D31 because wp-custom-css sets it with
   !important and it is the right colour - only the shape, size and the
   unreadable label colour change here. */
ul.products > li.product .product-loop-meta .loop-add-to-cart-btn,
ul.products > li.product .product-loop-meta .animated-meta a.loop-add-to-cart-btn,
ul.products > li.product .product-loop-meta.no-transform .button.loop-add-to-cart-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  width: 100%;
  height: auto;
  min-height: 44px;
  margin: 0;
  padding: 10px 14px;
  border-radius: 10px;
  color: #ffffff;
  font-size: 14px;
  font-weight: 600;
  line-height: 1.25;
  text-align: center;
  transition: filter 0.16s ease;
}

ul.products > li.product .product-loop-meta .loop-add-to-cart-btn:hover,
ul.products > li.product .product-loop-meta .loop-add-to-cart-btn:focus,
ul.products > li.product .product-loop-meta .animated-meta a.loop-add-to-cart-btn:hover,
ul.products > li.product .product-loop-meta .animated-meta a.loop-add-to-cart-btn:focus {
  color: #ffffff;
  filter: brightness(1.35);
}

/* The cart glyph has fill="#000000" baked into the path attribute, so it has
   to be overridden rather than inherited. */
ul.products > li.product .product-loop-meta .loop-add-to-cart-btn .woostify-svg-icon {
  color: currentColor;
  margin-right: 0;
}

ul.products > li.product .product-loop-meta .loop-add-to-cart-btn svg {
  width: 15px;
  height: 15px;
  flex: 0 0 auto;
}

ul.products > li.product .product-loop-meta .loop-add-to-cart-btn svg path {
  fill: currentColor;
}

/* ---- 7. wishlist, demoted to what it is -------------------------------- */
ul.products > li.product .tinvwl-loop-button-wrapper {
  margin-top: 10px;
}

ul.products > li.product .tinvwl-loop-button-wrapper .tinvwl_add_to_wishlist_button {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: #5f6d6f;
  font-size: 12.5px;
  font-weight: 500;
}

ul.products > li.product .tinvwl-loop-button-wrapper .tinvwl_add_to_wishlist_button:hover,
ul.products > li.product .tinvwl-loop-button-wrapper .tinvwl_add_to_wishlist_button:focus {
  color: #122d31;
}

/* ---- 8. phone sizing --------------------------------------------------- */
@media (max-width: 600px) {
  ul.products > li.product > .product-loop-wrapper {
    border-radius: 12px;
  }

  ul.products > li.product .product-loop-content,
  ul.products > li.product .product-loop-content.text-center {
    padding: 11px 10px 13px;
  }

  ul.products > li.product .woocommerce-loop-product__title {
    margin: 0 0 8px;
    font-size: 13px;
    line-height: 1.35;
  }

  ul.products > li.product .product-loop-meta .price {
    margin: 0 0 10px;
    font-size: 16px;
  }

  ul.products > li.product:not(.purchasable):not(.outofstock) .product-loop-meta .animated-meta::before {
    margin: 0 0 10px;
    font-size: 13px;
  }

  ul.products > li.product .product-loop-meta .price del,
  ul.products > li.product .product-loop-meta .price del .woocommerce-Price-amount {
    margin-right: 5px;
    font-size: 12.5px;
  }

  ul.products > li.product .product-loop-meta .loop-add-to-cart-btn,
  ul.products > li.product .product-loop-meta .animated-meta a.loop-add-to-cart-btn {
    padding: 9px 8px;
    font-size: 13px;
    border-radius: 9px;
  }

  ul.products > li.product .tinvwl-loop-button-wrapper .tinvwl_add_to_wishlist_button {
    font-size: 12px;
  }

  ul.products > li.product .product-loop-image-wrapper .onsale,
  ul.products > li.product .product-loop-image-wrapper .woostify-tag-on-sale {
    top: 8px;
    padding: 3px 8px !important;
    font-size: 10px;
  }

  ul.products > li.product .product-loop-image-wrapper .onsale.sale-left {
    left: 8px;
  }
}

/* ---- 9. the bar above the grid ---------------------------------------- */
/* Same surface: it frames the grid on every archive. Desktop shipped a bare
   native select and a `#8f8f8f` result count. */
@media (min-width: 601px) {
  .woostify-sorting .woocommerce-result-count {
    color: #4a5658;
    font-size: 14px;
  }

  .woocommerce-ordering select.orderby,
  .woostify-sorting select {
    min-height: 42px;
    padding: 0 34px 0 14px;
    border: 1px solid #dde2e3;
    border-radius: 999px;
    background-color: #ffffff;
    color: #22343a;
    font-size: 14px;
  }

  .woocommerce-ordering select.orderby:focus,
  .woostify-sorting select:focus {
    border-color: #122d31;
    outline: none;
    box-shadow: 0 0 0 3px rgba(18, 45, 49, 0.14);
  }
}

/* ---- 10. the condition chip and category shelf, moved out of PHP ------- */
/* These rules are byte-for-byte the ones `ing_shelf_styles()` in
   ing-seo-trust.php used to echo as an inline <style id="ing-shelf-css">
   inside the product loop. They are here, and that function now returns an
   empty string, because of a real defect:

   The style tag was echoed from `woocommerce_shop_loop_item_title`, i.e. from
   inside the loop. On a category archive that is raw theme output and it
   worked. On a SINGLE PRODUCT page the loop that runs is "Related products",
   which Elementor renders through its own escaping - and that strips the
   <style> element while keeping its text. The result, live on all 145 product
   pages: 1,050 characters of raw CSS printed as visible body text inside the
   first related-product tile, starting `.ing-chip{display:inline-block...`.
   Confirmed in the DOM - the tile contained a text node and no <style>
   element at all.

   A stylesheet is where this belonged anyway: it now loads once, from a
   cacheable file, instead of being inlined into the HTML of every archive. */
.ing-chip {
  display: inline-block;
  margin: 0 0 6px;
  padding: 2px 9px;
  border-radius: 999px;
  font-size: 11px;
  line-height: 1.7;
  font-weight: 700;
  letter-spacing: .05em;
  text-transform: uppercase;
  border: 1px solid #d8dcdd;
  color: #4a5658;
  background: #f4f6f6;
}
.ing-chip-used  { border-color: #c9a24a; color: #6b4e12; background: #fdf6e6; }
.ing-chip-parts { border-color: #cfd4d6; color: #5b6668; background: #f2f4f5; }
.ing-chip-new   { border-color: #bcd6cf; color: #1c5145; background: #eef7f4; }

.ing-shelf {
  margin: 0 0 18px;
  padding: 12px 14px;
  border: 1px solid #e2e4e6;
  border-radius: 10px;
  background: #fafbfb;
  font-size: 14px;
  line-height: 1.5;
}
.ing-shelf-h {
  display: block;
  margin: 0 0 8px;
  font-size: 11px;
  letter-spacing: .08em;
  text-transform: uppercase;
  font-weight: 700;
  color: #0f3436;
}
.ing-shelf-list {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 0;
  padding: 0;
  list-style: none;
}
.ing-shelf-list li { margin: 0; padding: 0; }
.ing-shelf-list a,
.ing-shelf-list span.ing-shelf-here {
  display: inline-block;
  padding: 5px 11px;
  border: 1px solid #d8dcdd;
  border-radius: 999px;
  background: #fff;
  text-decoration: none;
  color: #22343a;
}
.ing-shelf-list a:hover { border-color: #0f3436; background: #f2f6f6; }
.ing-shelf-list span.ing-shelf-here {
  background: #0f3436;
  border-color: #0f3436;
  color: #fff;
  font-weight: 700;
}
.ing-shelf-list .ing-shelf-n { opacity: .65; font-weight: 400; }
.ing-shelf-note { margin: 9px 0 0; font-size: 13px; color: #4a5658; }

@media (max-width: 600px) {
  .ing-shelf { padding: 10px 11px; font-size: 13px; }
  .ing-shelf-list a,
  .ing-shelf-list span.ing-shelf-here { padding: 4px 9px; font-size: 13px; }
  .ing-chip { font-size: 10px; padding: 1px 7px; }
}
/* END ING PREMIUM GRID 2026-07-28 */

/* BEGIN ING PAGE-TYPE MOBILE 2026-07-28
   Third fenced block in woostify/style.css, appended AFTER
   `ING MOBILE PASS 2026-07-27` and `ING PREMIUM GRID 2026-07-28`. Do not
   reorder them: the premium grid deliberately wins over the mobile pass at
   equal specificity, and this block deliberately wins over both.

   The first two blocks were written from an 8-URL sample: homepage, the shop
   archive, three product pages, two posts and /contact. Auditing all 60 page
   types on 2026-07-28 (tools/mobile-audit.js, URL list from
   build_audit_urls.py) found four things that sample could not have seen,
   because none of those 8 URLs is a form page or a cart.

   1. CART: the product thumbnail was painted ON TOP of the product name.
      Woostify absolutely-positions `.product-thumbnail` at `left: 0` below
      992px and compensates with `.cart_item { padding-left: 85px }`. Elementor's
      cart widget then sets `table.cart tr { padding: 16px 28px }` - a shorthand
      that resets padding-left to 28px - and it loads after the theme. Measured
      on an iPhone 13: thumbnail spans x 56-111, the name starts at x 84, so the
      first two characters of the first two lines of every cart line item were
      covered. "Vintage Wood Lincoln Logs - Mixed Lot..." read "...age Wood
      Lincoln Logs - ...ed Lot...".
   2. FORM FIELDS AT 14px: iOS Safari zooms the whole page when a field under
      16px receives focus, and does not zoom back out. That hits checkout (14
      fields), my-account, both contact forms and every product search box on
      the site. This is the one place this block uses `!important`: Elementor's
      checkout stylesheet reaches the fields through
      `#customer_details .form-row .input-text`, an ID selector, and matching it
      selector-for-selector would mean copying a 9-part chain that changes with
      the plugin. Nothing here changes a checkout SETTING or any checkout
      behaviour - it is the rendered font size of an input.
   3. BLOG PAGINATION: the store pagination got 44px targets in July; the blog
      index prints bare `<a class="page-numbers">` straight into a div with no
      `ul`, so those selectors never reached it. Page links measured 8x20px.
   4. SINGLE-PRODUCT WISHLIST: open item 2 from MOBILE-AUDIT.md, confirmed on
      every one of the five product render states - 128x28px.

   Everything below is presentation. No markup, no PHP, no product data, no
   price, no stock, no shipping, no payment, no checkout setting.
*/

/* ---- 1. cart line item: stop the thumbnail covering the product name -----
   Scoped to `max-width: 767px`, which is exactly the window where the bug
   exists, and it takes three media queries to see why:

     woostify/style.css          @media (max-width: 991px)
       .cart_item { padding-left: 85px }        <- reserves room for the thumb
       .product-thumbnail { position: absolute; left: 0 }
     widget-woocommerce-cart.css @media (max-width: 767px)
       table.cart tr { padding: 16px 28px }     <- shorthand, wipes the 85px

   So 768-991px is already correct and must not be touched; 767px and below is
   broken. Restoring Woostify's own 85px rather than inventing a number keeps
   the two ranges rendering identically. Verified with tools/diff-pagetype.js:
   1920/1440/1024/768 identical on all 8 sample URLs, 601 changes /cart only. */
@media (max-width: 767px) {
  .elementor-widget-woocommerce-cart .woocommerce table.cart tbody tr.cart_item,
  .woocommerce-cart-form__contents:not(.elementor-menu-cart__products) tbody tr.cart_item {
    padding-left: 85px;
  }
}

@media (max-width: 600px) {
  /* ---- 2. form fields: 16px, so iOS does not zoom the page on focus ------
     Restricted to text-entry controls. Buttons and submits are left alone
     because their font size is also their box size here. */
  input[type="text"],
  input[type="email"],
  input[type="tel"],
  input[type="url"],
  input[type="number"],
  input[type="password"],
  input[type="search"],
  input[type="date"],
  input:not([type]),
  input.input-text,
  select,
  textarea {
    font-size: 16px !important;
  }

  /* The 2026-07-27 block set the sort control to 14px explicitly. Same reason
     applies to it, and it is a select: bumped here rather than edited there so
     that block stays byte-identical to what was verified in July. */
  .woocommerce-ordering select.orderby,
  .woostify-sorting select {
    font-size: 16px !important;
  }

  /* WooCommerce login/register fields ship 40px tall. */
  .woocommerce form.woocommerce-form-login .woocommerce-Input--text,
  .woocommerce form.register .woocommerce-Input--text {
    min-height: 44px;
  }

  /* The show/hide-password toggle is a 16x31 icon sitting half outside the
     field. Give it a real box inside the field and reserve room for it. */
  .woocommerce form .password-input {
    display: block;
    position: relative;
  }

  .woocommerce form .password-input .woocommerce-Input--text {
    padding-right: 48px;
  }

  .woocommerce form .show-password-input {
    top: 0;
    right: 0;
    width: 44px;
    height: 100%;
    min-height: 44px;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
  }

  /* ---- 3. blog pagination ------------------------------------------------
     The blog index prints its page links as bare children of a centred div,
     with no `ul` and no `.woocommerce-pagination` wrapper, so the July rules
     could not see them. `div >` keeps this off the store pagination, which is
     already correct. */
  div > a.page-numbers,
  div > span.page-numbers {
    box-sizing: border-box;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 44px;
    height: 44px;
    margin: 2px;
    padding: 0 8px;
    border-radius: 22px;
  }

  div > a.page-numbers {
    color: #3d3d3d;
  }

  /* ---- 4. single-product wishlist ---------------------------------------
     MOBILE-AUDIT.md open item 2. The July rule was scoped
     `ul.products > li.product ...`, i.e. the loop only; the copy in the product
     summary lives in `div.tinv-wraper` and was never covered. */
  .tinv-wraper .tinvwl_add_to_wishlist_button,
  .woocommerce div.product .tinvwl_add_to_wishlist_button {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    padding: 6px 4px;
  }

  /* ---- 5. runaway images in page content --------------------------------
     /trademark-verification renders the USPTO registration screenshot at
     865x1024 inside a 390px column, because the file 404s (migration loss - see
     SEO-WORK-LOG) and an image that fails to load falls back to its width/height
     attributes. Clamping it keeps one dead file from throwing the page layout
     79-500px wide. It does NOT bring the image back; that needs the original
     re-uploaded and is logged as a human job.

     The `a` rule is the one that actually does the work, and it is worth
     knowing why: the img ALREADY computes `max-width: 100%`. It is wrapped in
     an `<a>` that Elementor renders `display: inline-block` with no max-width,
     so the anchor shrink-to-fits to the broken image's `width="865"` attribute
     and the img's 100% then resolves against 865px. Clamping the img alone
     changes nothing - the containing block has to be clamped first. */
  .elementor-widget-container a:has(img),
  .entry-content a:has(img) {
    max-width: 100%;
  }

  .elementor-widget-container img,
  .entry-content img,
  .woocommerce-product-details__short-description img {
    max-width: 100%;
    height: auto;
  }

  /* ---- 6. the last three controls in the funnel -------------------------
     Measured on the after-run: the cart quantity stepper is 90x30 in total -
     an 88x28 input between a minus and a plus that are each about 17px of
     glyph. Changing quantity on a phone means hitting a 17px target next to
     the field you do not want to focus. The stepper keeps its pill shape and
     its 1-unit steps; it just gets a 44px row.

     The two WooCommerce checkboxes wrap their own label, so the tap target is
     the whole label row, not the 13px box - 20px on checkout, 28px on
     my-account. Both are raised to 44px. Neither rule changes what the control
     DOES; "ship to a different address" still toggles the same section. */
  .woocommerce .quantity {
    min-height: 44px;
  }

  /* Elementor pins this one with `max-height: 28px; min-height: 28px` on
     `.elementor-widget-woocommerce-cart .woocommerce .input-text.qty`, so the
     max-height has to be lifted too or min-height simply loses. */
  .woocommerce .quantity input.qty,
  .elementor-widget-woocommerce-cart .woocommerce .quantity .input-text.qty {
    min-height: 44px;
    max-height: 44px;
  }

  .woocommerce .quantity .product-qty {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 40px;
    min-height: 44px;
  }

  .woocommerce form .woocommerce-form__label-for-checkbox,
  .woocommerce-checkout .woocommerce-form__label-for-checkbox,
  .woocommerce-form-login .woocommerce-form__label-for-checkbox {
    display: flex;
    align-items: center;
    min-height: 44px;
  }
}
/* END ING PAGE-TYPE MOBILE 2026-07-28 */

/* BEGIN ING ARCHIVE HEADER 2026-07-30
   The top of every product archive - the shop and all 22 category terms.
   Fourth block in ing-design.css, appended after the three restored ones so it
   wins over them at equal specificity.

   WHAT WAS WRONG, measured on the live site with tools/design4-header.js after
   the design layer was restored:

   1. THE SHOP HAD NO HEADING ABOVE ITS PRODUCTS. `/all-miners` opened with the
      condition strip at y=151 and put the grid at y=385. Its <h1>, "ASIC Miners
      for Sale - New, Used and Repair Parts", rendered at **y=2303** - below the
      grid AND below the pagination - because my-custom-plugin deliberately
      moves `woocommerce_product_archive_description` to
      `woocommerce_after_shop_loop` so the SEO copy does not bury the products,
      and page 1's heading is the literal <h1> at the top of that copy. Right
      words, wrong end of the document, on the store's single most important
      commercial page. ing-seo-headings.php section 3b now prints it through
      `woocommerce_page_title` instead and strips the duplicate out of the
      description at render time.

   2. THE SAME ELEMENT WAS TWO DIFFERENT SIZES ON SIBLING PAGES. The shop's <h1>
      computed 48px; every category's computed 23.8px - smaller than the <h2>s
      further down the same page. Both are now the one size.

   3. THE CATEGORY LEDE WAS #8f8f8f ON WHITE at 14px - 3.2:1, below WCAG AA, and
      running the full 1370px measure. It is the only sentence on the page that
      explains what the shelf is.

   4. THE SORTING BAR WAS 84px OF NOTHING: a 28px result count and a 42px select
      with no relationship to each other and no line separating the chrome from
      the grid.

   Presentation only, plus one strip of a duplicated heading. Nothing here
   changes what is sorted, what is counted, or what is in the archive.
*/

/* ---- 1. the header band ------------------------------------------------- */
/* WooCommerce's own wrapper; it exists on every product archive and, as of
   ing-seo-headings.php section 3b, on the shop as well. */
.woocommerce-products-header {
  margin: 0 0 20px;
  padding: 0 0 18px;
  border-bottom: 1px solid #e6eaeb;
}

/* Two classes, because Woostify's customizer reaches the title through a
   single-class `.page-title` rule and the Elementor kit sets a bare `h1`. */
.woocommerce-products-header .woocommerce-products-header__title,
.woocommerce-products-header h1.page-title {
  margin: 0 0 10px;
  font-size: 34px;
  line-height: 1.18;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: #16292b;
}

/* ---- 2. the lede -------------------------------------------------------- */
/* A measure, not the full container width: 22 terms carry a written sentence
   here and at 1370px it reads as a caption rather than as copy. */
.woocommerce-products-header .term-description {
  max-width: 74ch;
  margin: 0;
}

.woocommerce-products-header .term-description,
.woocommerce-products-header .term-description p {
  margin: 0;
  font-size: 16px;
  line-height: 1.6;
  color: #3d3d3d;
}

.woocommerce-products-header .term-description p + p {
  margin-top: 10px;
}

.woocommerce-products-header .term-description a {
  color: #0f3436;
  text-decoration: underline;
  text-underline-offset: 2px;
}

/* ---- 3. the toolbar above the grid -------------------------------------- */
/* Desktop and tablet only. The 2026-07-27 mobile pass deliberately stacks these
   two full-width on a phone and gives the select a 44px box; making it a flex
   row here would undo that, so this stops at 601px. */
@media (min-width: 601px) {
  .woostify-sorting {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    height: auto;
    margin: 0 0 20px;
    padding: 0 0 14px;
    border-bottom: 1px solid #eef1f2;
  }

  .woostify-sorting .woostify-toolbar-left {
    display: flex;
    align-items: center;
    gap: 16px;
    margin: 0;
  }

  .woostify-sorting .woocommerce-result-count {
    margin: 0;
    font-size: 14px;
    line-height: 1.4;
    color: #4a5658;
  }

  .woostify-sorting .woocommerce-ordering,
  .woocommerce-ordering {
    margin: 0;
    float: none;
  }
}

/* ---- 4. phone ----------------------------------------------------------- */
@media (max-width: 600px) {
  .woocommerce-products-header {
    margin: 0 0 14px;
    padding: 0 0 13px;
  }

  .woocommerce-products-header .woocommerce-products-header__title,
  .woocommerce-products-header h1.page-title {
    margin: 0 0 8px;
    font-size: 26px;
    line-height: 1.22;
  }

  .woocommerce-products-header .term-description,
  .woocommerce-products-header .term-description p {
    font-size: 15px;
    line-height: 1.55;
  }
}
/* END ING ARCHIVE HEADER 2026-07-30 */

