/*
Theme Name:   StoreOH Child
Theme URI:    https://storeoh.com
Description:  Child theme for StoreOH. Adds the marketplace layout, product card and brand styling on top of Astra. Everything here is CSS and hooks only, so pages stay fully editable in Elementor.
Author:       Sahal Shaikh
Author URI:   https://storeoh.com
Template:     astra
Version:      4.0.0
Text Domain:  storeoh-child
*/

/* ==========================================================================
   StoreOH — design tokens
   Change a value here and it updates everywhere. This is the only block you
   should need to edit for colour, spacing or density changes.
   ========================================================================== */

:root {
  /* Brand */
  --so-navy:        #102134;
  --so-navy-700:    #1B3149;
  --so-navy-500:    #2C4763;
  --so-orange:      #FE6A08;
  --so-orange-600:  #E55E05;
  --so-orange-50:   #FFF0E5;

  /* Neutrals */
  --so-ink:         #131A22;   /* body text */
  --so-grey-50:     #F7F8F9;
  --so-grey-100:    #F2F3F4;
  --so-grey-200:    #E8EAED;
  --so-grey-300:    #D9DCE0;
  --so-grey-600:    #6B7280;
  --so-white:       #FFFFFF;

  /* Status */
  --so-in-stock:    #067647;
  --so-low-stock:   #B45309;
  --so-error:       #B42318;

  /* Type */
  --so-font-display: "Poppins", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --so-font-body:    "Inter", system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;

  /* Density — the numbers that make it read as a marketplace */
  --so-container:   1500px;
  --so-grid-gap:    14px;
  --so-card-pad:    12px;
  --so-radius:      6px;
  --so-radius-sm:   4px;

  /* Elevation */
  --so-shadow-hover: 0 4px 16px rgba(16, 33, 52, .13);
}

/* ==========================================================================
   1. Base
   ========================================================================== */

body {
  font-family: var(--so-font-body);
  color: var(--so-ink);
  background: var(--so-grey-100);
}

h1, h2, h3, h4, h5, h6,
.site-title,
.elementor-heading-title {
  font-family: var(--so-font-display);
  letter-spacing: -0.01em;
}

/* Wider container than Astra's default — marketplaces run wide */
.ast-container,
.ast-container-fluid > .ast-container,
.site-content .ast-container {
  max-width: var(--so-container);
}

/* Content sits on white, page on grey — gives the store a card-on-canvas feel */
.woocommerce-page .site-content > .ast-container,
.archive .site-content > .ast-container,
.single-product .site-content > .ast-container {
  background: var(--so-white);
  border-radius: var(--so-radius);
  padding-top: 22px;
  padding-bottom: 30px;
}

a { text-decoration: none; }

/* Visible keyboard focus — do not remove */
a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
.button:focus-visible {
  outline: 2px solid var(--so-orange);
  outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; animation: none !important; }
}

/* ==========================================================================
   2. Header — sticky, search-led
   ========================================================================== */

.ast-primary-header-bar,
.ast-above-header-bar {
  background-color: var(--so-navy);
}

.ast-primary-header-bar .main-header-menu > .menu-item > .menu-link,
.ast-primary-header-bar .ast-header-html,
.ast-primary-header-bar .ast-builder-menu a {
  color: var(--so-white);
}

.ast-primary-header-bar .main-header-menu > .menu-item > .menu-link:hover {
  color: var(--so-orange);
}

/* Category bar directly beneath the main header */
.ast-below-header-bar {
  background-color: var(--so-navy-700);
  min-height: 42px;
}

.ast-below-header-bar .menu-link {
  color: var(--so-white);
  font-size: 13.5px;
  font-weight: 500;
}

.ast-below-header-bar .menu-link:hover { color: var(--so-orange); }

/* Search box in the header — wide, not an icon in the corner */
.ast-header-search .search-field,
.storeoh-search input[type="search"] {
  width: 100%;
  height: 42px;
  border: 0;
  border-radius: var(--so-radius);
  padding: 0 16px;
  font-size: 15px;
  font-family: var(--so-font-body);
  background: var(--so-white);
  color: var(--so-ink);
}

.ast-header-search .search-field::placeholder { color: var(--so-grey-600); }

/* Cart count badge */
.ast-cart-menu-wrap .ast-count,
.ast-addon-cart-wrap .ast-cart-menu-wrap .ast-count {
  background: var(--so-orange);
  color: var(--so-navy);
  font-weight: 700;
}

/* ==========================================================================
   3. Product grid — density over whitespace
   ========================================================================== */

.woocommerce ul.products,
.wc-block-grid__products {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: var(--so-grid-gap);
  margin: 0;
  padding: 0;
  list-style: none;
}

/* Neutralise the float/percentage widths WooCommerce and Astra apply */
.woocommerce ul.products li.product,
.woocommerce-page ul.products li.product {
  width: 100% !important;
  margin: 0 !important;
  float: none !important;
  clear: none !important;
}

@media (max-width: 1400px) { .woocommerce ul.products { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
@media (max-width: 1100px) { .woocommerce ul.products { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 760px)  { .woocommerce ul.products { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; } }

/* ==========================================================================
   4. The product card — the piece that carries the whole store
   ========================================================================== */

.woocommerce ul.products li.product {
  position: relative;
  display: flex;
  flex-direction: column;
  background: var(--so-white);
  border: 1px solid var(--so-grey-200);
  border-radius: var(--so-radius);
  padding: var(--so-card-pad);
  transition: box-shadow .15s ease, border-color .15s ease;
  text-align: left;
}

.woocommerce ul.products li.product:hover {
  border-color: var(--so-grey-300);
  box-shadow: var(--so-shadow-hover);
}

/* Image — square, contained, never cropped */
.woocommerce ul.products li.product a img {
  aspect-ratio: 1 / 1;
  object-fit: contain;
  width: 100%;
  height: auto;
  background: var(--so-white);
  margin: 0 0 10px;
  border-radius: var(--so-radius-sm);
}

/* Title — two lines, then ellipsis. CJ titles are long and unruly. */
.woocommerce ul.products li.product .woocommerce-loop-product__title {
  font-family: var(--so-font-body);
  font-size: 13.5px;
  line-height: 1.4;
  font-weight: 400;
  color: var(--so-ink);
  margin: 0 0 6px;
  padding: 0;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  min-height: 2.8em;
}

.woocommerce ul.products li.product a:hover .woocommerce-loop-product__title {
  color: var(--so-orange-600);
}

/* Price — orange only when it is a deal, so orange stays a signal */
.woocommerce ul.products li.product .price {
  font-family: var(--so-font-display);
  font-size: 19px;
  font-weight: 600;
  color: var(--so-ink);
  margin: 0 0 4px;
  line-height: 1.25;
  display: block;
}

.woocommerce ul.products li.product .price ins {
  text-decoration: none;
  color: var(--so-orange);
  font-weight: 700;
}

.woocommerce ul.products li.product .price del {
  font-size: 13px;
  font-weight: 400;
  color: var(--so-grey-600);
  opacity: 1;
  margin-left: 6px;
}

/* Shipping and stock lines — added by functions.php */
.so-card-meta {
  font-size: 12px;
  line-height: 1.5;
  color: var(--so-grey-600);
  margin: 0 0 10px;
}

.so-card-meta .so-instock { color: var(--so-in-stock); font-weight: 500; }
.so-card-meta .so-lowstock { color: var(--so-low-stock); font-weight: 500; }
.so-card-meta .so-ship { display: block; }

/* Push the button to the bottom so cards line up regardless of title length.

   Orange outline, no fill. The border carries the accent so the button is
   visible without twenty solid blocks flattening the grid, and the price stays
   the loudest thing on the card. It fills orange on hover.

   The label is navy at rest and white on the navy hover fill. Orange on white
   measures 2.8:1 and white on orange 2.8:1, both of which fail at this size,
   so neither is used for text. The orange lives in the border, where contrast
   rules do not apply.

   Related products, up-sells and cross-sells use the same markup, so they pick
   this up without a second rule. */
.woocommerce ul.products li.product .button,
.woocommerce ul.products li.product .added_to_cart,
.woocommerce .related ul.products li.product .button,
.woocommerce .up-sells ul.products li.product .button,
.woocommerce .cross-sells ul.products li.product .button {
  margin-top: auto;
  width: 100%;
  text-align: center;
  background: transparent;
  color: var(--so-navy);
  border: 1.5px solid var(--so-orange);
  border-radius: 999px;
  font-family: var(--so-font-body);
  font-size: 13.5px;
  font-weight: 600;
  letter-spacing: 0;
  padding: 9px 14px;
  box-shadow: none;
  transition: background .15s ease, border-color .15s ease, color .15s ease;
}

.woocommerce ul.products li.product .button:hover,
.woocommerce ul.products li.product .added_to_cart:hover,
.woocommerce ul.products li.product .button:focus-visible {
  background: var(--so-navy);
  border-color: var(--so-navy);
  color: var(--so-white);
}

/* Once something is in the cart the state should be obvious, so that one goes
   solid. It is the only filled button in the grid, which is the point. */
.woocommerce ul.products li.product .button.added {
  background: var(--so-orange);
  border-color: var(--so-orange);
  color: var(--so-navy);
}

.woocommerce ul.products li.product .added_to_cart {
  margin-top: 6px;
  border-style: dashed;
  font-weight: 500;
}

/* Savings flag — navy on orange, which is the accessible pairing */
.woocommerce span.onsale,
.so-save-badge {
  position: absolute;
  top: 10px;
  left: 10px;
  z-index: 2;
  background: var(--so-orange);
  color: var(--so-navy);
  font-family: var(--so-font-display);
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: .02em;
  line-height: 1;
  padding: 5px 8px;
  border-radius: var(--so-radius-sm);
  min-height: 0;
  min-width: 0;
  margin: 0;
}

/* ==========================================================================
   5. Buttons — MOVED
   ========================================================================== */

/* The button rules that used to live here filled orange at rest and were
   superseded by section 28, which covers every button on the site in one
   place. They were left in for a while and did nothing except get edited by
   mistake, so they are gone.

   Every button rule belongs in section 28. Nowhere else. */

/* ==========================================================================
   6. Shop and category pages
   ========================================================================== */

.woocommerce .woocommerce-result-count,
.woocommerce .woocommerce-ordering {
  font-size: 13px;
  color: var(--so-grey-600);
  margin-bottom: 14px;
}

.woocommerce .woocommerce-ordering select {
  font-size: 13px;
  border: 1px solid var(--so-grey-300);
  border-radius: var(--so-radius-sm);
  padding: 6px 10px;
  background: var(--so-white);
}

/* Filter sidebar */
.woocommerce .widget-area .widget,
.woocommerce-page .widget-area .widget {
  background: var(--so-white);
  border: 1px solid var(--so-grey-200);
  border-radius: var(--so-radius);
  padding: 14px 16px;
  margin-bottom: 14px;
}

.woocommerce .widget-area .widget-title {
  font-family: var(--so-font-display);
  font-size: 14px;
  font-weight: 600;
  color: var(--so-navy);
  margin: 0 0 10px;
  padding: 0 0 8px;
  border-bottom: 1px solid var(--so-grey-200);
}

.woocommerce .widget-area .widget ul { margin: 0; padding: 0; list-style: none; }

.woocommerce .widget-area .widget ul li {
  font-size: 13.5px;
  line-height: 1.9;
  border: 0;
  padding: 0;
}

.woocommerce .widget-area .widget ul li a { color: var(--so-ink); }
.woocommerce .widget-area .widget ul li a:hover { color: var(--so-orange-600); }

/* Category header block */
.woocommerce .page-title,
.woocommerce-products-header__title {
  font-family: var(--so-font-display);
  font-size: 24px;
  font-weight: 600;
  color: var(--so-navy);
  margin-bottom: 4px;
}

/* Breadcrumbs */
.woocommerce .woocommerce-breadcrumb {
  font-size: 12.5px;
  color: var(--so-grey-600);
  margin: 0 0 14px;
  padding: 0;
}

.woocommerce .woocommerce-breadcrumb a { color: var(--so-grey-600); }
.woocommerce .woocommerce-breadcrumb a:hover { color: var(--so-orange-600); }

/* Pagination */
.woocommerce nav.woocommerce-pagination ul {
  border: 0;
  margin-top: 26px;
}

.woocommerce nav.woocommerce-pagination ul li {
  border: 0;
  margin: 0 3px;
}

.woocommerce nav.woocommerce-pagination ul li a,
.woocommerce nav.woocommerce-pagination ul li span {
  border: 1px solid var(--so-grey-300);
  border-radius: var(--so-radius-sm);
  padding: 7px 13px;
  font-size: 13.5px;
  color: var(--so-ink);
}

.woocommerce nav.woocommerce-pagination ul li span.current {
  background: var(--so-navy);
  border-color: var(--so-navy);
  color: var(--so-white);
}

/* ==========================================================================
   7. Single product — gallery left, buy box right
   ========================================================================== */

.single-product div.product .product_title {
  font-family: var(--so-font-display);
  font-size: 25px;
  font-weight: 600;
  line-height: 1.3;
  color: var(--so-ink);
  margin-bottom: 10px;
}

.single-product div.product .summary .price {
  font-family: var(--so-font-display);
  font-size: 28px;
  font-weight: 700;
  color: var(--so-ink);
  margin-bottom: 14px;
}

.single-product div.product .summary .price ins {
  text-decoration: none;
  color: var(--so-orange);
}

.single-product div.product .summary .price del {
  font-size: 17px;
  font-weight: 400;
  color: var(--so-grey-600);
  opacity: 1;
}

/* The buy box used to be drawn here, around form.cart. It now lives in section
   23 as .so-buy, and this rule was drawing a second bordered box inside that
   one. Removed rather than tuned: there should be one panel, not a box in a
   box. */

.single-product div.product .stock.in-stock {
  color: var(--so-in-stock);
  font-weight: 500;
  font-size: 14px;
}

.single-product .woocommerce-tabs ul.tabs {
  border-bottom: 1px solid var(--so-grey-200);
  padding: 0;
  margin: 30px 0 0;
}

.single-product .woocommerce-tabs ul.tabs::before { border: 0; }

.single-product .woocommerce-tabs ul.tabs li {
  background: transparent;
  border: 0;
  border-radius: 0;
  margin: 0 18px 0 0;
  padding: 0;
}

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

.single-product .woocommerce-tabs ul.tabs li a {
  font-family: var(--so-font-display);
  font-size: 14px;
  font-weight: 500;
  color: var(--so-grey-600);
  padding: 10px 0;
  display: block;
}

.single-product .woocommerce-tabs ul.tabs li.active a {
  color: var(--so-navy);
  box-shadow: inset 0 -2px 0 var(--so-orange);
}

.single-product .related > h2,
.single-product .upsells > h2 {
  font-family: var(--so-font-display);
  font-size: 19px;
  font-weight: 600;
  color: var(--so-navy);
  margin-bottom: 14px;
}

/* ==========================================================================
   8. Cart and checkout — short, plain, no flourishes
   ========================================================================== */

.woocommerce table.shop_table {
  border: 1px solid var(--so-grey-200);
  border-radius: var(--so-radius);
  border-collapse: separate;
}

.woocommerce table.shop_table th {
  font-family: var(--so-font-display);
  font-size: 13px;
  font-weight: 600;
  color: var(--so-navy);
  background: var(--so-grey-50);
}

.woocommerce table.shop_table td { font-size: 14px; }

.woocommerce-checkout #payment {
  background: var(--so-grey-50);
  border: 1px solid var(--so-grey-200);
  border-radius: var(--so-radius);
}

.woocommerce-checkout #payment div.payment_box {
  background: var(--so-white);
  border: 1px solid var(--so-grey-200);
}

.woocommerce-checkout #payment div.payment_box::before { display: none; }

.woocommerce form .form-row input.input-text,
.woocommerce form .form-row textarea,
.woocommerce form .form-row select,
.select2-container .select2-selection--single {
  border: 1px solid var(--so-grey-300);
  border-radius: var(--so-radius-sm);
  padding: 10px 12px;
  font-size: 14px;
  height: auto;
}

/* Trust line under the pay button — added by functions.php */
.so-checkout-trust {
  font-size: 12.5px;
  color: var(--so-grey-600);
  text-align: center;
  margin-top: 12px;
  line-height: 1.6;
}

/* Notices */
.woocommerce-message,
.woocommerce-info {
  border-top-color: var(--so-orange);
  background: var(--so-orange-50);
  font-size: 14px;
}

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

/* ==========================================================================
   9. Homepage category blocks — four thumbnails and a link, Amazon style
   Use these classes from an Elementor HTML widget, or with the shortcode
   in functions.php.
   ========================================================================== */

.so-cat-block {
  background: var(--so-white);
  border-radius: var(--so-radius);
  padding: 16px;
  height: 100%;
  display: flex;
  flex-direction: column;
}

.so-cat-block__title {
  font-family: var(--so-font-display);
  font-size: 17px;
  font-weight: 600;
  color: var(--so-navy);
  margin: 0 0 12px;
}

.so-cat-block__grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 10px;
  margin-bottom: 12px;
}

.so-cat-block__item img {
  width: 100%;
  aspect-ratio: 1 / 1;
  object-fit: contain;
  background: var(--so-grey-50);
  border-radius: var(--so-radius-sm);
  display: block;
}

