/*
 * WooCommerce-specific styles for the excavator-pro theme (Bedrock Equipment Co.).
 * Enqueued only on WooCommerce pages (see inc/woocommerce-hooks.php) and loaded after
 * assets/css/tokens.css, whose custom properties are the only source of color/spacing/
 * typography values used below — no new hardcoded design values are introduced here.
 * Mobile-first: base rules target small screens, min-width media queries layer up.
 */

/* -----------------------------------------------------------------------
 * 1. Shop archive grid
 * ----------------------------------------------------------------------- */

/* Breadcrumb: WooCommerce's own archive-product.php / single-product.php print
   `woocommerce_breadcrumb()` (hooked to woocommerce_before_main_content at
   priority 20), not the theme's excavator_pro_breadcrumb() component used on
   page.php/single.php/archive.php — CSS-only restyle to the same look
   (assets/css/style.css section 17) so shop/product pages match everywhere
   else, without a template override. */
.woocommerce-breadcrumb {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  font-size: var(--fs-sm);
  color: var(--color-text-muted);
  margin: 0 0 var(--space-6);
}

.woocommerce-breadcrumb a {
  color: var(--color-text-muted);
}

.woocommerce-breadcrumb a:hover,
.woocommerce-breadcrumb a:focus-visible {
  color: var(--color-accent);
}

/* Archive header: WooCommerce's default "Shop" / category title + optional
   term description, wrapped in .woocommerce-products-header by
   archive-product.php. Matches .page-header/.page-title elsewhere. */
.woocommerce-products-header {
  margin-bottom: var(--space-8);
}

.woocommerce-products-header__title.page-title {
  font-size: var(--fs-2xl);
  margin-bottom: 0;
}

.woocommerce-products-header .woocommerce-products-header__title.page-title + * {
  margin-top: var(--space-2);
}

.term-description,
.woocommerce-products-header + .term-description {
  color: var(--color-text-muted);
  max-width: 65ch;
}

/* Result count + sort dropdown row */

.woocommerce-notices-wrapper:empty {
  display: none;
}

.woocommerce > .woocommerce-notices-wrapper + p.woocommerce-result-count,
form.woocommerce-ordering,
p.woocommerce-result-count {
  margin: 0 0 var(--space-6);
}

.woocommerce > .woocommerce-notices-wrapper + p.woocommerce-result-count {
  margin: 0;
}

/* WooCommerce prints result-count and the ordering <form> as adjacent
   siblings, not inside a shared wrapper — a flex row on the common parent
   (.woocommerce, scoped narrowly to avoid affecting cart/checkout markup
   nested in the same body class) lines them up the way a real toolbar would,
   full-width shop pages having no sidebar to otherwise separate them. */
.woocommerce:not(.woocommerce-cart):not(.woocommerce-checkout):not(.woocommerce-account) > p.woocommerce-result-count {
  float: none;
  display: inline-block;
}

.woocommerce-ordering {
  float: none;
  display: inline-block;
}

@media (min-width: 640px) {
  .woocommerce-result-count {
    float: left;
    margin-bottom: 0 !important;
  }

  .woocommerce-ordering {
    float: right;
    margin-bottom: 0 !important;
  }
}

.woocommerce-ordering select {
  appearance: none;
  padding-right: var(--space-8);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%235b6470' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right var(--space-2) center;
  background-size: 16px;
}

/* Pagination */

.woocommerce-pagination {
  margin-top: var(--space-8);
  clear: both;
}

.woocommerce-pagination ul.page-numbers {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  list-style: none;
  margin: 0;
  padding: 0;
  justify-content: center;
}

.woocommerce-pagination .page-numbers li {
  display: inline-flex;
}

.woocommerce-pagination .page-numbers a,
.woocommerce-pagination .page-numbers span {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 40px;
  height: 40px;
  padding-inline: var(--space-2);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  font-family: var(--font-heading);
  font-weight: 600;
  font-size: var(--fs-sm);
  color: var(--color-text);
}

.woocommerce-pagination .page-numbers a:hover,
.woocommerce-pagination .page-numbers a:focus-visible {
  border-color: var(--color-accent);
  color: var(--color-accent);
}

.woocommerce-pagination .page-numbers span.current {
  background: var(--color-accent);
  border-color: var(--color-accent);
  color: var(--color-bg);
}

.woocommerce ul.products {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-6) var(--space-4);
  list-style: none;
  margin: 0 0 var(--space-8);
  padding: 0;
}

/* WooCommerce core's own stylesheet still puts a `content: ''; display: table;`
   clearfix on ul.products::before/::after — a leftover from the old
   float-based product grid, harmless there since a zero-size table pseudo
   collapses invisibly. Once the container is `display: grid` (above), grid
   generates a real, empty grid item for it instead of collapsing it, which
   shows up as a phantom blank card in the first cell. Grid never needed a
   clearfix, so just drop the generated content entirely. */
.woocommerce ul.products::before,
.woocommerce ul.products::after {
  content: none;
}

.woocommerce ul.products li.product {
  margin: 0 !important;
  width: auto !important;
  float: none !important;
  clear: none !important;
}

@media (min-width: 640px) {
  .woocommerce ul.products {
    gap: var(--space-6);
  }
}

