/* ==========================================================================
   GENESIS single product page
   Design source: "Nuova proposta grafica.dc.html" -> Turn 9, "Funnel 1 —
   Pagina prodotto kit" (the approved web product page). The split layout in
   the second half of this file began as Turn 1's product detail and was
   brought onto Turn 9's frame: grid-and-glow stage, badges over the viewer,
   500px rail that opens with the rating row and closes with the trust grid
   and the verified-buyer quote.

   ⚠️ RESTYLE ONLY - no template fork. content-single-product.php carries real
   behaviour (variation swatches, add to cart, copies/stock, NFT block,
   sponsored products, tabs) so this targets the rendered classes instead.

   Scoped to `body.single-product`, and written with explicit values rather than
   relying on gns-base's `.gns-scope` root - the parent's template has no such
   wrapper and forking 281 lines of logic to add one is not worth it.

   ⚠️ Much of the design's product screen has no data behind it here: the
   Assembled/Layers slicing viewer, AR, "312 completed prints", the
   Personal/Commercial licence tiers and the production-node estimate all need
   the slicing and Hermes backends. Those sections are NOT faked - this styles
   the real content the page already has.
   ========================================================================== */

body.single-product {
  background-color: var(--gns-bg);
  color: var(--gns-text);
}

body.single-product .site,
body.single-product #page,
body.single-product .site-content {
  background-color: var(--gns-bg);
}

/* --------------------------------------------------------- typography ---- */

/*
 * ⚠️ The parent styles the product title as gradient text:
 *     background-clip: text; -webkit-text-fill-color: transparent;
 * With no gradient painted behind it the title renders completely INVISIBLE -
 * `color` is ignored while the fill colour is transparent. Reset the clip and
 * the fill so the colour applies again. The design uses a plain title here.
 */
body.single-product .summary h1,
body.single-product .product_title,
body.single-product h1.entry-title {
  font-family: var(--gns-font);
  font-weight: 500;
  letter-spacing: -.03em;
  line-height: 1.12;
  color: var(--gns-text);
  text-transform: none;
}

/*
 * ⚠️ !important is required here, not laziness.
 *
 * The parent paints the title as gradient text via `.entry-title` and
 * `.woocommerce div.product .product_title.entry-title`, both setting
 * `-webkit-text-fill-color: transparent` with `background-clip: text`. With no
 * gradient behind it the heading is INVISIBLE, and `color` is ignored while the
 * fill is transparent.
 *
 * Out-specifying it by selector was tried and does not reliably match - the
 * rendered nesting differs from the parent's own selector chain. A transparent
 * fill is a correctness bug, not a style preference, so it is forced.
 */
body.single-product .product_title,
body.single-product h1.entry-title,
body.single-product .entry-title {
  background: none !important;
  -webkit-background-clip: border-box !important;
          background-clip: border-box !important;
  -webkit-text-fill-color: var(--gns-text) !important;
}

body.single-product .summary p,
body.single-product .woocommerce-product-details__short-description,
body.single-product .woocommerce-Tabs-panel p,
body.single-product .woocommerce-Tabs-panel li {
  color: var(--gns-body);
  line-height: 1.65;
}

body.single-product .product-categories,
body.single-product .posted_in,
body.single-product .sku_wrapper {
  font: 500 10px var(--gns-font-mono);
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--gns-muted);
}

/* ------------------------------------------------------------ gallery ---- */

body.single-product .woocommerce-product-gallery__image,
body.single-product .woocommerce-product-gallery img,
body.single-product .single-product-image img {
  border-radius: var(--gns-r-hero);
  background: var(--gns-card);
}

body.single-product .flex-control-thumbs li img,
body.single-product .woocommerce-product-gallery__wrapper .thumbnail img {
  border-radius: var(--gns-r-card);
  border: 1px solid var(--gns-border);
  opacity: .7;
  transition: opacity .15s ease, border-color .15s ease;
}
body.single-product .flex-control-thumbs li img:hover,
body.single-product .flex-control-thumbs li img.flex-active {
  opacity: 1;
  border-color: var(--gns-cyan);
}

/* Gallery arrows sit on dark now. */
body.single-product .flex-direction-nav a,
body.single-product .slick-arrow {
  background: var(--gns-scrim);
  border: 1px solid var(--gns-border-strong);
  border-radius: 50%;
  color: var(--gns-text);
  backdrop-filter: blur(4px);
}

/* -------------------------------------------------------------- price ---- */

body.single-product .summary .price,
body.single-product p.price,
body.single-product span.price {
  color: var(--gns-text);
  font-weight: 700;
}
body.single-product .summary .price del { color: var(--gns-muted); font-weight: 400; }
body.single-product .summary .price ins { color: var(--gns-text); text-decoration: none !important; }

/* ------------------------------------------------------- meta / badges --- */

body.single-product .meta-copies,
body.single-product .copies-badge,
body.single-product .stock {
  display: inline-flex;
  align-items: center;
  height: 24px;
  padding: 0 10px;
  border-radius: var(--gns-r-pill);
  border: 1px solid var(--gns-border-strong);
  background: var(--gns-elevated);
  color: var(--gns-body);
  font: 500 10px var(--gns-font-mono);
  letter-spacing: .1em;
  text-transform: uppercase;
}
body.single-product .stock.in-stock { border-color: var(--gns-border-cyan); color: var(--gns-cyan-ink); }
body.single-product .stock.out-of-stock { border-color: var(--gns-border-magenta); color: var(--gns-magenta-ink); }

/*
 * ⚠️ The `display: inline-flex` above UN-HID an element the parent had put away:
 * WooCommerce's stock line renders as `<p class="stock hide in-stock">284 in
 * stock</p>`, and `.hide` is how the parent suppresses it - because the same
 * number is already in `.top-section` as the copies chip. The badge rule above
 * matches on `.stock` alone and overrode that, so the rail carried the fact
 * twice, in two shapes.
 */
body.single-product .stock.hide { display: none; }

/* And an order, in case a product ever renders it WITHOUT `.hide`: everything
   else in the rail is ordered, so an unordered item defaults to 0 and would
   land above the product's own title. */
.gns-pdp__rail p.stock { order: 1; }

/* Creator row */
body.single-product .creator-name,
body.single-product .product-creator {
  color: var(--gns-body);
  font-size: 13px;
}
body.single-product .creator-name a,
body.single-product .product-creator a { color: var(--gns-text); text-decoration: none; }
body.single-product .creator-name a:hover { color: var(--gns-cyan-ink); }

/* ---------------------------------------------------------- variations --- */

body.single-product .variations th,
body.single-product .variations label,
body.single-product .variations_form label {
  font: 500 10px var(--gns-font-mono) !important;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--gns-muted) !important;
}

body.single-product .variations select,
body.single-product .qty,
body.single-product input[type="number"],
body.single-product input[type="text"] {
  background-color: var(--gns-elevated) !important;
  color: var(--gns-text) !important;
  border: 1px solid var(--gns-border-strong) !important;
  border-radius: var(--gns-r-input);
  height: 46px;
  padding: 0 14px;
}
body.single-product .variations select option { background: var(--gns-surface); color: var(--gns-text); }

/* woo-variation-swatches */
/*
 * ⚠️ `woo-variation-swatches` is a BODY class, not a wrapper inside the page.
 * This block was written with a descendant combinator - `body.single-product
 * .woo-variation-swatches ...` - which asks for an element carrying that class
 * somewhere INSIDE the body, and there is none. It therefore matched nothing,
 * and the plugin's own light-mode paint went straight through: a white ground
 * and a 2px black selected ring on every colour chip, on a near-black page.
 *
 * Compounded onto the body it also out-specifies the plugin - 0,5,1 against the
 * 0,4,0 of `.woo-variation-swatches .variable-items-wrapper
 * .variable-item:not(.radio-variable-item)` (frontend.min.css) - which is what
 * lets the rest of this block work without a single !important.
 */
body.single-product.woo-variation-swatches .variable-items-wrapper .variable-item {
  background: var(--gns-elevated);
  border: 1px solid var(--gns-border-strong);
  border-radius: var(--gns-r-input);
  box-shadow: none;
  color: var(--gns-body);
}
body.single-product.woo-variation-swatches .variable-items-wrapper .variable-item.selected,
body.single-product.woo-variation-swatches .variable-items-wrapper .variable-item:hover {
  border-color: var(--gns-cyan);
  color: var(--gns-text);
  box-shadow: 0 0 0 2px var(--gns-cyan-tint-2);
}
/*
 * A colour is recognised rather than read, so the chip is the colour itself
 * behind a hairline frame - square, at the chip radius, not the 11px input
 * radius the labelled options use.
 *
 * The long selector earns its length: the plugin's `.wvs-style-squared`
 * variant sets `border-radius: 2px` from 0,5,0, so the radius is the one
 * property here that needs five classes of its own to land.
 */
body.single-product.woo-variation-swatches .variable-items-wrapper .variable-item.color-variable-item {
  border-radius: var(--gns-r-chip);
}
body.single-product.woo-variation-swatches .color-variable-item .variable-item-span-color {
  display: block;
  width: 100%;
  height: 100%;
  border-radius: calc(var(--gns-r-chip) - 2px);
}
body.single-product .reset_variations { color: var(--gns-cyan-ink); }

/* ------------------------------------------------------- add to cart ----- */

body.single-product .single_add_to_cart_button,
body.single-product .custom-cart-button,
body.single-product button.button.alt {
  height: 52px;
  padding: 0 26px;
  border: 0;
  border-radius: var(--gns-r-pill);
  background: var(--gns-gradient) !important;
  color: var(--gns-on-accent) !important;
  font-family: var(--gns-font);
  font-size: 15px;
  font-weight: 700;
  letter-spacing: -.01em;
  box-shadow: var(--gns-glow-cta);
  transition: filter .15s ease, transform .15s ease;
}
body.single-product .single_add_to_cart_button:hover { filter: brightness(1.06); }
body.single-product .single_add_to_cart_button:active { transform: translateY(1px); }
body.single-product .single_add_to_cart_button:disabled,
body.single-product .single_add_to_cart_button.disabled {
  opacity: .45;
  box-shadow: none;
  cursor: not-allowed;
}

/* Secondary actions (wishlist, share, visit store) */
body.single-product .visit-store-button,
body.single-product .favourite-button,
body.single-product .share-button {
  border: 1px solid var(--gns-border-heavy);
  border-radius: var(--gns-r-pill);
  background: transparent;
  color: var(--gns-body);
}
body.single-product .visit-store-button:hover { border-color: var(--gns-cyan); color: var(--gns-text); }

/* --------------------------------------------------------------- tabs ---- */

body.single-product .woocommerce-tabs ul.tabs,
body.single-product .product-tabs-nav {
  border-bottom: 1px solid var(--gns-border);
  padding: 0;
  margin: 0 0 22px;
  display: flex;
  gap: 26px;
  list-style: none;
}
body.single-product .woocommerce-tabs ul.tabs::before,
body.single-product .woocommerce-tabs ul.tabs li::before,
body.single-product .woocommerce-tabs ul.tabs li::after {
  display: none; /* WooCommerce's rounded-tab decorations */
}
body.single-product .woocommerce-tabs ul.tabs li,
body.single-product .product-tabs-nav li {
  background: none !important;
  border: 0 !important;
  border-radius: 0 !important;
  margin: 0;
  padding: 0;
  box-shadow: none !important;
}
body.single-product .woocommerce-tabs ul.tabs li a,
body.single-product .product-tabs-nav li a {
  display: block;
  padding: 12px 0;
  font-size: 13.5px;
  font-weight: 500;
  color: var(--gns-secondary-2) !important;
  border-bottom: 2px solid transparent;
  text-decoration: none;
}
body.single-product .woocommerce-tabs ul.tabs li.active a,
body.single-product .product-tabs-nav li.active a {
  color: var(--gns-text) !important;
  border-bottom-color: var(--gns-cyan);
}

body.single-product .woocommerce-Tabs-panel h2 { display: none; } /* duplicate of the tab label */

/* ------------------------------------------------------------ reviews ---- */

body.single-product .star-rating,
body.single-product .stars a { color: var(--gns-cyan-ink); }
body.single-product .woocommerce-review-link,
body.single-product .woocommerce-review__author { color: var(--gns-body); }
body.single-product .comment_container,
body.single-product .woocommerce-Reviews .comment-text {
  background: var(--gns-card);
  border: 1px solid var(--gns-border);
  border-radius: var(--gns-r-card);
  padding: 14px 16px;
}