.so-cat-block__label {
  font-size: 11.5px;
  color: var(--so-grey-600);
  margin-top: 4px;
  display: -webkit-box;
  -webkit-line-clamp: 1;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.so-cat-block__more {
  margin-top: auto;
  font-size: 13.5px;
  font-weight: 500;
  color: var(--so-orange-600);
}

.so-cat-block__more:hover { text-decoration: underline; }

/* ==========================================================================
   10. Footer
   ========================================================================== */

.site-footer,
.ast-small-footer {
  background: var(--so-navy);
  color: var(--so-grey-300);
}

.site-footer a,
.ast-small-footer a { color: var(--so-grey-300); }
.site-footer a:hover,
.ast-small-footer a:hover { color: var(--so-orange); }

/* ==========================================================================
   11. Mobile
   ========================================================================== */

@media (max-width: 760px) {
  .woocommerce ul.products li.product { padding: 9px; }

  .woocommerce ul.products li.product .woocommerce-loop-product__title {
    font-size: 12.5px;
    min-height: 2.7em;
  }

  .woocommerce ul.products li.product .price { font-size: 16px; }

  .woocommerce ul.products li.product .button { font-size: 12.5px; padding: 8px 10px; }

  .single-product div.product .product_title { font-size: 20px; }
  .single-product div.product .summary .price { font-size: 23px; }

  .woocommerce-page .site-content > .ast-container,
  .archive .site-content > .ast-container,
  .single-product .site-content > .ast-container {
    padding-left: 12px;
    padding-right: 12px;
  }

  .so-cat-block { padding: 12px; }
}

/* ==========================================================================
   12. Header — search, cart, account, category nav
   ========================================================================== */

.so-search {
  display: flex;
  align-items: stretch;
  width: 100%;
  background: var(--so-white);
  border-radius: var(--so-radius);
  overflow: hidden;
  border: 2px solid transparent;
  transition: border-color .15s ease;
}

.so-search:focus-within { border-color: var(--so-orange); }

.so-search__cat {
  flex: 0 0 auto;
  border: 0;
  border-right: 1px solid var(--so-grey-300);
  background: var(--so-grey-100);
  color: var(--so-ink);
  font-family: var(--so-font-body);
  font-size: 12.5px;
  font-weight: 500;
  padding: 0 26px 0 12px;
  max-width: 160px;
  height: 42px;
  cursor: pointer;
  outline: none;
  border-radius: 0;
  -webkit-appearance: none;
  appearance: none;
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%236B7280'%3E%3Cpath d='M7 10l5 5 5-5z'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 4px center;
  background-size: 18px;
}

.so-search__field {
  flex: 1 1 auto;
  border: 0;
  outline: none;
  height: 42px;
  padding: 0 14px;
  font-family: var(--so-font-body);
  font-size: 14.5px;
  color: var(--so-ink);
  background: var(--so-white);
  min-width: 0;
}

.so-search__field::placeholder { color: var(--so-grey-600); }

.so-search__btn {
  flex: 0 0 auto;
  width: 54px;
  border: 0;
  background: var(--so-orange);
  color: var(--so-navy);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  transition: background .15s ease;
}

.so-search__btn:hover { background: var(--so-orange-600); }

.so-search__btn svg {
  width: 21px;
  height: 21px;
  display: block;
  fill: currentColor;
}

/* --- Cart --- */
.so-cart {
  display: inline-flex;
  align-items: flex-end;
  gap: 7px;
  color: var(--so-white);
  line-height: 1;
  padding: 6px 8px;
  border-radius: var(--so-radius-sm);
  border: 1px solid transparent;
  white-space: nowrap;
}

.so-cart:hover { color: var(--so-white); border-color: rgba(255, 255, 255, .35); }
.so-cart__icon { position: relative; display: inline-flex; }

.so-cart__count {
  position: absolute;
  top: -6px;
  right: -8px;
  min-width: 19px;
  height: 19px;
  padding: 0 5px;
  border-radius: 999px;
  background: var(--so-orange);
  color: var(--so-navy);
  font-family: var(--so-font-display);
  font-size: 11.5px;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
}

.so-cart__label { font-family: var(--so-font-display); font-size: 13.5px; font-weight: 600; }

/* --- Account --- */
.so-account {
  display: inline-flex;
  flex-direction: column;
  gap: 2px;
  color: var(--so-white);
  line-height: 1.25;
  padding: 5px 8px;
  border-radius: var(--so-radius-sm);
  border: 1px solid transparent;
  white-space: nowrap;
}

.so-account:hover { color: var(--so-white); border-color: rgba(255, 255, 255, .35); }
.so-account__top { font-size: 11.5px; color: var(--so-grey-300); }
.so-account__main { font-family: var(--so-font-display); font-size: 13.5px; font-weight: 600; }

/* --- Category navigation --- */
.so-catnav {
  display: flex;
  align-items: center;
  gap: 2px;
  overflow-x: auto;
  scrollbar-width: none;
  -ms-overflow-style: none;
}

.so-catnav::-webkit-scrollbar { display: none; }

.so-catnav__item {
  flex: 0 0 auto;
  font-family: var(--so-font-body);
  font-size: 13px;
  font-weight: 500;
  color: var(--so-white);
  padding: 8px 11px;
  border-radius: var(--so-radius-sm);
  border: 1px solid transparent;
  white-space: nowrap;
}

.so-catnav__item:hover { color: var(--so-white); border-color: rgba(255, 255, 255, .4); }
.so-catnav__item--all { font-weight: 600; }

/* Account icon: hidden on desktop, the only thing shown on mobile */
.so-account__icon { display: none; }

/* --- Hamburger toggle: mobile only, opens the drawer --- */
.so-menu-toggle {
  display: none;
  align-items: center;
  gap: 7px;
  padding: 8px 6px;
  margin-left: -6px;
  min-height: 40px;
  background: none;
  border: 0;
  color: var(--so-white);
  cursor: pointer;
}

.so-menu-toggle__bars {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 4px;
  width: 21px;
}

.so-menu-toggle__bars span {
  display: block;
  height: 2px;
  border-radius: 2px;
  background: currentColor;
}

.so-menu-toggle__label {
  font-family: var(--so-font-display);
  font-size: 14px;
  font-weight: 600;
}

@media (max-width: 1100px) {
  .so-search__cat { display: none; }
  .so-account__top { display: none; }
}

/* --------------------------------------------------------------------------
   Mobile header — Amazon layout
   Row 1: logo + account + cart      Row 2: search      Row 3: category scroll
   Driven by the classes on the Elementor containers, so desktop is untouched.
   -------------------------------------------------------------------------- */

@media (max-width: 767px) {

  /* announcement strip */
  .so-hdr-announce { padding: 5px 12px !important; }
  .so-announce { font-size: 11px; line-height: 1.35; gap: 0 6px; }
  .so-announce__item--3,
  .so-announce__sep--2 { display: none; }

  /* main bar wraps into two rows */
  .so-hdr-main {
    flex-wrap: wrap !important;
    padding: 7px 12px !important;
    gap: 8px !important;
    row-gap: 8px !important;
    column-gap: 8px !important;
    align-items: center !important;
  }

  /* hamburger and logo share row 1, left side */
  .so-hdr-logo {
    width: auto !important;
    flex: 0 0 auto !important;
    order: 1;
    padding: 0 !important;
    gap: 10px !important;
  }

  .so-menu-toggle { display: inline-flex; }

  /* the toggle widget must not stretch, whatever the container alignment */
  .so-hdr-menu-widget {
    width: auto !important;
    flex: 0 0 auto !important;
  }

  .so-hdr-logo img,
  .so-hdr-logo .elementor-widget-theme-site-logo img {
    max-height: 34px !important;
    width: auto !important;
    max-width: 132px !important;
    object-fit: contain;
  }

  .so-hdr-actions {
    width: auto !important;
    flex: 1 1 auto !important;
    order: 2;
    justify-content: flex-end !important;
    gap: 4px !important;
    padding: 0 !important;
  }

  .so-hdr-search {
    width: 100% !important;
    flex: 0 0 100% !important;
    order: 3;
    padding: 0 !important;
  }

  /* account collapses to a single icon */
  .so-account { flex-direction: row; padding: 6px; gap: 0; }
  .so-account__icon { display: inline-flex; }
  .so-account__main { display: none; }

  /* cart keeps the badge, drops the word */
  .so-cart { padding: 6px; gap: 0; }
  .so-cart__label { display: none; }
  .so-cart__icon svg { width: 24px; height: 24px; }
  .so-cart__count { top: -5px; right: -7px; min-width: 17px; height: 17px; font-size: 11px; }

  /* search bar sized for touch, 16px stops iOS zooming on focus */
  .so-search { border-radius: 6px; }
  .so-search__field { height: 40px; font-size: 16px; padding: 0 12px; }
  .so-search__btn { width: 48px; }
  .so-search__btn svg { width: 19px; height: 19px; }

  /* category row scrolls horizontally, edge to edge */
  .so-hdr-cats { padding: 0 !important; position: relative; }
  .so-catnav { padding: 0 12px; gap: 0; }
  .so-catnav__item { font-size: 12.5px; padding: 9px 10px; }

  /* fade at the right edge, so it reads as scrollable rather than cut off */
  .so-hdr-cats::after {
    content: "";
    position: absolute;
    inset: 0 0 0 auto;
    width: 30px;
    background: linear-gradient(90deg, rgba(27, 49, 73, 0), var(--so-navy-700));
    pointer-events: none;
  }

  /* stop the sticky header eating the screen */
  .elementor-location-header { position: relative; }
}

@media (max-width: 380px) {
  .so-hdr-logo img { max-height: 30px !important; max-width: 116px !important; }
  .so-announce { font-size: 10.5px; }
  .so-announce__item--2,
  .so-announce__sep { display: none; }
  .so-cart__label,
  .so-account__main { display: none; }
}

/* ==========================================================================
   12b. Mobile navigation drawer
   Printed on wp_footer at body level, not inside the header — a fixed panel
   nested in the header gets clipped, and turns unusable once sticky is on.
   ========================================================================== */

.so-drawer-root {
  --so-drawer-w: min(84vw, 360px);
  position: fixed;
  inset: 0;
  z-index: 99999;
}

.so-drawer-root[hidden] { display: none; }

.so-drawer__scrim {
  position: absolute;
  inset: 0;
  background: rgba(19, 26, 34, .62);
  opacity: 0;
  transition: opacity .22s ease;
}

.so-drawer {
  position: absolute;
  top: 0;
  left: 0;
  bottom: 0;
  display: flex;
  flex-direction: column;
  width: var(--so-drawer-w);
  background: var(--so-white);
  transform: translateX(-100%);
  transition: transform .26s cubic-bezier(.2, .7, .3, 1);
  box-shadow: 0 0 30px rgba(16, 33, 52, .32);
  outline: none;
}

.so-drawer-root.is-open .so-drawer__scrim { opacity: 1; }
.so-drawer-root.is-open .so-drawer { transform: none; }

/* --- head --- */
.so-drawer__head {
  flex: 0 0 auto;
  background: var(--so-navy);
  color: var(--so-white);
  padding: 12px 20px 18px;
}

.so-drawer__account {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 8px;
  min-height: 40px;
  color: var(--so-white);
  font-family: var(--so-font-display);
  font-size: 13.5px;
  font-weight: 600;
}

.so-drawer__account:hover { color: var(--so-orange); }
.so-drawer__account-icon { display: inline-flex; }

.so-drawer__title { margin: 2px 0 0; line-height: 1.12; }

.so-drawer__title span {
  display: block;
  font-family: var(--so-font-display);
  font-size: 17px;
  font-weight: 600;
  color: var(--so-grey-300);
}

.so-drawer__title strong {
  display: block;
  font-family: var(--so-font-display);
  font-size: 26px;
  font-weight: 700;
  letter-spacing: -0.01em;
}

/* --- body --- */
.so-drawer__body {
  flex: 1 1 auto;
  overflow-y: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
}

.so-drawer__section + .so-drawer__section { border-top: 9px solid var(--so-grey-100); }

.so-drawer__heading {
  margin: 0;
  padding: 16px 20px 4px;
  font-family: var(--so-font-display);
  font-size: 17px;
  font-weight: 700;
  color: var(--so-ink);
}

.so-drawer__list { margin: 0; padding: 0 0 8px; list-style: none; }
.so-drawer__list li { margin: 0; }

.so-drawer__link {
  display: block;
  padding: 13px 20px;
  min-height: 48px;
  font-size: 15px;
  color: var(--so-ink);
}

.so-drawer__link:hover,
.so-drawer__link:focus { background: var(--so-grey-100); color: var(--so-ink); }

.so-drawer__link--lead {
  font-family: var(--so-font-display);
  font-size: 17px;
  font-weight: 700;
  padding: 16px 20px;
}

.so-drawer__list li.is-folded { display: none; }
.so-drawer__list.is-expanded li.is-folded { display: block; }

.so-drawer__more {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 12px 20px 18px;
  min-height: 48px;
  background: none;
  border: 0;
  font-family: var(--so-font-body);
  font-size: 15px;
  color: var(--so-ink);
  cursor: pointer;
}

.so-drawer__more svg { transition: transform .18s ease; }
.so-drawer__more.is-expanded svg { transform: rotate(180deg); }

/* --- close, sitting on the scrim beside the panel --- */
.so-drawer__close {
  position: absolute;
  top: 6px;
  left: var(--so-drawer-w);
  width: 52px;
  height: 52px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: none;
  border: 0;
  color: var(--so-white);
  cursor: pointer;
  opacity: 0;
  transition: opacity .22s ease .06s;
}

.so-drawer-root.is-open .so-drawer__close { opacity: 1; }

/* Desktop never sees it, but belt and braces if the class is left on a widget */
@media (min-width: 768px) {
  .so-drawer-root { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .so-drawer,
  .so-drawer__scrim,
  .so-drawer__close,
  .so-drawer__more svg { transition: none; }
}

/* --- focus ring across the header and drawer --- */
.elementor-location-header a:focus-visible,
.elementor-location-header button:focus-visible,
.elementor-location-header input:focus-visible,
.elementor-location-header select:focus-visible,
.so-drawer a:focus-visible,
.so-drawer button:focus-visible {
  outline: 2px solid var(--so-orange);
  outline-offset: 2px;
}

/* ==========================================================================
   13. Hero carousel
   ========================================================================== */

.so-hero {
  position: relative;
  width: 100%;
  overflow: hidden;
  background: var(--so-grey-100);
  line-height: 0;
}

.so-hero__track { position: relative; width: 100%; }

.so-hero__slide {
  display: block;
  width: 100%;
  opacity: 0;
  visibility: hidden;
  transition: opacity .5s ease;
}

.so-hero__slide:first-child { position: relative; }

.so-hero__slide:not(:first-child) {
  position: absolute;
  inset: 0;
}

.so-hero__slide.is-active { opacity: 1; visibility: visible; z-index: 1; }

.so-hero__slide img {
  width: 100%;
  height: auto;
  display: block;
}

/* Arrows */
.so-hero__nav {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: 3;
  width: 42px;
  height: 74px;
  border: 0;
  border-radius: var(--so-radius);
  background: rgba(255, 255, 255, .72);
  color: var(--so-navy);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  transition: background .15s ease;
}

.so-hero__nav:hover { background: rgba(255, 255, 255, .95); }
.so-hero__nav svg { width: 22px; height: 22px; fill: currentColor; }
.so-hero__nav--prev { left: 14px; }
.so-hero__nav--next { right: 14px; }

/* Dots */
.so-hero__dots {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 14px;
  z-index: 3;
  display: flex;
  justify-content: center;
  gap: 7px;
  line-height: 0;
}

.so-hero__dot {
  width: 9px;
  height: 9px;
  padding: 0;
  border: 0;
  border-radius: 999px;
  background: rgba(16, 33, 52, .28);
  cursor: pointer;
  transition: background .15s ease, width .15s ease;
}

.so-hero__dot.is-active { background: var(--so-navy); width: 24px; }

@media (max-width: 767px) {
  .so-hero__nav { display: none; }
  .so-hero__dots { bottom: 10px; }
}

/* ==========================================================================
   14. Card grid — the white cards that overlap the hero
   ========================================================================== */

.so-cards {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 16px;
  align-items: stretch;
}

.so-cards--overlap {
  position: relative;
  z-index: 2;
  margin-top: -78px;
}

.so-card {
  background: var(--so-white);
  border-radius: var(--so-radius);
  border: 1px solid var(--so-grey-200);
  padding: 16px;
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.so-card__title {
  font-family: var(--so-font-display);
  font-size: 17px;
  font-weight: 600;
  line-height: 1.3;
  color: var(--so-navy);
  margin: 0 0 13px;
}

.so-card__quad {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px;
  margin-bottom: 13px;
}

.so-card__quad-item { display: block; color: var(--so-ink); min-width: 0; }

.so-card__quad-img {
  display: block;
  background: var(--so-grey-50);
  border-radius: var(--so-radius-sm);
  overflow: hidden;
}

.so-card__quad-img img {
  width: 100%;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  display: block;
  transition: transform .25s ease;
}

.so-card__quad-item:hover .so-card__quad-img img { transform: scale(1.04); }

.so-card__quad-label {
  display: -webkit-box;
  -webkit-line-clamp: 1;
  -webkit-box-orient: vertical;
  overflow: hidden;
  font-size: 12px;
  line-height: 1.4;
  color: var(--so-grey-600);
  margin-top: 6px;
}

.so-card__quad-item:hover .so-card__quad-label { color: var(--so-orange-600); }

.so-card__more {
  margin-top: auto;
  font-size: 13.5px;
  font-weight: 500;
  color: var(--so-orange-600);
}

.so-card__more:hover { text-decoration: underline; }

/* Image card fills its box edge to edge */
.so-card--image { padding: 0; overflow: hidden; }

.so-card--image .so-card__image { display: block; line-height: 0; }

.so-card--image .so-card__image img {
  width: 100%;
  aspect-ratio: 3 / 2;
  object-fit: cover;
  display: block;
}

.so-card--image .so-card__more { padding: 13px 16px 15px; }

@media (max-width: 1200px) { .so-cards { grid-template-columns: repeat(2, 1fr); } }

@media (max-width: 767px) {
  .so-cards { grid-template-columns: 1fr; gap: 12px; }
  .so-cards--overlap { margin-top: 14px; }
  .so-card { padding: 14px; }
}

/* ==========================================================================
   15. Product carousel
   ========================================================================== */

.so-row {
  background: var(--so-white);
  border: 1px solid var(--so-grey-200);
  border-radius: var(--so-radius);
  padding: 16px 18px 18px;
  overflow: hidden;
  min-width: 0;               /* allow shrinking inside Elementor flex containers */
  max-width: 100%;
}

.so-row__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 13px;
}

.so-row__title {
  font-family: var(--so-font-display);
  font-size: 20px;
  font-weight: 600;
  color: var(--so-navy);
  margin: 0;
}

.so-row__more {
  font-size: 13.5px;
  font-weight: 500;
  color: var(--so-orange-600);
  white-space: nowrap;
}

.so-row__more:hover { text-decoration: underline; }

.so-row__wrap {
  position: relative;
  overflow: hidden;
  min-width: 0;
}

.so-row__track {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: calc((100% - 5 * 12px) / 6);
  gap: 12px;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  scrollbar-width: none;
  -ms-overflow-style: none;
  padding-bottom: 2px;
  min-width: 0;               /* override min-width:auto — the grid's intrinsic
                                  min is the sum of all column tracks, which is
                                  what pushes the page wider than the viewport */
}

.so-row__track::-webkit-scrollbar { display: none; }

.so-row__item {
  scroll-snap-align: start;
  display: block;
  color: var(--so-ink);
  min-width: 0;
}

.so-row__img {
  display: block;
  background: var(--so-grey-50);
  border-radius: var(--so-radius-sm);
  overflow: hidden;
  margin-bottom: 8px;
}

.so-row__img img {
  width: 100%;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  display: block;
  transition: transform .25s ease;
}

.so-row__item:hover .so-row__img img { transform: scale(1.04); }

.so-row__name {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  font-size: 12.5px;
  line-height: 1.4;
  margin-bottom: 4px;
  min-height: 2.8em;
}

.so-row__item:hover .so-row__name { color: var(--so-orange-600); }

.so-row__price {
  display: block;
  font-family: var(--so-font-display);
  font-size: 15px;
  font-weight: 600;
  color: var(--so-ink);
}

.so-row__price ins { text-decoration: none; color: var(--so-orange); font-weight: 700; }
.so-row__price del { font-size: 12px; font-weight: 400; color: var(--so-grey-600); opacity: 1; margin-left: 5px; }

.so-row__nav {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: 2;
  width: 34px;
  height: 62px;
  border: 1px solid var(--so-grey-300);
  border-radius: var(--so-radius-sm);
  background: rgba(255, 255, 255, .96);
  color: var(--so-navy);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  box-shadow: 0 2px 8px rgba(16, 33, 52, .12);
  transition: opacity .15s ease;
}

.so-row__nav svg { width: 17px; height: 17px; fill: currentColor; }
.so-row__nav--prev { left: -10px; }
.so-row__nav--next { right: -10px; }
.so-row__nav.is-hidden { opacity: 0; pointer-events: none; }

@media (max-width: 1100px) {
  .so-row__track { grid-auto-columns: calc((100% - 3 * 12px) / 4); }
}

@media (max-width: 767px) {
  .so-row { padding: 14px; }
  .so-row__title { font-size: 17px; }
  .so-row__track { grid-auto-columns: calc((100% - 10px) / 2.3); }
  .so-row__nav { display: none; }
}

/* ==========================================================================
   16. Promo strip and trust bar
   ========================================================================== */

.so-promo-strip {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 16px;
}

.so-promo-strip__item {
  display: block;
  line-height: 0;
  border-radius: var(--so-radius);
  overflow: hidden;
  border: 1px solid var(--so-grey-200);
}

.so-promo-strip__item img {
  width: 100%;
  aspect-ratio: 3 / 2;
  object-fit: cover;
  display: block;
  transition: transform .3s ease;
}

.so-promo-strip__item:hover img { transform: scale(1.02); }

@media (max-width: 767px) { .so-promo-strip { grid-template-columns: 1fr; gap: 12px; } }

.so-trust {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 14px;
}

.so-trust__item {
  display: flex;
  align-items: center;
  gap: 12px;
  background: var(--so-white);
  border: 1px solid var(--so-grey-200);
  border-radius: var(--so-radius);
  padding: 15px 16px;
}

.so-trust__icon { color: var(--so-orange); flex: 0 0 auto; display: inline-flex; }
.so-trust__text { display: flex; flex-direction: column; gap: 2px; line-height: 1.35; min-width: 0; }
.so-trust__text strong { font-family: var(--so-font-display); font-size: 13.5px; font-weight: 600; color: var(--so-navy); }
.so-trust__text span { font-size: 12px; color: var(--so-grey-600); }

@media (max-width: 900px) { .so-trust { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 480px) { .so-trust { grid-template-columns: 1fr; } }

/* ==========================================================================
   17. Footer
   ========================================================================== */

.so-foot-links { list-style: none; margin: 0; padding: 0; }
.so-foot-links li { margin-bottom: 7px; }
.so-foot-links a { font-size: 13px; color: #C3CEDA; transition: color .15s ease; }
.so-foot-links a:hover { color: var(--so-orange); }
.so-foot-bottom { font-size: 12.5px; color: #8FA0B4; text-align: center; }

.so-announce {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 0 8px;
  font-size: 13px;
  font-weight: 500;
  color: var(--so-white);
  text-align: center;
  line-height: 1.4;
}

.so-announce__sep { opacity: .5; }

/* ==========================================================================
   18. Utilities and Elementor safety net
   ========================================================================== */

.screen-reader-text {
  position: absolute !important;
  width: 1px; height: 1px;
  overflow: hidden; clip: rect(1px, 1px, 1px, 1px);
  white-space: nowrap;
}

.so-noimg {
  display: block;
  width: 100%;
  aspect-ratio: 1 / 1;
  background: var(--so-grey-100);
  border-radius: var(--so-radius-sm);
}

/* Shortcode and HTML widgets must fill their container whatever alignment
   the Elementor container is set to. */
.elementor-widget-shortcode,
.elementor-widget-shortcode > .elementor-widget-container,
.elementor-widget-html,
.elementor-widget-html > .elementor-widget-container {
  width: 100%;
}

/* The homepage sits on grey so the white cards read as cards */
body.home .site-content,
body.home #content { background: var(--so-grey-100); }

/* Full bleed helper for the hero inside a boxed Elementor container */
.so-fullbleed {
  width: 100vw;
  margin-left: calc(50% - 50vw);
  margin-right: calc(50% - 50vw);
}

/* ==========================================================================
   16. Archive — shop, category, tag and search
   One layout serves all four. The rail is a real grid column on desktop and a
   bottom sheet on mobile, which is why it is not inside Astra's sidebar.
   ========================================================================== */

.so-archive {
  display: grid;
  grid-template-columns: 258px minmax(0, 1fr);
  gap: 24px;
  align-items: start;
  max-width: var(--so-container);
  margin: 0 auto;
  width: 100%;
}

/* minmax(0, 1fr) rather than 1fr. A grid track defaults to min-width: auto,
   so a wide product title would push the column past its share and overflow
   the page. Zero breaks that chain. */
.so-archive__main { min-width: 0; }

.so-archive__head { margin-bottom: 14px; }

.so-archive__title {
  font-family: var(--so-font-display);
  font-size: 24px;
  font-weight: 600;
  color: var(--so-navy);
  line-height: 1.25;
  margin: 0;
}

.so-archive__term { color: var(--so-orange); }

.so-archive__intro {
  margin-top: 8px;
  font-size: 14px;
  line-height: 1.6;
  color: var(--so-grey-600);
  max-width: 70ch;
}

.so-zone { margin-bottom: 18px; }
.so-zone:empty { display: none; }

/* -------------------------------------------------------------- subcategories */

.so-subcats {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 14px;
}

.so-subcat {
  display: inline-block;
  padding: 7px 14px;
  border: 1px solid var(--so-grey-300);
  border-radius: 999px;
  background: var(--so-white);
  font-size: 13px;
  font-weight: 500;
  color: var(--so-ink);
  text-decoration: none;
  transition: border-color .15s ease, color .15s ease;
}

.so-subcat:hover {
  border-color: var(--so-orange);
  color: var(--so-orange-600);
}

/* ------------------------------------------------------------------ toolbar */

.so-toolbar {
  background: var(--so-white);
  border: 1px solid var(--so-grey-200);
  border-radius: var(--so-radius);
  padding: 10px 14px;
  margin-bottom: var(--so-grid-gap);
}

.so-toolbar__row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
}

.so-toolbar__count .woocommerce-result-count {
  margin: 0;
  font-size: 13.5px;
  color: var(--so-grey-600);
}

.so-toolbar__actions {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-left: auto;
}

.so-toolbar .woocommerce-ordering { margin: 0; }

.so-toolbar .woocommerce-ordering select,
.so-toolbar select.orderby {
  height: 38px;
  border: 1px solid var(--so-grey-300);
  border-radius: var(--so-radius-sm);
  background-color: var(--so-white);
  font-family: var(--so-font-body);
  font-size: 13.5px;
  color: var(--so-ink);
  padding: 0 30px 0 12px;
  cursor: pointer;
  -webkit-appearance: none;
  appearance: none;
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%236B7280'%3E%3Cpath d='M7 10l5 5 5-5z'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 6px center;
  background-size: 18px;
}

.so-toolbar__filters {
  display: none;
  align-items: center;
  gap: 7px;
  height: 38px;
  padding: 0 16px;
  border: 1px solid var(--so-navy);
  border-radius: var(--so-radius-sm);
  background: var(--so-white);
  font-family: var(--so-font-body);
  font-size: 13.5px;
  font-weight: 600;
  color: var(--so-navy);
  cursor: pointer;
}

.so-toolbar__filters::before {
  content: "";
  width: 15px;
  height: 15px;
  background: currentColor;
  -webkit-mask: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M3 5h18v2l-7 7v5l-4 2v-7L3 7V5z'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M3 5h18v2l-7 7v5l-4 2v-7L3 7V5z'/%3E%3C/svg%3E") center / contain no-repeat;
}

/* --------------------------------------------------------------- active chips */

.so-chips {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px solid var(--so-grey-200);
}

.so-chip {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 5px 10px;
  border-radius: var(--so-radius-sm);
  background: var(--so-orange-50);
  border: 1px solid var(--so-orange);
  font-size: 12.5px;
  font-weight: 500;
  color: var(--so-navy);
  text-decoration: none;
  line-height: 1.3;
}

.so-chip__x { font-size: 15px; line-height: 1; color: var(--so-orange-600); }
.so-chip:hover { background: var(--so-white); }

.so-chips__clear {
  font-size: 12.5px;
  font-weight: 600;
  color: var(--so-grey-600);
  text-decoration: underline;
}

.so-chips__clear:hover { color: var(--so-orange-600); }

/* ==========================================================================
   17. Filter rail
   ========================================================================== */

.so-archive__rail {
  position: sticky;
  top: 16px;
  align-self: start;
  max-height: calc(100vh - 32px);
  overflow-y: auto;
  overscroll-behavior: contain;
}

.so-filters {
  background: var(--so-white);
  border: 1px solid var(--so-grey-200);
  border-radius: var(--so-radius);
  padding: 4px 16px 12px;
}

.so-filters__head {
  display: none;
  align-items: center;
  justify-content: space-between;
  padding: 12px 0 10px;
  border-bottom: 1px solid var(--so-grey-200);
}

.so-filters__heading {
  font-family: var(--so-font-display);
  font-size: 16px;
  font-weight: 600;
  color: var(--so-navy);
}

.so-filters__close {
  border: 0;
  background: none;
  font-size: 26px;
  line-height: 1;
  color: var(--so-navy);
  cursor: pointer;
  padding: 0 4px;
}

.so-facet {
  padding: 14px 0;
  border-bottom: 1px solid var(--so-grey-200);
}

.so-facet:last-of-type { border-bottom: 0; }

.so-facet__title {
  font-family: var(--so-font-display);
  font-size: 14px;
  font-weight: 600;
  color: var(--so-navy);
  margin: 0 0 9px;
}

.so-facet__list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.so-facet__list li { margin: 0; }

.so-facet__list a {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 5px 0;
  font-size: 13.5px;
  line-height: 1.4;
  color: var(--so-ink);
  text-decoration: none;
}

.so-facet__list a:hover { color: var(--so-orange-600); }

.so-facet__list li.is-current > a {
  font-weight: 600;
  color: var(--so-orange-600);
}

.so-facet__count {
  flex: 0 0 auto;
  font-size: 12px;
  color: var(--so-grey-600);
}

.so-facet__back a {
  font-weight: 600;
  color: var(--so-grey-600);
}

.so-facet__back a::before {
  content: "‹";
  margin-right: 5px;
}

/* stars */

.so-stars { letter-spacing: 1px; }
.so-star { color: var(--so-grey-300); font-size: 14px; }
.so-star.is-on { color: var(--so-orange); }
.so-stars__label { font-size: 12.5px; color: var(--so-grey-600); margin-left: 4px; }

.so-facet__list--stars a { justify-content: flex-start; }

/* price range inputs */

.so-price-range {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-top: 11px;
}

.so-price-range input[type="number"] {
  width: 100%;
  min-width: 0;
  height: 34px;
  padding: 0 8px;
  border: 1px solid var(--so-grey-300);
  border-radius: var(--so-radius-sm);
  font-family: var(--so-font-body);
  font-size: 13px;
  color: var(--so-ink);
  background: var(--so-white);
}

.so-price-range input:focus {
  outline: none;
  border-color: var(--so-orange);
}

.so-price-range__dash { color: var(--so-grey-600); }

.so-price-range__go {
  flex: 0 0 auto;
  height: 34px;
  padding: 0 12px;
  border-radius: var(--so-radius-sm);
  background: transparent;
  color: var(--so-navy);
  border: 1.5px solid var(--so-orange);
  font-family: var(--so-font-body);
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  transition: background .15s ease, border-color .15s ease, color .15s ease;
}

.so-price-range__go:hover,
.so-price-range__go:focus-visible {
  background: var(--so-navy);
  border-color: var(--so-navy);
  color: var(--so-white);
}

/* ==========================================================================
   18. Empty state
   ========================================================================== */

.so-empty {
  background: var(--so-white);
  border: 1px solid var(--so-grey-200);
  border-radius: var(--so-radius);
  padding: 36px 24px;
  text-align: center;
}

.so-empty__lead {
  font-family: var(--so-font-display);
  font-size: 18px;
  font-weight: 600;
  color: var(--so-navy);
  margin: 0 0 6px;
}

.so-empty__hint {
  font-size: 14px;
  color: var(--so-grey-600);
  margin: 0 0 18px;
}

.so-empty__reset {
  display: inline-block;
  margin: 10px 0 18px;
  padding: 10px 20px;
  border-radius: var(--so-radius-sm);
  background: transparent;
  color: var(--so-navy);
  border: 1.5px solid var(--so-orange);
  font-weight: 600;
  font-size: 14px;
  text-decoration: none;
  transition: background .15s ease, border-color .15s ease, color .15s ease;
}

.so-empty__reset:hover {
  background: var(--so-navy);
  border-color: var(--so-navy);
  color: var(--so-white);
}

.so-empty__cats {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 8px;
  margin-top: 8px;
}

.so-empty__cats a {
  padding: 7px 14px;
  border: 1px solid var(--so-grey-300);
  border-radius: 999px;
  font-size: 13px;
  color: var(--so-ink);
  text-decoration: none;
}

.so-empty__cats a:hover { border-color: var(--so-orange); color: var(--so-orange-600); }

/* ==========================================================================
   19. Archive — tablet and mobile
   ========================================================================== */

@media (max-width: 1024px) {
  .so-archive { grid-template-columns: 1fr; gap: 0; }

  .so-toolbar__filters { display: inline-flex; }

  .so-archive__scrim {
    position: fixed;
    inset: 0;
    background: rgba(16, 33, 52, .45);
    z-index: 9998;
    opacity: 0;
    pointer-events: none;
    transition: opacity .2s ease;
  }

  .so-archive.is-filters-open .so-archive__scrim {
    opacity: 1;
    pointer-events: auto;
  }

  .so-archive__rail {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    top: auto;
    max-height: 82vh;
    z-index: 9999;
    transform: translateY(100%);
    transition: transform .25s ease;
    background: var(--so-white);
    border-radius: 14px 14px 0 0;
    box-shadow: 0 -6px 26px rgba(16, 33, 52, .22);
    padding-bottom: env(safe-area-inset-bottom, 0);
  }

  .so-archive.is-filters-open .so-archive__rail { transform: translateY(0); }

  .so-filters {
    border: 0;
    border-radius: 0;
    background: transparent;
    padding: 0 18px 18px;
  }

  .so-filters__head {
    display: flex;
    position: sticky;
    top: 0;
    background: var(--so-white);
    z-index: 1;
  }
}

@media (prefers-reduced-motion: reduce) {
  .so-archive__rail,
  .so-archive__scrim { transition: none; }
}

@media (max-width: 760px) {
  .so-archive__title { font-size: 19px; }
  .so-toolbar { padding: 9px 11px; }
  .so-toolbar__count { width: 100%; }
  .so-toolbar__actions { width: 100%; margin-left: 0; }
  .so-toolbar__filters { flex: 1 1 auto; justify-content: center; }
  .so-toolbar .woocommerce-ordering { flex: 1 1 auto; }
  .so-toolbar .woocommerce-ordering select { width: 100%; }
  .so-empty { padding: 26px 16px; }
}

/* ==========================================================================
   20. FiboSearch — dressed to match the StoreOH search bar
   The plugin ships its own markup and class names, so this restyles it rather
   than replacing it. If a FiboSearch update ever changes a class name, the
   worst case is the bar reverts to their default look. Nothing breaks.
   ========================================================================== */

.so-header .dgwt-wcas-search-wrapp,
.dgwt-wcas-search-wrapp {
  max-width: none;
  width: 100%;
}

.dgwt-wcas-search-wrapp .dgwt-wcas-sf-wrapp {
  background: var(--so-white);
  border: 2px solid transparent;
  border-radius: var(--so-radius);
  overflow: hidden;
  display: flex;
  align-items: stretch;
  transition: border-color .15s ease;
}

.dgwt-wcas-search-wrapp.dgwt-wcas-is-focus .dgwt-wcas-sf-wrapp,
.dgwt-wcas-search-wrapp .dgwt-wcas-sf-wrapp:focus-within {
  border-color: var(--so-orange);
}

.dgwt-wcas-search-wrapp input[type="search"].dgwt-wcas-search-input {
  height: 42px;
  border: 0;
  outline: 0;
  box-shadow: none;
  border-radius: 0;
  background: var(--so-white);
  font-family: var(--so-font-body);
  font-size: 14.5px;
  color: var(--so-ink);
  padding: 0 14px;
  min-width: 0;
}

.dgwt-wcas-search-wrapp input.dgwt-wcas-search-input::placeholder {
  color: var(--so-grey-600);
  opacity: 1;
}

/* The category selector, when the plugin offers one. */
.dgwt-wcas-search-wrapp .dgwt-wcas-search-filter,
.dgwt-wcas-search-wrapp select.dgwt-wcas-search-filter {
  border: 0;
  border-right: 1px solid var(--so-grey-300);
  background-color: var(--so-grey-100);
  color: var(--so-ink);
  font-family: var(--so-font-body);
  font-size: 12.5px;
  font-weight: 500;
  height: 42px;
  border-radius: 0;
}

.dgwt-wcas-search-wrapp .dgwt-wcas-search-submit {
  width: 54px;
  min-width: 54px;
  height: 42px;
  border: 0;
  border-radius: 0;
  background: var(--so-orange);
  color: var(--so-navy);
  transition: background .15s ease;
}

.dgwt-wcas-search-wrapp .dgwt-wcas-search-submit:hover,
.dgwt-wcas-search-wrapp .dgwt-wcas-search-submit:focus {
  background: var(--so-orange-600);
}

.dgwt-wcas-search-wrapp .dgwt-wcas-search-submit .dgwt-wcas-ico-magnifier,
.dgwt-wcas-search-wrapp .dgwt-wcas-search-submit svg { fill: var(--so-navy); }

.dgwt-wcas-search-wrapp .dgwt-wcas-preloader,
.dgwt-wcas-search-wrapp .dgwt-wcas-close { right: 62px; }

/* suggestions panel */

.dgwt-wcas-suggestions-wrapp {
  border: 1px solid var(--so-grey-200);
  border-radius: var(--so-radius);
  box-shadow: var(--so-shadow-hover);
  font-family: var(--so-font-body);
  overflow: hidden;
}

.dgwt-wcas-suggestion {
  padding: 9px 12px;
  border-bottom: 1px solid var(--so-grey-100);
}

.dgwt-wcas-suggestion:last-child { border-bottom: 0; }

.dgwt-wcas-suggestion.dgwt-wcas-suggestion-selected,
.dgwt-wcas-suggestion:hover {
  background: var(--so-orange-50);
}

.dgwt-wcas-st-title,
.dgwt-wcas-st--title {
  font-size: 13.5px;
  font-weight: 500;
  color: var(--so-ink);
  line-height: 1.35;
}

.dgwt-wcas-suggestion .dgwt-wcas-sp,
.dgwt-wcas-suggestion .dgwt-wcas-st-price {
  font-family: var(--so-font-display);
  font-weight: 600;
  color: var(--so-navy);
}

.dgwt-wcas-suggestion .dgwt-wcas-sp ins { text-decoration: none; color: var(--so-orange-600); }
.dgwt-wcas-suggestion .dgwt-wcas-sp del { color: var(--so-grey-600); font-weight: 400; }

.dgwt-wcas-si img { border-radius: var(--so-radius-sm); }

.dgwt-wcas-st-breadcrumbs,
.dgwt-wcas-sd { color: var(--so-grey-600); font-size: 12px; }

.dgwt-wcas-suggestion-headline .dgwt-wcas-st-title,
.dgwt-wcas-suggestion-headline {
  font-family: var(--so-font-display);
  font-size: 11.5px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--so-grey-600);
  background: var(--so-grey-50);
}

.dgwt-wcas-details-wrapp { border-left: 1px solid var(--so-grey-200); }

.dgwt-wcas-all-results {
  font-weight: 600;
  color: var(--so-navy);
  background: var(--so-grey-50);
}

.dgwt-wcas-all-results:hover { color: var(--so-orange-600); }

.so-toolbar__badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  border-radius: 999px;
  background: var(--so-orange);
  color: var(--so-navy);
  font-size: 11px;
  font-weight: 700;
  line-height: 1;
}

/* ==========================================================================
   21. Archive top spacing
   Astra puts 4em above the content area, which is right for a blog post and
   far too much above a product grid. The breadcrumb should sit close under
   the category bar the way it does on a marketplace.
   ========================================================================== */

.storeoh.woocommerce-shop #primary,
.storeoh.tax-product_cat #primary,
.storeoh.tax-product_tag #primary,
.storeoh.woocommerce-page.search #primary,
.storeoh.post-type-archive-product #primary {
  margin-top: 16px;
  padding-top: 0;
}

/* The products header is empty now that the child theme prints the heading,
   but an empty element still takes its margin. */
.woocommerce-products-header {
  margin: 0;
  padding: 0;
}

.woocommerce-products-header:empty { display: none; }

.storeoh .woocommerce-breadcrumb {
  margin: 0 0 12px;
  font-size: 13px;
  color: var(--so-grey-600);
  max-width: var(--so-container);
  margin-left: auto;
  margin-right: auto;
  width: 100%;
}

.storeoh .woocommerce-breadcrumb a { color: var(--so-grey-600); }
.storeoh .woocommerce-breadcrumb a:hover { color: var(--so-orange-600); }
.so-crumb-sep { color: var(--so-grey-300); margin: 0 2px; }

@media (max-width: 760px) {
  .storeoh.woocommerce-shop #primary,
  .storeoh.tax-product_cat #primary,
  .storeoh.woocommerce-page.search #primary { margin-top: 10px; }
}

/* Drawer wordmark. Sized by width with height left to follow, so the lockup
   always keeps its proportions and neither the bag nor the type can be clipped
   at any drawer width. */
.so-drawer__logo {
  display: block;
  width: 168px;
  max-width: 100%;
  height: auto;
  margin-top: 7px;
}

@media (max-width: 360px) {
  .so-drawer__logo { width: 146px; }
}

/* ==========================================================================
   22. Single product — layout
   Two columns, not three. Amazon runs three because it has reviews, questions
   and competing sellers to fill them. On thin data three columns reads as
   cramped, and cramped is what makes a page feel overwhelming.
   ========================================================================== */

.woocommerce div.product .so-pdp,
.so-pdp {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
  gap: 40px;
  align-items: start;
  max-width: var(--so-container);
  margin: 0 auto 36px;
  width: 100%;
}

/* Astra floats these into 48% halves, and prints its dynamic CSS into the head
   after the child stylesheet, so specificity alone does not win. Grid owns the
   columns here; !important is the pragmatic way to stop the two fighting and
   leaving the buy panel at half the width of its own cell. */
.woocommerce div.product .so-pdp .so-pdp__gallery,
.woocommerce div.product .so-pdp div.summary,
.so-pdp .summary.entry-summary {
  float: none !important;
  width: 100% !important;
  max-width: 100% !important;
  min-width: 0;
  margin: 0 !important;
  padding: 0;
  clear: none !important;
}

.so-pdp__gallery { position: relative; }

/* A second breadcrumb and a category link above the title, both from Astra's
   product structure. The real breadcrumb is above the grid. */
.so-pdp .summary .woocommerce-breadcrumb,
.so-pdp .summary .ast-woo-product-category,
.so-pdp .summary .product-category { display: none; }

/* ---------------------------------------------------------------- gallery
   The rail is printed by the theme, not by flexslider, and the column split
   lives on .so-pdp__gallery which is our own element. Nothing here depends on
   markup generated at run time, which is what broke the last two attempts. */

.so-pdp__gallery { position: relative; }

@media (min-width: 992px) {
  .so-pdp__gallery {
    display: grid;
    grid-template-columns: 76px minmax(0, 1fr);
    gap: 12px;
    align-items: start;
  }

  .so-pdp__gallery > .so-thumbs { grid-column: 1; grid-row: 1; }
  .so-pdp__gallery > div.images,
  .so-pdp__gallery > .woocommerce-product-gallery { grid-column: 2; grid-row: 1; }
}

.woocommerce div.product .so-pdp div.images,
.so-pdp .woocommerce-product-gallery {
  width: 100% !important;
  max-width: 100% !important;
  float: none !important;
  margin: 0 !important;
  padding: 0;
  opacity: 1 !important;
}

.so-pdp .woocommerce-product-gallery__wrapper { min-width: 0; margin: 0; width: 100%; }

.so-pdp .woocommerce-product-gallery .flex-viewport {
  width: 100% !important;
  border: 1px solid var(--so-grey-200);
  border-radius: var(--so-radius);
  background: var(--so-white);
  overflow: hidden;
}

.so-pdp .woocommerce-product-gallery__image { width: 100%; }
.so-pdp .woocommerce-product-gallery__image a { display: block; }

/* Square frame with the image contained. CJ photos arrive at wildly different
   shapes, and a gallery that changes height as you click through is the most
   obvious sign of an unfinished store.

   Scoped with > so it only hits the real slide image. jQuery-zoom injects a
   second img.zoomImg into this same element at the photo's natural size and
   pans it under the cursor. The old unscoped rule was forcing that overlay to
   100% width and a square aspect too, which cancelled the magnification and
   left only the panning: the "slides up and down instead of zooming" effect. */
.so-pdp .woocommerce-product-gallery__image > img,
.so-pdp .woocommerce-product-gallery__image > a > img {
  width: 100% !important;
  max-width: 100% !important;
  height: auto;
  aspect-ratio: 1 / 1;
  object-fit: contain;
  background: var(--so-white);
  border-radius: var(--so-radius);
  display: block;
}

/* The zoom overlay must keep its natural size or there is nothing to magnify. */
.so-pdp .woocommerce-product-gallery__image img.zoomImg {
  width: auto !important;
  height: auto !important;
  max-width: none !important;
  aspect-ratio: auto !important;
  object-fit: none !important;
  border-radius: 0;
  background: var(--so-white);
}

.so-pdp .woocommerce-product-gallery__image,
.so-pdp .woocommerce-product-gallery__image > a {
  position: relative;
  overflow: hidden;
  border-radius: var(--so-radius);
  cursor: zoom-in;
}

/* Flexslider's own navigation, in both its forms. Ours replaces it. */
.so-pdp .flex-control-nav,
.so-pdp .flex-control-thumbs,
.so-pdp .flex-control-paging { display: none !important; }

.so-thumbs {
  list-style: none !important;
  margin: 12px 0 0 !important;
  padding: 0 !important;
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.so-thumbs__item {
  list-style: none !important;
  margin: 0 !important;
  padding: 0;
  width: 76px;
}

.so-thumbs__item::marker { content: none; }

.so-thumbs__btn {
  display: block;
  width: 100%;
  padding: 0;
  border: 1px solid var(--so-grey-300);
  border-radius: var(--so-radius-sm);
  background: var(--so-white);
  cursor: pointer;
  overflow: hidden;
  transition: border-color .15s ease;
}

.so-thumbs__btn img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 1 / 1;
  object-fit: cover;
}

.so-thumbs__btn:hover { border-color: var(--so-navy); }

.so-thumbs { scrollbar-width: thin; scrollbar-color: var(--so-grey-300) transparent; }
.so-thumbs::-webkit-scrollbar { width: 4px; height: 4px; }
.so-thumbs::-webkit-scrollbar-track { background: transparent; }
.so-thumbs::-webkit-scrollbar-thumb { background: var(--so-grey-300); border-radius: 999px; }
.so-thumbs::-webkit-scrollbar-thumb:hover { background: var(--so-grey-600); }

.so-thumbs__btn.is-active {
  border-color: var(--so-orange);
  border-width: 2px;
}

@media (min-width: 992px) {
  .so-thumbs {
    flex-direction: column;
    flex-wrap: nowrap;
    margin: 0 !important;
    max-height: 540px;
    overflow-y: auto;
    overscroll-behavior: contain;
  }
}

.so-pdp .woocommerce-product-gallery__trigger { top: 12px; right: 12px; z-index: 4; }

.so-pdp.is-unavailable .woocommerce-product-gallery__image img { opacity: .5; }

.so-pdp__soldout {
  position: absolute;
  top: 14px;
  left: 14px;
  z-index: 5;
  background: var(--so-grey-600);
  color: var(--so-white);
  font-family: var(--so-font-display);
  font-size: 12px;
  font-weight: 700;
  padding: 6px 10px;
  border-radius: var(--so-radius-sm);
}

/* ------------------------------------------------------- right hand column */

.woocommerce div.product .so-pdp .product_title,
.so-pdp .product_title {
  font-family: var(--so-font-display);
  font-size: 26px;
  font-weight: 600;
  line-height: 1.28;
  color: var(--so-navy);
  margin: 0 0 10px;
  padding: 0;
}

/* The category, where the badge row used to be. Same pill as the subcategory
   chips on the archives, so the two read as the same thing in both places. */
.so-pdp__cat { margin: 0 0 14px; }

.so-pdp__cat a {
  display: inline-block;
  padding: 5px 13px;
  border: 1px solid var(--so-grey-300);
  border-radius: 999px;
  background: var(--so-white);
  font-family: var(--so-font-body);
  font-size: 12.5px;
  font-weight: 500;
  line-height: 1.4;
  color: var(--so-grey-600);
  text-decoration: none;
  transition: border-color .15s ease, color .15s ease;
}

.so-pdp__cat a:hover,
.so-pdp__cat a:focus-visible {
  border-color: var(--so-orange);
  color: var(--so-navy);
}

.woocommerce div.product .so-pdp p.price,
.so-pdp .summary p.price {
  font-family: var(--so-font-display);
  font-size: 30px;
  font-weight: 600;
  color: var(--so-navy);
  line-height: 1.15;
  margin: 0 0 18px;
}

.so-pdp .summary p.price del {
  font-size: 17px;
  font-weight: 400;
  color: var(--so-grey-600);
  margin-right: 8px;
  opacity: 1;
}

.so-pdp .summary p.price ins {
  text-decoration: none;
  color: var(--so-orange-600);
  background: none;
}

/* ==========================================================================
   23. Buy panel

   One vertical rhythm, declared once and used everywhere below:

     --so-buy-gap   14px   between blocks
     --so-buy-tight  6px   between lines inside a block

   Every margin in this panel is one of those two values. Spacing drifted
   before because each piece was tuned on its own, and the result read as
   uneven even though no single number was wrong.
   ========================================================================== */

.so-buy {
  --so-buy-gap: 14px;
  --so-buy-tight: 6px;
  background: var(--so-white);
  border: 1px solid var(--so-grey-300);
  border-radius: var(--so-radius);
  padding: 18px;
  margin-bottom: 10px;
}

/* WooCommerce's own form and every wrapper inside it. These arrive with
   borders, backgrounds and margins from the parent theme, and each one adds
   another few pixels nobody asked for. */
.so-pdp .so-buy form.cart,
.so-pdp .so-buy .variations_form,
.so-pdp .so-buy .single_variation_wrap,
.so-pdp .so-buy .woocommerce-variation-add-to-cart,
.so-pdp .so-buy .woocommerce-variation {
  border: 0;
  background: none;
  padding: 0;
  margin: 0;
  box-shadow: none;
}

.so-buy__delivery { margin-bottom: var(--so-buy-gap); }
.so-buy__delivery p { margin: 0 0 var(--so-buy-tight); font-size: 14px; line-height: 1.5; }
.so-buy__delivery p:last-child { margin-bottom: 0; }

.so-delivery__label { color: var(--so-grey-600); }
.so-delivery strong { color: var(--so-navy); font-weight: 600; }

.so-cutoff { color: var(--so-grey-600); font-size: 13px !important; }
.so-cutoff__clock { font-weight: 600; color: var(--so-navy); }

.so-freeship { color: var(--so-orange-600); font-weight: 600; }
.so-freeship.is-eligible { color: #1E7A3C; }

.so-stock { font-weight: 600; }
.so-stock--in        { color: #1E7A3C; }
.so-stock--low       { color: #B4530A; }
.so-stock--backorder { color: var(--so-grey-600); }
.so-stock--out       { color: var(--so-grey-600); }

.so-shipsfrom {
  display: block;
  font-weight: 400;
  font-size: 13px;
  color: var(--so-grey-600);
  margin-top: 2px;
}

.so-buy__form {
  border-top: 1px solid var(--so-grey-200);
  padding-top: var(--so-buy-gap);
}

/* Empty wrappers still take their margin. WooCommerce prints the variation
   price, description and availability containers whether or not there is
   anything in them, which is where the hole above Quantity came from. */
.so-pdp .woocommerce-variation:empty,
.so-pdp .woocommerce-variation-price:empty,
.so-pdp .woocommerce-variation-description:empty,
.so-pdp .woocommerce-variation-availability:empty {
  display: none;
  margin: 0;
}

.so-qty {
  display: block;
  float: none !important;
  clear: both;
  margin: 0;
}

.so-qty::after { content: ""; display: table; clear: both; }

.so-qty-label {
  display: block;
  font-family: var(--so-font-display);
  font-size: 13px;
  font-weight: 600;
  color: var(--so-navy);
  margin: 0 0 5px;
}

.woocommerce div.product .so-buy__form .quantity,
.so-buy__form .quantity {
  float: none !important;
  display: block;
  margin: 0 !important;
}

.woocommerce .so-buy__form .quantity input.qty {
  width: 84px !important;
  height: 44px;
  border: 1px solid var(--so-grey-300);
  border-radius: var(--so-radius-sm);
  font-family: var(--so-font-body);
  font-size: 14.5px;
  text-align: center;
  color: var(--so-ink);
  background: var(--so-white);
}

/* --------------------------------------------------------------- buttons
   Same treatment as the product cards on the category pages: transparent with
   an orange border at rest, navy fill with a white label on hover. Orange
   never fills at rest, so it stays a signal rather than becoming wallpaper.

   Side by side rather than two full width bars. A button stretched across a
   700px column reads as a banner, not as something to press. */

.so-buy__actions {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-top: var(--so-buy-gap, 14px);
  max-width: 300px;
  clear: both;
}

/* WooCommerce and Astra both put a bottom margin on .button, which stacked on
   top of the flex gap and left an uneven hole between the two actions. The gap
   is the only thing that should space them. */
.woocommerce div.product .so-buy__actions > .button,
.woocommerce div.product .so-buy__actions > button,
.so-buy__actions > .button,
.so-buy__actions .single_add_to_cart_button,
.so-buy__actions .so-buynow {
  margin: 0 !important;
}

.woocommerce div.product .so-buy__form button.button,
.woocommerce div.product .so-buy__form button.button.alt,
.so-buy__form .single_add_to_cart_button,
.so-buy__form .so-buynow {
  flex: 0 0 auto;
  width: 100%;
  min-height: 46px;
  padding: 12px 20px;
  border: 1.5px solid var(--so-orange);
  border-radius: 999px;
  background: transparent;
  color: var(--so-navy);
  font-family: var(--so-font-body);
  font-size: 14.5px;
  font-weight: 600;
  letter-spacing: 0;
  text-transform: none;
  box-shadow: none;
  transition: background .15s ease, border-color .15s ease, color .15s ease;
}

.woocommerce div.product .so-buy__form button.button:hover,
.woocommerce div.product .so-buy__form button.button.alt:hover,
.so-buy__form .single_add_to_cart_button:hover,
.so-buy__form .so-buynow:hover {
  background: var(--so-navy);
  border-color: var(--so-navy);
  color: var(--so-white);
}

/* Buy now is the second action, so its border is quieter. */
.woocommerce div.product .so-buy__form button.so-buynow,
.so-buy__form .so-buynow {
  margin-top: 0;
  border-color: var(--so-grey-300);
  color: var(--so-grey-600);
}

.woocommerce div.product .so-buy__form button.so-buynow:hover,
.so-buy__form .so-buynow:hover {
  border-color: var(--so-navy);
  color: var(--so-white);
}

/* WooCommerce disables Add to Cart until a variation is chosen. Astra paints
   that state pale blue, which looked like a third unrelated button. */
.woocommerce div.product .so-buy__form button.button.disabled,
.woocommerce div.product .so-buy__form button.button.alt.disabled,
.woocommerce div.product .so-buy__form button.button:disabled,
.woocommerce div.product .so-buy__form button.button:disabled[disabled] {
  background: transparent;
  border-color: var(--so-grey-200);
  color: var(--so-grey-300);
  cursor: not-allowed;
  opacity: 1;
}

.woocommerce div.product .so-buy__form button.button.disabled:hover,
.woocommerce div.product .so-buy__form button.button:disabled:hover {
  background: transparent;
  border-color: var(--so-grey-200);
  color: var(--so-grey-300);
}

/* quantity */

/* WooCommerce floats its .quantity div, which is why the label, the box and
   both buttons ended up on one line. The wrapper clears it. */
.so-qty {
  display: block;
  float: none !important;
  clear: both;
  margin: 0;
}

.so-qty::after { content: ""; display: table; clear: both; }

.so-qty-label {
  display: block;
  font-family: var(--so-font-display);
  font-size: 13px;
  font-weight: 600;
  color: var(--so-navy);
  margin: 0 0 5px;
}



.woocommerce div.product .so-buy__form .quantity,
.so-buy__form .quantity {
  float: none !important;
  display: block;
  margin: 0 !important;
}

.so-assurance {
  list-style: none;
  margin: var(--so-buy-gap, 14px) 0 0;
  padding: 13px 0 0;
  border-top: 1px solid var(--so-grey-200);
  display: flex;
  flex-wrap: wrap;
  gap: 6px 18px;
}

.so-assurance__item {
  position: relative;
  padding-left: 19px;
  margin: 0;
  font-size: 13px;
  color: var(--so-grey-600);
  line-height: 1.4;
}

.so-assurance__item::before {
  content: "";
  position: absolute;
  left: 0;
  top: 3px;
  width: 13px;
  height: 13px;
  background: #1E7A3C;
  -webkit-mask: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4z'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4z'/%3E%3C/svg%3E") center / contain no-repeat;
}

.so-pdp__sku {
  font-size: 12.5px;
  color: var(--so-grey-600);
  margin: 0 0 18px;
}

/* --------------------------------------------------------- about this item */

.so-pdp__about {
  border-top: 1px solid var(--so-grey-200);
  padding-top: 18px;
}

.so-pdp__about-title {
  font-family: var(--so-font-display);
  font-size: 15px;
  font-weight: 600;
  color: var(--so-navy);
  margin: 0 0 9px;
}

.so-pdp__about-body { font-size: 14px; line-height: 1.65; color: var(--so-ink); }
.so-pdp__about-body ul { padding-left: 18px; margin: 0; }
.so-pdp__about-body li { margin-bottom: 6px; }
.so-pdp__about-body > :last-child { margin-bottom: 0; }

/* ==========================================================================
   24. Variation swatches
   ========================================================================== */

.so-swatches { display: flex; flex-wrap: wrap; gap: 8px; margin: 0; }

/* A row whose only option has been chosen for the shopper by script. Hidden
   here rather than in PHP, because hiding a control WooCommerce still requires
   is how Add to Cart ends up permanently disabled. */
.so-pdp .so-variation-resolved { display: none !important; }

.so-swatch {
  min-width: 46px;
  padding: 8px 14px;
  border: 1.5px solid var(--so-grey-300);
  border-radius: var(--so-radius-sm);
  background: var(--so-white);
  font-family: var(--so-font-body);
  font-size: 13.5px;
  font-weight: 500;
  color: var(--so-ink);
  cursor: pointer;
  transition: border-color .15s ease, color .15s ease;
}

/* Astra paints button:hover with its own accent, which is blue. Every state
   is declared here so none of it can leak through. */
.so-pdp .so-swatch:hover,
.so-pdp .so-swatch:focus,
.so-pdp .so-swatch:focus-visible,
.so-pdp .so-swatch:active {
  background: var(--so-white);
  border-color: var(--so-navy);
  color: var(--so-navy);
  outline: none;
  box-shadow: none;
}

.so-pdp .so-swatch.is-selected:hover,
.so-pdp .so-swatch.is-selected:focus {
  border-color: var(--so-orange);
  color: var(--so-navy);
}

.so-pdp .so-swatch.is-unavailable:hover {
  background: var(--so-white);
  border-color: var(--so-grey-200);
  color: var(--so-grey-300);
}

.so-pdp .so-thumbs__btn:hover,
.so-pdp .so-thumbs__btn:focus,
.so-pdp .so-thumbs__btn:active {
  background: var(--so-white);
  border-color: var(--so-navy);
  outline: none;
  box-shadow: none;
}

.so-swatch.is-selected {
  border-color: var(--so-orange);
  border-width: 2px;
  color: var(--so-navy);
  font-weight: 600;
}

.so-swatch.is-unavailable {
  color: var(--so-grey-300);
  border-color: var(--so-grey-200);
  text-decoration: line-through;
  cursor: not-allowed;
}

.woocommerce div.product .so-pdp table.variations {
  margin: 0;
  border: 0;
  background: none;
}

.so-pdp table.variations tbody,
.so-pdp table.variations tr,
.so-pdp table.variations td,
.so-pdp table.variations th {
  display: block;
  width: auto;
  padding: 0;
  border: 0;
  background: none;
}

.so-pdp table.variations th.label {
  font-family: var(--so-font-display);
  font-size: 13px;
  font-weight: 600;
  color: var(--so-navy);
  text-align: left;
  margin: 0 0 5px;
}

.so-pdp table.variations th.label label { margin: 0; font-weight: 600; }
.so-pdp table.variations td.value { margin: 0 0 var(--so-buy-gap, 14px); }

/* Hidden, not removed. WooCommerce reads and writes this select to work out
   which combinations exist. Deleting it breaks variations entirely. */
.so-pdp table.variations select {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
}

/* WooCommerce puts the Clear link inside the LAST td.value, so its line box
   plus margin stacked on top of that cell's bottom margin. That is the whole
   reason the gap above Quantity was larger than the gap between Color and
   Size, and no amount of tuning the cell margin would have evened it out.

   It is hidden rather than repositioned. Now that the first buyable variation
   is selected on load, Clear would show on every variable product, and using
   it returns the shopper to no selection, a price range and a dead Add to
   Cart. It is a link whose only function is to undo something helpful. */
.so-pdp .reset_variations {
  display: none !important;
}

.woocommerce div.product .so-pdp .woocommerce-variation-price {
  font-family: var(--so-font-display);
  font-size: 22px;
  font-weight: 600;
  color: var(--so-navy);
  margin: 0 0 var(--so-buy-gap, 14px);
}

.so-pdp .woocommerce-variation-price .price { font-size: inherit; margin: 0; }
.so-pdp .woocommerce-variation-availability p { font-size: 13.5px; font-weight: 600; margin: 0 0 var(--so-buy-tight, 6px); }
.so-pdp .woocommerce-variation-description { font-size: 13.5px; color: var(--so-grey-600); margin: 0 0 var(--so-buy-tight, 6px); }

/* ==========================================================================
   25. Below the fold
   Stacked sections, not tabs. A tab hides content behind a click, which costs
   you on a phone and reads as secondary to a crawler.
   ========================================================================== */

.so-pdp__sections,
.woocommerce .related,
.woocommerce .up-sells {
  max-width: var(--so-container);
  margin: 0 auto 30px;
  width: 100%;
}

.so-section {
  background: var(--so-white);
  border: 1px solid var(--so-grey-200);
  border-radius: var(--so-radius);
  padding: 22px 24px;
  margin-bottom: 16px;
}

.so-section__title {
  font-family: var(--so-font-display);
  font-size: 18px;
  font-weight: 600;
  color: var(--so-navy);
  margin: 0 0 14px;
  padding-bottom: 11px;
  border-bottom: 1px solid var(--so-grey-200);
}

.so-section__body {
  font-size: 14.5px;
  line-height: 1.7;
  color: var(--so-ink);
  max-width: 78ch;
}

/* Imported descriptions arrive with h1s and h2s inside them. Left alone they
   render larger than the page title. Everything is flattened to one size. */
.so-section__body h1,
.so-section__body h2,
.so-section__body h3,
.so-section__body h4,
.so-section__body h5,
.so-section__body h6 {
  font-family: var(--so-font-display);
  font-size: 15px;
  font-weight: 600;
  color: var(--so-navy);
  line-height: 1.4;
  margin: 20px 0 8px;
  text-transform: none;
  letter-spacing: 0;
}

.so-section__body > :first-child { margin-top: 0; }
.so-section__body > :last-child { margin-bottom: 0; }
.so-section__body p { margin: 0 0 12px; }
.so-section__body ul,
.so-section__body ol { margin: 0 0 14px; padding-left: 20px; }
.so-section__body li { margin-bottom: 5px; }
.so-section__body .so-speclist { list-style: disc; }

.so-section__body img {
  max-width: 100%;
  height: auto;
  border-radius: var(--so-radius-sm);
}

.so-section__body table { width: 100%; border-collapse: collapse; margin-bottom: 14px; }

.so-section__body table.shop_attributes th,
.so-section__body table.shop_attributes td {
  padding: 10px 13px;
  border-bottom: 1px solid var(--so-grey-200);
  font-size: 13.5px;
  text-align: left;
  line-height: 1.5;
}

.so-section__body table.shop_attributes th {
  width: 30%;
  color: var(--so-grey-600);
  font-weight: 600;
  background: var(--so-grey-50);
}

.so-section__body table.shop_attributes p { margin: 0; }

.woocommerce .so-pdp__sections .woocommerce-tabs { display: none; }

/* reviews */

.so-section--reviews .comment-form-rating .stars a { color: var(--so-orange); }

.so-section--reviews textarea,
.so-section--reviews input[type="text"],
.so-section--reviews input[type="email"] {
  border: 1px solid var(--so-grey-300);
  border-radius: var(--so-radius-sm);
  font-family: var(--so-font-body);
}

.woocommerce .related > h2,
.woocommerce .up-sells > h2 {
  font-family: var(--so-font-display);
  font-size: 19px;
  font-weight: 600;
  color: var(--so-navy);
  margin: 0 0 16px;
}

/* ==========================================================================
   26. Single product — tablet and mobile
   ========================================================================== */

@media (max-width: 991px) {
  .woocommerce div.product .so-pdp,
  .so-pdp {
    grid-template-columns: minmax(0, 1fr);
    gap: 22px;
  }

  .woocommerce div.product .so-pdp .product_title,
  .so-pdp .product_title { font-size: 21px; }

  .woocommerce div.product .so-pdp p.price,
  .so-pdp .summary p.price { font-size: 25px; }

  .so-buy { padding: 15px; }
  .so-section { padding: 17px; }
  .so-section__title { font-size: 16px; }
  .so-section__body { font-size: 14px; }
}

@media (max-width: 600px) {
  .so-pdp .flex-control-thumbs li { width: 62px; }
  .so-pdp .flex-control-thumbs { gap: 7px; }
  .so-assurance { gap: 5px 14px; }
}

/* ==========================================================================
   27. WooCommerce notices
   The "added to your cart" bar and its friends. Left alone these arrive in
   WooCommerce's green and Astra's blue button, neither of which belongs here.
   ========================================================================== */

.woocommerce-notices-wrapper { max-width: var(--so-container); margin: 0 auto; width: 100%; }

.woocommerce .woocommerce-message,
.woocommerce .woocommerce-info,
.woocommerce .woocommerce-error,
.woocommerce-page .woocommerce-message,
.woocommerce-page .woocommerce-info,
.woocommerce-page .woocommerce-error {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  background: var(--so-white);
  border: 1px solid var(--so-grey-300);
  border-left: 4px solid var(--so-orange);
  border-radius: var(--so-radius);
  color: var(--so-ink);
  font-family: var(--so-font-body);
  font-size: 14px;
  line-height: 1.5;
  padding: 14px 18px;
  margin: 0 0 18px;
  box-shadow: var(--so-shadow);
}

.woocommerce .woocommerce-message::before,
.woocommerce .woocommerce-info::before,
.woocommerce .woocommerce-error::before {
  position: static;
  flex: 0 0 auto;
  margin: 0;
  font-size: 15px;
  line-height: 1;
  color: var(--so-orange);
}

.woocommerce .woocommerce-message { border-left-color: #1E7A3C; }
.woocommerce .woocommerce-message::before { color: #1E7A3C; }
.woocommerce .woocommerce-error { border-left-color: #B4530A; }
.woocommerce .woocommerce-error::before { color: #B4530A; }

.woocommerce .woocommerce-error { flex-direction: column; align-items: flex-start; }
.woocommerce .woocommerce-error li { margin: 0; }

/* The View cart / Continue shopping button inside a notice.
   Astra styles .woocommerce a.button with its own global colour and wins on
   specificity from its inline dynamic CSS, so these are forced. */
.woocommerce .woocommerce-message a.button,
.woocommerce .woocommerce-info a.button,
.woocommerce .woocommerce-error a.button,
.woocommerce .woocommerce-message .button,
.woocommerce .woocommerce-info .button,
.woocommerce .woocommerce-error .button,
.woocommerce-page .woocommerce-message a.button,
.woocommerce-page .woocommerce-info a.button,
.woocommerce-page .woocommerce-message .button,
.woocommerce .woocommerce-message .button.wc-forward,
.woocommerce .woocommerce-info .button.wc-forward {
  margin-left: auto;
  flex: 0 0 auto;
  display: inline-flex !important;
  align-items: center;
  justify-content: center;
  min-height: 38px;
  padding: 0 20px !important;
  line-height: 1 !important;
  border: 1.5px solid var(--so-orange) !important;
  border-radius: 999px !important;
  background: transparent !important;
  background-color: transparent !important;
  color: var(--so-navy) !important;
  font-family: var(--so-font-body);
  font-size: 13.5px;
  font-weight: 600;
  text-transform: none;
  letter-spacing: 0;
  box-shadow: none !important;
  transition: background .15s ease, border-color .15s ease, color .15s ease;
}

.woocommerce .woocommerce-message a.button:hover,
.woocommerce .woocommerce-info a.button:hover,
.woocommerce .woocommerce-message .button:hover,
.woocommerce .woocommerce-info .button:hover,
.woocommerce-page .woocommerce-message a.button:hover,
.woocommerce-page .woocommerce-message .button:hover {
  background: var(--so-navy) !important;
  background-color: var(--so-navy) !important;
  border-color: var(--so-navy) !important;
  color: var(--so-white) !important;
}

@media (max-width: 600px) {
  .woocommerce .woocommerce-message,
  .woocommerce .woocommerce-info { padding: 12px 14px; font-size: 13.5px; }
  .woocommerce .woocommerce-message .button { margin-left: 0; width: 100%; text-align: center; }
  .so-buy__actions { max-width: none; }
}

/* ==========================================================================
   28. BUTTONS — the whole site, one rule
   ==========================================================================

   Read this before styling any button anywhere in this theme.

   Every button on StoreOH is the same object: transparent at rest with an
   orange border and a navy label, filling navy with a white label on hover.
   Orange never fills at rest. That is the entire system, and it is what keeps
   orange reading as a signal rather than as wallpaper.

   This block exists because the alternative was found not to work. Buttons
   were previously styled surface by surface, one context at a time, and each
   new WooCommerce page brought another button in Astra's blue or WooCommerce's
   purple that had to be chased down separately. The selector list below is
   deliberately broad so a page nobody has looked at yet still comes out right.

   Adding a new surface? Add its selector here, not in a new block.

   Variants live AFTER this and win on specificity:
     .so-buynow ......... grey border, the visibly second action
     :disabled .......... grey throughout
     notice buttons ..... shorter, in section 27
   ========================================================================== */

.woocommerce a.button,
.woocommerce button.button,
.woocommerce input.button,
.woocommerce a.button.alt,
.woocommerce button.button.alt,
.woocommerce input.button.alt,
.woocommerce #respond input#submit,
.woocommerce #place_order,
.woocommerce-page a.button,
.woocommerce-page button.button,
.woocommerce-page input.button,
.woocommerce-page a.button.alt,
.woocommerce-page button.button.alt,
.woocommerce-page input.button.alt,
.woocommerce-page #respond input#submit,
.woocommerce .wc-block-components-button,
.woocommerce-cart .wc-proceed-to-checkout a.checkout-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 44px;
  padding: 11px 24px;
  border: 1.5px solid var(--so-orange);
  border-radius: 999px;
  background: transparent;
  background-color: transparent;
  color: var(--so-navy);
  font-family: var(--so-font-body);
  font-size: 14.5px;
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: 0;
  text-transform: none;
  text-decoration: none;
  text-align: center;
  box-shadow: none;
  cursor: pointer;
  transition: background .15s ease, border-color .15s ease, color .15s ease;
}

.woocommerce a.button:hover,
.woocommerce button.button:hover,
.woocommerce input.button:hover,
.woocommerce a.button.alt:hover,
.woocommerce button.button.alt:hover,
.woocommerce input.button.alt:hover,
.woocommerce #respond input#submit:hover,
.woocommerce #place_order:hover,
.woocommerce-page a.button:hover,
.woocommerce-page button.button:hover,
.woocommerce-page input.button:hover,
.woocommerce-page a.button.alt:hover,
.woocommerce-page button.button.alt:hover,
.woocommerce-page #respond input#submit:hover,
.woocommerce .wc-block-components-button:hover,
.woocommerce-cart .wc-proceed-to-checkout a.checkout-button:hover {
  background: var(--so-navy);
  background-color: var(--so-navy);
  border-color: var(--so-navy);
  color: var(--so-white);
}

.woocommerce a.button:focus-visible,
.woocommerce button.button:focus-visible,
.woocommerce input.button:focus-visible {
  outline: 2px solid var(--so-orange);
  outline-offset: 2px;
}

.woocommerce a.button.disabled,
.woocommerce button.button.disabled,
.woocommerce button.button:disabled,
.woocommerce input.button:disabled,
.woocommerce-page button.button:disabled {
  background: transparent;
  border-color: var(--so-grey-200);
  color: var(--so-grey-300);
  cursor: not-allowed;
  opacity: 1;
}

/* Product cards keep their own sizing; only the colours are shared. */
.woocommerce ul.products li.product .button,
.woocommerce ul.products li.product .added_to_cart {
  min-height: 0;
  padding: 9px 14px;
  font-size: 13.5px;
}

/* Coupon and quantity inputs sit next to buttons and should match their
   height, or the cart page looks assembled rather than designed. */
.woocommerce .coupon input.input-text,
.woocommerce table.cart td.actions .input-text {
  min-height: 44px;
  border: 1px solid var(--so-grey-300);
  border-radius: var(--so-radius-sm);
  font-family: var(--so-font-body);
  font-size: 14px;
  padding: 0 14px;
}

/* ==========================================================================
   29. Single product — mobile reading order
   Title, then the photo, then the thumbnails, then the decision.

   display: contents removes the summary box so its children become flex items
   of .so-pdp in their own right. That is the only way to lift the title above
   the gallery, since the two live in different parents.
   ========================================================================== */

@media (max-width: 991px) {
  .woocommerce div.product .so-pdp,
  .so-pdp {
    display: flex;
    flex-direction: column;
    gap: 0;
  }

  /* Column flex inherits align-items: start from the desktop rule, which sizes
     each child to its content. That is why the buy panel sat narrower than
     the cards below it. */
  .so-pdp { align-items: stretch; }

  .so-pdp .summary.entry-summary { display: contents; }

  .woocommerce div.product .so-pdp .product_title,
  .so-pdp .product_title { order: 1; margin-bottom: 10px; }

  /* Under the title, above the photo. After the thumbnail strip, which is
     where it landed before, it read as a caption for the gallery. */
  .so-pdp__cat { order: 2; margin-bottom: 14px; }

  /* A rule under the thumbnails, not just a margin. On a phone the photo
     block runs straight into the price with nothing to say one has ended and
     the other begun, and margin alone reads as a gap rather than as a
     division. This separates browsing from buying. */
  .so-pdp__gallery {
    order: 3;
    margin: 0 0 22px !important;
    padding-bottom: 20px;
    border-bottom: 1px solid var(--so-grey-200);
  }

  .woocommerce div.product .so-pdp p.price,
  .so-pdp .summary p.price {
    order: 4;
    font-size: 26px;
    line-height: 1.2;
    margin: 14px 0 18px;
  }

  .so-buy { order: 5; width: 100%; }
  .so-pdp__sku { order: 6; }
  .so-pdp__about { order: 7; }

  /* Main image above its thumbnails, which is not the DOM order. */
  .so-pdp__gallery {
    display: flex;
    flex-direction: column;
  }

  .so-pdp__gallery > div.images,
  .so-pdp__gallery > .woocommerce-product-gallery { order: 1; }

  /* One scrolling row rather than a wrapping block. Ten photos wrapped to
     three rows of thumbnails pushed the price and the buy panel most of a
     screen further down, which is the wrong thing to spend a phone viewport
     on. */
  .so-pdp__gallery > .so-thumbs {
    order: 2;
    margin: 12px 0 0 !important;
    flex-wrap: nowrap;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scroll-snap-type: x proximity;
    -webkit-overflow-scrolling: touch;
    padding-bottom: 6px !important;
  }

  .so-pdp__gallery > .so-thumbs .so-thumbs__item {
    flex: 0 0 auto;
    width: 66px;
    scroll-snap-align: start;
  }

  /* Zoom is a pointer behaviour. On touch the lightbox does the job. */
  .so-pdp .woocommerce-product-gallery__image,
  .so-pdp .woocommerce-product-gallery__image > a { cursor: default; }
}

/* NAMING — READ BEFORE ADDING A CLASS HERE

   The header cart link is .so-cart, set in section 12. This page grid was
   originally called .so-cart too, which turned that link into a two column
   grid and pushed the cart badge through the account block. The page is
   .so-cartpage for that reason. Do not shorten it back.

   Same trap in script: document.querySelector('.so-cart') on a cart page
   returns the HEADER link, because it comes first in the DOM. */

/* ==========================================================================
   30. CART PAGE
   ==========================================================================

   The layout is built with CSS grid applied to WooCommerce's own table
   elements. The table, its rows and its cells are re-typed to grid and block
   and then placed by name.

   That is deliberate and it is not a shortcut. WooCommerce's cart.js re-renders
   .woocommerce-cart-form and .cart_totals over AJAX on every quantity change,
   coupon and removal, replacing whatever markup was there with a fresh copy
   from the server. A layout built by rewriting the markup in a template
   override would survive that; a layout built in a JavaScript DOM shuffle
   would not. Styling the real elements means the page comes back correct
   after every update with nothing to re-run.

   The one thing that IS added by script is the pair of quantity buttons, and
   they are re-added on WooCommerce's updated_wc_div event.

   Column order, left to right: image, name, price, quantity, line total.
   Remove sits under the name rather than in a column of its own, because a
   column of crosses is a column of accidents.
   ========================================================================== */

/* Astra prints the page title above the shortcode. Ours carries the count. */
.so-cart-page .entry-header .entry-title,
.so-cart-page .ast-archive-description { display: none; }

.so-cart-head {
  display: flex;
  align-items: baseline;
  gap: 12px;
  flex-wrap: wrap;
  padding-bottom: 14px;
  margin-bottom: 20px;
  border-bottom: 1px solid var(--so-grey-200);
}

.so-cart-head__title {
  font-family: var(--so-font-display);
  font-size: 26px;
  font-weight: 600;
  line-height: 1.15;
  color: var(--so-navy);
  margin: 0;
}

.so-cart-head__count {
  font-size: 14px;
  color: var(--so-grey-600);
  margin: 0;
}

/* --------------------------------------------------------------- the grid */

.so-cartpage {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 348px;
  align-items: start;
  gap: 26px;
}

/* min-width: 0 is what stops a long product title blowing the whole column
   out to the width of its content. Grid tracks default to min-width: auto. */
.so-cartpage__main,
.so-cartpage__aside { min-width: 0; }

.so-cartpage__aside {
  position: sticky;
  top: 16px;
}

/* --------------------------------------------------- free delivery meter */

.so-meter {
  border: 1px solid var(--so-grey-200);
  border-radius: var(--so-radius);
  background: var(--so-grey-50);
  padding: 12px 14px;
  margin-bottom: 18px;
}

.so-meter__text {
  display: flex;
  align-items: center;
  gap: 9px;
  margin: 0 0 9px;
  font-size: 14px;
  line-height: 1.35;
  color: var(--so-ink);
}

.so-meter__text strong { font-weight: 600; color: var(--so-navy); }

.so-meter__icon {
  display: inline-flex;
  flex: 0 0 auto;
  color: var(--so-orange);
}

.so-meter__track {
  height: 6px;
  border-radius: 999px;
  background: var(--so-grey-200);
  overflow: hidden;
}

.so-meter__fill {
  display: block;
  height: 100%;
  border-radius: 999px;
  background: var(--so-orange);
  transition: width .3s ease;
}

.so-meter.is-eligible { border-color: rgba(6, 118, 71, .3); background: rgba(6, 118, 71, .06); }
.so-meter.is-eligible .so-meter__icon { color: var(--so-in-stock); }
.so-meter.is-eligible .so-meter__fill { background: var(--so-in-stock); }

/* --------------------------------------------------- table becomes a list */

.woocommerce-cart .woocommerce-cart-form { margin: 0; }

.woocommerce-cart table.shop_table.cart,
.woocommerce-cart table.cart {
  display: block;
  width: 100%;
  border: 0;
  border-radius: 0;
  margin: 0;
  background: transparent;
}

.woocommerce-cart table.cart thead,
.woocommerce-cart table.cart tbody { display: block; width: 100%; }

/* Every row goes to block first, then the item rows go to grid. Doing it in
   that order avoids :has() on the actions row, which would otherwise be the
   only thing on the page needing it. */
.woocommerce-cart table.cart tbody > tr { display: block; width: 100%; }

/* The header strip. Same track sizes as a row so the labels sit over their
   own columns rather than near them. */
.woocommerce-cart table.cart thead tr {
  display: grid;
  grid-template-columns: 88px minmax(0, 1fr) 96px 128px 104px;
  column-gap: 16px;
  align-items: center;
  padding: 0 0 9px;
  border-bottom: 1px solid var(--so-grey-200);
}

.woocommerce-cart table.cart thead th {
  padding: 0;
  border: 0;
  background: transparent;
  font-family: var(--so-font-body);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--so-grey-600);
}

.woocommerce-cart table.cart thead th.product-remove { display: none; }
.woocommerce-cart table.cart thead th.product-price,
.woocommerce-cart table.cart thead th.product-quantity { text-align: left; }
.woocommerce-cart table.cart thead th.product-subtotal { text-align: right; }

/* --------------------------------------------------------------- one item */

.woocommerce-cart table.cart tbody tr.cart_item {
  display: grid;
  grid-template-columns: 88px minmax(0, 1fr) 96px 128px 104px;
  grid-template-areas:
    "thumb name  price qty total"
    "thumb rm    price qty total";
  grid-template-rows: auto auto;
  column-gap: 16px;
  align-content: start;
  padding: 18px 0;
  border-bottom: 1px solid var(--so-grey-200);
  background: transparent !important;
}

.woocommerce-cart table.cart tbody tr.cart_item td {
  display: block;
  padding: 0;
  border: 0;
  background: transparent;
  vertical-align: top;
}

/* shop_table_responsive prints a data-title label before every cell below
   768px. This layout supplies its own, so they are switched off outright. */
.woocommerce-cart table.cart tbody tr.cart_item td::before { content: none !important; }

.woocommerce-cart table.cart td.product-thumbnail { grid-area: thumb; }
.woocommerce-cart table.cart td.product-name      { grid-area: name; }
.woocommerce-cart table.cart td.product-remove    { grid-area: rm; }
.woocommerce-cart table.cart td.product-price     { grid-area: price; align-self: start; }
.woocommerce-cart table.cart td.product-quantity  { grid-area: qty; align-self: start; }
.woocommerce-cart table.cart td.product-subtotal  { grid-area: total; align-self: start; text-align: right; }

/* Image. WooCommerce hard-sets 32px on cart thumbnails, which is a thumbnail
   of a thumbnail. At 88px the photo is doing what it is there for: reminding
   someone what they picked. */
.woocommerce-cart table.cart td.product-thumbnail a { display: block; }

.woocommerce-cart table.cart td.product-thumbnail img {
  width: 88px !important;
  height: 88px;
  object-fit: contain;
  background: var(--so-white);
  border: 1px solid var(--so-grey-200);
  border-radius: var(--so-radius-sm);
  padding: 4px;
}

/* Name cell. Flex column so the order can be set: title, variation data,
   then our stock and delivery line, which WooCommerce fires before the
   variation data rather than after it. */
.woocommerce-cart table.cart td.product-name {
  display: flex;
  flex-direction: column;
  gap: 5px;
  min-width: 0;
  padding-top: 1px;
}

.woocommerce-cart table.cart td.product-name > a {
  order: 1;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  font-family: var(--so-font-body);
  font-size: 14.5px;
  font-weight: 500;
  line-height: 1.4;
  color: var(--so-ink);
}

.woocommerce-cart table.cart td.product-name > a:hover { color: var(--so-orange-600); }

.woocommerce-cart table.cart td.product-name .variation {
  order: 2;
  display: flex;
  flex-wrap: wrap;
  gap: 4px 12px;
  margin: 0;
  font-size: 12.5px;
  color: var(--so-grey-600);
}

.woocommerce-cart table.cart td.product-name .variation dt,
.woocommerce-cart table.cart td.product-name .variation dd {
  margin: 0;
  padding: 0;
  float: none;
  clear: none;
  font-weight: 400;
}

.woocommerce-cart table.cart td.product-name .variation dt { font-weight: 600; color: var(--so-navy); }
.woocommerce-cart table.cart td.product-name .variation dd p { margin: 0; }

.so-ci-meta {
  order: 3;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 3px 14px;
  font-size: 12.5px;
  line-height: 1.5;
}

.so-ci-stock { font-weight: 600; }
.so-ci-stock--in        { color: var(--so-in-stock); }
.so-ci-stock--low       { color: var(--so-low-stock); }
.so-ci-stock--backorder { color: var(--so-low-stock); }
.so-ci-stock--out       { color: var(--so-grey-600); }

.so-ci-eta { color: var(--so-grey-600); }
.so-ci-eta strong { color: var(--so-ink); font-weight: 600; }

.woocommerce-cart table.cart td.product-name .backorder_notification {
  order: 4;
  margin: 0;
  font-size: 12.5px;
  color: var(--so-low-stock);
}

/* Remove, as a word. */
.woocommerce-cart table.cart td.product-remove { padding-top: 4px; }

.woocommerce-cart table.cart td.product-remove a.remove,
.woocommerce-cart table.cart td.product-remove a.so-remove {
  display: inline-flex;
  align-items: center;
  width: auto;
  height: auto;
  border-radius: 0;
  background: none !important;
  color: var(--so-grey-600) !important;
  font-family: var(--so-font-body);
  font-size: 12.5px;
  font-weight: 500;
  line-height: 1.4;
  text-decoration: underline;
  text-underline-offset: 2px;
}

.woocommerce-cart table.cart td.product-remove a.remove:hover {
  color: var(--so-orange-600) !important;
  background: none !important;
}

/* Price and line total. */
.woocommerce-cart table.cart td.product-price {
  font-size: 14px;
  color: var(--so-grey-600);
  padding-top: 1px;
}

.woocommerce-cart table.cart td.product-subtotal {
  font-family: var(--so-font-display);
  font-size: 16px;
  font-weight: 600;
  color: var(--so-navy);
  padding-top: 1px;
}

.woocommerce-cart table.cart td.product-price del,
.woocommerce-cart table.cart td.product-subtotal del {
  color: var(--so-grey-600);
  font-weight: 400;
  font-size: .86em;
}

.woocommerce-cart table.cart td.product-price ins,
.woocommerce-cart table.cart td.product-subtotal ins {
  text-decoration: none;
  color: var(--so-orange-600);
}

/* ------------------------------------------------------ quantity stepper */

.woocommerce-cart table.cart td.product-quantity .quantity {
  display: inline-flex;
  align-items: stretch;
  float: none;
  margin: 0;
  border: 1px solid var(--so-grey-300);
  border-radius: 999px;
  background: var(--so-white);
  overflow: hidden;
}

.woocommerce-cart table.cart td.product-quantity .quantity input.qty {
  width: 42px;
  min-height: 0;
  height: 36px;
  padding: 0 2px;
  border: 0;
  border-radius: 0;
  background: transparent;
  font-family: var(--so-font-body);
  font-size: 14px;
  font-weight: 600;
  color: var(--so-ink);
  text-align: center;
  box-shadow: none;
  -moz-appearance: textfield;
  appearance: textfield;
}

.woocommerce-cart table.cart td.product-quantity .quantity input.qty::-webkit-outer-spin-button,
.woocommerce-cart table.cart td.product-quantity .quantity input.qty::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}

.so-qty-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  min-height: 36px;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--so-navy);
  font-family: var(--so-font-body);
  font-size: 17px;
  font-weight: 600;
  line-height: 1;
  cursor: pointer;
  transition: background .15s ease, color .15s ease;
}

.so-qty-btn:hover { background: var(--so-grey-100); }
.so-qty-btn:disabled { color: var(--so-grey-300); cursor: not-allowed; background: transparent; }

/* While the line is waiting on the server. Subtle on purpose: WooCommerce
   already dims the whole form, and two overlays read as a stutter. */
.quantity.is-busy { opacity: .5; pointer-events: none; }

/* The update button is only reachable when the script is not running. With
   it running the line updates itself, and a button that never needs pressing
   is a button that makes people wonder if they missed a step. */
.so-cart-page.so-cart-auto-on .woocommerce-cart-form.so-auto-live td.actions button[name="update_cart"],
.so-cart-page.so-cart-auto-on .woocommerce-cart-form.so-auto-live td.actions input[name="update_cart"] {
  display: none;
}

/* -------------------------------------------------- coupon / actions row */

.woocommerce-cart table.cart td.actions {
  display: block;
  width: 100%;
  padding: 18px 0 0;
  border: 0;
  background: transparent;
  text-align: left;
}

.woocommerce-cart table.cart td.actions::before { content: none !important; }

.so-coupon-toggle {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 0;
  border: 0;
  background: none;
  color: var(--so-navy);
  font-family: var(--so-font-body);
  font-size: 13.5px;
  font-weight: 600;
  cursor: pointer;
}

.so-coupon-toggle svg { color: var(--so-orange); }
.so-coupon-toggle:hover { color: var(--so-orange-600); }

.woocommerce-cart table.cart td.actions .coupon {
  display: flex;
  align-items: center;
  gap: 8px;
  float: none;
  width: auto;
  max-width: 420px;
  padding: 0;
  margin: 12px 0 0;
}

.woocommerce-cart table.cart td.actions .coupon.is-collapsed { display: none; }

.woocommerce-cart table.cart td.actions .coupon label { display: none; }

.woocommerce-cart table.cart td.actions .coupon input.input-text {
  flex: 1 1 auto;
  width: auto;
  min-height: 42px;
  margin: 0;
  border: 1px solid var(--so-grey-300);
  border-radius: 999px;
  background: var(--so-white);
  font-size: 14px;
  padding: 0 16px;
}

.woocommerce-cart table.cart td.actions .coupon .button {
  flex: 0 0 auto;
  min-height: 42px;
  padding: 0 20px;
  font-size: 13.5px;
}

.woocommerce-cart table.cart td.actions > button[name="update_cart"],
.woocommerce-cart table.cart td.actions > input[name="update_cart"] {
  float: none;
  margin: 12px 0 0;
  min-height: 42px;
  padding: 0 20px;
  font-size: 13.5px;
}

.so-cart-back {
  margin: 18px 0 0;
  font-size: 14px;
}

.so-cart-back a {
  color: var(--so-navy);
  font-weight: 500;
}

.so-cart-back a:hover { color: var(--so-orange-600); }

/* ------------------------------------------------------- order summary */

.woocommerce-cart .so-cartpage__aside .cart-collaterals,
.woocommerce-cart .so-cartpage__aside .cart-collaterals .cart_totals {
  width: 100%;
  float: none;
  margin: 0;
}

.woocommerce-cart .so-cartpage__aside .cart_totals {
  border: 1px solid var(--so-grey-200);
  border-radius: var(--so-radius);
  background: var(--so-grey-50);
  padding: 18px;
}

/* WooCommerce's own "Cart totals" heading. Hidden rather than filtered out,
   so anything reading the DOM for it still finds it. */
.woocommerce-cart .so-cartpage__aside .cart_totals > h2 { display: none; }

.so-sum__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  padding-bottom: 12px;
  margin-bottom: 4px;
  border-bottom: 1px solid var(--so-grey-200);
}

.so-sum__title {
  font-family: var(--so-font-display);
  font-size: 17px;
  font-weight: 600;
  color: var(--so-navy);
  margin: 0;
}

.so-sum__count {
  font-size: 13px;
  color: var(--so-grey-600);
}

.woocommerce-cart .so-cartpage__aside .cart_totals table.shop_table {
  display: table;
  width: 100%;
  border: 0;
  border-radius: 0;
  margin: 0;
  background: transparent;
}

.woocommerce-cart .so-cartpage__aside .cart_totals table.shop_table tr { border: 0; }

.woocommerce-cart .so-cartpage__aside .cart_totals table.shop_table th,
.woocommerce-cart .so-cartpage__aside .cart_totals table.shop_table td {
  padding: 9px 0;
  border: 0;
  background: transparent;
  font-family: var(--so-font-body);
  font-size: 14px;
  line-height: 1.5;
  vertical-align: top;
}

.woocommerce-cart .so-cartpage__aside .cart_totals table.shop_table th {
  width: 46%;
  font-weight: 500;
  color: var(--so-grey-600);
  text-transform: none;
  letter-spacing: 0;
}

.woocommerce-cart .so-cartpage__aside .cart_totals table.shop_table td {
  text-align: right;
  font-weight: 500;
  color: var(--so-ink);
}

.woocommerce-cart .so-cartpage__aside .cart_totals tr.cart-discount td { color: var(--so-in-stock); }

.woocommerce-cart .so-cartpage__aside .cart_totals tr.order-total th,
.woocommerce-cart .so-cartpage__aside .cart_totals tr.order-total td {
  padding-top: 14px;
  border-top: 1px solid var(--so-grey-200);
  font-family: var(--so-font-display);
  font-size: 19px;
  font-weight: 600;
  color: var(--so-navy);
}

.woocommerce-cart .so-cartpage__aside .cart_totals tr.order-total small {
  display: block;
  font-family: var(--so-font-body);
  font-size: 11.5px;
  font-weight: 400;
  color: var(--so-grey-600);
}

/* Shipping. Kept, not hidden: a total that changes at checkout is the single
   most common reason a full cart is abandoned. */
.woocommerce-cart .so-cartpage__aside .cart_totals .woocommerce-shipping-methods {
  margin: 0;
  padding: 0;
  list-style: none;
  text-align: right;
}

.woocommerce-cart .so-cartpage__aside .cart_totals .woocommerce-shipping-methods li {
  margin: 0 0 4px;
  font-size: 13.5px;
}

.woocommerce-cart .so-cartpage__aside .cart_totals .woocommerce-shipping-destination {
  margin: 6px 0 0;
  font-size: 12.5px;
  color: var(--so-grey-600);
}

.woocommerce-cart .so-cartpage__aside .cart_totals .shipping-calculator-button {
  font-size: 12.5px;
  font-weight: 600;
  color: var(--so-navy);
  text-decoration: underline;
  text-underline-offset: 2px;
}

.woocommerce-cart .so-cartpage__aside .cart_totals .shipping-calculator-form {
  margin-top: 10px;
  text-align: left;
}

.woocommerce-cart .so-cartpage__aside .cart_totals .shipping-calculator-form .button {
  width: 100%;
  min-height: 40px;
  font-size: 13.5px;
}

/* The one action on the page. */
.woocommerce-cart .so-cartpage__aside .wc-proceed-to-checkout {
  padding: 16px 0 0;
  margin: 0;
}

.woocommerce-cart .so-cartpage__aside .wc-proceed-to-checkout a.checkout-button {
  display: flex;
  width: 100%;
  min-height: 50px;
  margin: 0;
  padding: 13px 20px;
  font-family: var(--so-font-display);
  font-size: 15.5px;
  font-weight: 600;
  letter-spacing: .01em;
}

/* Optional variant. Switched on with STOREOH_CART_CTA_SOLID in functions.php.
   It is the one place on the store where orange fills at rest, so it is off
   by default and turned on deliberately, not by drifting into it. */
.so-cart-cta-solid .so-cartpage__aside .wc-proceed-to-checkout a.checkout-button,
.so-cart-cta-solid .so-cart-fixed .checkout-button {
  background: var(--so-orange);
  background-color: var(--so-orange);
  border-color: var(--so-orange);
  color: var(--so-white);
}

.so-cart-cta-solid .so-cartpage__aside .wc-proceed-to-checkout a.checkout-button:hover,
.so-cart-cta-solid .so-cart-fixed .checkout-button:hover {
  background: var(--so-orange-600);
  background-color: var(--so-orange-600);
  border-color: var(--so-orange-600);
  color: var(--so-white);
}

.so-sum__note {
  margin: 10px 0 0;
  font-size: 12px;
  line-height: 1.5;
  color: var(--so-grey-600);
  text-align: center;
}

.so-sum__trust {
  margin: 16px 0 0;
  padding: 14px 0 0;
  border-top: 1px solid var(--so-grey-200);
  list-style: none;
}

.so-sum__trust li {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 0 0 9px;
  font-size: 13px;
  color: var(--so-ink);
}

.so-sum__trust li:last-child { margin-bottom: 0; }

.so-sum__trust-icon {
  display: inline-flex;
  flex: 0 0 auto;
  color: var(--so-navy-500);
}

.so-sum__pay {
  margin: 12px 0 0;
  font-size: 12px;
  color: var(--so-grey-600);
  text-align: center;
}

/* --------------------------------------------------------- fixed bar, phone
   Built by script from the real total and the real checkout link, so it can
   never disagree with the summary. It hides itself while the summary button
   is on screen, so there is never a moment with two of the same button
   visible at once. */

.so-cart-fixed {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 9000;
  display: none;
  align-items: center;
  gap: 12px;
  padding: 10px 14px calc(10px + env(safe-area-inset-bottom, 0px));
  background: var(--so-white);
  border-top: 1px solid var(--so-grey-200);
  box-shadow: 0 -4px 18px rgba(16, 33, 52, .12);
  transform: translateY(110%);
  transition: transform .22s ease;
}

.so-cart-fixed.is-visible { transform: translateY(0); }

.so-cart-fixed__total {
  display: flex;
  flex-direction: column;
  line-height: 1.25;
  min-width: 0;
}

.so-cart-fixed__label {
  font-size: 11.5px;
  color: var(--so-grey-600);
}

.so-cart-fixed__value {
  font-family: var(--so-font-display);
  font-size: 18px;
  font-weight: 600;
  color: var(--so-navy);
}

/* The bar is appended to <body>, which puts it outside the .woocommerce
   wrapper that the button block in section 28 is scoped to. So this one
   button has to be dressed by hand. Same object, same values. */
.so-cart-fixed .checkout-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 1 1 auto;
  min-height: 46px;
  padding: 11px 20px;
  border: 1.5px solid var(--so-orange);
  border-radius: 999px;
  background: transparent;
  color: var(--so-navy);
  font-family: var(--so-font-display);
  font-size: 15px;
  font-weight: 600;
  line-height: 1.2;
  text-align: center;
  text-decoration: none;
  transition: background .15s ease, border-color .15s ease, color .15s ease;
}

.so-cart-fixed .checkout-button:hover,
.so-cart-fixed .checkout-button:active {
  background: var(--so-navy);
  border-color: var(--so-navy);
  color: var(--so-white);
}

/* ------------------------------------------------------- recommendations */

.so-cart-recs {
  margin-top: 34px;
  padding-top: 24px;
  border-top: 1px solid var(--so-grey-200);
}

.so-cart-recs__title {
  font-family: var(--so-font-display);
  font-size: 19px;
  font-weight: 600;
  color: var(--so-navy);
  margin: 0 0 14px;
}

/* ------------------------------------------------------------ empty cart */

/* WooCommerce's own empty cart notice and Return to shop button, hidden so the
   designed empty state above is the only thing on screen.

   HIDDEN, NOT REMOVED, and that is not a style preference. When the last item
   goes, cart.js does not reload the page: it looks for .wc-empty-cart-message
   in the fetched response and swaps in that element's .woocommerce ancestor.
   Take the notice out of the markup and the lookup returns nothing, and
   jQuery's replaceWith on an empty set deletes rather than replaces — which
   left a blank page with no cart and no way out. Display: none keeps the
   element findable and off screen at the same time. */
.woocommerce-cart .cart-empty,
.woocommerce-cart .wc-empty-cart-message,
.woocommerce-cart .return-to-shop,
.woocommerce-checkout .cart-empty,
.woocommerce-checkout .wc-empty-cart-message,
.woocommerce-checkout .return-to-shop { display: none; }

.so-empty-cart {
  max-width: 520px;
  margin: 30px auto 40px;
  text-align: center;
}

.so-empty-cart__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 78px;
  height: 78px;
  margin-bottom: 18px;
  border-radius: 50%;
  background: var(--so-grey-100);
  color: var(--so-navy-500);
}