@media (min-width: 768px) {
  .woocommerce ul.products {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

@media (min-width: 1024px) {
  .woocommerce ul.products {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}

.woocommerce-result-count,
.woocommerce-ordering {
  font-family: var(--font-body);
  font-size: var(--fs-sm);
  color: var(--color-text-muted);
}

.woocommerce-ordering select {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  padding: var(--space-1) var(--space-2);
  font-family: var(--font-body);
  color: var(--color-text);
  background: var(--color-bg);
}

/* -----------------------------------------------------------------------
 * 2. Product card (woocommerce/content-product.php)
 * ----------------------------------------------------------------------- */

.excavator-card {
  position: relative;
  list-style: none;
  background: var(--color-bg);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-card);
  transition: box-shadow var(--duration-base) var(--ease-entrance), transform var(--duration-base) var(--ease-entrance), border-color var(--duration-base) var(--ease-entrance);
  overflow: hidden;
}

@media (prefers-reduced-motion: no-preference) {
  .excavator-card:hover {
    transform: translateY(-4px) scale(1.01);
  }
}

.excavator-card:hover {
  box-shadow: var(--shadow-card-hover);
  border-color: var(--color-accent);
}

.excavator-card__inner {
  position: relative;
  display: flex;
  flex-direction: column;
  height: 100%;
}

.excavator-card .woocommerce-loop-product__link {
  display: flex;
  flex-direction: column;
  color: inherit;
  text-decoration: none;
}

/* Thumbnail + hover-swap to second gallery image (pure CSS, no JS) */

.excavator-card__media {
  position: relative;
  display: block;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  background: var(--color-bg-alt);
}

.excavator-card__media img.excavator-card__img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: opacity var(--duration-base) var(--ease-entrance), transform 0.6s var(--ease-entrance);
}

@media ( prefers-reduced-motion: no-preference ) {
  .excavator-card:hover .excavator-card__img {
    transform: scale(1.06);
  }
}

.excavator-card__img--primary {
  opacity: 1;
}

.excavator-card__img--secondary {
  opacity: 0;
}

.excavator-card:hover .excavator-card__img--secondary {
  opacity: 1;
}

.excavator-card:hover .excavator-card__img--primary {
  opacity: 0;
}

/* Sale + Featured badges, absolutely positioned over the media area. Sale sits
   top-left (matches the sale-price color story in the price row below);
   Featured sits top-right so both can appear on the same card without
   overlapping — a card can be both on sale and hand-picked as Featured. */

.excavator-card__badge {
  position: absolute;
  top: var(--space-3);
  z-index: 2;
  display: inline-block;
  font-family: var(--font-heading);
  font-weight: 600;
  font-size: var(--fs-sm);
  letter-spacing: 0.02em;
  text-transform: uppercase;
  padding: var(--space-1) var(--space-2);
  border-radius: var(--radius-sm);
  line-height: 1;
}

.excavator-card__badge--sale {
  left: var(--space-3);
  background: var(--color-sale);
  color: var(--color-bg);
}

.excavator-card__badge--featured {
  right: var(--space-3);
  background: var(--color-accent);
  color: var(--color-bg);
}

/* Title, price, and spec-strip: the base rules below (plain `.excavator-card
   X`) are what apply on the homepage's featured-products slider, where cards
   render inside a `.slider__track` <div>, not a real `ul.products` — and
   critically with no `.woocommerce` body class either, since the front page
   isn't a WooCommerce-recognized page template. There, nothing competes with
   these rules and they win outright.
   On the shop archive / related-products (both genuinely `.woocommerce ...
   ul.products li.product`), WooCommerce's own core stylesheet ALSO targets
   these same elements directly — e.g. `.woocommerce ul.products li.product
   .price` (specificity (0,4,2)), and — this one caught us out —
   `.woocommerce .products ul` as a catch-all for ANY nested <ul>, which
   matches our spec-strip too since it's a <ul> nested inside ul.products
   (also (0,4,2)+). The base rules alone are only (0,2,0)/(0,1,0) and
   silently lose there on every property both sides set (font-size, color,
   padding) despite loading later. So each base rule below is immediately
   followed by a `.woocommerce ul.products li.product.excavator-card`-prefixed
   duplicate that matches (and beats) WooCommerce's specificity for the
   archive/related-products context specifically — same root cause, and same
   fix, as the compound-selector note for the shared `.slider` component in
   style.css section 7 (a later, lower-specificity rule still loses). */

.excavator-card .woocommerce-loop-product__title,
.woocommerce ul.products li.product.excavator-card .woocommerce-loop-product__title {
  font-family: var(--font-heading);
  font-weight: 600;
  font-size: var(--fs-lg);
  color: var(--color-text);
  margin: var(--space-4) var(--space-4) var(--space-1);
  line-height: 1.25;
  transition: color var(--duration-fast) var(--ease-feedback);
}

.excavator-card:hover .woocommerce-loop-product__title {
  color: var(--color-accent-dark);
}

/* Rating (default hook output, styled to sit quietly above the price) */

.excavator-card .star-rating {
  margin: 0 var(--space-4) var(--space-1);
  font-size: var(--fs-sm);
  color: var(--color-accent);
}

/* Price (rendered by woocommerce_template_loop_price() — WooCommerce's own markup, styled only).
   Barlow Condensed rather than the body font, at a bumped size — the same "editorial oversized
   numeral" treatment the hero's quick-specs strip uses for its values, applied here to the
   number contractors actually scan the grid for. */

.excavator-card .price,
.woocommerce ul.products li.product.excavator-card .price {
  margin: 0 var(--space-4) var(--space-3);
  font-family: var(--font-heading);
  font-size: var(--fs-xl);
  font-weight: 600;
  letter-spacing: 0.01em;
  color: var(--color-text);
}

.excavator-card .price del,
.woocommerce ul.products li.product.excavator-card .price del {
  color: var(--color-text-muted);
  font-weight: 400;
  font-size: var(--fs-base);
  opacity: 0.8;
  margin-right: var(--space-2);
}

.excavator-card .price ins,
.woocommerce ul.products li.product.excavator-card .price ins {
  color: var(--color-sale);
  text-decoration: none;
  font-weight: 600;
}

/* Spec strip: icon + value only, no label, for the 4 card-highlight attributes */

.excavator-card__specs,
.woocommerce ul.products li.product.excavator-card ul.excavator-card__specs {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2) var(--space-4);
  list-style: none;
  margin: 0 var(--space-4) var(--space-4);
  padding: var(--space-3) 0 0;
  border-top: 1px solid var(--color-border);
}

.excavator-card__spec {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  font-family: var(--font-body);
  font-size: var(--fs-xs);
}

.excavator-card__spec-icon {
  display: inline-flex;
  color: var(--color-text-muted);
}

.excavator-card__spec-icon svg {
  width: var(--fs-sm);
  height: var(--fs-sm);
  display: block;
}

.excavator-card__spec-value {
  color: var(--color-text);
  font-weight: 500;
  white-space: nowrap;
}

/* Add-to-cart button (default hook output — woocommerce_template_loop_add_to_cart()) */

/* margin-top: auto (not a fixed margin) pushes the button to the bottom of
   .excavator-card__inner's flex column regardless of how much content sits
   above it — without this, cards whose products don't have one of the 4
   card-highlight spec attributes (so excavator_pro_loop_spec_strip renders
   no spec-strip row for them — see e.g. the Attachments category, where only
   some attachments have a matching spec) sit shorter than cards that do, so
   buttons in the same grid row land at different heights instead of lining
   up. Needs the same `.woocommerce ul.products li.product.excavator-card`
   specificity-duplicate as everything else in this file (see the big comment
   above) — WooCommerce core's own `.woocommerce ul.products li.product .button`
   rule sets a fixed margin-top and otherwise wins outright. */
.excavator-card a.add_to_cart_button,
.excavator-card a.button,
.woocommerce ul.products li.product.excavator-card a.add_to_cart_button,
.woocommerce ul.products li.product.excavator-card a.button {
  display: block;
  margin: auto var(--space-4) var(--space-4);
  padding: var(--space-2) var(--space-4);
  background: var(--color-accent);
  color: var(--color-bg);
  border-radius: var(--radius-sm);
  font-family: var(--font-heading);
  font-weight: 600;
  font-size: var(--fs-sm);
  letter-spacing: 0.02em;
  text-align: center;
  text-decoration: none;
  text-transform: uppercase;
  transition: background var(--duration-fast) var(--ease-feedback);
}

.excavator-card a.add_to_cart_button:hover,
.excavator-card a.button:hover {
  background: var(--color-accent-dark);
  color: var(--color-bg);
}

.excavator-card a.added_to_cart {
  display: block;
  margin: 0 var(--space-4) var(--space-4);
  text-align: center;
  font-family: var(--font-body);
  font-size: var(--fs-sm);
  color: var(--color-success);
}

/* -----------------------------------------------------------------------
 * 2b. Single product page.
 *
 *     Structure is still 100% WooCommerce's own single-product.php /
 *     content-single-product.php — no template override (see
 *     docs/woocommerce-template-rules.md). Everything below either styles a class
 *     WooCommerce already outputs, or styles a block inc/product-page.php adds on one
 *     of WooCommerce's existing action hooks.
 *
 *     Layout: an explicit two-column CSS grid on div.product rather than relying on
 *     WooCommerce core's float-based .woocommerce-product-gallery/.summary rules. The
 *     grid is what makes the gallery column stickable (floats can't be sticky), and it
 *     lets every later block the hooks add — tabs, FAQ, related — span both columns
 *     without each one needing its own clearfix.
 * ----------------------------------------------------------------------- */

.single-product div.product {
  position: relative;
}

/* WooCommerce ships woocommerce-layout.css, which floats the gallery and the summary
   at `width: 48%` from the very first pixel. Floats can't be sticky and don't
   participate in the grid below, and the 48% was silently shrinking *both* columns to
   half of their own grid track — so neutralise the pair here rather than fighting them
   in every rule that follows.
   The selectors look heavier than they need to be; they aren't. Core's rule is the
   list `.woocommerce #content div.product div.images, .woocommerce div.product
   div.images, …`, and header.php wraps the whole site in <div id="content">, so the ID
   branch matches at (1,3,2) — `.images` is a class, not an element. Matching that means
   carrying the ID *and* out-classing it, which is what the extra `.images` /
   `.entry-summary` qualifiers do, for (1,4,2). The ID-less variants below keep the same
   override working in the shortcode contexts that render a product outside #content. */
.woocommerce #content div.product > div.images.woocommerce-product-gallery,
.woocommerce #content div.product > div.summary.entry-summary,
.woocommerce div.product > div.images.woocommerce-product-gallery,
.woocommerce div.product > div.summary.entry-summary {
  float: none;
  width: 100%;
  clear: none;
}