/* ------------------------------------------------- sponsored / related --- */

/*
 * Section rhythm. The air between the sections below the fold used to come out
 * of `.product-rating h2`'s own 50px top margin, so flattening the heading
 * scale below would have butted User Reviews straight onto the last row of
 * Related products. It belongs on the section either way.
 */
body.single-product .related.products,
body.single-product .up-sells.products,
body.single-product .product-rating {
  margin-top: 64px;
}

/*
 * The two section headings below the fold, at one size.
 *
 * They came from the parent at two: `.related.products h2` 18px/700
 * (style.css:1118) and `.product-rating h2` 32px/700 in cyan-to-magenta
 * gradient text (style.css:4745), stacked one above the other on the same page.
 * The gradient is the brand's hero device - it belongs on a scene title, not on
 * "User Reviews" - so both read as what they are: the label on a section.
 */
body.single-product .sponsored-products h2,
body.single-product .related h2,
body.single-product .up-sells h2,
body.single-product .product-rating h2 {
  font-family: var(--gns-font);
  font-size: 22px;
  font-weight: 600;
  line-height: 1.25;
  letter-spacing: -.02em;
  color: var(--gns-text);
  text-transform: none;
  margin: 0 0 16px;
  background: none;
  -webkit-text-fill-color: currentColor;
}
@media (max-width: 767.98px) {
  /*
   * Answers genesys/style.css:5923-5926, which is
   * `.product-rating h2 { margin: 30px 0 20px !important; font-size: 18px !important }`
   * - the only two declarations here that need it.
   */
  body.single-product .product-rating h2 {
    font-size: 19px !important;
    margin: 0 0 16px !important;
  }
  body.single-product .related h2,
  body.single-product .up-sells h2 { font-size: 19px; }
}

/*
 * The related-products grid.
 *
 * ⚠️ THIS LOOP HAD NO GRID ANYWHERE. `ul.products` is laid out by shop.css
 * (`.gns-shop ul.products`) and archive.css (`body.gns-archive ul.products`),
 * and a product page is neither - so Related products fell back to
 * WooCommerce's 1990s float layout while the cards themselves came from the
 * redesign. Four 303px squares in a 1375px row, images stretched to fill them.
 *
 * `auto-fill` with a 240px floor is the same rule the shop uses, so a card is
 * the same size here as on the results page it came from.
 */
body.single-product .related ul.products,
body.single-product .up-sells ul.products {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 14px;
  margin: 0;
  padding: 0;
  list-style: none;
}
/*
 * ⚠️ The same empty-first-slot trap shop.css documents: WooCommerce clears its
 * float layout with `ul.products::before/::after { content: " "; display: table }`,
 * and in a grid container a pseudo-element is a grid ITEM, so `::before` eats
 * the first cell and pushes every card one slot along.
 */
body.single-product .related ul.products::before,
body.single-product .related ul.products::after,
body.single-product .up-sells ul.products::before,
body.single-product .up-sells ul.products::after {
  content: none;
}

body.single-product .product-card,
body.single-product .sponsored-product {
  background: var(--gns-card);
  border: 1px solid var(--gns-border-faint);
  border-radius: var(--gns-r-card);
  overflow: hidden;
  transition: border-color .15s ease, transform .15s ease;
}
body.single-product .product-card:hover {
  border-color: var(--gns-border-cyan);
  transform: translateY(-2px);
}
body.single-product .product-card .product-title a,
body.single-product .product-card h4 a { color: var(--gns-text); text-decoration: none; }
body.single-product .product-card .product-meta,
body.single-product .product-card .creator-name { color: var(--gns-secondary-2); font-size: 11px; }

/* ------------------------------------------------------------ panels ----- */

body.single-product .nft-section,
body.single-product .support-files,
body.single-product .safety-section,
body.single-product .accordion-item,
body.single-product .accordion-content,
body.single-product .accordion-header,
body.single-product .details-section,
body.single-product .product-details-box,
body.single-product .woocommerce-Tabs-panel {
  background-color: var(--gns-card);
  border-color: var(--gns-border);
  color: var(--gns-body);
}
body.single-product .accordion-item,
body.single-product .details-section,
body.single-product .product-details-box {
  border: 1px solid var(--gns-border);
  border-radius: var(--gns-r-panel);
  overflow: hidden;
}
/* Tables inside the spec panels */
body.single-product .accordion-content table,
body.single-product .woocommerce-product-attributes,
body.single-product .shop_attributes {
  background: transparent;
  color: var(--gns-body);
  width: 100%;
}
body.single-product .woocommerce-product-attributes th,
body.single-product .shop_attributes th { color: var(--gns-muted); font-weight: 500; }
body.single-product .woocommerce-product-attributes td,
body.single-product .shop_attributes td { color: var(--gns-body); }
body.single-product .woocommerce-product-attributes tr,
body.single-product .shop_attributes tr { border-bottom: 1px solid var(--gns-border-faint); }

body.single-product hr,
body.single-product .divider { border-color: var(--gns-border); }

/*
 * Scoped to .site-main: the footer is a sibling of #page.site, so a bare
 * `body.single-product a` turned the footer's links cyan on this page while
 * every other page kept the parent's white footer.
 */
body.single-product .site-main a { color: var(--gns-cyan-ink); }
/*
 * ...except the ones that are buttons. `.visit-office` is a filled brand-cyan
 * chip whose label the parent paints white; the blanket rule above repainted
 * it in the accent it is sitting ON - 2.58:1 in light, and in dark, where the
 * ink IS the brand cyan, cyan on cyan at 1.0. Text on the brand fill is
 * --gns-on-accent, which is what every other filled control in the redesign
 * uses.
 */
body.single-product .site-main a.visit-office { color: var(--gns-on-accent); }
body.single-product .breadcrumb,
body.single-product .woocommerce-breadcrumb {
  font: 500 10px var(--gns-font-mono);
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--gns-muted);
}
body.single-product .woocommerce-breadcrumb a { color: var(--gns-secondary-2); }

/* ------------------------------------------------------ light-theme ink --- */
/*
 * These carry the parent theme's #7D7D7D. Against the dark ground that is
 * about 5.3:1 and passes, which is why it went unnoticed - but against the
 * light ground it is 3.81:1, under AA. Mapping them onto --gns-body fixes the
 * light theme and leaves dark unchanged in substance (body is lighter still).
 */
body.single-product .site-main .latest-comment,
body.single-product .site-main .tab-content li,
body.single-product .site-main .tab-content p,
body.single-product .site-main .variant-card-header {
  color: var(--gns-body) !important;
}
/*
 * The tabs were in that list too. They are out because the parent sets their
 * ink WITHOUT !important (`.product-tab { color: …darkgrey }`, style.css:2248),
 * so the component below simply outranks it - and it needs two inks, one per
 * state, which a single blanket !important cannot express.
 */

/*
 * The running total under the variation picker (.total-price .price-main) is
 * unstyled black - 1.07:1 on the dark ground. It is the page's live price, so
 * it takes the emphasis colour rather than body.
 */
body.single-product .site-main .total-price .price-main,
body.single-product .site-main .total-price {
  color: var(--gns-text) !important;
}

/* --------------------------------------------------- variation swatches --- */
/*
 * woo-variation-swatches renders the variant picker as
 * `li.variable-item.button-variable-item` with a white ground, a black
 * 2px box-shadow ring and black label text. Against the dark page that is
 * black-on-dark at about 1.07:1 - the label is effectively invisible - and it
 * was missed because the plugin's own stylesheet is the only thing styling it.
 *
 * Tokenised so it is right in both themes rather than only inverted for dark.
 */
body.single-product .variable-item.button-variable-item {
  background-color: var(--gns-elevated) !important;
  border: 1px solid var(--gns-border-strong) !important;
  border-radius: var(--gns-r-input) !important;
  box-shadow: none !important;
  transition: border-color .15s ease, background-color .15s ease;
}
body.single-product .variable-item.button-variable-item .variable-item-span {
  color: var(--gns-text) !important;
  font-family: var(--gns-font);
  font-size: 13px;
}
body.single-product .variable-item.button-variable-item:hover {
  border-color: var(--gns-cyan) !important;
}
body.single-product .variable-item.button-variable-item.selected {
  background-color: var(--gns-cyan-tint-2) !important;
  border-color: var(--gns-cyan) !important;
  box-shadow: none !important;
}
body.single-product .variable-item.button-variable-item.selected .variable-item-span {
  color: var(--gns-text) !important;
  font-weight: 700;
}

/* ========================================================== panel borders === */
/*
 * The parent draws every panel on this page with a fixed light hairline -
 * --wp--preset--color--lightgrey (#F3F3F3), plus two literals (#F3F3F3 and
 * #E5E7EB). None of them invert, so on the dark ground each block was outlined
 * in near-white: the gallery frame, the tab panel, the variant card and its
 * header, the details and printer sections, the accordion, and the two
 * column-dividing left borders.
 *
 * Scoped to body.single-product, which the redesign owns. --gns-border is a
 * hairline in both themes, so light mode keeps the same reading it had - the
 * parent's #F3F3F3 on white and this token on the light ground are within a
 * few percent of each other.
 *
 * ⚠️ The tabs used to be in this list - `.product-tabbed-layout` for the box
 * around them and `.product-tab:not(.active)` for each tab's own underline.
 * Both are gone now: the strip is drawn by the component further down, which
 * has no box and one continuous rule instead of a border per tab.
 */
body.single-product .variant-card,
body.single-product .variant-card .variant-card-header,
body.single-product .variation-image-container,
body.single-product .dimensions-div,
body.single-product .accordion,
body.single-product .part-details,
body.single-product .part-general-info,
body.single-product .part-details .general-info,
body.single-product .part-printers-section,
body.single-product #main-carousel .splide__slide img,
body.single-product #thumbnail-carousel .splide__slide img {
  border-color: var(--gns-border);
}

/*
 * .part-printers-section carries its divider INLINE
 * (`border-top: 1px solid #e5e7eb`), so the rule above - which does reach it -
 * still loses. !important is the only lever against an inline declaration;
 * narrowed to the one property so nothing else about the element changes.
 */
body.single-product .part-printers-section {
  border-top-color: var(--gns-border) !important;
}

/* A control rather than a panel, so it takes the stronger hairline - at 2px
   the faint one reads as a smudge. */
body.single-product .view-printers-btn {
  border-color: var(--gns-border-strong);
}

/* =================================================== supported printers === */
/*
 * The modal behind "View supported printers (N)" on a kit.
 *
 * Nothing in the redesign had ever reached it - it opens on click, so it is
 * invisible to a page audit - and it was built in a different palette
 * altogether: a white panel (#fff), #e5e7eb rules, #111827 and #6b7280 ink, a
 * #667eea → #764ba2 PURPLE gradient on the title, a #6366f1 indigo focus ring
 * and a #10b981 green tick. None of those are GENESIS colours, and half of it
 * sat on the dark page as a white slab - with the search input already dark,
 * because the child theme's global input styling did reach that one element.
 *
 * Retinted rather than rebuilt: same markup, same behaviour, tokens throughout,
 * so it is right in both themes.
 */
body.single-product .printers-modal .modal-container {
  background: var(--gns-card);
  border: 1px solid var(--gns-border);
  border-radius: var(--gns-r-panel);
  box-shadow: 0 24px 70px rgba(0, 0, 0, .5);
}
body.single-product .printers-modal .modal-header {
  border-bottom-color: var(--gns-border);
}
/*
 * ⚠️ Six !importants, all answering the parent's. genesys/style.css:8395 sets
 * every one of these with !important, including the purple gradient and the
 * transparent text fill that reveals it.
 */
body.single-product .printers-modal .modal-header h3 {
  background: none !important;
  -webkit-text-fill-color: var(--gns-text) !important;
  color: var(--gns-text) !important;
  font-family: var(--gns-font) !important;
  font-size: 15px !important;
  letter-spacing: -.01em;
}
body.single-product .printers-modal .modal-close-btn { color: var(--gns-body); }
body.single-product .printers-modal .modal-close-btn:hover {
  background: var(--gns-tint);
  color: var(--gns-text);
}