.so-empty-cart__title {
  font-family: var(--so-font-display);
  font-size: 22px;
  font-weight: 600;
  color: var(--so-navy);
  margin: 0 0 8px;
}

.so-empty-cart__text {
  font-size: 14.5px;
  line-height: 1.6;
  color: var(--so-grey-600);
  margin: 0 0 20px;
}

.woocommerce-cart .so-empty-cart__cta {
  min-width: 200px;
  min-height: 46px;
}

.so-empty-cart__cats {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 8px;
  margin: 26px 0 0;
  padding: 0;
  list-style: none;
}

.so-empty-cart__cats a {
  display: inline-block;
  padding: 7px 14px;
  border: 1px solid var(--so-grey-300);
  border-radius: 999px;
  font-size: 13px;
  font-weight: 500;
  color: var(--so-navy);
  transition: border-color .15s ease, color .15s ease;
}

.so-empty-cart__cats a:hover {
  border-color: var(--so-navy);
  color: var(--so-orange-600);
}

/* ==========================================================================
   31. Cart — tablet and phone
   ========================================================================== */

@media (max-width: 1100px) {
  .so-cartpage { grid-template-columns: minmax(0, 1fr) 310px; gap: 20px; }
}

@media (max-width: 900px) {
  .so-cartpage {
    grid-template-columns: 1fr;
    gap: 22px;
  }

  /* Sticky in a single column would pin the summary to the top of its own
     row and do nothing useful. The fixed bar covers this width instead. */
  .so-cartpage__aside { position: static; }

  .so-cart-head { margin-bottom: 16px; }
  .so-cart-head__title { font-size: 22px; }

  .woocommerce-cart table.cart thead { display: none; }

  .woocommerce-cart table.cart tbody tr.cart_item {
    grid-template-columns: 84px minmax(0, 1fr);
    grid-template-areas:
      "thumb name"
      "thumb price"
      "qty   total"
      "rm    rm";
    column-gap: 14px;
    row-gap: 8px;
    padding: 16px 0;
  }

  .woocommerce-cart table.cart td.product-thumbnail img { width: 84px !important; height: 84px; }

  .woocommerce-cart table.cart td.product-price {
    align-self: start;
    font-size: 13.5px;
  }

  .woocommerce-cart table.cart td.product-quantity { align-self: center; }

  .woocommerce-cart table.cart td.product-subtotal {
    align-self: center;
    font-size: 17px;
  }

  .woocommerce-cart table.cart td.product-remove { padding-top: 0; }

  .woocommerce-cart table.cart td.actions .coupon { max-width: none; }

  .so-cart-fixed { display: flex; }
}