/* Below the two-column breakpoint the page is a single stacked column: gallery, then
   the full summary, then tabs. The mobile sticky add-to-cart bar (section 3c) is what
   keeps the buy action reachable there, so the summary doesn't need to compete for
   horizontal space with the gallery on a tablet. */
@media (min-width: 1024px) {
  .single-product div.product {
    display: grid;
    /* Slightly wider right column: it carries the buy box *and* the description
       and specification tabs, so it needs more room than the gallery. */
    grid-template-columns: minmax(0, 5fr) minmax(0, 6fr);
    column-gap: var(--space-12);
    align-items: start;
  }

  .single-product div.product > * {
    grid-column: 2;
    min-width: 0;
  }

  /* The sale badge is absolutely positioned, but it is still a grid child, and an
     absolutely-positioned grid child with a definite position takes its *grid area* as
     its containing block — so the `grid-column: 2` default above was pinning it to the
     top-left of the summary column, right on top of the product title. Placing it in
     the gallery's own cell puts it back over the image where it belongs. */
  .single-product div.product > .product-sale-badge {
    grid-column: 1;
    grid-row: 1;
  }

  .single-product #content div.product > div.images.woocommerce-product-gallery,
  .single-product div.product > div.images.woocommerce-product-gallery {
    grid-column: 1;
    /* Span every row the right-hand column produces (summary, then tabs) so the
       gallery has the whole content column to travel alongside. */
    grid-row: 1 / -1;
    align-self: start;
    /* --site-header-height is published by main.js's initHeaderHeightVar();
       the fallback covers first paint before JS runs. */
    position: sticky;
    top: calc(var(--site-header-height, 80px) + var(--space-6));
  }

  .single-product #content div.product > div.summary.entry-summary,
  .single-product div.product > div.summary.entry-summary {
    grid-column: 2;
    grid-row: 1;
  }

  /* Description / Additional information / Reviews sit under the buy box in the same
     column, not full-width beneath both. Full width left a tall empty gutter under the
     sticky gallery and stretched body copy to an unreadable line length; stacking them
     here fills that gutter and gives the gallery something to stay beside. */
  .single-product div.product > .woocommerce-tabs {
    grid-column: 2;
    grid-row: 2;
    margin-top: var(--space-8);
  }
}

/* Gallery */

.woocommerce-product-gallery {
  position: relative;
  background: var(--color-bg-alt);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: var(--space-3);
}

.woocommerce-product-gallery__wrapper {
  border-radius: var(--radius-md);
  overflow: hidden;
  background: var(--color-bg);
}

.woocommerce-product-gallery__image img {
  width: 100%;
  height: auto;
  display: block;
}

/* WooCommerce's zoom + lightbox theme supports wrap the main image in an <a>;
   give it a cursor that says so, since the trigger is otherwise invisible. */
.woocommerce-product-gallery__image > a {
  display: block;
  cursor: zoom-in;
}

/* Thumbnail rail. WooCommerce's flexslider integration prints these as
   ul.flex-control-thumbs; a fixed 4-up grid (5-up from tablet) matches the
   reference layout and keeps every thumb the same size regardless of how many
   gallery images a product has.
   Core lays the same list out as 25%-wide floated <li>s at
   `.woocommerce div.product div.images .flex-control-thumbs li` (0,4,3) — inside a grid
   that width resolves against the *track*, shrinking each thumb to a quarter of its own
   cell. The `.images.woocommerce-product-gallery` double-qualifier below takes the
   overrides to (0,5,3) so the grid actually governs the sizing. Same reason for the
   img rules: core sets `opacity: .5` on them at (0,4,4). */
.woocommerce div.product div.images.woocommerce-product-gallery .flex-control-thumbs {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--space-2);
  margin: var(--space-3) 0 0;
  padding: 0;
  list-style: none;
}

@media (min-width: 640px) {
  .woocommerce div.product div.images.woocommerce-product-gallery .flex-control-thumbs {
    grid-template-columns: repeat(5, minmax(0, 1fr));
  }
}

.woocommerce div.product div.images.woocommerce-product-gallery .flex-control-thumbs li {
  width: auto;
  float: none;
  margin: 0;
}

.woocommerce div.product div.images.woocommerce-product-gallery .flex-control-thumbs li img {
  width: 100%;
  height: auto;
  display: block;
  background: var(--color-bg);
  border-radius: var(--radius-sm);
  border: 2px solid var(--color-border);
  opacity: 0.75;
  cursor: pointer;
  transition: opacity var(--duration-fast) var(--ease-feedback), border-color var(--duration-fast) var(--ease-feedback);
}

.woocommerce div.product div.images.woocommerce-product-gallery .flex-control-thumbs li img:hover,
.woocommerce div.product div.images.woocommerce-product-gallery .flex-control-thumbs li img.flex-active {
  opacity: 1;
  border-color: var(--color-accent);
}

/* Percentage sale badge over the gallery (excavator_pro_single_sale_badge(),
   inc/product-page.php).
   Two positions, because WooCommerce prints this as a sibling of the gallery, not a
   child. At rest against div.product (below) it lands on the gallery's top-left corner,
   which is right — but the gallery is sticky, so on scroll the image travelled and left
   the badge behind. initSaleBadgePlacement() in main.js moves it into the gallery so it
   rides along; .is-in-gallery is that state. The base rule stays as the no-JS fallback. */
.woocommerce-product-gallery > .product-sale-badge.is-in-gallery {
  /* The gallery is position: relative, so this now anchors to the image box itself and
     travels with it for the whole sticky scroll. */
  top: var(--space-4);
  left: var(--space-4);
}

.single-product .product-sale-badge {
  position: absolute;
  top: var(--space-4);
  left: var(--space-4);
  z-index: 3;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 62px;
  height: 62px;
  border-radius: 50%;
  background: var(--color-sale);
  color: var(--color-bg);
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: var(--fs-lg);
  letter-spacing: 0.01em;
  line-height: 1;
  box-shadow: var(--shadow-card);
}

/* Summary column */

.summary.entry-summary {
  margin-top: var(--space-8);
}

@media (min-width: 1024px) {
  .summary.entry-summary {
    margin-top: 0;
  }
}

/* Aggregate rating badge, above the title */

.product-rating-badge {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin-bottom: var(--space-3);
}

/* Two stacked star rows clipped to a percentage width — renders an exact 4.8
   instead of rounding a half star up to a full one. */
.product-rating-badge__stars {
  position: relative;
  display: inline-block;
  font-size: var(--fs-lg);
  letter-spacing: 0.12em;
  line-height: 1;
  /* The full row is absolutely positioned over the empty one, so the element
     needs the empty row to establish its width — hence no explicit width here. */
  white-space: nowrap;
}

.product-rating-badge__stars-empty {
  color: var(--color-border);
}

.product-rating-badge__stars-full {
  position: absolute;
  top: 0;
  left: 0;
  overflow: hidden;
  color: var(--color-warning);
  white-space: nowrap;
}

.product-rating-badge__score {
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: var(--fs-lg);
  color: var(--color-text);
  line-height: 1;
}

.product-rating-badge__count {
  font-size: var(--fs-sm);
  color: var(--color-text-muted);
}

.single-product .product_title.entry-title {
  font-size: var(--fs-2xl);
  line-height: 1.1;
  text-transform: uppercase;
  margin-bottom: var(--space-3);
}

@media (min-width: 1024px) {
  .single-product .product_title.entry-title {
    font-size: var(--fs-3xl);
  }
}

/* Short accent rule under the title, matching the section-marker language used
   by .excavator-spec-grid and .footer-col__title. */
.single-product .product_title.entry-title::after {
  content: "";
  display: block;
  width: 48px;
  height: 3px;
  margin-top: var(--space-3);
  background: var(--color-accent);
}

/* Price. Selectors deliberately match (and beat) the specificity of WooCommerce's
   own `.woocommerce div.product p.price` core rule — see the "Compound selectors"
   note in style.css section 7 for the same cascade issue elsewhere in this theme. */