/* `.search-box` is shared with the site header's search, which is a white
   field; the wrapper sits square behind an 11px-radius input, so its four
   corners showed as white nicks. */
body.single-product .printers-modal .search-box { background: transparent; }

/* The input is the one element that was already dark - it just had a white
   panel behind it. Pinned to the same tokens as every other field. */
body.single-product .printers-modal .search-box input {
  background: var(--gns-elevated);
  border: 1px solid var(--gns-border-strong);
  border-radius: var(--gns-r-input);
  color: var(--gns-text);
  font-family: var(--gns-font);
  font-style: normal;
}
body.single-product .printers-modal .search-box input::placeholder {
  color: var(--gns-muted);
  font-style: normal;
}
body.single-product .printers-modal .search-box input:focus {
  border-color: var(--gns-cyan);
  background: var(--gns-elevated);
  color: var(--gns-text);
}
body.single-product .printers-modal .search-box .search-icon { color: var(--gns-muted); }
body.single-product .printers-modal .search-box input:focus ~ .search-icon { color: var(--gns-cyan-ink); }
body.single-product .printers-modal .search-clear-btn { color: var(--gns-muted); }
body.single-product .printers-modal .search-clear-btn:hover {
  background: var(--gns-tint);
  color: var(--gns-text);
}

body.single-product .printers-modal .printer-item {
  background: var(--gns-tint-weak);
  border: 1px solid var(--gns-border);
  border-radius: var(--gns-r-card);
}
body.single-product .printers-modal .printer-item:hover {
  background-color: var(--gns-tint);
  border-color: var(--gns-border-cyan);
  box-shadow: none;
}
body.single-product .printers-modal .printer-icon svg { color: var(--gns-secondary-2); }
body.single-product .printers-modal .printer-name { color: var(--gns-text); }
body.single-product .printers-modal .printer-key {
  color: var(--gns-secondary-2);
  font-family: var(--gns-font-mono);
}
/*
 * The tick. #10b981 was the only green in the product, and there is no green
 * token to map it onto - affirmative here is cyan, the same colour the trust
 * row's ✓ and the selected swatch already use.
 */
body.single-product .printers-modal .printer-check { background: var(--gns-cyan); }
body.single-product .printers-modal .printer-check svg { color: var(--gns-on-accent); }

body.single-product .printers-modal .printers-empty { color: var(--gns-muted); }
body.single-product .printers-modal .modal-body::-webkit-scrollbar-thumb {
  background: var(--gns-border-heavy);
  border-radius: 4px;
}
body.single-product .printers-modal .modal-body::-webkit-scrollbar-thumb:hover {
  background: var(--gns-secondary);
}

/* ============================================================ bootstrap card === */
/*
 * The "Total: $ 25.50 / quantity / Add to cart" bar on simple products is
 * `<div class="card price-card">`, and `.card` here is BOOTSTRAP's, not the
 * parent theme's:
 *
 *     bootstrap.min.css  .card { background-color: #fff;
 *                                border: 1px solid rgba(0,0,0,.125) }
 *
 * Nothing in the redesign was neutralising it on this template, so the bar
 * stayed a white slab on the dark ground with --gns-text on top of it - the
 * total measured 1.15:1, i.e. invisible. The border is the mirror image: a
 * black hairline that disappears once the card is dark.
 *
 * Scoped to body.single-product and to `.card`, so it cannot reach the
 * redesign's own `.gns-card`, which is a different class and already correct.
 *
 * ⚠️ This only appears on products that render an add-to-cart form - a simple
 * product like a filament. The variable product used for the first audit does
 * not draw this bar at all, which is exactly why it was missed: one product
 * URL is not the same as "the product template".
 */
body.single-product .card {
  background-color: var(--gns-card);
  border-color: var(--gns-border);
}

/*
 * The tab body inherits its colour from `.product-tabbed-layout`, which the
 * parent paints --wp--preset--color--darkgrey (#7D7D7D). That is 3.81:1 on the
 * light ground - under AA for the entire product description - and 4.52 on the
 * dark one, so it is marginal in both rather than wrong in one, which is why
 * the dark-theme audit reported the page clean.
 *
 * Found on a simple product; it applies to every product, the earlier audit
 * just never measured this page in light.
 */
body.single-product .product-tabbed-layout {
  color: var(--gns-body);
}

/* ========================================================== spec tabs === */
/*
 * DESCRIPTION / SUPPORT FILES / SAFETY / TECHNICAL FEATURES.
 *
 * Until now this was Bootstrap's `nav-tabs` widget with the parent's colours
 * painted over it, and it read like one: a rounded box around the whole thing,
 * each tab stretched to `width: 33.3333%` (style.css:2249) so two tabs left a
 * third of the row empty, and a separate underline per tab - the inactive one
 * in --wp--preset--color--lightgrey, a near-white line drawn across a
 * near-black page.
 *
 * What replaces it is the voice the rail beside it already speaks: the mono
 * uppercase micro-labels that say WEIGHT:, COLOR:, TOTAL:. The tabs are those
 * labels, sitting on one continuous hairline, with a cyan bar under the live
 * one carrying the same bloom as the Add to cart button. No box, because the
 * page is already the container.
 *
 * ⚠️ FOUR !IMPORTANTS, ALL ANSWERING ONE. The parent pins the tab borders from
 * three rules that cannot be outranked:
 *     .product-tab         { border-bottom: 1px solid …lightgrey !important }  :2248
 *     .product-tab:hover   { border-bottom: 3px solid …violamain !important }  :2265
 *     .product-tab.active  { border: none !important;
 *                            border-bottom: 3px solid …violamain !important }  :2274
 * They are cancelled in one place below and nowhere else.
 */
body.single-product .product-tabbed-layout {
  margin: 24px 0 0;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: none;
}

/* The rule the strip sits on. Put on <nav> rather than .nav-tabs, which the
   parent clears with `border-bottom: none !important` (style.css:2233). */
body.single-product .product-tabbed-layout > nav {
  border-bottom: 1px solid var(--gns-border);
}
body.single-product .product-tabbed-layout .nav-tabs {
  display: flex;
  flex-wrap: nowrap;
  gap: 34px;
  border: 0;
  /* Four tabs on a kit do not fit a phone. They slide instead of stacking, so
     the strip stays one line and keeps reading as a switcher. */
  overflow-x: auto;
  scrollbar-width: none;
  -ms-overflow-style: none;
}
body.single-product .product-tabbed-layout .nav-tabs::-webkit-scrollbar { display: none; }

body.single-product .product-tab {
  position: relative;
  flex: 0 0 auto;
  width: auto;
  margin: 0;
  padding: 2px 0 15px;
  border: 0 !important;     /* the three parent rules quoted above */
  border-radius: 0;
  background: none;
  font: 500 11px/1 var(--gns-font-mono);
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--gns-body);
  white-space: nowrap;
  cursor: pointer;
  transition: color .18s ease;
}
body.single-product .product-tab:hover { color: var(--gns-text); }
body.single-product .product-tab.active {
  color: var(--gns-text);
  font-weight: 500;         /* the parent jumps to 700, which shifts the row */
}

/*
 * The indicator. It is the only thing that says which tab you are on, so it is
 * drawn rather than implied: a 2px bar the width of its own label, sitting on
 * the strip's hairline, with the cyan bloom the CTA above it carries.
 */
body.single-product .product-tab::after {
  content: "";
  position: absolute;
  right: 0;
  bottom: -1px;
  left: 0;
  height: 2px;
  border-radius: 2px;
  background: var(--gns-cyan);
  opacity: 0;
  transform: scaleX(.35);
  transform-origin: left center;
  transition: opacity .2s ease, transform .24s cubic-bezier(.2, .8, .2, 1);
}
body.single-product .product-tab:hover::after { opacity: .3; transform: none; }
body.single-product .product-tab.active::after {
  opacity: 1;
  transform: none;
  box-shadow: 0 0 12px rgba(0, 191, 255, .55);
}

/* -------------------------------------------------------- tab panels --- */

body.single-product .product-tabbed-layout .tab-content { padding: 0; }
body.single-product .product-tabbed-layout .tab-pane {
  padding: 28px 0 0;
  transform: translateY(6px);
  transition: opacity .25s ease, transform .25s ease;
}
body.single-product .product-tabbed-layout .tab-pane.show { transform: none; }

/*
 * Prose measure. The detail column runs the full 1375px, and the description
 * was setting at about 180 characters a line.
 */
body.single-product .product-tabbed-layout .tab-pane > p,
body.single-product .product-tabbed-layout .tab-pane > strong,
body.single-product .product-tabbed-layout .tab-pane > ul,
body.single-product .product-tabbed-layout #nav-description,
body.single-product .product-tabbed-layout #nav-safety {
  max-width: 74ch;
  font-size: 15px;
  line-height: 1.7;
}

/*
 * Support Files: the link is the control, so it looks like one.
 *
 * The parent sizes this box rather than letting its contents do it -
 * `.pdf-container` (style.css:2298) sets `height: 60px; margin: 40px;
 * justify-content: space-between`, which pushed a single line of text 40px
 * down and 40px in from everything else in the panel, and threw the download
 * button out to the far edge.
 */
body.single-product .pdf-container {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: 10px;
  height: auto;
  margin: 0;
}

/* The bullet lists in Description and Safety, pulled back to the text edge. */
body.single-product .product-tabbed-layout #nav-description ul,
body.single-product .product-tabbed-layout #nav-safety ul {
  margin: 0;
  padding-left: 20px;
}
body.single-product .product-tabbed-layout .tab-pane li::marker { color: var(--gns-cyan); }
body.single-product .pdf-container a:not(.download-icon) {
  display: inline-flex;
  flex-direction: row;      /* the parent stacks it - `.pdf-container a`, style.css:2306 */
  align-items: center;
  gap: 10px;
  padding: 11px 16px;
  border: 1px solid var(--gns-border-strong);
  border-radius: var(--gns-r-input);
  background: var(--gns-tint-weak);
  color: var(--gns-text);
  font-size: 13.5px;
  text-decoration: none;
  transition: border-color .15s ease, background-color .15s ease;
}
body.single-product .pdf-container a:not(.download-icon):hover {
  border-color: var(--gns-cyan);
  background: var(--gns-cyan-tint);
}
/* 40px of file icon beside a 13.5px label - `.pdf-container a i`, style.css:2322. */
body.single-product .pdf-container a:not(.download-icon) i {
  font-size: 17px;
  color: var(--gns-cyan-ink);
}
body.single-product .pdf-container .download-icon i {
  font-size: 15px !important;   /* answers `.pdf-container .download-icon i { …!important }`, style.css:2327 */
  color: inherit;
}
body.single-product .pdf-container .download-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 42px;
  height: 42px;
  border: 1px solid var(--gns-border-strong);
  border-radius: var(--gns-r-input);
  color: var(--gns-body);
  text-decoration: none;
  transition: border-color .15s ease, color .15s ease;
}
body.single-product .pdf-container .download-icon:hover {
  border-color: var(--gns-cyan);
  color: var(--gns-cyan-ink);
}
/* The empty state, said once and quietly. */
body.single-product .pdf-container p {
  margin: 0;
  font: 500 11px/1 var(--gns-font-mono);
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--gns-muted) !important;   /* answers the .tab-content p rule above */
}

/* ------------------------------------------------------- spec sheet --- */
/*
 * Technical Features is a TablePress table, and it arrived as a white slab
 * with #111 text sitting on the dark page - unreadable, and hidden behind the
 * second tab, which is why it survived the earlier contrast pass.
 *
 * TablePress draws entirely from custom properties declared on `.tablepress`
 * itself, so the whole thing retints by redeclaring them - no !important, and
 * striping, hover and borders all follow. Set ON the table, never on an
 * ancestor: names like `--text-color` and `--padding` are generic enough to
 * hit anything else that reads them.
 */