@media (max-width: 600px) {
  .so-cart-head__title { font-size: 20px; }

  .woocommerce-cart table.cart tbody tr.cart_item {
    grid-template-columns: 72px minmax(0, 1fr);
    column-gap: 12px;
  }

  .woocommerce-cart table.cart td.product-thumbnail img { width: 72px !important; height: 72px; }
  .woocommerce-cart table.cart td.product-name > a { font-size: 13.5px; }

  .woocommerce-cart .so-cartpage__aside .cart_totals { padding: 15px; }
  .so-cart-recs__title { font-size: 17px; }

  .so-empty-cart { margin: 18px auto 26px; }
  .so-empty-cart__title { font-size: 19px; }
}

/* ==========================================================================
   32. CART — HOLDING THE LINE AGAINST ASTRA AND WOOCOMMERCE
   ==========================================================================

   Everything in this block is a specificity fight, not a design decision. It
   is kept separate from section 30 so the design stays readable and the
   defensive work is in one place with its reasons attached.

   Three things outrank ordinary class selectors on this page:

   1. WooCommerce writes its cart rules twice, once as `table.cart` and once
      as `#content table.cart`. Astra's content wrapper IS id="content", so
      the second form matches here and carries an ID. No class-only selector
      can beat it, however long. This is why text-align, float and margin
      below are forced rather than merely specific.

   2. Astra injects its own rules into the woocommerce-general stylesheet,
      including a decorative `a.remove:before` — an absolutely positioned
      ring with border-radius 100%, drawn to circle the × that WooCommerce
      normally puts there. With a worded "Remove" label the ring stretches
      into an ellipse and strikes through the text. It has to be removed at
      the pseudo-element, which no amount of styling on the link itself does.

   3. Astra centres the coupon box with auto margins and sets it to flex,
      which also defeats the collapsed state in section 30.

   Rule for anyone adding to this block: `!important` here needs a comment
   naming what it is beating. Anything without one is a guess, and guesses
   are how this file turns into a pile.
   ========================================================================== */