.woocommerce div.product .summary p.price {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: var(--space-3);
  font-family: var(--font-heading);
  font-size: var(--fs-3xl);
  font-weight: 700;
  letter-spacing: 0.01em;
  line-height: 1;
  /* Dark by default; only the <ins> half of a sale price turns red (below). Colouring
     the <p> red instead and correcting it for the non-sale case would need :has(), which
     silently leaves every regular-priced product looking discounted wherever :has()
     isn't supported. */
  color: var(--color-text);
  margin: 0 0 var(--space-4);
}

/* Struck original price sits inline before the sale price (not stacked above it),
   so the discount reads as one "was / now" statement at a glance. */
.woocommerce div.product .summary p.price del {
  order: -1;
  font-size: var(--fs-xl);
  font-weight: 400;
  color: var(--color-text-muted);
  opacity: 0.85;
  margin: 0;
}

.woocommerce div.product .summary p.price ins {
  color: var(--color-sale);
  text-decoration: none;
  background: transparent;
}

.woocommerce-product-details__short-description {
  color: var(--color-text-muted);
  font-size: var(--fs-base);
  margin-bottom: var(--space-4);
}

.woocommerce-product-details__short-description p:last-child {
  margin-bottom: 0;
}

/* Trust bar (excavator_pro_product_trust_bar()) */

.product-trust-bar {
  list-style: none;
  margin: 0 0 var(--space-6);
  padding: var(--space-4) 0;
  border-top: 1px solid var(--color-border);
  border-bottom: 1px solid var(--color-border);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.product-trust-bar__item {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--color-text);
  line-height: 1.35;
}

.product-trust-bar__icon {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  background: var(--color-accent-light);
  color: var(--color-accent);
}

.product-trust-bar__icon svg {
  width: 17px;
  height: 17px;
}

/* Stock status */

.single-product p.stock {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-family: var(--font-body);
  font-weight: 600;
  font-size: var(--fs-sm);
  margin: 0 0 var(--space-3);
}

.single-product p.stock::before {
  content: "";
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: currentColor;
}

.single-product p.stock.in-stock {
  color: var(--color-success);
}

.single-product p.stock.out-of-stock {
  color: var(--color-sale);
}

/* Quantity stepper + add to cart */

.single-product form.cart {
  display: flex;
  flex-wrap: wrap;
  align-items: stretch;
  gap: var(--space-3);
  margin: 0 0 var(--space-6);
}

/* Variable products print a variations table above the button; it needs the full
   row to itself rather than sitting beside the quantity field. */
.single-product form.cart .variations,
.single-product form.cart .woocommerce-variation-add-to-cart,
.single-product form.cart .woocommerce-variation-price {
  flex: 1 0 100%;
}

.single-product form.cart .quantity {
  margin: 0;
}

/* The stepper wrapper is printed by excavator_pro_quantity_stepper_before()/_after()
   from inside WooCommerce's own quantity-input template, so the <input> between the
   two buttons is still entirely core's (name, min/max/step, validation). */
.product-qty {
  display: flex;
  align-items: stretch;
  height: 100%;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-bg);
  overflow: hidden;
}

.product-qty__button {
  flex-shrink: 0;
  width: 40px;
  border: 0;
  background: transparent;
  color: var(--color-text);
  font-size: var(--fs-lg);
  line-height: 1;
  cursor: pointer;
  transition: background-color var(--duration-fast) var(--ease-feedback);
}

.product-qty__button:hover,
.product-qty__button:focus-visible {
  background: var(--color-bg-alt);
}

.single-product form.cart .quantity .qty,
.product-qty .qty {
  width: 3.25rem;
  height: auto;
  min-height: 52px;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: transparent;
  text-align: center;
  font-family: var(--font-body);
  font-weight: 600;
  font-size: var(--fs-base);
  color: var(--color-text);
  /* Firefox + WebKit spinners duplicate the -/+ buttons and crowd a 52px field. */
  -moz-appearance: textfield;
  appearance: textfield;
}

.product-qty .qty::-webkit-outer-spin-button,
.product-qty .qty::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}

.single-product .single_add_to_cart_button.button {
  /* Grows to fill the row beside the fixed-width stepper, so the primary action is
     always the widest target on the page. */
  flex: 1 1 200px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 52px;
  padding: var(--space-3) var(--space-8);
  font-size: var(--fs-base);
  letter-spacing: 0.04em;
}

/* Delivery timeline (excavator_pro_product_timeline()) */

.product-timeline {
  margin: 0 0 var(--space-6);
  padding: var(--space-6) var(--space-4);
  background: var(--color-bg-alt);
  border-radius: var(--radius-md);
}

.product-timeline__track {
  position: relative;
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  list-style: none;
  margin: 0;
  padding: 0;
  max-width: 460px;
  margin-inline: auto;
}

/* The connecting rule sits behind the icon circles. Inset by 15% at each end so
   it starts and stops under the first/last circle instead of poking out past them. */
.product-timeline__line {
  position: absolute;
  top: 24px;
  left: 15%;
  right: 15%;
  height: 2px;
  background: var(--color-border);
  z-index: 0;
}

.product-timeline__step {
  position: relative;
  z-index: 1;
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  padding: 0 var(--space-1);
  min-width: 0;
}

.product-timeline__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 48px;
  height: 48px;
  border-radius: 50%;
  background: var(--color-dark);
  color: var(--color-bg);
  margin-bottom: var(--space-2);
}

.product-timeline__icon svg {
  width: 22px;
  height: 22px;
}

.product-timeline__date {
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: var(--fs-sm);
  color: var(--color-text);
  line-height: 1.2;
}

.product-timeline__label {
  font-size: var(--fs-xs);
  font-weight: 600;
  color: var(--color-text-muted);
  line-height: 1.3;
}

@media (min-width: 480px) {
  .product-timeline__icon {
    width: 56px;
    height: 56px;
  }

  .product-timeline__icon svg {
    width: 26px;
    height: 26px;
  }

  .product-timeline__line {
    top: 28px;
  }

  .product-timeline__date {
    font-size: var(--fs-base);
  }

  .product-timeline__label {
    font-size: var(--fs-sm);
  }
}

/* Buyer testimonials (excavator_pro_product_testimonials()) */

.product-testimonials {
  margin: 0 0 var(--space-6);
  padding: var(--space-4) 0 0;
  border-top: 1px solid var(--color-border);
}

.product-testimonials__item {
  margin: 0;
  animation: product-testimonial-in var(--duration-base) var(--ease-entrance);
}

@keyframes product-testimonial-in {
  from {
    opacity: 0;
    transform: translateX(12px);
  }

  to {
    opacity: 1;
    transform: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  .product-testimonials__item {
    animation: none;
  }
}

.product-testimonials__quote {
  margin: 0 0 var(--space-3);
  padding: 0;
  border: 0;
  font-size: var(--fs-sm);
  line-height: 1.6;
  color: var(--color-text);
}

.product-testimonials__meta {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-3);
  padding-top: var(--space-3);
  border-top: 1px solid var(--color-border);
}

.product-testimonials__author {
  font-size: var(--fs-xs);
  font-style: italic;
  font-weight: 500;
  color: var(--color-text-muted);
}

.product-testimonials__company {
  font-style: normal;
}

.product-testimonials__stars {
  color: var(--color-warning);
  font-size: var(--fs-sm);
  letter-spacing: 0.08em;
  line-height: 1;
}

.product-testimonials__dots {
  display: flex;
  justify-content: center;
  gap: var(--space-2);
  margin-top: var(--space-3);
}

.product-testimonials__dot {
  width: 7px;
  height: 7px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: var(--color-border);
  cursor: pointer;
  transition: background-color var(--duration-fast) var(--ease-feedback);
}

.product-testimonials__dot.is-active {
  background: var(--color-accent);
}

/* Contact boxes (excavator_pro_product_contact_boxes()) */

.product-contact {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-2);
  margin: 0 0 var(--space-4);
}