body.single-product .product-tabbed-layout .tablepress {
  --text-color: var(--gns-body);
  --odd-text-color: var(--gns-body);
  --even-text-color: var(--gns-body);
  /*
   * ⚠️ The page ground, not `transparent`. TablePress lets a table's author set
   * per-row colours from the admin and emits them as `#tablepress-N tr.row-8`,
   * which no stylesheet can outrank - this table paints two rows solid #00BFFF
   * with white text. A row's background sits behind its cells, so opaque cells
   * cover it and transparent ones let it through as a saturated bar with
   * unreadable text. This keeps every sheet legible whatever the author chose.
   * It assumes the detail block stays on the page ground, which it does.
   */
  --odd-bg-color: var(--gns-bg);
  --even-bg-color: var(--gns-bg);
  --head-text-color: var(--gns-text);
  --head-bg-color: transparent;
  --hover-text-color: var(--gns-text);
  --hover-bg-color: var(--gns-tint-weak);
  --border-color: var(--gns-border-faint);
  --padding: 12px 16px 12px 0;

  width: 100%;
  max-width: 900px;
  margin: 0;
  font-family: var(--gns-font);
  font-size: 13px;
}
/* A spec sheet is read across, so it scrolls rather than wrapping "cold to 80"
   and "ASTM D3418" onto second lines. */
body.single-product .product-tabbed-layout #nav-features { overflow-x: auto; }
body.single-product .product-tabbed-layout .tablepress { min-width: 480px; }

/*
 * The measurement itself, in mono so a column of numbers lines up. `width: 1%`
 * with nowrap is the shrink-to-fit idiom: the three value columns take exactly
 * what they need and the label column keeps the rest.
 */
body.single-product .product-tabbed-layout .tablepress td.column-2,
body.single-product .product-tabbed-layout .tablepress td.column-3,
body.single-product .product-tabbed-layout .tablepress td.column-4 {
  width: 1%;
  white-space: nowrap;
  font-family: var(--gns-font-mono);
  font-size: 12px;
  color: var(--gns-secondary-2);
}
body.single-product .product-tabbed-layout .tablepress td.column-3 { color: var(--gns-text); }
body.single-product .product-tabbed-layout .tablepress td.column-1 { color: var(--gns-text); }
body.single-product .product-tabbed-layout .tablepress td.column-1 strong { font-weight: 500; }

/*
 * The column header row. TablePress puts this data in tbody with no header
 * class, so it is found by what makes it one: every cell bold, which no data
 * row here is - those bold only their label.
 */
body.single-product .product-tabbed-layout .tablepress
  tr:has(td.column-2 strong):has(td.column-3 strong):has(td.column-4 strong) td {
  font: 500 10px/1.4 var(--gns-font-mono);
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--gns-muted);
}
body.single-product .product-tabbed-layout .tablepress
  tr:has(td.column-2 strong):has(td.column-3 strong):has(td.column-4 strong) td strong {
  font-weight: 500;
}

/*
 * A full-width cell is a section banner - "SUGGESTED PRINT SETS (1)",
 * "PROPERTY" - and the person who built the table said so twice: a `.highrow`
 * span, and per-table custom CSS that paints the row solid #00BFFF with white
 * text. TablePress emits that as `#tablepress-2 tr.row-8`, an ID selector no
 * stylesheet can outrank, so the band is kept rather than fought - toned to a
 * cyan wash behind a cyan rule, which is the same statement at the page's
 * volume instead of a saturated bar.
 *
 * ⚠️ The wash goes over an OPAQUE layer, not on its own. --gns-cyan-tint-2 is
 * 10% cyan; laid straight onto the cell it let the author's solid row show
 * through almost undimmed, and cyan-ink text on a cyan bar is invisible. Two
 * background layers - the tint over the page ground - is the whole fix.
 */
body.single-product .product-tabbed-layout .tablepress td[colspan] {
  padding: 12px 16px;
  border-top: 0;
  border-left: 2px solid var(--gns-cyan);
  background: linear-gradient(var(--gns-cyan-tint-2), var(--gns-cyan-tint-2)), var(--gns-bg);
  font: 500 10.5px/1.4 var(--gns-font-mono);
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--gns-cyan-ink);
}
body.single-product .product-tabbed-layout .tablepress td[colspan] strong { font-weight: 500; }
/*
 * The air above a band, taken from the row before it. A cell cannot have a
 * margin and a transparent border would just extend the band's own wash
 * upward, so the space is asked for from the last row of the section above.
 */
body.single-product .product-tabbed-layout .tablepress tr:has(+ tr td[colspan]) td {
  padding-bottom: 30px;
}

/*
 * A row with a label and nothing else is a sub-heading inside the section -
 * "Physical", "Thermal", "Mechanical at 23°C / 50% rh" - not a measurement
 * with three blanks, which is how it read.
 *
 * Two selectors for one condition because the cells arrive in two shapes: this
 * table wraps every value in a span, so its blanks are `<td><span></span></td>`
 * rather than an empty cell. Columns 3 AND 4 both have to be blank - a row
 * missing only its unit is still a measurement.
 */
body.single-product .product-tabbed-layout .tablepress tr:has(td.column-3 > span:empty):has(td.column-4 > span:empty) td.column-1,
body.single-product .product-tabbed-layout .tablepress tr:has(td.column-3:empty):has(td.column-4:empty) td.column-1 {
  padding-top: 22px;
  font: 500 10px/1.4 var(--gns-font-mono);
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--gns-secondary-2);
}

/* A long sheet is read across, so the row it is on says so. */
body.single-product .product-tabbed-layout .tablepress tbody tr:hover td {
  color: var(--gns-text);
}

/* Tighten the strip on a phone so the common three-tab kit fits without a
   swipe; four still slide, which is what the scroller is for. */
@media (max-width: 600px) {
  body.single-product .product-tabbed-layout .nav-tabs { gap: 22px; }
  body.single-product .product-tab { font-size: 10.5px; letter-spacing: .11em; }
}

@media (prefers-reduced-motion: reduce) {
  body.single-product .product-tab::after,
  body.single-product .product-tabbed-layout .tab-pane { transition: none; }
  body.single-product .product-tabbed-layout .tab-pane { transform: none; }
}



/* ==========================================================================
   SPLIT LAYOUT - viewer left, purchase rail right
   Design: "Nuova proposta grafica.dc.html" -> the desktop product detail.

   ⚠️ This section is no longer a pure restyle. The markup it targets comes from
   woocommerce/content-single-product.php and woocommerce/single-product/rating.php,
   both forked into this theme - see the header comment on the first of those for
   why the layout could not be reached without them.

   The frame is one grid: an elastic stage and a fixed 520px rail, filling the
   viewport below the header. --gns-header-h is measured and published by
   theme-switch.js, so the split sits exactly under the bar whether or not the
   beta banner is showing.
   ========================================================================== */

.gns-pdp__split {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 500px;
  min-height: calc(100vh - var(--gns-header-h, 63px));
  align-items: stretch;
}

/* The parent floats and percentage-sizes .summary for its own two-column flow.
   In a grid the float is ignored, the width is not. */
.gns-pdp .summary.entry-summary {
  float: none;
  width: auto;
  max-width: none;
  margin: 0;
  padding: 30px 34px;
}

/* ---------------------------------------------------------------- stage --- */
/*
 * The glow is the design's, verbatim: a cyan wash centred slightly above the
 * middle, which is what lifts the model off the ground without lighting the
 * whole panel.
 */
/*
 * Sticky, and a FIXED height rather than a minimum. Both matter:
 *
 *   - the design's stage is one viewport panel, and a grid row sized by its
 *     content grew to 1784px around a portrait render;
 *   - a fixed height is what gives the gallery inside it a bounded flex
 *     context, which is what lets the main carousel shrink and the thumbnails
 *     stay on the floor of the stage;
 *   - sticky keeps the model in view while the rail scrolls past it, which is
 *     how the design's single-screen layout survives a rail carrying more than
 *     a screen of content.
 *
 * `top` is the measured header height, published by theme-switch.js - the
 * header is fixed, so anything sticky has to clear it.
 */
.gns-pdp__stage {
  position: sticky;
  top: var(--gns-header-h, 63px);
  align-self: start;
  display: flex;
  flex-direction: column;
  min-width: 0;
  height: calc(100vh - var(--gns-header-h, 63px));
  padding: 26px 32px 30px;
  /*
   * The artboard's stage: the technical grid (the --gns-grid token: 44px
   * lines at .02) under a 620x460 cyan wash, centred a little above the
   * middle. Turn 1's "horizon" ring behind the model went with the layout it
   * belonged to.
   */
  background:
    var(--gns-grid),
    radial-gradient(620px 460px at 50% 44%, var(--gns-cyan-tint-2), transparent 72%);
  overflow: hidden;
}


/* ----------------------------------------------------------- breadcrumb --- */
/*
 * The visible crumb trail, printed inside the stage. The one WooCommerce puts
 * in .site-main stays in the document for search engines and is hidden here -
 * it was already hidden before this redesign, so nothing is being taken away.
 */
body.single-product .site-main > .woocommerce-breadcrumb { display: none; }

.gns-pdp__crumbs {
  position: relative;
  z-index: 1;
  font: 500 11px var(--gns-font-mono);
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--gns-muted);
}
.gns-pdp__crumbs a { color: inherit; text-decoration: none; }
.gns-pdp__crumbs a:hover { color: var(--gns-text); }
.gns-pdp__crumb-sep { padding: 0 8px; opacity: .6; }

/* -------------------------------------------------------------- gallery --- */
/*
 * The gallery is two Splide carousels - the main image, then a nav carousel
 * acting as the thumbnails. The design stacks them: the model fills the stage,
 * the thumbnails sit on the floor of it.
 *
 * The main carousel keeps its own drag behaviour. The design's "trascina per
 * ruotare" rotation is NOT layered on top of it: drag here already means "next
 * image", and replacing a working control with a decorative one is a bad trade.
 *
 * ⚠️ `min-height: 0` on the flex child is what lets the main carousel SHRINK to
 * the space left over. Without it a flex item refuses to go below its content
 * height, and a tall portrait render pushed the thumbnails off the stage.
 */
.gns-pdp__stage .woocommerce-product-gallery {
  position: relative;
  z-index: 1;
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 22px;
  min-height: 0;
  width: auto;
  max-width: none;
  margin: 0;
  padding: 0;
  float: none;
}

/*
 * The viewer panel. The artboard frames the photograph in a 24px-radius box on
 * the elevated surface, 76% of the stage wide, the picture contained inside it
 * - not bled to the edges under a drop shadow, which was Turn 1.
 */
.gns-pdp__stage .woocommerce-product-gallery > .splide:first-child {
  flex: 1;
  min-height: 0;
  width: 100%;
  max-width: 76%;
  margin: 0 auto;
  padding: 22px;
  border: 1px solid var(--gns-border-faint);
  border-radius: var(--gns-r-hero);
  background: var(--gns-elevated);
}
.gns-pdp__stage .woocommerce-product-gallery > .splide:first-child .splide__track,
.gns-pdp__stage .woocommerce-product-gallery > .splide:first-child .splide__list,
.gns-pdp__stage .woocommerce-product-gallery > .splide:first-child .splide__slide {
  height: 100%;
}
.gns-pdp__stage .woocommerce-product-gallery > .splide:first-child .splide__slide {
  display: flex;
  align-items: center;
  justify-content: center;
}
/*
 * Contained and shadowed, the same treatment the cards give a model.
 *
 * ⚠️ `width/height: 100%` is what stops the picture loading in zoomed, and it
 * is not interchangeable with the `auto` + `max-*: 100%` that was here.
 *
 * The parent runs Panzoom over every main slide
 * (genesys/assets/js/header.js:223) with `contain: 'outside'` - "never let the
 * element be smaller than its box". Panzoom measures the <img> ELEMENT, not the
 * picture painted inside it. Sized with `auto`, that element takes the image's
 * intrinsic size - 600x400 inside a 791x616 stage - so Panzoom dutifully wrote
 * `transform: scale(1.4625)` onto every slide at mount and the product arrived
 * cropped, before anyone had touched it.
 *
 * Filling the slide and letting `object-fit: contain` do the fitting leaves the
 * element exactly the size of its container, so containment has nothing to
 * correct and the scale stays 1. The picture still letterboxes; the difference
 * is entirely in what Panzoom measures.
 *
 * Stylesheets are applied before any script runs, so Panzoom reads the
 * corrected box at construction. Reordering these declarations, or moving them
 * to a script, brings the zoom back.
 */
.gns-pdp__stage .woocommerce-product-gallery > .splide:first-child img {
  width: 100%;
  height: 100%;
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  border-radius: 12px;
}

/* The thumbnail strip. Tiles, arrows and states are set in the
   "thumbnail strip" section at the end of this file, next to the Details and
   Parts fixes they were reworked with. */