/* Astra's decorative ring around the remove link. Drawn for a × glyph, wrong
   for a word. */
.so-cart-page.woocommerce-cart table.cart td.product-remove a.remove::before,
.so-cart-page.woocommerce-cart table.cart td.product-remove a.remove::after {
  content: none !important;
  display: none !important;
}

.so-cart-page.woocommerce-cart table.cart td.product-remove a.remove {
  position: static !important;  /* Astra sets relative to anchor the ring. */
  padding: 0 !important;
  margin: 2px 0 0 !important;
}

/* WooCommerce centres this cell from the #content block, which parked the
   word "Remove" in the middle of the product column. */
.so-cart-page.woocommerce-cart table.cart td.product-remove {
  text-align: left !important;
}

/* WooCommerce: `#content table.cart td.actions { text-align: right }`. */
.so-cart-page.woocommerce-cart table.cart td.actions {
  text-align: left !important;
}

/* WooCommerce floats the coupon left; Astra then centres it with auto margins
   and forces display: flex, which also overrode the collapsed state. */
.so-cart-page.woocommerce-cart table.cart td.actions .coupon {
  display: flex !important;
  float: none !important;
  width: 100% !important;
  max-width: 430px !important;
  margin: 10px 0 0 !important;
  padding: 0 !important;
}