@media (min-width: 480px) {
  .product-contact {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

.product-contact__box {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3);
  background: var(--color-bg-alt);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  text-decoration: none;
  min-width: 0;
  transition: border-color var(--duration-fast) var(--ease-feedback), box-shadow var(--duration-fast) var(--ease-feedback);
}

.product-contact__box:hover,
.product-contact__box:focus-visible {
  border-color: var(--color-accent);
  box-shadow: var(--shadow-card);
}

.product-contact__icon {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--color-accent);
}

.product-contact__icon svg {
  width: 20px;
  height: 20px;
}

.product-contact__text {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.product-contact__label {
  font-family: var(--font-heading);
  font-size: var(--fs-xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--color-text-muted);
  line-height: 1.2;
}

.product-contact__value {
  font-size: var(--fs-sm);
  font-weight: 700;
  color: var(--color-text);
  line-height: 1.3;
  overflow-wrap: break-word;
}

/* Meta (SKU / category), printed after the add-to-cart form */

.single-product .product_meta {
  margin-top: 0;
  padding-top: var(--space-4);
  border-top: 1px solid var(--color-border);
  color: var(--color-text-muted);
  font-size: var(--fs-sm);
}

.single-product .product_meta > span {
  display: block;
  margin-bottom: var(--space-1);
}

.single-product .product_meta a {
  color: var(--color-text-muted);
}

.single-product .product_meta a:hover,
.single-product .product_meta a:focus-visible {
  color: var(--color-accent);
}

/* -----------------------------------------------------------------------
 * 3. Specification panel (excavator_pro_single_product_spec_grid(), rendered inside
 *    the Description tab — see excavator_pro_description_tab_content()).
 * ----------------------------------------------------------------------- */

.excavator-spec-grid {
  position: relative;
  margin: var(--space-8) 0 0;
  padding: var(--space-6);
  background: var(--color-bg-alt);
  border: 1px solid var(--color-border);
  /* Accent edge rather than a full accent border: marks the panel as the page's
     reference data without turning it into a colored box. */
  border-left: 4px solid var(--color-accent);
  border-radius: var(--radius-md);
}

.excavator-spec-grid__title {
  font-family: var(--font-heading);
  font-size: var(--fs-xl);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--color-text);
  margin: 0 0 var(--space-4);
}

.excavator-spec-grid__list {
  display: grid;
  grid-template-columns: 1fr;
  margin: 0;
}

.excavator-spec-grid__row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--space-4);
  padding: var(--space-3) 0;
  border-bottom: 1px solid var(--color-border);
  /* Grid/flex items default to a min-width of their content's natural size,
     not 0 — without this, a row can refuse to shrink to fit its grid cell. */
  min-width: 0;
}

.excavator-spec-grid__label {
  margin: 0;
  color: var(--color-text-muted);
  font-family: var(--font-body);
  font-size: var(--fs-sm);
}

.excavator-spec-grid__value {
  margin: 0;
  color: var(--color-text);
  font-family: var(--font-body);
  font-weight: 600;
  font-size: var(--fs-sm);
  text-align: right;
  overflow-wrap: break-word;
}

/* auto-fit against a real track floor rather than a viewport media query: the panel now
   lives inside the ~600px product content column on desktop, where a hard 2-column rule
   would squeeze "Transport Dimensions / 146 x 63 x 96 in" into an unreadable row. This
   way it is one column when the panel is narrow and two when it has the width for it,
   whatever the viewport is doing. minmax(320px, 1fr) — not bare 1fr — because a bare
   1fr track's minimum is its content's natural width, so a long value could widen the
   grid past its container instead of wrapping. */
.excavator-spec-grid__list {
  grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
  column-gap: var(--space-8);
}

.excavator-spec-grid__row:last-child {
  border-bottom: none;
}

/* -----------------------------------------------------------------------
 * 3b. Product tabs, FAQ accordion, and related products
 * ----------------------------------------------------------------------- */

.woocommerce-tabs {
  margin-top: var(--space-12);
}

.woocommerce-tabs ul.tabs {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-6);
  list-style: none;
  margin: 0 0 var(--space-6);
  padding: 0 0 var(--space-1);
  border-bottom: 1px solid var(--color-border);
}

/* Core draws the tab list as grey rounded "folder" pills, complete with two 5px
   pseudo-element corner curves per tab and a full-width bottom rule of its own. The
   underline treatment below replaces all of it, so the chrome has to be removed rather
   than merely recoloured — otherwise the curves sit under the tabs as stray dots. */
.woocommerce div.product .woocommerce-tabs ul.tabs {
  padding: 0 0 var(--space-1);
  margin: 0 0 var(--space-6);
  overflow: visible;
}

.woocommerce div.product .woocommerce-tabs ul.tabs::before {
  display: none;
}

.woocommerce div.product .woocommerce-tabs ul.tabs li,
.woocommerce div.product .woocommerce-tabs ul.tabs li.active {
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: transparent;
}

.woocommerce div.product .woocommerce-tabs ul.tabs li::before,
.woocommerce div.product .woocommerce-tabs ul.tabs li::after {
  display: none;
}

.woocommerce div.product .woocommerce-tabs ul.tabs li a,
.woocommerce div.product .woocommerce-tabs ul.tabs li.active a {
  display: inline-block;
  padding-bottom: var(--space-3);
  font-family: var(--font-heading);
  font-weight: 600;
  font-size: var(--fs-lg);
  text-transform: uppercase;
  letter-spacing: 0.02em;
  color: var(--color-text-muted);
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
}

.woocommerce div.product .woocommerce-tabs ul.tabs li.active a,
.woocommerce div.product .woocommerce-tabs ul.tabs li a:hover,
.woocommerce div.product .woocommerce-tabs ul.tabs li a:focus-visible {
  color: var(--color-text);
  border-bottom-color: var(--color-accent);
}

.woocommerce-tabs .panel {
  max-width: 900px;
  color: var(--color-text);
  line-height: 1.8;
}

.woocommerce-tabs .panel h2,
.woocommerce-tabs .panel h3 {
  font-size: var(--fs-xl);
  text-transform: uppercase;
}

.woocommerce-tabs table.shop_attributes {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--fs-sm);
}

.woocommerce-tabs table.shop_attributes th,
.woocommerce-tabs table.shop_attributes td {
  padding: var(--space-3) var(--space-2);
  border-bottom: 1px solid var(--color-border);
  text-align: left;
}

.woocommerce-tabs table.shop_attributes th {
  width: 40%;
  font-family: var(--font-body);
  font-weight: 600;
  color: var(--color-text-muted);
}

/* FAQ accordion (excavator_pro_product_faq()). The .faq-item markup and its
   animation are shared with the homepage FAQ section — style.css owns the item
   styling and main.js's initFaqAccordion() already picks these up, so only the
   section wrapper needs rules here. */

/* The FAQ, logo strip and related products are hooked to
   woocommerce_after_single_product, so they render outside div.product (see section 9c
   of inc/product-page.php) and are plain full-width blocks, not grid items. */
.product-faq {
  margin-top: var(--space-12);
  padding-top: var(--space-12);
  border-top: 1px solid var(--color-border);
}

.product-faq__title {
  font-size: var(--fs-2xl);
  text-transform: uppercase;
  text-align: center;
  margin-bottom: var(--space-6);
}

.product-faq__list {
  max-width: 900px;
  margin-inline: auto;
}

/* -----------------------------------------------------------------------
 * 3d. "Recommended by Industry Leaders" logo strip
 *     (excavator_pro_product_industry_leaders(), rendered after div.product)
 * ----------------------------------------------------------------------- */

.industry-leaders {
  margin-top: var(--space-12);
  padding-top: var(--space-12);
  border-top: 1px solid var(--color-border);
}

/* Centred heading with a rule running out to each side. The rules are flex siblings of
   the text rather than a background gradient behind it, so they shrink to whatever the
   translated heading actually needs instead of being masked by a hardcoded width. */
.industry-leaders__title {
  display: flex;
  align-items: center;
  gap: var(--space-6);
  font-size: var(--fs-xl);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  text-align: center;
  margin: 0 0 var(--space-8);
  color: var(--color-text);
}