.gns-pdp__stage .woocommerce-product-gallery > .splide--nav { flex: 0 0 auto; }

/* ----------------------------------------------------------------- rail --- */

.gns-pdp__rail {
  display: flex;
  flex-direction: column;
  gap: 14px;
  border-left: 1px solid var(--gns-border);
  background: var(--gns-surface);
  min-width: 0;
}

/*
 * The badge row, top-left of the VIEWER now, as the artboard draws it -
 * "BEST SELLER" on the gradient, "Spedizione in 48h" outlined. The template
 * fills it with what has a source: the discount and the best-seller mark are
 * computed, the category and the copies are the product's own. It used to be
 * `.top-section` at the head of the rail; the rail opens with the rating row
 * now, as designed.
 */
.gns-pdp__badges {
  position: relative;
  z-index: 2;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  margin: 14px 0 0;
}
.gns-pdp__badges .gns-pdp__badge {
  display: inline-flex;
  align-items: center;
  height: auto;
  padding: 5px 11px;
  border: 1px solid var(--gns-border-strong);
  border-radius: var(--gns-r-chip);
  background: var(--gns-surface);
  color: var(--gns-secondary-2);
  font: 500 10.5px/1.2 var(--gns-font);
  letter-spacing: .02em;
  text-transform: none;
}
.gns-pdp__badges .gns-pdp__badge--accent {
  border-color: transparent;
  background: var(--gns-gradient);
  color: var(--gns-on-accent);
  font-weight: 800;
  letter-spacing: .04em;
  text-transform: uppercase;
}

/*
 * ⚠️ Written at (0,4,1) on purpose. genesys/style.css:3612
 * `.woocommerce div.product .product_title.entry-title` is (0,3,1) and sets
 * `font-weight: 700` and `margin-right: 150px` - the rail's title rendered
 * bold and 150px short of its column until this out-specified it. Nothing
 * there is !important, so specificity alone settles it.
 */
.woocommerce div.product.gns-pdp .gns-pdp__rail .product_title.entry-title,
.gns-pdp__rail .product_title {
  margin: 0;
  /* Cancels: genesys/style.css:5888 `.woocommerce div.product
     .product_title.entry-title { margin-right: 50px !important }` inside its
     narrow-screen media query - the one declaration of the pair that IS
     !important, so it has to be answered in kind. */
  margin-right: 0 !important;
  font-size: 28px;
  font-weight: 500;
  letter-spacing: -.03em;
  line-height: 1.15;
}

/* ---------------------------------------------------------- rating row --- */
/*
 * "★★★★★ 4.8 · 1.216 recensioni · 96% lo consiglia" - the first line of the
 * artboard's rail. The stars are two stacked runs: a muted base and a magenta
 * overlay clipped to the average, so 4.3 reads as four and a third.
 */
.gns-pdp__rating {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  font-size: 12px;
  color: var(--gns-secondary-2);
}
.gns-pdp__stars {
  position: relative;
  display: inline-block;
  font-size: 13px;
  line-height: 1;
  letter-spacing: 1px;
  color: var(--gns-border-heavy);
}
.gns-pdp__stars-fill {
  position: absolute;
  top: 0;
  left: 0;
  overflow: hidden;
  white-space: nowrap;
  color: var(--gns-magenta-ink);
}
.gns-pdp__rating-avg { font-weight: 500; color: var(--gns-text); }
.gns-pdp__rating-sep { color: var(--gns-muted); }
.gns-pdp__recommend { font-weight: 700; color: var(--gns-text); }

/* ---------------------------------------------------------- byline row --- */

.gns-pdp__byline {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  margin: -4px 0 0;
  font-size: 13px;
  color: var(--gns-body);
}
.gns-pdp__avatar {
  width: 30px;
  height: 30px;
  border-radius: 50%;
  object-fit: cover;
  flex: 0 0 auto;
}
.gns-pdp__by a {
  color: var(--gns-text);
  font-weight: 700;
  text-decoration: none;
}
.gns-pdp__by a:hover { color: var(--gns-cyan-ink); }
.gns-pdp__reviews {
  font-size: 12.5px;
  color: var(--gns-muted);
  text-decoration: none;
}
.gns-pdp__reviews:hover { color: var(--gns-body); }

/* The brand and the SKU: the quiet line the design has no slot for. */
.gns-pdp__rail .flex-div {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  margin: -6px 0 0;
}
.gns-pdp__rail .flex-div p {
  margin: 0;
  font: 500 10.5px var(--gns-font-mono);
  letter-spacing: .08em;
  color: var(--gns-muted);
}

/* ------------------------------------------------------------ materials --- */
/*
 * "MATERIALE E FINITURA" in the design; the real control is the variation
 * swatch list, which is the same thing wearing WooCommerce's markup.
 *
 * `display: contents` on the form and its inner wrapper dissolves both boxes so
 * the attribute table and the price/CTA block become direct children of the
 * rail. That is what lets the material list sit under the byline while the
 * total is pushed to the floor - they are two levels apart in the markup, and
 * `margin-top: auto` cannot reach across a parent.
 *
 * ⚠️ The design's per-row price delta ("+ € 6") is not rendered: WooCommerce
 * publishes a price for the SELECTED variation only, so a delta per option
 * would have to be computed from the variation set and does not exist in this
 * markup.
 */
/*
 * ⚠️ `:not()` the theme's own blocks. On a SIMPLE product the first <div> in
 * form.cart is not the parent's wrapper but the G-Coin line (or the deal line)
 * that functions.php prints through woocommerce_before_add_to_cart_button -
 * and dissolving that scattered "or" and "1.49 Gtok" into two separate rail
 * children, 30px apart. The parent's wrapper on a variable product has no
 * class, so the exclusion is exact.
 */
.gns-pdp__rail form.cart,
.gns-pdp__rail form.cart > div:first-child:not(.gns-pdp__total):not(.gns-pdp__deal) {
  display: contents;
}

.gns-pdp__rail table.variations {
  display: block;
  width: 100%;
  margin: 0;
  border: 0;
}
.gns-pdp__rail table.variations tbody,
.gns-pdp__rail table.variations tr {
  display: block;
  width: 100%;
}
.gns-pdp__rail table.variations th.label,
.gns-pdp__rail table.variations td.value {
  display: block;
  width: 100%;
  padding: 0;
  border: 0;
  text-align: left;
}
.gns-pdp__rail table.variations th.label {
  margin-bottom: 11px;
  font: 500 10.5px var(--gns-font-mono);
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--gns-muted);
}
/*
 * `<label>Color</label><span>: Bronze</span>` - no space in the markup, but the
 * parent gives every label and span `margin: 0 2px`, and the 4px that adds up
 * to landed between the word and its colon: "COLOR : BRONZE".
 */
.gns-pdp__rail table.variations th.label label {
  font: inherit;
  color: inherit;
  margin-right: 0;
}
.gns-pdp__rail .woo-selected-variation-item-name {
  color: var(--gns-body);
  margin-left: 0;
}

/*
 * The options themselves.
 *
 * ⚠️ There are TWO option lists in this markup and only one of them is live.
 * woo-variation-swatches renders `ul.variable-items-wrapper`; the parent hides
 * it outright -
 *
 *     style.css:2074  .printable-product ul.variable-items-wrapper
 *                     { display: none !important }
 *
 * - and drives the variation from its own `button.part-button` instead. So the
 * design's rows are built on `.part-button`. Styling the plugin's list and
 * hiding the parent's buttons, which is the obvious way round, leaves the
 * control invisible and the product unbuyable.
 *
 * The parent lays the buttons out as `width: calc(25% - 6px)` chips in a
 * `.d-flex.flex-wrap` cell; the design lists them as full-width rows.
 */
.gns-pdp__rail td.value {
  display: flex !important;
  flex-direction: column;
  gap: 9px;
}
.gns-pdp__rail .part-button {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  min-height: 48px;
  margin: 0;
  padding: 11px 14px;
  border-radius: 12px;
  border: 1px solid transparent;
  background: var(--gns-tint-weak);
  color: var(--gns-text);
  font-family: var(--gns-font);
  font-size: 13px;
  font-weight: 500;
  line-height: 1.3;
  text-align: left;
  cursor: pointer;
  transition: border-color .15s ease, background-color .15s ease;
}
.gns-pdp__rail .part-button:hover { background: var(--gns-tint); }
.gns-pdp__rail .part-button.selected,
.gns-pdp__rail .part-button.hover {
  border: 1px solid var(--gns-cyan);
  background: var(--gns-cyan-tint);
}

/* The plugin's list, on any screen where the parent has not hidden it. Colour
   attributes carry a real swatch there - the design's square, not the plugin's
   circle.

   ⚠️ A COLUMN IS ONLY RIGHT FOR SOME OF THESE, and this rule used to apply it
   to all of them. It was written for a kit's model picker, where each option is
   a sentence ("Vampire 1:32 TPU") and belongs on its own full-width row. The
   filaments carry a Color attribute with twenty swatches, and stacking those
   one per row made the picker 1,291px tall - the rail on
   /product/pla-ecogenius/ measured 1,395px for what should be two compact
   controls, pushing the price and the Add to cart button nearly two thousand
   pixels below the fold.

   So the direction is chosen per attribute type rather than for all of them,
   using the classes the plugin already puts on the wrapper. */
.gns-pdp__rail .variable-items-wrapper {
  display: flex;
  flex-direction: column;
  gap: 9px;
  margin: 0;
  padding: 0;
  list-style: none;
}

/*
 * Colour: a wrapping row of square chips. There is no reading order to preserve
 * - a colour is recognised, not read - so they tile.
 *
 * The size comes from the plugin's own custom properties rather than from a
 * fight with it. Its base rule reads `width: var(--wvs-single-product-item-width,
 * 30px)` at 0,4,0, so declaring a width here would need a selector built to
 * beat it; setting the property it already reads needs no specificity at all.
 *
 * `flex: 0 0 auto` still has to be said - twenty items each asking for their
 * share of a wrapping row would otherwise be shrunk to slivers.
 */
.gns-pdp__rail .color-variable-items-wrapper {
  --wvs-single-product-item-width: 36px;
  --wvs-single-product-item-height: 36px;
  flex-flow: row wrap;
  gap: 8px;
}
.gns-pdp__rail .color-variable-items-wrapper .variable-item {
  flex: 0 0 auto;
  min-height: 0;      /* the 48px hit target below is for labelled rows only */
}
/*
 * The plugin gives every item `margin: 4px` (0,4,0), which the `margin: 0`
 * below cannot reach from 0,2,0 - the swatches sat on 8px of gap plus 8px of
 * margin, and indented 4px past the price and the CTA. Mirroring the plugin's
 * own specificity ties it, and this sheet loads later.
 */
.gns-pdp__rail .variable-items-wrapper .variable-item:not(.radio-variable-item) {
  margin: 0;
}

/*
 * Labelled options: also a row, but sized to their own label rather than
 * stretched across the rail. "1.00 kg" as a 507px button was the giveaway that
 * the column was wrong here too; a long model name simply takes more width and
 * the row wraps under it.
 */
.gns-pdp__rail .button-variable-items-wrapper {
  flex-flow: row wrap;
  gap: 8px;
}
.gns-pdp__rail .button-variable-items-wrapper .variable-item {
  width: auto;
  flex: 0 1 auto;
}
/*
 * What is left after the paint moved up to the site-wide block. Everything a
 * 0,2,0 selector cannot reach - fill, border, radius, padding, width - is
 * declared there or by the plugin, so it is not restated here: this rule now
 * only says how tall a hit target has to be and how far apart a swatch sits
 * from its label.
 */
.gns-pdp__rail .variable-item {
  gap: 12px;
  min-height: 48px;
}
.gns-pdp__rail .variable-item .variable-item-span {
  font-size: 13px;
  font-weight: 500;
  color: var(--gns-text);
}

/* ------------------------------------------------------ rail ordering --- */
/*
 * `display: contents` above dissolved the form, so everything the parent puts
 * inside it is now a direct flex child of the rail - in DOM order, which is not
 * the design's order. The design's rail reads: what it is, who made it, what it
 * is made of, what it costs, buy. The parent also emits three blocks the design
 * has no slot for at all - a Details card, a Parts/Plates accordion and a
 * per-part specification table - and they are real, per-variation content, so
 * they go BELOW the CTA rather than being hidden.
 */