.so-cart-page.woocommerce-cart table.cart td.actions .coupon.is-collapsed {
  display: none !important;
}

.so-cart-page.woocommerce-cart table.cart td.actions .coupon label {
  display: none !important;
}

/* WooCommerce sets float, border, padding and margin on the coupon field
   inside the same #content block. */
.so-cart-page.woocommerce-cart table.cart td.actions .coupon input.input-text {
  float: none !important;
  flex: 1 1 auto !important;
  width: auto !important;
  min-height: 44px !important;
  margin: 0 !important;
  padding: 0 16px !important;
  border: 1px solid var(--so-grey-300) !important;
  border-radius: 999px !important;
}

.so-cart-page.woocommerce-cart table.cart td.actions .coupon .button {
  float: none !important;
  flex: 0 0 auto !important;
  min-height: 44px !important;
  margin: 0 !important;
  padding: 0 22px !important;
}

/* Astra sets display on buttons inside td.actions, which kept the Update cart
   button on screen even though the line updates itself. The rule that hides
   it lives in section 30; this is the same rule with the weight to land. */
.so-cart-page.so-cart-auto-on .woocommerce-cart-form.so-auto-live td.actions button[name="update_cart"],
.so-cart-page.so-cart-auto-on .woocommerce-cart-form.so-auto-live td.actions input[name="update_cart"] {
  display: none !important;
}