.industry-leaders__title::before,
.industry-leaders__title::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--color-border);
}

.industry-leaders__list {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: var(--space-8) var(--space-12);
  list-style: none;
  margin: 0;
  padding: 0;
}

/* Marquee. All of this is gated behind .is-marquee, which initIndustryLeadersMarquee()
   in main.js only adds once it has cloned the logos and measured the shift distance —
   so with JS off, reduced motion on, or the speed set to 0, the rules above stand and
   the strip stays a static centred row. */
.industry-leaders__viewport.is-marquee {
  overflow: hidden;
  /* Fades the logos out into the page at both ends instead of letting them appear and
     vanish against a hard edge mid-glyph. */
  -webkit-mask-image: linear-gradient(to right, transparent, #000 8%, #000 92%, transparent);
  mask-image: linear-gradient(to right, transparent, #000 8%, #000 92%, transparent);
}

.industry-leaders__viewport.is-marquee .industry-leaders__list {
  /* A marquee track must never wrap or centre — it is one long line that happens to be
     wider than its viewport. */
  flex-wrap: nowrap;
  justify-content: flex-start;
  width: max-content;
  animation: industry-leaders-scroll var(--marquee-duration, 30s) linear infinite;
}

/* Pause on hover so a visitor can actually look at a logo — and it pairs with the
   greyscale-to-colour hover on the logos themselves, which is unusable on a moving
   target. focus-within covers a keyboard user landing on one. */
.industry-leaders__viewport.is-marquee:hover .industry-leaders__list,
.industry-leaders__viewport.is-marquee:focus-within .industry-leaders__list {
  animation-play-state: paused;
}

.industry-leaders__viewport.is-marquee .industry-leaders__item {
  flex: 0 0 auto;
}

@keyframes industry-leaders-scroll {
  from {
    transform: translate3d(0, 0, 0);
  }

  to {
    /* Exactly one original set, so the first clone lands where the original started and
       the seam is invisible. main.js sets --marquee-shift from the measured width. */
    transform: translate3d(calc(-1 * var(--marquee-shift, 0px)), 0, 0);
  }
}

/* Belt and braces: main.js already bails on reduced motion, but if the preference is
   toggled after load the animation stops here too. */
@media (prefers-reduced-motion: reduce) {
  .industry-leaders__viewport.is-marquee .industry-leaders__list {
    animation: none;
  }
}

.industry-leaders__item {
  display: flex;
  align-items: center;
  justify-content: center;
}

/* Greyscale by default so a row of unrelated brand palettes reads as one quiet
   credibility band; full colour on hover. Also drops to ~55% opacity, because
   grayscale() alone still leaves a dark logo louder than a light one.
   Qualified as `.industry-leaders__item img.…` rather than the bare class because
   WooCommerce core ships `.woocommerce img, .woocommerce-page img { height: auto;
   max-width: 100% }` at (0,1,1) — a lone BEM class is (0,1,0) and loses to it, which
   left every logo rendering at its full intrinsic 300px. */
.industry-leaders__item img.industry-leaders__logo {
  display: block;
  width: auto;
  height: 38px;
  max-width: 170px;
  object-fit: contain;
  filter: grayscale(100%);
  opacity: 0.55;
  transition: filter var(--duration-base) var(--ease-entrance), opacity var(--duration-base) var(--ease-entrance);
}

.industry-leaders__item:hover img.industry-leaders__logo,
.industry-leaders__item:focus-within img.industry-leaders__logo {
  filter: grayscale(0%);
  opacity: 1;
}

/* Touch devices have no hover to reveal the colour, and a permanently greyed-out row
   reads as broken rather than deliberate there — so show the logos in colour outright. */
@media (hover: none) {
  .industry-leaders__item img.industry-leaders__logo {
    filter: none;
    opacity: 1;
  }
}

@media (prefers-reduced-motion: reduce) {
  .industry-leaders__item img.industry-leaders__logo {
    transition: none;
  }
}

@media (min-width: 640px) {
  .industry-leaders__item img.industry-leaders__logo {
    height: 46px;
    max-width: 200px;
  }
}

.related.products {
  margin-top: var(--space-12);
  padding-top: var(--space-12);
  border-top: 1px solid var(--color-border);
}

.related.products > h2 {
  font-size: var(--fs-2xl);
  margin-bottom: var(--space-6);
  text-align: center;
}

/* -----------------------------------------------------------------------
 * 3c. Mobile sticky add-to-cart bar (excavator_pro_sticky_add_to_cart()).
 *     Revealed by main.js once the real form.cart scrolls out of view; the button
 *     forwards its click to that form rather than being a second cart form.
 * ----------------------------------------------------------------------- */

.product-sticky-bar {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  z-index: 50;
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  /* Keeps the bar clear of the iOS home indicator / Android gesture bar. */
  padding-bottom: calc(var(--space-3) + env(safe-area-inset-bottom, 0px));
  background: var(--color-bg);
  border-top: 1px solid var(--color-border);
  box-shadow: 0 -4px 16px rgba(20, 22, 26, 0.1);
  transform: translateY(100%);
  transition: transform var(--duration-base) var(--ease-entrance);
}

.product-sticky-bar.is-visible {
  transform: none;
}

@media (prefers-reduced-motion: reduce) {
  .product-sticky-bar {
    transition: none;
  }
}

/* Desktop keeps the sticky gallery column instead; a fixed bottom bar there just
   covers content the visitor is trying to read. */
@media (min-width: 1024px) {
  .product-sticky-bar {
    display: none;
  }
}

.product-sticky-bar__info {
  display: flex;
  flex-direction: column;
  min-width: 0;
  flex: 1 1 auto;
}

.product-sticky-bar__name {
  font-size: var(--fs-xs);
  color: var(--color-text-muted);
  line-height: 1.2;
  /* One line only — the machine names on this store run long, and the bar must
     not grow tall enough to eat the viewport. */
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.product-sticky-bar__price {
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: var(--fs-lg);
  color: var(--color-text);
  line-height: 1.2;
}

.product-sticky-bar__price del {
  display: none;
}

.product-sticky-bar__price ins {
  text-decoration: none;
  color: var(--color-sale);
}

.product-sticky-bar__button {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-3) var(--space-4);
  font-size: var(--fs-sm);
}

.product-sticky-bar__button svg {
  width: 18px;
  height: 18px;
}

/* -----------------------------------------------------------------------
 * 4. Cart / checkout / my-account — CSS-only restyle of WooCommerce's default markup.
 *    No HTML structure is changed anywhere in this project for these pages; only
 *    WooCommerce's own default classes are targeted here.
 * ----------------------------------------------------------------------- */

.woocommerce-cart table.shop_table,
.woocommerce-checkout table.shop_table,
.woocommerce-account table.shop_table {
  width: 100%;
  border-collapse: collapse;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  overflow: hidden;
  font-family: var(--font-body);
  font-size: var(--fs-sm);
  color: var(--color-text);
}

.woocommerce table.shop_table th {
  background: var(--color-bg-alt);
  font-family: var(--font-heading);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  font-size: var(--fs-xs);
  color: var(--color-text-muted);
  padding: var(--space-3);
  text-align: left;
}

.woocommerce table.shop_table td {
  padding: var(--space-3);
  border-top: 1px solid var(--color-border);
}

.woocommerce table.shop_table tfoot th,
.woocommerce table.shop_table tfoot td {
  border-top: 1px solid var(--color-border);
  font-weight: 600;
}

.woocommerce td.product-name a {
  color: var(--color-text);
  font-weight: 500;
  text-decoration: none;
}

.woocommerce .quantity .qty {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  padding: var(--space-1) var(--space-2);
  font-family: var(--font-body);
  color: var(--color-text);
  background: var(--color-bg);
  width: 4rem;
}

.woocommerce .cart-collaterals .cart_totals,
.woocommerce-checkout #order_review {
  background: var(--color-bg-alt);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: var(--space-4) var(--space-6);
}

.woocommerce .cart-collaterals .cart_totals h2,
.woocommerce-checkout #order_review_heading {
  font-family: var(--font-heading);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  color: var(--color-text);
  font-size: var(--fs-lg);
  margin: 0 0 var(--space-4);
}