.gns-pdp__rail .gns-pdp__rating  { order: 1; }
.gns-pdp__rail .product_title    { order: 2; }
.gns-pdp__rail .gns-pdp__byline  { order: 3; }
.gns-pdp__rail .flex-div         { order: 4; }
.gns-pdp__rail .gns-pdp__lead    { order: 5; }
.gns-pdp__rail .gns-pdp__bullets { order: 6; }
.gns-pdp__rail table.variations  { order: 7; }
.gns-pdp__rail .total-price,
.gns-pdp__rail .price-card       { order: 8; }
.gns-pdp__rail .woocommerce-variation-add-to-cart,
.gns-pdp__rail form.cart > .single_add_to_cart_button { order: 9; }
.gns-pdp__rail .gns-pdp__trust   { order: 10; }
.gns-pdp__rail .gns-pdp__quote   { order: 11; }
.gns-pdp__rail .variant-card     { order: 12; }
.gns-pdp__rail .accordion        { order: 13; }
.gns-pdp__rail .part-details     { order: 14; }

/* --------------------------------------------------------------- total --- */
/*
 * The price block, in flow. The artboard's floor is the verified-buyer
 * quote, which is what carries `margin-top: auto` now.
 *
 * ⚠️ The price shown is the PARENT'S `.total-price`, not one this theme
 * renders. It is the better number: `.price-main` says "Free Product" where
 * WooCommerce's price_html says "GCOIN 0.00", and the parent's own script keeps
 * it in step with the chosen variation. Its `.total-price-title` label ("Total:")
 * was set to `display: none`; the design puts a label there, so it comes back.
 */
.gns-pdp__rail .single_variation_wrap,
.gns-pdp__rail .single_variation {
  display: contents;
}

.gns-pdp__rail .total-price {
  display: flex;
  flex-direction: column;
  gap: 5px;
  margin-top: 4px;
  padding-top: 14px;
  border-top: 1px solid var(--gns-border);
}
/*
 * ⚠️ No `display` here on purpose. The parent's script writes
 * `style="display: none"` on this label inline and clears it when a priced
 * variation is chosen - so a free file shows the price alone, which is correct.
 * Forcing it visible would put "Total:" over "Free Product".
 */
.gns-pdp__rail .total-price .total-price-title {
  font: 500 10px var(--gns-font-mono);
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--gns-muted);
}
.gns-pdp__rail .total-price .price-main {
  font-size: 38px;
  font-weight: 500;
  letter-spacing: -.04em;
  line-height: 1;
  color: var(--gns-text);
}
.gns-pdp__rail .total-price .discount:not(:empty) {
  font: 500 12px var(--gns-font-mono);
  color: var(--gns-muted);
  text-decoration: line-through;
}

/*
 * The G-Coin line.
 *
 * The design sets it BESIDE the price, right-aligned - "€ 100" on the left,
 * "oppure 99.000 Gtok" on the right. It stacks under the price here instead,
 * and deliberately: the price and this figure are printed by two different
 * blocks (the parent's `.total-price` / `.price-card`, and this theme's hook)
 * with no shared wrapper to make a row out of, and the only ways to fake one
 * are to move nodes in JavaScript or to position this absolutely over a box
 * whose height is not ours. Stacked, it takes the same label-over-value shape
 * as the price above it, so the two read as one block either way.
 */
/* One line, in the slot the artboard gives "oppure 3 rate da € 66,66". */
.gns-pdp__total {
  display: flex;
  align-items: baseline;
  gap: 6px;
  margin: 0;
  font-size: 11.5px;
  color: var(--gns-cyan-ink);
}
.gns-pdp__total-label { color: var(--gns-secondary); }
.gns-pdp__total-gtok { font: 500 11.5px var(--gns-font-mono); }

/* The cart block: the G-Coin line, the quantity stepper and the CTA. */
.gns-pdp__rail .woocommerce-variation-add-to-cart {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 12px;
}
.gns-pdp__rail .woocommerce-variation-add-to-cart .quantity { align-self: flex-start; }

/* WooCommerce's raw variation price and stock line, which the parent's
   .total-price already states in better words. */
.gns-pdp__rail .woocommerce-variation-price,
.gns-pdp__rail .woocommerce-variation-availability { display: none; }

/* ------------------------------------------------- lead and bullets ----- */
/*
 * The artboard's 13.5px lead and its four dotted lines. Sourced by
 * inc/product/data.php from the product's own copy.
 */
.gns-pdp__lead {
  margin: 0;
  font-size: 13.5px;
  line-height: 1.6;
  color: var(--gns-secondary);
  text-wrap: pretty;
}
.gns-pdp__bullets {
  display: flex;
  flex-direction: column;
  gap: 7px;
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: 12.5px;
  line-height: 1.45;
  color: var(--gns-body);
}
.gns-pdp__bullets li {
  display: flex;
  align-items: flex-start;
  gap: 9px;
}
.gns-pdp__bullets li::before {
  content: "";
  flex: 0 0 auto;
  width: 5px;
  height: 5px;
  margin-top: 6px;
  border-radius: 50%;
  background: var(--gns-cyan);
}
/* The first line leads, as on the artboard: bold, and its dot is the gradient. */
.gns-pdp__bullets li:first-child { font-weight: 700; color: var(--gns-text); }
.gns-pdp__bullets li:first-child::before { background: var(--gns-gradient); }

/* --------------------------------------------------------------- deal ---- */
/* "€ 249,99 · −20% lancio" beside the price, from functions.php. */
.gns-pdp__deal {
  display: flex;
  align-items: center;
  gap: 6px;
  margin: -2px 0 0;
  font-size: 12px;
  color: var(--gns-secondary);
}
.gns-pdp__deal s { color: var(--gns-muted); }
.gns-pdp__deal b { font-weight: 700; color: var(--gns-magenta-ink); }

/* -------------------------------------------------------------- trust ---- */
.gns-pdp__trust {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
  margin: 4px 0 0;
  padding: 0;
  list-style: none;
  font-size: 11.5px;
  line-height: 1.4;
  color: var(--gns-secondary-2);
}
.gns-pdp__trust li {
  display: flex;
  align-items: flex-start;
  gap: 8px;
}
.gns-pdp__trust a {
  color: inherit;
  text-decoration: underline;
  text-underline-offset: 2px;
}
.gns-pdp__trust a:hover { color: var(--gns-text); }
.gns-pdp__tick { flex: 0 0 auto; font-weight: 700; color: var(--gns-cyan-ink); }

/* -------------------------------------------------------------- quote ---- */
/* The floor of the rail: a verified buyer, in a hairline card. */
.gns-pdp__quote {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: auto 0 0;
  padding: 13px;
  border: 1px solid var(--gns-border);
  border-radius: 13px;
}
.gns-pdp__quote-avatar {
  flex: 0 0 auto;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  object-fit: cover;
}
.gns-pdp__quote-body blockquote { margin: 0; padding: 0; border: 0; }
.gns-pdp__quote-body p {
  margin: 0;
  font-size: 11.5px;
  line-height: 1.55;
  color: var(--gns-body);
}
.gns-pdp__quote-body figcaption {
  margin-top: 3px;
  font-size: 11px;
  color: var(--gns-muted);
}

/* ------------------------------------------------- parent detail blocks --- */
/*
 * The Details card, the Parts/Plates accordion and the per-part table. Below
 * the CTA now; given the panel treatment so they read as reference material
 * rather than as part of the purchase decision.
 */
.gns-pdp__rail .variant-card,
.gns-pdp__rail .accordion,
.gns-pdp__rail .part-details {
  border: 1px solid var(--gns-border);
  border-radius: var(--gns-r-card);
  background: var(--gns-tint-weak);
  overflow: hidden;
}

/*
 * The CTA: the artboard's 56px gradient pill under the cyan CTA glow.
 *
 * ⚠️ !important where the parent's is. genesys/style.css:2217
 * `.custom-cart-button` fixes `height: 40px`, `padding`, `width: calc(100% -
 * 158px)`, `margin-left: 10px`, `font-size: 14px`, `line-height: 18.23px` and
 * a white ground - every one of them !important - which is why the 56px this
 * rule always asked for measured 40px, 10px in from the rail's edge. Only
 * !important beats !important.
 */
.gns-pdp__rail .single_add_to_cart_button {
  width: 100% !important;
  height: 56px !important;
  margin: 10px 0 0 !important;
  padding: 0 24px !important;
  border: 0 !important;
  border-radius: var(--gns-r-pill) !important;
  background: var(--gns-gradient) !important;
  color: var(--gns-on-accent) !important;
  font-family: var(--gns-font) !important;
  font-size: 15.5px !important;
  font-weight: 700 !important;
  line-height: 56px !important;
  text-align: center;
  cursor: pointer;
  box-shadow: var(--gns-glow-cta);
  transition: transform .15s ease, box-shadow .15s ease;
}
.gns-pdp__rail .single_add_to_cart_button:hover {
  transform: translateY(-1px);
  box-shadow: 0 16px 44px rgba(0, 191, 255, .32);
}
.gns-pdp__rail .single_add_to_cart_button:disabled,
.gns-pdp__rail .single_add_to_cart_button.disabled {
  background: var(--gns-elevated);
  color: var(--gns-muted);
  box-shadow: none;
  transform: none;
  cursor: not-allowed;
}

/* --------------------------------------------------------------- detail --- */
/*
 * The description and the tabs, under the split and full width. In the parent
 * these were inside the summary, which is why the old rail ran to three
 * screens.
 */
.gns-pdp__detail {
  padding: 40px 36px 56px;
  border-top: 1px solid var(--gns-border);
}
.gns-pdp__detail .latest-comment {
  max-width: 78ch;
  margin: 0 0 32px;
  font-size: 14px;
  line-height: 1.6;
  color: var(--gns-body);
}

/* ---------------------------------------------------------- narrow ------- */
/*
 * Below the point where a 520px rail leaves the stage too little to be a stage,
 * the split becomes one column: viewer, then rail, then detail. The rail's
 * `margin-top: auto` stops mattering once the column is content-height, so the
 * total simply follows the materials.
 */
@media (max-width: 1100px) {
  .gns-pdp__split {
    grid-template-columns: minmax(0, 1fr);
    min-height: 0;
  }
  /* The stage stops being a sticky viewport panel: in one column there is
     nothing for it to stick beside, and keeping `height: calc(100vh - …)`
     left an 837px box holding a 400px image. */
  .gns-pdp__stage {
    position: static;
    height: auto;
    min-height: 58vh;
    padding: 20px;
  }
  .gns-pdp__stage .woocommerce-product-gallery > .splide:first-child {
    max-height: 52vh;
    max-width: 100%;
    padding: 14px;
  }
  .gns-pdp__rail { border-left: 0; border-top: 1px solid var(--gns-border); }
  .gns-pdp .summary.entry-summary { padding: 26px 20px 32px; }
  .gns-pdp__detail { padding: 32px 20px 44px; }
}


/* ------------------------------------------------- parent layout resets --- */
/*
 * The parent lays this page out for its own two-column float flow, and four of
 * its rules actively fight the split. They are listed with what they did:
 *
 *   style.css:1071  .woocommerce div.product { display: flex }
 *                   -> made .gns-pdp__split and .gns-pdp__detail two COLUMNS,
 *                      so the description sat beside the rail instead of under
 *                      the whole page.
 *   style.css:1142  .woocommerce-product-gallery { width: calc(30% - 25px)
 *                   !important; float: left }
 *                   -> pinned the viewer to 90px inside a 448px stage.
 *   style.css:1175  .product .summary { width: calc(50% - 25px);
 *                   float: left !important; margin-left: 50px }
 *                   -> held the rail at 250px of its 520px grid track.
 *   style.css:1145  #main-carousel .splide__slide img { max-height: 350px
 *                   !important; border: 1px solid lightgrey }
 *                   -> capped the model and drew a near-white frame round it.
 *
 * `!important` here is answering `!important` there; where the parent's rule is
 * not important, specificity alone settles it.
 */
.woocommerce div.product.gns-pdp { display: block; }

.gns-pdp__stage .woocommerce-product-gallery {
  width: auto !important;
  float: none !important;
}