/* Two line title clamp, belt and braces.
   Making td.product-name a flex container (section 30, so the stock and
   delivery line can be ordered after the variation data) blockifies its
   children: Chrome rewrites display: -webkit-box to flow-root on a flex item,
   which is the one value -webkit-line-clamp needs. Chrome's newer standard
   line-clamp still holds it to two lines, but Safari's does not, so a plain
   max-height does the clipping and the clamp adds the ellipsis wherever it
   is honoured. Neither one alone covers both. */
.so-cart-page.woocommerce-cart table.cart td.product-name > a {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  max-height: 2.8em;
  overflow: hidden;
}

/* Section 8 gives shop tables a filled header row. The cart wants a rule, not
   a band. */
.so-cart-page.woocommerce-cart table.cart thead th {
  background: transparent !important;
}

/* The quantity box: Astra sets a width on .quantity and on the input. */
.so-cart-page.woocommerce-cart table.cart td.product-quantity .quantity {
  width: auto !important;
  max-width: none !important;
}

.so-cart-page.woocommerce-cart table.cart td.product-quantity .quantity input.qty {
  width: 42px !important;
  max-width: 42px !important;
  padding: 0 2px !important;
  margin: 0 !important;
  border: 0 !important;
  border-radius: 0 !important;
  box-shadow: none !important;
}

/* WooCommerce's `#content ... .button.alt { float: right }` would drag the
   checkout button out of the summary panel. */
.so-cart-page.woocommerce-cart .wc-proceed-to-checkout a.checkout-button {
  float: none !important;
  width: 100% !important;
  margin: 0 !important;
}

/* Vertical rhythm: WooCommerce sets vertical-align: middle on every cart cell
   from the same #content block, which fights the grid placement. */
.so-cart-page.woocommerce-cart table.cart tbody tr.cart_item td {
  vertical-align: top !important;
}

/* --------------------------------------------------------------- phone
   WooCommerce's shop_table_responsive right-aligns every cell with
   !important below 768px. It does that on the assumption the table has
   collapsed into label-on-the-left, value-on-the-right pairs, which is what
   its own mobile cart does. This one has not collapsed, it has become a card
   grid, so the assumption is wrong and every product title, price and
   quantity ended up hard against the right edge. */

@media (max-width: 768px) {
  .so-cart-page.woocommerce-cart table.cart tbody tr.cart_item td.product-name,
  .so-cart-page.woocommerce-cart table.cart tbody tr.cart_item td.product-name > a,
  .so-cart-page.woocommerce-cart table.cart tbody tr.cart_item td.product-price,
  .so-cart-page.woocommerce-cart table.cart tbody tr.cart_item td.product-quantity,
  .so-cart-page.woocommerce-cart table.cart tbody tr.cart_item td.product-remove,
  .so-cart-page.woocommerce-cart table.cart td.actions {
    text-align: left !important;
  }

  .so-cart-page.woocommerce-cart table.cart tbody tr.cart_item td.product-subtotal {
    text-align: right !important;
  }

  /* Same stylesheet stripes alternate rows. The rows here are separated by a
     rule, not a fill. */
  .so-cart-page.woocommerce-cart table.cart tbody tr.cart_item,
  .so-cart-page.woocommerce-cart table.cart tbody tr.cart_item td {
    background-color: transparent !important;
  }
}

/* Clearance for the fixed bar.
   The spacer is a real element appended after the footer by the script rather
   than padding on a wrapper, because the wrapper's name is not knowable: this
   site's footer is built in Elementor, so .site-footer does not exist and a
   rule hung on it silently did nothing. An element the theme creates itself
   is always the right height and always in the right place. */
.so-cart-fixed-spacer { display: none; }

@media (max-width: 900px) {
  .so-cart-page.so-cart-sticky-on .so-cart-fixed-spacer {
    display: block;
    height: calc(74px + env(safe-area-inset-bottom, 0px));
  }
}

/* --------------------------------------------------- the coupon disclosure

   Astra styles every <button> on the page, including ones that are not meant
   to look like buttons: `button:hover` sets a solid fill and color: #fff.
   The "Have a coupon code?" link is a <button> because it toggles something,
   so it inherited a blue block and white-turning-orange text on hover. It has
   to be reset in all four states, not just at rest. */

.so-cart-page .so-coupon-toggle,
.so-cart-page .so-coupon-toggle:hover,
.so-cart-page .so-coupon-toggle:focus,
.so-cart-page .so-coupon-toggle:active {
  background: none !important;
  background-color: transparent !important;
  border: 0 !important;
  box-shadow: none !important;
  padding: 0 !important;
  color: var(--so-navy) !important;
}

.so-cart-page .so-coupon-toggle:hover {
  color: var(--so-orange-600) !important;
}

.so-cart-page .so-coupon-toggle:focus-visible {
  outline: 2px solid var(--so-orange);
  outline-offset: 3px;
}

/* --------------------------------------------------- the coupon error state

   WooCommerce puts its coupon error INSIDE the .coupon element, as
   <p class="coupon-error-notice">, and adds .has-error to the field. Since
   .coupon is a flex row, that paragraph arrived as a third flex item: it got
   squeezed to about a word wide and wrapped down the page, which stretched
   the row to 277px, which stretched the field to 277px, which — with the pill
   radius on it — turned the coupon box into a circle.

   Three things stop that. The row wraps, the notice claims a full row of its
   own, and the field's height is pinned rather than left to the row. */

.so-cart-page.woocommerce-cart table.cart td.actions .coupon {
  flex-wrap: wrap !important;
  align-items: center !important;
  column-gap: 8px !important;
  row-gap: 10px !important;   /* Not 0. Whatever wraps onto the next line —
                                 the button on a narrow screen, the error
                                 notice on any screen — needs clearance, and
                                 a row-gap is the one value that covers both
                                 without either element carrying a margin
                                 that then has to be cancelled elsewhere. */
}

.so-cart-page.woocommerce-cart table.cart td.actions .coupon input.input-text {
  flex: 1 1 150px !important;
  min-width: 0 !important;       /* flex items default to min-width: auto,
                                    which is what stopped the field shrinking
                                    to fit a phone. */
  height: 44px !important;
  max-height: 44px !important;
  align-self: center !important;
}

.so-cart-page.woocommerce-cart table.cart td.actions .coupon input.input-text.has-error {
  border-color: var(--so-error) !important;
}

.so-cart-page.woocommerce-cart table.cart td.actions .coupon .coupon-error-notice {
  flex: 1 0 100% !important;
  order: 9 !important;           /* after the field and the button, whatever
                                    order WooCommerce inserts it in. */
  width: 100% !important;
  margin: 0 !important;          /* Spacing comes from the row-gap above, so
                                    there is one place to change it. */
  padding: 0 !important;
  border: 0;
  background: none;
  font-size: 12.5px;
  line-height: 1.45;
  color: var(--so-error);
}

@media (max-width: 600px) {
  /* Give the field back the width the button was taking. */
  .so-cart-page.woocommerce-cart table.cart td.actions .coupon .button {
    padding: 0 16px !important;
    font-size: 13px;
  }
}

@media (max-width: 480px) {
  /* Below this the two will not sit side by side at a usable field width, so
     they stack on purpose rather than wrapping by accident. Both go full
     width: a half width button sitting under a full width field reads as a
     layout fault, and a full width one is a better thumb target anyway. */
  .so-cart-page.woocommerce-cart table.cart td.actions .coupon input.input-text,
  .so-cart-page.woocommerce-cart table.cart td.actions .coupon .button {
    flex: 1 0 100% !important;
    width: 100% !important;
  }

  .so-cart-page.woocommerce-cart table.cart td.actions .coupon .button {
    padding: 0 20px !important;
    font-size: 13.5px;
  }
}

/* ==========================================================================
   33. CHECKOUT — SKIN ONLY
   ==========================================================================

   This store runs the WooCommerce CHECKOUT BLOCK, not the classic
   [woocommerce_checkout] shortcode. That single fact sets the rules for
   everything below.

   The block is a React application. It owns its own DOM and re-renders on
   every field change, so markup moved underneath it does not stay moved.
   It also hands payment gateways a container to mount into, and for hosted
   card fields that container holds an iframe the gateway sizes itself.

   So this section is a skin and nothing more. Colours, type, spacing,
   borders, radii, focus rings. No layout is rearranged, no element is
   hidden, no behaviour is altered. The page that renders is the page
   WooCommerce shipped, wearing the store's clothes.

   Two rules that are not stylistic preferences:

     1. Nothing is set to display: none. If something should not be on the
        checkout it comes out in WooCommerce settings, not in CSS. Hiding a
        required field here leaves it required and unfillable.

     2. No overflow: hidden on any payment container. A gateway iframe sized
        by its own script gets cropped by it, and the customer sees half a
        card field with nothing in the console to explain it.

   The block styles ship at a high specificity, which is why .so-checkout-page
   prefixes these rules. That class comes from inc/checkout.php and exists for
   no other reason.

   What the block looks like out of the box, and what it becomes:

     Place order button ..... #046BD2, WooCommerce blue ....... theme button
     Inputs ................. 50px, 0.8px near-black, 4px ..... theme field
     Step titles ............ slate #1E293B ................... navy
     Order summary .......... transparent, no border ......... the cart panel
   ========================================================================== */

/* ------------------------------------------------------------ page shell */

.so-checkout-page .entry-header .entry-title {
  font-family: var(--so-font-display);
  font-size: 26px;
  font-weight: 600;
  line-height: 1.15;
  color: var(--so-navy);
  margin-bottom: 20px;
  padding-bottom: 14px;
  border-bottom: 1px solid var(--so-grey-200);
}

/* ---------------------------------------------------------- step headings */

.so-checkout-page .wc-block-components-title,
.so-checkout-page .wc-block-components-checkout-step__title,
.so-checkout-page .wc-block-components-title.wc-block-components-checkout-step__title {
  font-family: var(--so-font-display);
  font-size: 18px;
  font-weight: 600;
  color: var(--so-navy);
  letter-spacing: -0.005em;
}

.so-checkout-page .wc-block-components-checkout-step__description,
.so-checkout-page .wc-block-components-checkout-step__heading-content {
  font-family: var(--so-font-body);
  font-size: 13.5px;
  line-height: 1.55;
  color: var(--so-grey-600);
}

/* The block draws a number badge beside each step heading. */
.so-checkout-page .wc-block-components-checkout-step__heading::before,
.so-checkout-page .wc-block-components-checkout-step:before {
  color: var(--so-grey-600);
}

/* ---------------------------------------------------------------- fields */

.so-checkout-page .wc-block-components-text-input input[type="text"],
.so-checkout-page .wc-block-components-text-input input[type="email"],
.so-checkout-page .wc-block-components-text-input input[type="tel"],
.so-checkout-page .wc-block-components-text-input input[type="number"],
.so-checkout-page .wc-block-components-textarea,
.so-checkout-page .wc-block-components-combobox-control input.components-combobox-control__input,
.so-checkout-page .wc-blocks-components-select .wc-blocks-components-select__select {
  border: 1px solid var(--so-grey-300);
  border-radius: var(--so-radius-sm);
  background: var(--so-white);
  font-family: var(--so-font-body);
  color: var(--so-ink);
  box-shadow: none;
  transition: border-color .15s ease, box-shadow .15s ease;

  /* 16px, and it stays 16px.
     iOS Safari zooms the whole page when a text field smaller than 16px
     takes focus, and it does not zoom back out. The page is then wider than
     the viewport and everything sits cut off at both edges, which reads as
     a broken responsive layout rather than as a zoom. WooCommerce ships the
     block at 16px for exactly this reason; the theme had dropped it to 15
     for looks. One pixel is not worth a broken checkout on an iPhone. */
  font-size: 16px;
}

.so-checkout-page .wc-block-components-text-input input:focus,
.so-checkout-page .wc-block-components-textarea:focus,
.so-checkout-page .wc-block-components-combobox-control input.components-combobox-control__input:focus,
.so-checkout-page .wc-blocks-components-select .wc-blocks-components-select__select:focus {
  border-color: var(--so-orange);
  box-shadow: 0 0 0 3px var(--so-orange-50);
  outline: none;
}

/* The floating label sitting inside the field. */
.so-checkout-page .wc-block-components-text-input label,
.so-checkout-page .wc-blocks-components-select__label {
  font-family: var(--so-font-body);
  font-size: 15px;
  color: var(--so-grey-600);
}

.so-checkout-page .wc-block-components-text-input.is-active label {
  font-size: 12px;
  color: var(--so-grey-600);
}

/* "+ Add apartment, suite, etc." and similar inline reveals. */
.so-checkout-page .wc-block-components-address-form__address_2-toggle {
  font-family: var(--so-font-body);
  font-weight: 500;
  color: var(--so-navy);
}

.so-checkout-page .wc-block-components-address-form__address_2-toggle:hover {
  color: var(--so-orange-600);
}

/* -------------------------------------------------------------- validation
   The block marks a bad field with .has-error and prints a message under it.
   Both are recoloured; neither is moved, and the message is never hidden. */

