/* ===========================================================================
 * home-catalog.css — the live home catalog's card presentation layer, and nothing else.
 *
 * ⚠️ SOURCE FILE, HAND-AUTHORED. scripts/build-site.mjs copies this byte-for-byte to
 *    public/site/home-catalog.css and links it from index.html ONLY. D-13-03: NEVER
 *    hand-edit the copy under public/site/ — the transform rebuilds that tree from
 *    scratch on every run and silently reverts it. Every change goes here.
 *
 * ⚠️ THIS FILE MUST NEVER GROW.
 *    14-UI-SPEC § "home-catalog.css rules (the complete list)" closes the list at
 *    rules 1–13 below (rules 12 and 13 were added by plan 14-08 for UAT gap G-14-5).
 *    It adds no hover, focus or animation styling — those stay inherited from the
 *    theme unchanged — and it never references another file or another origin: no
 *    fetched image, no pulled-in stylesheet, no web font.
 *    The conditional line-height backstop the UI-SPEC once sanctioned for the sale
 *    price is WITHDRAWN. Its selector was less specific than the theme's loop-item
 *    price rule (the theme's is (0,5,0)), and on staging it was measured to have no
 *    effect. Any future override of a property the theme sets on the price paragraph
 *    must reach (0,5,0), or target the struck/sale amounts, which only inherit it.
 *
 * D-14-14 — LAST IN <head>. build-site appends the link after the age gate's own
 * stylesheet. Being last in <head> only settles ties between EQUAL specificities: it
 * lets these rules win over theme rules of the same specificity, and it does NOT beat
 * the theme's more specific (0,5,0) price-paragraph rules.
 * No new colours: every value below is a kit global or an already-committed neutral.
 * =========================================================================== */

/* 1. Sale price: no browser-default underline (no theme `ins` rule reaches these
 *    widgets), and the amount never breaks across lines. */
.e-loop-item .price ins { text-decoration: none; white-space: nowrap; }

/* 2. Struck regular price: secondary grey (AA on white), the theme's 4px gap, and the
 *    amount kept intact. The strike itself stays the user-agent default (D-14-13).
 *    14px (plan 14-08, G-14-5) so the pair fits the narrowest grid price box, 125.0px at
 *    1025–1200px viewports (the theme's 960px container step): at 18px the pair needs
 *    128.6px, at 14px 114.8px. Even the worst current 3-digit pair ($300.00 → $299.99)
 *    keeps 1.0px of slack. 15px was measured and rejected: it overflows that worst pair
 *    by 2.8px. The sale price (ins) keeps the inherited 18px. */
.e-loop-item .price del { color: #54595F; margin-right: 4px; white-space: nowrap; font-size: 14px; }

/* 3. Sale badge: a fixed-size navy/gold chip on the image's top-left, clear of the
 *    carousel label that overlaps the image bottom. pointer-events: none so the image
 *    link and the grid's full-card overlay still receive every click. */
.e-loop-item .adx-sale-badge { position: absolute; top: 8px; left: 8px; z-index: 2; padding: 4px 8px; background: #172F3B; color: #B09257; border: 1px solid #B09257; border-radius: 3px; font-family: "Josefin Sans", Sans-serif; font-size: 11px; font-weight: 600; line-height: 1; letter-spacing: .1em; text-transform: uppercase; pointer-events: none; }

/* 4. Carousel image: one fixed box (the emitted 800x933 ratio) so varied product photos
 *    keep every slide the same height, contained on white rather than cropped. */
.elementor-8688 .elementor-element-9546991 img { aspect-ratio: 800 / 933; height: auto; object-fit: contain; background: #FFFFFF; }

/* 5. Grid image: overrides only the inherited cover crop, which cut blend-jar labels in
 *    the narrow column. The inherited 214px height stays. */
.elementor-8930 .elementor-element-28fbce0 img { object-fit: contain; background: #FFFFFF; }

/* 6. Null-image placeholder: a neutral box with a centred, decorative vial glyph. */
.e-loop-item .adx-img-placeholder { display: flex; align-items: center; justify-content: center; width: 100%; background: #E9E9E9; color: #7A7A7A; }
.e-loop-item .adx-img-placeholder svg { width: 40px; height: 40px; opacity: .6; }

/* 7. Carousel placeholder: the same box as a carousel image (rule 4). */
.elementor-8688 .adx-img-placeholder { aspect-ratio: 800 / 933; }

/* 8. Grid placeholder: the same box as a grid image (the inherited 214px). */
.elementor-8930 .adx-img-placeholder { height: 214px; }

/* 9. Empty label slot: keeps its line so every card's title and price stay aligned. */
.e-loop-item .adx-label--empty { visibility: hidden; }

/* 10. Single-slide guard: Swiper never initialises under 2 slides, and an uninitialised
 *     slide is full width. Hold a lone card at its normal 4/2/1-per-view width. The
 *     :has(:only-of-type) scope leaves first paint for 2+ slides unchanged. */
.elementor-element-5eeebbd:has(.swiper-slide:only-of-type) .swiper-slide { max-width: calc((100% - 30px) / 4); }
@media (max-width: 1024px) {
  .elementor-element-5eeebbd:has(.swiper-slide:only-of-type) .swiper-slide { max-width: calc((100% - 10px) / 2); }
}
@media (max-width: 767px) {
  .elementor-element-5eeebbd:has(.swiper-slide:only-of-type) .swiper-slide { max-width: 100%; }
}

/* 11. Hide the inert prev/next arrows when there is only one slide to scroll to. */
.elementor-element-5eeebbd:has(.swiper-slide:only-of-type) .elementor-swiper-button { display: none; }

/* 12. Grid SALE chip (plan 14-08, UAT gap G-14-5): the grid chip now lives in the label
 *     widget, whose `.elementor-widget` position (relative) makes it the containing
 *     block. `top: auto` is required: with rule 3's `top` still set the box would be
 *     over-constrained. The chip sits 4px (the xs token) above the label, flush with the
 *     text column's left edge. `nowrap` is mandatory: measured, a chip allowed to wrap
 *     collapses to a stacked 27x54px box. `pointer-events: none` is inherited from
 *     rule 3, so the card's full-card link still receives every click. */
.elementor-8930 .adx-sale-badge { top: auto; left: 0; bottom: calc(100% + 4px); white-space: nowrap; }

/* 13. Unbreakable sale pair (plan 14-08, UAT gap G-14-5): the struck and sale amounts are
 *     each nowrap already (rules 1–2), so the literal space after the struck price was
 *     the pair's only break opportunity. This removes it. The theme sets no white-space
 *     on the price paragraph, so (0,2,1) applies. A wrapped line can therefore never
 *     reach the theme's 1px line box. This rule deliberately leaves line-height alone. */
.e-loop-item .price:has(del) { white-space: nowrap; }