.woocommerce div.product.gns-pdp div.summary,
.gns-pdp .summary.entry-summary {
  width: auto !important;
  float: none !important;
  margin: 0 !important;
}

.gns-pdp__stage #main-carousel .splide__slide img {
  height: 100% !important;
  max-height: 100% !important;
  border: 0 !important;
}


/* ------------------------------------------------- simple products ------- */
/*
 * A simple product does not go through the variations form at all: the parent
 * wraps the price, the quantity and the CTA in `div.card.price-card`, with its
 * own `.single-price > .price-title` label instead of `.total-price`. So the
 * floor of the rail has two shapes, and both need placing.
 *
 * ⚠️ Without an explicit order this card lands FIRST. `display: contents` on
 * `form.cart` dissolves the form, and everything else in the rail carries an
 * order of 1-10 while the card defaults to 0 - which put the price and the Add
 * to cart button above the product's own title.
 */
.gns-pdp__rail .price-card {
  order: 8;
  margin: 4px 0 0;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 12px;
  padding: 14px 0 0;
  border: 0;
  border-top: 1px solid var(--gns-border);
  border-radius: 0;
  background: none;
  box-shadow: none;
}
.gns-pdp__rail .single-price {
  display: flex;
  flex-direction: column;
  gap: 5px;
}
.gns-pdp__rail .single-price .price-title {
  font: 500 10px var(--gns-font-mono);
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--gns-muted);
}
.gns-pdp__rail .single-price .woocommerce-Price-amount {
  font-size: 38px;
  font-weight: 500;
  letter-spacing: -.04em;
  line-height: 1;
  color: var(--gns-text);
}
.gns-pdp__rail .price-card .quantity { align-self: flex-start; }

/* The CTA is the same button in both shapes; in the simple one it is nested in
   the card rather than being a child of the rail. */
.gns-pdp__rail .price-card .single_add_to_cart_button { margin-top: 2px; }

/* --------------------------------------------------------- quantity ------ */
/* The design has no quantity control. This one is real and it stays; it is
   sized down so it reads as a setting rather than as a second CTA. */
.gns-pdp__rail .quantity {
  display: flex;
  align-items: center;
  gap: 6px;
  height: 40px;
  padding: 0 6px;
  border: 1px solid var(--gns-border-strong);
  border-radius: var(--gns-r-pill);
  background: var(--gns-tint-weak);
}
.gns-pdp__rail .quantity .qty-text { font-size: 11.5px; color: var(--gns-muted); }
.gns-pdp__rail .quantity input.qty {
  width: 42px;
  border: 0;
  background: none;
  color: var(--gns-text);
  font-size: 13px;
  text-align: center;
}
.gns-pdp__rail .quantity button {
  width: 26px;
  height: 26px;
  border: 0;
  border-radius: 50%;
  background: var(--gns-tint);
  color: var(--gns-body);
  cursor: pointer;
}
.gns-pdp__rail .quantity button:hover { background: var(--gns-tint-strong); color: var(--gns-text); }


/* ==========================================================================
   DETAILS, PARTS AND THE THUMBNAIL STRIP

   Three blocks the parent renders with its own light-design markup, which the
   split rail inherited untouched. Each is fixed here rather than hidden: they
   all carry real per-variation data.
   ========================================================================== */

/* ------------------------------------------------------- details card ---- */
/*
 * ⚠️ The thumbnail inside the Details card is REMOVED, not restyled. The stage
 * to its left is already showing the same photograph at 40x the size, and in
 * the card it was doing active harm: `.variation-image-container` lays the
 * image and `.dimensions-div` out as siblings, so the dimensions wrapped
 * around a 150px picture and the icon column collided with the values.
 *
 * The <img> stays in the markup - the parent's lazy-loader walks these on
 * scroll and the sync layer keys off the container - so this hides it rather
 * than asking the template to stop printing it.
 */
.gns-pdp__rail .variation-image-container > img { display: none; }

.gns-pdp__rail .variant-card { overflow: hidden; }
.gns-pdp__rail .variant-card-header,
.gns-pdp__rail .accordion-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 11px 14px;
  margin: 0;
  border: 0;
  border-bottom: 1px solid var(--gns-border);
  background: var(--gns-tint-weak);
  font: 500 10.5px var(--gns-font-mono);
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--gns-muted) !important;
}

.gns-pdp__rail .variant-content-container { padding: 13px 14px 14px; }

.gns-pdp__rail .variation-image-container,
.gns-pdp__rail .dimensions-div {
  display: block;
  border: 0 !important;
  border-radius: 0;
  padding: 0;
  margin: 0;
  background: none;
}

/*
 * The spec rows. A grid rather than the parent's `flex + space-between`, which
 * spread three short pairs across the full card and then wrapped "Depth: 20 cm"
 * onto a line of its own. Auto-fit columns keep the labels aligned down the
 * card and collapse to fewer columns on a narrow rail instead of wrapping
 * unevenly.
 */
.gns-pdp__rail .dimensions-div .flex-div {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(118px, 1fr));
  gap: 7px 14px;
  margin: 0 0 9px;
  justify-content: start;
}
/* The icon rows carry one long value ("18 + - Full consent rights (Adult)"),
   so they stay a single full-width cell rather than being cut into columns. */
.gns-pdp__rail .dimensions-div .flex-div:not(:first-child) {
  grid-template-columns: 1fr;
}
.gns-pdp__rail .dimensions-div .flex-div:last-child { margin-bottom: 0; }

.gns-pdp__rail .part-settings {
  display: flex;
  align-items: center;
  gap: 7px;
  margin: 0;
  font-size: 12.5px;
  color: var(--gns-text);
}
.gns-pdp__rail .part-settings .title {
  display: inline-flex;
  align-items: center;
  font: 500 10px var(--gns-font-mono);
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--gns-muted);
  white-space: nowrap;
}

/*
 * The icon labels (audience, consent rating) are dark-on-transparent SVGs
 * drawn for the light design, so on the dark card they were all but invisible.
 * `invert(1)` flips them to light; the light theme gets them back untouched.
 */
.gns-pdp__rail .part-settings .title img {
  width: 14px;
  height: 14px;
  opacity: .8;
  filter: invert(1);
}
[data-theme="light"] .gns-pdp__rail .part-settings .title img { filter: none; }

/* The description under the specs. */
.gns-pdp__rail .variant-content-container .variation-detail + * ,
.gns-pdp__rail .variant-content-container > p {
  margin-top: 12px;
  font-size: 12.5px;
  line-height: 1.55;
  color: var(--gns-body);
}

/* ------------------------------------------------------ parts accordion --- */

.gns-pdp__rail .accordion-item {
  margin: 0;
  border: 0;
  border-radius: 0;
  background: none;
}
.gns-pdp__rail .accordion-header { cursor: pointer; }
.gns-pdp__rail .accordion-header .arrow {
  width: 11px;
  height: 11px;
  opacity: .7;
  filter: invert(1);
  transition: transform .2s ease;
}
[data-theme="light"] .gns-pdp__rail .accordion-header .arrow { filter: none; }
.gns-pdp__rail .accordion-header.active .arrow { transform: rotate(180deg); }

.gns-pdp__rail .accordion-content {
  padding: 13px 14px 14px;
  background: none;
  border: 0;
}

/*
 * The part picker. The parent positions `.search-icon-part` absolutely and
 * leaves the input unstyled, so on the dark rail the field had no visible
 * border or background and the magnifier landed on top of the first list item
 * instead of inside a field. Giving `.dropdown` the positioning context and the
 * input its 30px of left padding puts the glyph back where it belongs.
 */
.gns-pdp__rail .dropdown { position: relative; }
.gns-pdp__rail .dropdown .search-icon-part {
  position: absolute;
  top: 50%;
  left: 13px;
  transform: translateY(-50%);
  margin: 0;
  font-size: 11px;
  line-height: 1;
  color: var(--gns-muted);
  pointer-events: none;
}
/* The glyph is centred on the FIELD, not on the whole dropdown - the list below
   it would drag the midpoint down the panel. */
.gns-pdp__rail .dropdown .search-icon-part { top: 19px; transform: none; }

.gns-pdp__rail .dropdown-search {
  width: 100%;
  height: 38px;
  margin: 0;
  padding: 0 14px 0 32px;
  box-sizing: border-box;
  border: 1px solid var(--gns-border-strong);
  border-radius: var(--gns-r-pill);
  background: var(--gns-tint-weak);
  color: var(--gns-text);
  font-family: var(--gns-font);
  font-size: 12.5px;
}
.gns-pdp__rail .dropdown-search::placeholder { color: var(--gns-muted); opacity: 1; }
.gns-pdp__rail .dropdown-search:focus {
  outline: none;
  border-color: var(--gns-focus);
  box-shadow: 0 0 0 3px var(--gns-cyan-tint);
}

.gns-pdp__rail .dropdown-list {
  display: flex;
  flex-direction: column;
  gap: 2px;
  max-height: 210px;
  margin: 10px 0 0;
  padding: 0;
  overflow-y: auto;
  list-style: none;
  scrollbar-width: thin;
}
.gns-pdp__rail .dropdown-item {
  padding: 9px 12px;
  margin: 0;
  border-radius: 9px;
  font-size: 12.5px;
  color: var(--gns-body);
  cursor: pointer;
  transition: background-color .15s ease, color .15s ease;
}
.gns-pdp__rail .dropdown-item:hover,
.gns-pdp__rail .dropdown-item:focus-visible {
  background: var(--gns-tint);
  color: var(--gns-text);
}
.gns-pdp__rail .dropdown-item.selected,
.gns-pdp__rail .dropdown-item.active {
  background: var(--gns-cyan-tint);
  color: var(--gns-text);
  box-shadow: inset 0 0 0 1px var(--gns-border-cyan);
}

/* ---------------------------------------------------- thumbnail strip ---- */
/*
 * The switcher. It read as a carousel with two big arrows floating either side
 * of a single 150px tile, because the parent mounts the nav Splide with
 * `fixedWidth: 150, fixedHeight: 150` (genesys/assets/js/header.js:203) and
 * Splide keeps its arrows mounted whether or not there is anywhere to go.
 *
 * assets/js/product.js resizes the tiles to the artboard's 64px through Splide's
 * own options setter, so the widths it writes inline and the widths it uses for
 * its transform maths stay the same number. The arrows are handled here.
 *
 * `.is-overflow` is Splide's own class, set only when the slides do not all
 * fit. So a product with two photographs gets a plain row of tiles and no
 * chrome at all, and one with twelve still gets a way to reach the twelfth.
 */
.gns-pdp__stage .woocommerce-product-gallery > .splide--nav { max-width: 100%; }

.gns-pdp__stage .splide--nav:not(.is-overflow) .splide__arrows { display: none; }

.gns-pdp__stage .splide--nav .splide__arrow {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: var(--gns-elevated);
  border: 1px solid var(--gns-border-strong);
  opacity: 1;
  transform: translateY(-50%);
}
.gns-pdp__stage .splide--nav .splide__arrow--prev { left: -6px; }
.gns-pdp__stage .splide--nav .splide__arrow--next { right: -6px; }
.gns-pdp__stage .splide--nav .splide__arrow:hover { background: var(--gns-card); }
.gns-pdp__stage .splide--nav .splide__arrow svg {
  width: 11px;
  height: 11px;
  fill: var(--gns-body);
}
.gns-pdp__stage .splide--nav .splide__arrow:disabled { opacity: .35; }

/* The tiles. Sizing comes from Splide (see product.js); this is the dressing -
   the current one ringed in brand cyan, the rest quiet behind a hairline, at
   full opacity: the artboard does not dim them. */
.gns-pdp__stage .splide--nav .splide__slide {
  border-radius: 12px;
  border: 1px solid var(--gns-border-strong);
  background: var(--gns-elevated);
  overflow: hidden;
  opacity: 1;
  cursor: pointer;
  transition: opacity .15s ease, border-color .15s ease;
}
.gns-pdp__stage .splide--nav .splide__slide:hover { border-color: var(--gns-border-heavy); }
.gns-pdp__stage .splide--nav .splide__slide.is-active {
  opacity: 1;
  border-color: var(--gns-cyan);
  box-shadow: 0 0 0 1px var(--gns-cyan);
}
.gns-pdp__stage .splide--nav .splide__slide img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  padding: 0;
  border: 0 !important;
  border-radius: 11px;
}