/* Buttons: primary CTA everywhere in the WooCommerce flow uses the brand accent color */

.woocommerce a.button,
.woocommerce button.button,
.woocommerce input.button,
.woocommerce #respond input#submit,
.woocommerce .checkout-button,
.woocommerce #place_order {
  display: inline-block;
  background: var(--color-accent);
  color: var(--color-bg);
  border: none;
  border-radius: var(--radius-sm);
  padding: var(--space-3) var(--space-6);
  font-family: var(--font-heading);
  font-weight: 600;
  font-size: var(--fs-sm);
  letter-spacing: 0.02em;
  text-transform: uppercase;
  text-decoration: none;
  cursor: pointer;
  transition: background 0.2s ease;
}

.woocommerce a.button:hover,
.woocommerce button.button:hover,
.woocommerce input.button:hover,
.woocommerce #respond input#submit:hover,
.woocommerce .checkout-button:hover,
.woocommerce #place_order:hover {
  background: var(--color-accent-dark);
  color: var(--color-bg);
}

.woocommerce a.button.alt,
.woocommerce button.button.alt,
.woocommerce input.button.alt {
  background: var(--color-text);
}

.woocommerce a.button.alt:hover,
.woocommerce button.button.alt:hover,
.woocommerce input.button.alt:hover {
  background: var(--color-dark);
}

.woocommerce a.remove {
  color: var(--color-sale) !important;
}

/* Forms: cart coupon, checkout billing/shipping fields, my-account edit-address/forms */

.woocommerce form .form-row label {
  font-family: var(--font-body);
  font-size: var(--fs-sm);
  color: var(--color-text-muted);
}

.woocommerce form .form-row input.input-text,
.woocommerce form .form-row textarea,
.woocommerce form .form-row select,
.woocommerce-page form .form-row input.input-text,
.woocommerce table.shop_table td select {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  padding: var(--space-2) var(--space-3);
  font-family: var(--font-body);
  font-size: var(--fs-base);
  color: var(--color-text);
  background: var(--color-bg);
  width: 100%;
}

.woocommerce form .form-row input.input-text:focus,
.woocommerce form .form-row textarea:focus,
.woocommerce form .form-row select:focus {
  outline: none;
  border-color: var(--color-accent);
}

.woocommerce-checkout .woocommerce-additional-fields,
.woocommerce-checkout .woocommerce-billing-fields,
.woocommerce-checkout .woocommerce-shipping-fields {
  margin-bottom: var(--space-6);
}

.woocommerce-checkout .woocommerce-billing-fields h3,
.woocommerce-checkout .woocommerce-shipping-fields h3,
.woocommerce-checkout .woocommerce-additional-fields h3 {
  font-family: var(--font-heading);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  font-size: var(--fs-lg);
  color: var(--color-text);
}

/* Coupon row on the cart page */

.woocommerce .cart .coupon {
  display: flex;
  gap: var(--space-2);
  align-items: center;
}

.woocommerce .cart .coupon .input-text {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  padding: var(--space-2) var(--space-3);
}

/* Notices (added-to-cart, errors, info) */

.woocommerce-message,
.woocommerce-info,
.woocommerce-error,
.woocommerce-noreviews {
  border-top-color: var(--color-accent);
  background: var(--color-bg-alt);
  color: var(--color-text);
  font-family: var(--font-body);
  font-size: var(--fs-sm);
  border-radius: var(--radius-sm);
  padding: var(--space-4);
}

.woocommerce-error {
  border-top-color: var(--color-sale);
}

.woocommerce-message::before,
.woocommerce-info::before {
  color: var(--color-accent);
}

.woocommerce-error::before {
  color: var(--color-sale);
}

/* My Account: nav + dashboard */

.woocommerce-account .woocommerce-MyAccount-navigation {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-bg-alt);
  padding: var(--space-2) 0;
  margin-bottom: var(--space-6);
}

.woocommerce-account .woocommerce-MyAccount-navigation ul {
  list-style: none;
  margin: 0;
  padding: 0;
}

.woocommerce-account .woocommerce-MyAccount-navigation li {
  border-bottom: 1px solid var(--color-border);
}

.woocommerce-account .woocommerce-MyAccount-navigation li:last-child {
  border-bottom: none;
}

.woocommerce-account .woocommerce-MyAccount-navigation li a {
  display: block;
  padding: var(--space-3) var(--space-4);
  color: var(--color-text-muted);
  font-family: var(--font-body);
  font-weight: 500;
  text-decoration: none;
}

.woocommerce-account .woocommerce-MyAccount-navigation li.is-active a,
.woocommerce-account .woocommerce-MyAccount-navigation li a:hover {
  color: var(--color-accent);
}

.woocommerce-account .woocommerce-MyAccount-content {
  font-family: var(--font-body);
  color: var(--color-text);
}

.woocommerce-account .addresses .title h3 {
  font-family: var(--font-heading);
  font-weight: 600;
  color: var(--color-text);
}

@media (min-width: 768px) {
  .woocommerce-account .woocommerce-MyAccount-navigation,
  .woocommerce-account .woocommerce-MyAccount-content {
    display: inline-block;
    vertical-align: top;
  }

  .woocommerce-account .woocommerce-MyAccount-navigation {
    width: 25%;
    margin-right: var(--space-6);
  }

  .woocommerce-account .woocommerce-MyAccount-content {
    width: calc(75% - var(--space-6));
  }
}

/* -----------------------------------------------------------------------
 * 4b. WooCommerce Blocks — Cart & Checkout
 *
 * This store's Cart and Checkout pages render the WooCommerce Cart/Checkout
 * BLOCKS (`wp-block-woocommerce-cart` / `wp-block-woocommerce-checkout`), not
 * the classic shortcode templates the rules above target — confirmed by
 * inspecting the live DOM (`.wc-block-cart-items`, `.wc-block-components-*`
 * throughout, no `table.shop_table` or `#place_order` present at all). Same
 * CSS-only constraint applies (docs/woocommerce-template-rules.md #4): no
 * template/block markup is overridden here, only WooCommerce Blocks' own
 * stable, documented component classes are styled. My Account is unaffected
 * (still classic) and keeps the rules above.
 * ----------------------------------------------------------------------- */

/* Shared button component: Proceed to Checkout, Place Order, and the
   quantity stepper's own +/- all use .wc-block-components-button under the
   hood, so this one rule covers all of them. */
.wc-block-components-button.wp-element-button {
  background: var(--color-accent);
  color: var(--color-bg);
  border: none;
  border-radius: var(--radius-sm);
  font-family: var(--font-heading);
  font-weight: 600;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  transition: background 0.2s ease;
}

.wc-block-components-button.wp-element-button:hover,
.wc-block-components-button.wp-element-button:focus-visible {
  background: var(--color-accent-dark);
  color: var(--color-bg);
}

.wc-block-components-checkout-place-order-button.wp-element-button,
.wc-block-cart__submit-button.wp-element-button {
  padding: var(--space-4) var(--space-6);
  font-size: var(--fs-base);
}

/* Cart line-items table */

.wc-block-cart-items {
  width: 100%;
  border-top: 1px solid var(--color-border);
}

/* Below WooCommerce Blocks' own "is-mobile" breakpoint, the total/price
   column (amount + "Save $X" badge, both `white-space: nowrap` in WC's own
   default CSS) demands more width than a 390px viewport has left after the
   product column — confirmed via computed getBoundingClientRect during
   verification: the column's right edge landed 13px past the viewport edge.
   Letting both wrap, and stacking the badge under the price instead of
   alongside it, is enough room to fit without touching the table's column
   sizing at all (table-layout: fixed was tried here first and rejected — it
   fought WC's own first-row-based column width calculation and collapsed
   the product thumbnail to 4px in testing). */
@media (max-width: 480px) {
  .wc-block-cart-item__total {
    white-space: normal;
  }

  .wc-block-cart-item__total-price-and-sale-badge-wrapper {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: var(--space-1);
  }

  .wc-block-components-product-badge.wc-block-components-sale-badge {
    white-space: normal;
  }
}