.so-checkout-page .wc-block-components-text-input.has-error input,
.so-checkout-page .wc-block-components-text-input.has-error input:focus,
.so-checkout-page .wc-block-components-combobox.has-error input {
  border-color: var(--so-error);
}

.so-checkout-page .wc-block-components-text-input.has-error input:focus {
  box-shadow: 0 0 0 3px rgba(180, 35, 24, .12);
}

.so-checkout-page .wc-block-components-validation-error,
.so-checkout-page .wc-block-components-validation-error p {
  font-family: var(--so-font-body);
  font-size: 12.5px;
  line-height: 1.45;
  color: var(--so-error);
}

/* ------------------------------------------------------------- checkboxes */

.so-checkout-page .wc-block-components-checkbox__input[type="checkbox"] {
  border-color: var(--so-grey-300);
  border-radius: 3px;
}

.so-checkout-page .wc-block-components-checkbox__input[type="checkbox"]:checked {
  background-color: var(--so-orange);
  border-color: var(--so-orange);
}

.so-checkout-page .wc-block-components-checkbox__input[type="checkbox"]:focus {
  box-shadow: 0 0 0 3px var(--so-orange-50);
  outline: none;
}

.so-checkout-page .wc-block-components-checkbox__label,
.so-checkout-page .wc-block-checkout__terms {
  font-family: var(--so-font-body);
  font-size: 13.5px;
  line-height: 1.55;
  color: var(--so-ink);
}

.so-checkout-page .wc-block-checkout__terms a,
.so-checkout-page .wc-block-components-checkbox__label a {
  color: var(--so-navy);
  font-weight: 500;
  text-decoration: underline;
  text-underline-offset: 2px;
}

.so-checkout-page .wc-block-checkout__terms a:hover {
  color: var(--so-orange-600);
}

/* -------------------------------------------- radios: shipping and payment
   Used for shipping options and, once a gateway is live, for the payment
   method list. Selected state carries the brand orange. */

.so-checkout-page .wc-block-components-radio-control__option {
  border-color: var(--so-grey-200);
  font-family: var(--so-font-body);
}

.so-checkout-page .wc-block-components-radio-control__option-layout {
  color: var(--so-ink);
}

.so-checkout-page .wc-block-components-radio-control__label {
  font-size: 14.5px;
  font-weight: 500;
  color: var(--so-ink);
}

.so-checkout-page .wc-block-components-radio-control__secondary-label,
.so-checkout-page .wc-block-components-radio-control__description {
  font-size: 13px;
  color: var(--so-grey-600);
}

.so-checkout-page .wc-block-components-radio-control__input {
  border-color: var(--so-grey-300);
}

.so-checkout-page .wc-block-components-radio-control__input:checked {
  border-color: var(--so-orange);
  color: var(--so-orange);
}

.so-checkout-page .wc-block-components-radio-control-accordion-option--checked,
.so-checkout-page .wc-block-components-radio-control__option--checked-option-highlighted {
  border-color: var(--so-orange);
  background: var(--so-orange-50);
}

/* NOTE: no overflow rule on the accordion content below. A hosted card form
   mounts into it as an iframe and sizes itself; clipping it here would crop
   real card fields with nothing in the console to say why. */

/* ------------------------------------------------------------ the sidebar
   Given the same panel treatment as the cart's order summary, so the two
   pages read as one flow rather than two designs. */

.so-checkout-page .wc-block-checkout__sidebar .wc-block-components-sidebar-layout,
.so-checkout-page .wc-block-checkout__sidebar > .wc-block-components-order-summary,
.so-checkout-page .wc-block-checkout__sidebar {
  border-color: var(--so-grey-200);
}

.so-checkout-page .wc-block-components-checkout-order-summary,
.so-checkout-page .wc-block-checkout__sidebar .wc-block-components-panel {
  border-radius: var(--so-radius);
}

.so-checkout-page .wc-block-components-checkout-order-summary__title,
.so-checkout-page .wc-block-components-checkout-order-summary__title-text {
  font-family: var(--so-font-display);
  font-size: 17px;
  font-weight: 600;
  color: var(--so-navy);
}

.so-checkout-page .wc-block-components-order-summary-item__description,
.so-checkout-page .wc-block-components-product-name {
  font-family: var(--so-font-body);
  font-size: 14px;
  line-height: 1.4;
  color: var(--so-ink);
}

.so-checkout-page .wc-block-components-product-name:hover {
  color: var(--so-orange-600);
}

.so-checkout-page .wc-block-components-product-metadata,
.so-checkout-page .wc-block-components-product-metadata__description {
  font-size: 12.5px;
  color: var(--so-grey-600);
}

.so-checkout-page .wc-block-components-order-summary-item__image .wc-block-components-order-summary-item__quantity span {
  background: var(--so-navy);
  border-color: var(--so-navy);
  color: var(--so-white);
  font-family: var(--so-font-body);
}

.so-checkout-page .wc-block-components-order-summary-item__image img {
  border: 1px solid var(--so-grey-200);
  border-radius: var(--so-radius-sm);
  background: var(--so-white);
}

/* ------------------------------------------------------------------ totals */

.so-checkout-page .wc-block-components-totals-item,
.so-checkout-page .wc-block-components-totals-item__label {
  font-family: var(--so-font-body);
  font-size: 14px;
  color: var(--so-grey-600);
}

.so-checkout-page .wc-block-components-totals-item__value {
  font-family: var(--so-font-body);
  font-weight: 500;
  color: var(--so-ink);
}

.so-checkout-page .wc-block-components-totals-item__description {
  font-size: 12.5px;
  color: var(--so-grey-600);
}

.so-checkout-page .wc-block-components-totals-discount .wc-block-components-totals-item__value {
  color: var(--so-in-stock);
}

.so-checkout-page .wc-block-components-totals-footer-item,
.so-checkout-page .wc-block-components-totals-footer-item .wc-block-components-totals-item__label,
.so-checkout-page .wc-block-components-totals-footer-item .wc-block-components-totals-item__value {
  font-family: var(--so-font-display);
  font-size: 19px;
  font-weight: 600;
  color: var(--so-navy);
}

.so-checkout-page .wc-block-components-totals-footer-item .wc-block-components-totals-item__description {
  font-family: var(--so-font-body);
  font-size: 11.5px;
  font-weight: 400;
  color: var(--so-grey-600);
}

/* --------------------------------------------------------- coupon panel */

.so-checkout-page .wc-block-components-panel__button {
  font-family: var(--so-font-body);
  font-size: 14px;
  font-weight: 500;
  color: var(--so-navy);
}

.so-checkout-page .wc-block-components-panel__button:hover {
  color: var(--so-orange-600);
}

.so-checkout-page .wc-block-components-totals-coupon__input input {
  border-color: var(--so-grey-300);
  border-radius: var(--so-radius-sm);
}

.so-checkout-page .wc-block-components-chip {
  background: var(--so-grey-100);
  border-color: var(--so-grey-200);
  color: var(--so-ink);
  font-family: var(--so-font-body);
  font-size: 12.5px;
}

.so-checkout-page .wc-block-components-chip__remove {
  color: var(--so-grey-600);
}

.so-checkout-page .wc-block-components-chip__remove:hover {
  color: var(--so-error);
}

/* ---------------------------------------------------------------- buttons
   The site button system from section 28: orange border, navy label, navy
   fill on hover. The block ships #046BD2 and 4px corners. */

.so-checkout-page .wc-block-components-button:not(.is-link),
.so-checkout-page .wc-block-components-button:not(.is-link).contained,
.so-checkout-page .wc-block-components-checkout-place-order-button,
.so-checkout-page .wc-block-components-checkout-place-order-button.contained {
  border: 1.5px solid var(--so-orange);
  border-radius: 999px;
  background: transparent;
  background-color: transparent;
  color: var(--so-navy);
  font-family: var(--so-font-display);
  font-size: 15px;
  font-weight: 600;
  letter-spacing: .01em;
  box-shadow: none;
  transition: background-color .15s ease, border-color .15s ease, color .15s ease;
}

.so-checkout-page .wc-block-components-button:not(.is-link):hover,
.so-checkout-page .wc-block-components-button:not(.is-link):focus,
.so-checkout-page .wc-block-components-button:not(.is-link).contained:hover,
.so-checkout-page .wc-block-components-button:not(.is-link).contained:focus,
.so-checkout-page .wc-block-components-checkout-place-order-button:hover,
.so-checkout-page .wc-block-components-checkout-place-order-button:focus,
.so-checkout-page .wc-block-components-checkout-place-order-button.contained:hover,
.so-checkout-page .wc-block-components-checkout-place-order-button.contained:focus {
  background: var(--so-navy);
  background-color: var(--so-navy);
  border-color: var(--so-navy);
  color: var(--so-white);
  box-shadow: none;
}

.so-checkout-page .wc-block-components-button:not(.is-link) .wc-block-components-button__text,
.so-checkout-page .wc-block-components-checkout-place-order-button .wc-block-components-button__text {
  color: inherit;
}

.so-checkout-page .wc-block-components-checkout-place-order-button {
  min-height: 52px;
  font-size: 15.5px;
}

.so-checkout-page .wc-block-components-button.is-link {
  color: var(--so-navy);
  text-decoration: underline;
  text-underline-offset: 2px;
}

.so-checkout-page .wc-block-components-button.is-link:hover {
  color: var(--so-orange-600);
}

/* ---------------------------------------------------------------- notices */

.so-checkout-page .wc-block-components-notice-banner {
  border-radius: var(--so-radius);
  font-family: var(--so-font-body);
  font-size: 13.5px;
  line-height: 1.55;
}

.so-checkout-page .wc-block-components-notice-banner.is-error {
  border-color: var(--so-error);
  background: rgba(180, 35, 24, .06);
}

.so-checkout-page .wc-block-components-notice-banner.is-error > svg {
  fill: var(--so-error);
}

.so-checkout-page .wc-block-components-notice-banner.is-success {
  border-color: var(--so-in-stock);
  background: rgba(6, 118, 71, .06);
}

.so-checkout-page .wc-block-components-notice-banner.is-success > svg {
  fill: var(--so-in-stock);
}

.so-checkout-page .wc-block-components-notice-banner.is-info,
.so-checkout-page .wc-block-checkout__no-payment-methods-notice {
  border-color: var(--so-grey-300);
  background: var(--so-grey-50);
  color: var(--so-ink);
}

/* ---------------------------------------------------------- loading state */

.so-checkout-page .wc-block-components-spinner::before {
  border-top-color: var(--so-orange);
}

.so-checkout-page .wc-block-components-loading-mask__children {
  opacity: .55;
}

/* ==========================================================================
   34. CHECKOUT — PHONE
   ==========================================================================

   The block decides its own layout from the width of its container, not from
   a media query: a ResizeObserver puts is-large, is-medium, is-small or
   is-mobile on .wc-block-checkout and the sidebar layout keys off that. It
   usually lands correctly, but when it does not — a container it cannot
   measure, a builder wrapper between it and the page — it holds the desktop
   split at phone width and the row is wider than the screen.

   So the rules below do not assume which class won. They stack and full
   width the two columns at phone widths whatever state the block thinks it
   is in, and they set min-width: 0 on every flex and grid child in the
   chain, because those default to min-width: auto and will happily hold a
   track open wider than its container rather than let a field shrink.

   Nothing is hidden and nothing is reordered. The order summary sitting
   above the form on a phone is the block's own behaviour, and it is correct.
   ========================================================================== */

/* ------------------------------------------------ the sideways shift, found

   The checkout block carries the alignwide class, and Astra pulls alignwide
   blocks out of the content padding so they run edge to edge. Its rule is:

     @media (max-width: 1200px) {
       .ast-plain-container .entry-content[data-ast-blocks-layout] > .alignwide {
         margin-left:  calc(-1 * min(var(--ast-container-default-xlg-padding), 20px));
         margin-right: calc(-1 * min(var(--ast-container-default-xlg-padding), 20px));
       }
     }

   The min() is there to stop the pull exceeding the padding it is cancelling.
   It reads the XLG padding variable, which is 20px, but Astra narrows the
   container to 12px at phone widths without narrowing that variable. So the
   block was pulled 20px against 12px of padding and hung 8px off both edges,
   clipped, while the page title beside it stayed put. Hence a heading reading
   "hipping address" and fields with no left border.

   Measured at 372px before: block at x -8, width 372.8, container at x 12,
   width 332.8. After: both at x 12, width 332.8, and scrollWidth equals
   clientWidth.

   Cancelled rather than corrected. Guessing the real padding per breakpoint
   would mean tracking an Astra variable that is already wrong; a checkout
   form lined up with the page title is the better answer anyway.

   Astra's selector is four classes, which is why the earlier attempt at two
   lost silently. This one adds the element and the alignwide class to clear
   it without reaching for !important. Scoped to Astra's own breakpoint, so
   above 1200px, where Astra applies no pull, nothing here applies either. */

@media (max-width: 1200px) {
  body.so-checkout-page .entry-content > .wp-block-woocommerce-checkout.alignwide,
  body.so-checkout-page .wp-block-woocommerce-checkout.alignwide {
    margin-left: 0;
    margin-right: 0;
    width: auto;
    max-width: 100%;
  }
}

@media (max-width: 782px) {

  /* Stack, whatever the container observer decided. */
  .so-checkout-page .wc-block-checkout .wc-block-components-sidebar-layout,
  .so-checkout-page .wc-block-checkout.is-large .wc-block-components-sidebar-layout,
  .so-checkout-page .wc-block-checkout.is-medium .wc-block-components-sidebar-layout {
    flex-wrap: wrap;
  }

  .so-checkout-page .wc-block-checkout .wc-block-components-main,
  .so-checkout-page .wc-block-checkout .wc-block-components-sidebar,
  .so-checkout-page .wc-block-checkout.is-large .wc-block-components-main,
  .so-checkout-page .wc-block-checkout.is-large .wc-block-components-sidebar,
  .so-checkout-page .wc-block-checkout.is-medium .wc-block-components-main,
  .so-checkout-page .wc-block-checkout.is-medium .wc-block-components-sidebar {
    flex: 1 1 100%;
    width: 100%;
    max-width: 100%;
    padding-left: 0;
    padding-right: 0;
  }

  /* Nothing in the chain may be wider than what holds it. min-width: auto is
     the flex and grid default and is what lets one long line, one wide image
     or one unbreakable string push the whole page sideways. */
  .so-checkout-page .wc-block-checkout,
  .so-checkout-page .wc-block-checkout__main,
  .so-checkout-page .wc-block-checkout__sidebar,
  .so-checkout-page .wc-block-checkout__form,
  .so-checkout-page .wc-block-components-sidebar-layout,
  .so-checkout-page .wc-block-components-main,
  .so-checkout-page .wc-block-components-sidebar,
  .so-checkout-page .wc-block-components-address-form,
  .so-checkout-page .wc-block-components-address-form > *,
  .so-checkout-page .wc-block-components-text-input,
  .so-checkout-page .wc-block-components-order-summary-item,
  .so-checkout-page .wc-block-components-totals-item {
    min-width: 0;
    max-width: 100%;
    box-sizing: border-box;
  }

  .so-checkout-page .wc-block-components-text-input input,
  .so-checkout-page .wc-block-components-textarea,
  .so-checkout-page .wc-blocks-components-select .wc-blocks-components-select__select {
    width: 100%;
  }

  /* A long CJ product title in the summary is one word away from being an
     unbreakable string. */
  .so-checkout-page .wc-block-components-product-name,
  .so-checkout-page .wc-block-components-product-metadata,
  .so-checkout-page .wc-block-components-totals-item__label {
    overflow-wrap: anywhere;
    word-break: break-word;
  }

  /* Type and spacing down to match the rest of the store.

     The border under the page title comes off here, and that is the point of
     this block rather than a side effect. On a phone the block moves the
     order summary above the form, and the summary panel opens with a rule of
     its own. Two full width rules with nothing between them read as a
     rendering fault, and the stack that produced them measured 46px of dead
     white: Astra's header margin, then the block's own 24px top padding, then
     the gap before the summary.

     Title border gone, header margin zeroed, block padding zeroed. One rule
     instead of two, and 46px down to 14. The border stays on desktop, where
     the column below it starts with a heading rather than a bordered panel
     and there is nothing for it to collide with. */
  .so-checkout-page .entry-header,
  body.so-checkout-page .entry-header {
    margin-bottom: 0;
  }

  .so-checkout-page .entry-header .entry-title,
  body.so-checkout-page .entry-header .entry-title {
    font-size: 21px;
    margin-bottom: 14px;
    padding-bottom: 0;
    border-bottom: 0;
  }

  body.so-checkout-page .wp-block-woocommerce-checkout {
    padding-top: 0;
  }

  .so-checkout-page .wc-block-components-title,
  .so-checkout-page .wc-block-components-checkout-step__title,
  .so-checkout-page .wc-block-components-title.wc-block-components-checkout-step__title {
    font-size: 16.5px;
  }

  .so-checkout-page .wc-block-components-checkout-order-summary__title,
  .so-checkout-page .wc-block-components-checkout-order-summary__title-text {
    font-size: 16px;
  }

  .so-checkout-page .wc-block-components-totals-footer-item,
  .so-checkout-page .wc-block-components-totals-footer-item .wc-block-components-totals-item__label,
  .so-checkout-page .wc-block-components-totals-footer-item .wc-block-components-totals-item__value {
    font-size: 17.5px;
  }

  /* The one action on the page gets the full width of it. */
  .so-checkout-page .wc-block-checkout__actions_row,
  .so-checkout-page .wc-block-checkout__actions_row--justify-flex-end {
    flex-wrap: wrap;
  }

  .so-checkout-page .wc-block-components-checkout-place-order-button {
    width: 100%;
    min-height: 50px;
    font-size: 15px;
  }
}

@media (max-width: 480px) {
  .so-checkout-page .entry-header .entry-title { font-size: 19px; }

  .so-checkout-page .wc-block-components-order-summary-item__description,
  .so-checkout-page .wc-block-components-product-name { font-size: 13.5px; }
}

/* ==========================================================================
   35. CHECKOUT — THE DUPLICATE ORDER SUMMARY
   ==========================================================================

   On a phone the checkout was printing the order summary twice: once as the
   collapsed panel at the top, and again in full above the Place Order button.
   Same items, same totals, same coupon form, roughly 570px apart.

   This is WooCommerce's own doing, not a duplicated block in the page. The
   Checkout block renders the summary in the sidebar AND fills a second copy
   into the actions area, then hides one with a container query. Its rule:

     @container (min-width: 700px) {
       .wp-block-woocommerce-checkout-order-summary-block.checkout-order-summary-block-fill-wrapper {
         display: none;
       }
     }

   Note the direction. The copy near Place Order is hidden on DESKTOP, where
   the sidebar is visible beside the form. Below 700px there is no matching
   rule for the other way round, so both stay on screen. The container here
   measures 336px, so nothing hides and both render.

   The rule below is WooCommerce's own, inverted, against the same container
   at the same breakpoint. Nothing new is invented and the two rules cannot
   disagree.

   WHY THIS IS THE ONE display: none ON THE CHECKOUT

   Section 33 says nothing on this page is ever hidden, and that rule is
   there because hiding a field leaves it required and unfillable. This is a
   deliberate exception and it is safe for a specific reason: nothing is lost.
   The two copies are the same summary rendered twice, and the one that stays
   is fully working — expandable, with the coupon form and every total in it.

   WHICH COPY STAYS

   The top one. It is 71px collapsed against 567px expanded, it puts the
   total on screen the moment the page loads, and it matches the cart, where
   the summary also sits above the fold. Keeping the bottom copy instead
   would push Place Order about 570px further down a page that is already
   long.

   To swap them, change the selector below to
   .wc-block-checkout__sidebar .wp-block-woocommerce-checkout-order-summary-block
   and the summary will sit above Place Order instead.
   ========================================================================== */

@container (max-width: 699px) {
  .so-checkout-page .wp-block-woocommerce-checkout-order-summary-block.checkout-order-summary-block-fill-wrapper {
    display: none;
  }
}