@media (prefers-reduced-motion: reduce) {
  .gns-pdp__rail .accordion-header .arrow,
  .gns-pdp__rail .dropdown-item,
  .gns-pdp__stage .splide--nav .splide__slide { transition: none; }
}


/* ------------------------------------------- parts list, second pass ----- */
/*
 * Three light-design leftovers the first pass did not reach, each found by
 * measuring rather than by reading:
 *
 *   .dropdown-list  background #FFFFFF, and its items #F7F7F7 - the parent's
 *                   dropdown panel, which on the dark rail was a white slab
 *                   with near-white text on it.
 *   .dropdown-search  the parent's rule out-specifies a plain
 *                   `.gns-pdp__rail .dropdown-search`, so the field kept
 *                   `padding: 0 14px` and the magnifier sat ON the text.
 *                   `.dropdown input.dropdown-search` (0,2,1) settles it
 *                   without !important.
 *   .blur-overlay   a `linear-gradient(transparent, #FFFFFF)` fade over the
 *                   truncated description, i.e. a white smear across the card.
 */
.gns-pdp__rail .dropdown-list {
  background: var(--gns-bg);
  border: 1px solid var(--gns-border);
  border-radius: var(--gns-r-card);
  padding: 6px;
}
.gns-pdp__rail .dropdown-list li,
.gns-pdp__rail .dropdown-item {
  background: transparent;
  border: 0;
}
.gns-pdp__rail .dropdown-item:hover,
.gns-pdp__rail .dropdown-item:focus-visible {
  background: var(--gns-tint);
  color: var(--gns-text);
}

.gns-pdp__rail .dropdown input.dropdown-search {
  height: 40px;
  padding: 0 14px 0 34px;
  box-sizing: border-box;
}
.gns-pdp__rail .dropdown .search-icon-part { top: 20px; }

/*
 * The "read more" fade. It exists to signal that the text is clipped, so it is
 * kept - repainted onto the card's own colour instead of white. --gns-card is
 * a solid token in both themes, which is what a fade needs at its far end.
 */
/* ⚠️ The parent's selector is `.variant-card .variant-content-container
   .blur-overlay` (0,3,0). `body.single-product .blur-overlay` is (0,2,1) and
   loses to it, so the full path is repeated with one class more. */
body.single-product .variant-card .variant-content-container .blur-overlay,
body.single-product .view-nft-details .content .blur-overlay {
  background-image: linear-gradient(to bottom, rgba(13, 16, 22, 0), var(--gns-card));
}
[data-theme="light"] body.single-product .variant-card .variant-content-container .blur-overlay,
[data-theme="light"] body.single-product .view-nft-details .content .blur-overlay {
  background-image: linear-gradient(to bottom, rgba(255, 255, 255, 0), var(--gns-card));
}


/* ============================================================ lightbox ==== */
/*
 * The product gallery's click target, replacing the parent's Panzoom 5x jump -
 * see the note at the top of assets/js/product.js for what was removed.
 *
 * The dialog is dark in BOTH themes, and deliberately: it is a viewing surface
 * for a photograph, not a page surface. That is exactly what the --gns-scrim
 * and --gns-on-scrim tokens are for - tokens.css marks them as the two that do
 * not invert, because text over a scrim has to stay light whatever the page
 * beneath it is doing.
 */

.gns-lb {
  position: fixed;
  inset: 0;
  /* Above the fixed header, which is the tallest thing this theme stacks. */
  z-index: 9999;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 5vmin;
  background: rgba(6, 8, 12, .93);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}

/*
 * ⚠️ `touch-action: none` is what makes pinch-to-zoom possible at all. Without
 * it the browser claims the two-finger gesture for its own page zoom and the
 * pointer events never arrive - and `overflow: hidden` keeps a zoomed image
 * inside the stage rather than over the controls.
 */
.gns-lb__stage {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  margin: 0;
  overflow: hidden;
  touch-action: none;
}
.gns-lb__stage img {
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
  object-fit: contain;
  border-radius: var(--gns-r-card);
  /* A photograph on a near-black ground needs an edge, or a product shot with a
     white background bleeds into nothing at the corners. */
  box-shadow: 0 30px 90px rgba(0, 0, 0, .6);
  /* Centre, because the transform maths treats tx/ty as offsets FROM centre. */
  transform-origin: center center;
  cursor: zoom-in;
  /* The browser's own image drag would otherwise start on the first pan, and
     the selection highlight flashes on every double-click. */
  -webkit-user-drag: none;
  user-select: none;
  -webkit-user-select: none;
}
/* No transition on `transform`: a drag sets it on every pointermove, and
   easing between those makes the picture lag the finger. */
.gns-lb.is-zoomed .gns-lb__stage img { border-radius: 0; }

/* ------------------------------------------------------------ controls --- */

.gns-lb__close,
.gns-lb__nav {
  position: absolute;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* 44px is the WCAG 2.2 target minimum, and these float over a photograph
     where there is nothing else to aim at. */
  width: 44px;
  height: 44px;
  padding: 0;
  border: 1px solid var(--gns-on-scrim-border);
  border-radius: 50%;
  background: rgba(10, 12, 16, .55);
  color: var(--gns-on-scrim);
  cursor: pointer;
  transition: background-color .15s ease, border-color .15s ease;
}
.gns-lb__close:hover,
.gns-lb__nav:hover {
  background: rgba(10, 12, 16, .8);
  border-color: var(--gns-on-scrim);
}
.gns-lb__close:focus-visible,
.gns-lb__nav:focus-visible {
  outline: none;
  border-color: var(--gns-cyan);
  box-shadow: 0 0 0 3px var(--gns-cyan-tint-2);
}
.gns-lb__close svg,
.gns-lb__nav svg { width: 18px; height: 18px; }

.gns-lb__close { top: 18px; right: 18px; }
.gns-lb__nav--prev { left: 18px; top: 50%; transform: translateY(-50%); }
.gns-lb__nav--next { right: 18px; top: 50%; transform: translateY(-50%); }

.gns-lb__count {
  position: absolute;
  left: 50%;
  bottom: 18px;
  transform: translateX(-50%);
  margin: 0;
  padding: 5px 12px;
  border-radius: var(--gns-r-pill);
  background: rgba(10, 12, 16, .55);
  border: 1px solid var(--gns-on-scrim-border);
  font: 500 11px var(--gns-font-mono);
  letter-spacing: .1em;
  color: var(--gns-on-scrim);
}

/* The gallery image now says what a click does. */
.gns-pdp__stage #main-carousel .splide__slide img { cursor: zoom-in; }

@media (max-width: 560px) {
  .gns-lb { padding: 3vmin; }
  .gns-lb__nav--prev { left: 8px; }
  .gns-lb__nav--next { right: 8px; }
  .gns-lb__close { top: 10px; right: 10px; }
}

@media (prefers-reduced-motion: reduce) {
  .gns-lb__close,
  .gns-lb__nav { transition: none; }
}


/* ------------------------------------------------- part specification ---- */
/*
 * The panel that opens when a part is picked in the Parts list: a photograph of
 * the part and nine print settings.
 *
 * Two separate problems, found by measuring rather than by looking:
 *
 * 1. LAYOUT. `.part-general-info` is a flex ROW with no gap. The image is 160px
 *    and the settings block 319px, which is 479px inside a 415px panel - so the
 *    row wrapped, the picture landed on top of the settings with nothing
 *    between them, and the two were left misaligned by 10px. It is a column.
 *
 * 2. THE LABELS WERE INVISIBLE. Each setting renders as an icon and a value and
 *    nothing else; the name of the thing - "Recommended Material", "Bed
 *    Temperature", "Adhesion" - is only in `data-original-title`, i.e. a
 *    tooltip. So the panel read "PLA · 200 °C · 60 °C · Yes · Yes · 30%" and
 *    there was no way to tell which "Yes" was adhesion and which was support
 *    without hovering each one, which is not possible at all on a touchscreen.
 *
 *    `content: attr(data-original-title)` promotes that tooltip to a visible
 *    label. The data was already in the markup; it just had nowhere to be seen.
 */

.gns-pdp__rail .part-general-info {
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding: 12px;
  border: 0 !important;
}

/*
 * The part photograph. These are screenshots from the slicer on a light ground,
 * so `contain` on a plate rather than `cover` in a crop - the same treatment
 * the Details card and the product cards give opaque artwork.
 */
.gns-pdp__rail .part-general-info > img {
  width: 100%;
  height: 148px;
  object-fit: contain;
  border-radius: var(--gns-r-chip);
  background: var(--gns-tint-weak);
  padding: 8px;
  box-sizing: border-box;
}

/*
 * All nine settings in ONE grid rather than three rows of three. `display:
 * contents` dissolves the parent's `.flex-div` rows - which were
 * `justify-content: space-between`, so each row of three spread itself across
 * the full width and no column ever lined up with the row above it.
 */
.gns-pdp__rail .general-info {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(132px, 1fr));
  gap: 14px 16px;
}
.gns-pdp__rail .general-info > .flex-div {
  display: contents;
}

/*
 * ⚠️ More specific than the `.gns-pdp__rail .part-settings` rule in the Details
 * card above, which lays these out as one horizontal line. Here they need two:
 * label over value, or the label has nowhere to go.
 */
.gns-pdp__rail .general-info .part-settings {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 3px;
  min-width: 0;
}
.gns-pdp__rail .general-info .part-settings .title {
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
}
.gns-pdp__rail .general-info .part-settings .title::after {
  content: attr(data-original-title);
  font: 500 9.5px var(--gns-font-mono);
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--gns-muted);
  white-space: normal;
  line-height: 1.25;
}
/* Icons come from the parent at 21px, which overpowers a 9.5px label. */
.gns-pdp__rail .general-info .part-settings .title img {
  width: 15px;
  height: 15px;
  max-width: 15px;
  max-height: 15px;
  flex: 0 0 auto;
  opacity: .75;
}
/* The value, indented to clear the icon so the column reads as one block. */
.gns-pdp__rail .general-info .part-settings > span:not(.title) {
  padding-left: 21px;
  font-size: 13px;
  font-weight: 500;
  color: var(--gns-text);
  line-height: 1.3;
}

/* ------------------------------------------------ description + link ----- */

.gns-pdp__rail .part-detail {
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding: 12px;
}
.gns-pdp__rail .part-detail.hide { display: none; }

/*
 * The parent prints "Description:" as a bare bold line and the text under it.
 * A rule above it separates it from the specification block without needing a
 * second panel.
 */
.gns-pdp__rail .part-detail > p,
.gns-pdp__rail .part-detail > div:not(.part-general-info) {
  margin: 0;
  font-size: 12.5px;
  line-height: 1.55;
  color: var(--gns-body);
}

.gns-pdp__rail .part-printers-section,
.gns-pdp__rail .part-detail a[href="#"],
.gns-pdp__rail .supported-printers-btn {
  align-self: flex-start;
}

/*
 * "View supported printers (217)" arrives as the parent's white pill. On the
 * dark rail it was the brightest thing in the panel, louder than the CTA above
 * it, so it takes the theme's outline treatment instead.
 */
.gns-pdp__rail .part-detail button,
.gns-pdp__rail .part-printers-section button,
.gns-pdp__rail .supported-printers-btn {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  height: 40px;
  padding: 0 16px;
  border: 1px solid var(--gns-border-strong) !important;
  border-radius: var(--gns-r-pill);
  background: var(--gns-tint-weak) !important;
  color: var(--gns-body) !important;
  font-family: var(--gns-font);
  font-size: 12.5px;
  font-weight: 500;
  cursor: pointer;
  transition: border-color .15s ease, color .15s ease;
}
.gns-pdp__rail .part-detail button:hover,
.gns-pdp__rail .part-printers-section button:hover,
.gns-pdp__rail .supported-printers-btn:hover {
  border-color: var(--gns-border-heavy) !important;
  color: var(--gns-text) !important;
}
.gns-pdp__rail .part-detail button img,
.gns-pdp__rail .part-printers-section button img {
  width: 16px;
  height: 16px;
  opacity: .75;
  filter: invert(1);
}
[data-theme="light"] .gns-pdp__rail .part-detail button img,
[data-theme="light"] .gns-pdp__rail .part-printers-section button img,
[data-theme="light"] .gns-pdp__rail .general-info .part-settings .title img { filter: none; }