.wc-block-cart-items__header th {
  padding-bottom: var(--space-3);
  font-family: var(--font-heading);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  font-size: var(--fs-xs);
  color: var(--color-text-muted);
}

.wc-block-cart-items__row {
  border-bottom: 1px solid var(--color-border);
}

.wc-block-cart-items__row td {
  padding-block: var(--space-4);
}

.wc-block-cart-item__image img {
  border-radius: var(--radius-sm);
  background: var(--color-bg-alt);
}

.wc-block-components-product-name {
  font-family: var(--font-heading);
  font-weight: 600;
  font-size: var(--fs-base);
  color: var(--color-text);
  text-decoration: none;
}

.wc-block-components-product-name:hover,
.wc-block-components-product-name:focus-visible {
  color: var(--color-accent-dark);
}

.price.wc-block-components-product-price {
  font-family: var(--font-heading);
  font-weight: 600;
}

.wc-block-components-product-price__regular {
  color: var(--color-text-muted);
  font-weight: 400;
  opacity: 0.8;
}

.wc-block-components-product-price__value.is-discounted {
  color: var(--color-sale);
}

.wc-block-components-product-badge.wc-block-components-sale-badge {
  display: inline-block;
  margin-top: var(--space-1);
  padding: var(--space-1) var(--space-2);
  background: var(--color-accent-light);
  color: var(--color-accent-dark);
  border: none;
  border-radius: var(--radius-sm);
  font-family: var(--font-body);
  font-size: var(--fs-xs);
  font-weight: 600;
}

/* Quantity stepper: same bordered pill treatment as the classic `.qty` input above. */
.wc-block-components-quantity-selector {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  overflow: hidden;
}

.wc-block-components-quantity-selector__input {
  font-family: var(--font-body);
  color: var(--color-text);
}

.wc-block-components-quantity-selector__button {
  color: var(--color-text-muted);
}

.wc-block-components-quantity-selector__button:hover {
  color: var(--color-accent-dark);
}

.wc-block-cart-item__remove-link {
  color: var(--color-text-muted);
  transition: color 0.15s ease;
}

.wc-block-cart-item__remove-link:hover,
.wc-block-cart-item__remove-link:focus-visible {
  color: var(--color-sale);
}

/* Totals sidebar (cart) + order summary (checkout) — same "quiet panel"
   treatment as .cart_totals above: soft fill, no hard border, radius-lg to
   match the rest of the premium card language.
   `.wc-block-components-sidebar` is shared by both cart AND checkout (it's
   the checkout page's actual right-column wrapper, confirmed via computed
   DOM inspection: `.wc-block-components-sidebar.wc-block-checkout__sidebar`
   is the direct parent of `.wp-block-woocommerce-checkout-order-summary-block`)
   — so this one rule already panels the whole checkout sidebar. The inner
   order-summary block must NOT also get its own padding/background: its line
   items use an internal `display: table` layout (image/name/price as
   table-cell-like columns), and a second, nested layer of padding there
   double-compounds with the outer padding and starves that table of width —
   the product name column collapsed to single-character-per-line vertical
   text before this was caught in verification. */
.wc-block-components-sidebar {
  background: var(--color-bg-alt);
  border-radius: var(--radius-lg);
  padding: var(--space-6);
}

.wc-block-cart__totals-title,
.wc-block-components-order-summary__title,
.wp-block-woocommerce-checkout-order-summary-block .wc-block-components-title {
  font-family: var(--font-heading);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  font-size: var(--fs-lg);
  color: var(--color-text);
  margin-bottom: var(--space-4);
}

/* Checkout's order-summary line item packs image + name + price into one
   ~210px-wide row (the sidebar column at this viewport is narrow to begin
   with, and WooCommerce Blocks' own default CSS already spends some of that
   on internal padding before any of the rules above apply). Flexbox's
   default `flex: 0 1 auto` on the name column can get shrunk toward zero
   when its siblings' natural content width doesn't fit, and this component
   allows arbitrary mid-word breaks so a near-zero width renders as one
   character per line instead of wrapping normally — reproduced and confirmed
   during verification. `flex: 1 1 0%; min-width` guarantees the name column
   a sane floor and lets it wrap on word boundaries; the image and price
   columns give up the space instead, which is the correct trade-off since
   both tolerate it better (a smaller thumbnail; a price that wraps to 2
   lines, which it already does for "Save $X" beneath the amount). */
.wc-block-components-order-summary-item {
  flex-wrap: wrap;
  align-items: flex-start;
}

.wc-block-components-order-summary-item__description {
  flex: 1 1 0%;
  min-width: 70px;
}

.wc-block-components-order-summary-item__image {
  flex: 0 0 40px;
  width: 40px;
}

.wc-block-components-order-summary-item__image img {
  width: 40px;
  height: 40px;
}

/* Rather than squeeze into the same row as the image + name (there isn't
   room for all three at this sidebar width), the price wraps to its own
   full-width row beneath — plenty of space there for both the amount and
   the "Save $X" badge without truncating the product name. */
.wc-block-components-order-summary-item__total-price {
  flex: 1 0 100%;
  min-width: 0;
  margin-top: var(--space-1);
  padding-left: calc(40px + var(--space-2));
  text-align: left;
}

.wc-block-components-totals-item__label,
.wc-block-components-totals-item__value {
  font-family: var(--font-body);
  color: var(--color-text);
}

.wc-block-components-totals-footer-item .wc-block-components-totals-item__label,
.wc-block-components-totals-footer-item .wc-block-components-totals-item__value {
  font-family: var(--font-heading);
  font-weight: 600;
  font-size: var(--fs-lg);
  text-transform: uppercase;
  letter-spacing: 0.02em;
}

.wc-block-components-totals-wrapper {
  border-top: 1px solid var(--color-border);
  padding-top: var(--space-4);
  margin-top: var(--space-4);
}

/* Coupon / order-summary accordion panel */

.wc-block-components-panel__button {
  font-family: var(--font-body);
  font-weight: 600;
  color: var(--color-accent-dark);
}

.wc-block-components-panel__button-icon {
  color: currentColor;
}

/* Checkout steps */

.wc-block-components-checkout-step__title {
  font-family: var(--font-heading);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  font-size: var(--fs-lg);
  color: var(--color-text);
}

.wc-block-components-checkout-step__description {
  color: var(--color-text-muted);
  font-size: var(--fs-sm);
}

.wc-block-components-checkout-step {
  padding-bottom: var(--space-6);
  margin-bottom: var(--space-6);
  border-bottom: 1px solid var(--color-border);
}

/* Text inputs: WooCommerce Blocks floats the label via internal transforms
   on `.wc-block-components-text-input` (a wrapping <div>, not the <input>
   itself) — only border/radius/color are safe to touch here without
   fighting that positioning. */
.wc-block-components-text-input input,
.wc-block-components-text-input textarea,
.wc-block-components-dropdown-selector__button,
.wc-block-components-select-input .components-select-control__select {
  border-radius: var(--radius-sm) !important;
  font-family: var(--font-body);
}

.wc-block-components-text-input input:focus,
.wc-block-components-text-input.has-focus,
.wc-block-components-select-input.has-focus {
  outline: none;
}

.wc-block-components-text-input.has-focus,
.wc-block-components-select-input.has-focus {
  --wc-block-focus-color: var(--color-accent);
}

.wc-block-components-radio-control__label-group {
  font-family: var(--font-body);
}

.wc-block-components-radio-control__input:checked {
  accent-color: var(--color-accent);
}

/* Notices (e.g. "no payment methods available") */

.wc-block-components-notice-banner {
  border-radius: var(--radius-sm);
  font-family: var(--font-body);
}

.wc-block-components-notice-banner.is-error {
  border-left-color: var(--color-sale);
}

@media (min-width: 1024px) {
  .wc-block-components-sidebar-layout .wc-block-components-sidebar {
    padding: var(--space-6);
  }
}
