
        /* v4.20.8/9 — CRITICAL MOBILE FIX: defeat the v4.4.61 gallery freeze
         * on mobile + body-level overflow safety net.
         *
         * v4.20.17 — strengthened: added !important to the body overflow
         * rule and a JavaScript runtime safety net at the end of the
         * style block that sets inline style on html+body. Inline styles
         * beat external CSS, so this is the final escape hatch if any
         * theme or third-party CSS rule has overflow:visible !important
         * on html/body. */
        @media (max-width: 720px) {
            /* === v4.20.17 — Gallery responsive fix, frame-AGNOSTIC ===
             *
             * The diagnostic at 396px viewport showed:
             *   gallery width=438px inside parent width=364px
             *   gallery parent: <div class="tm-has-options ..."> (the
             *   product container, display:flex)
             *   Frame present: NO
             *
             * The .flowla-gallery-frame rules below don't apply when the
             * EOR relocator goes into SEO mode (not gallery mode) — no
             * frame wraps the gallery. Without a frame, the gallery is
             * a direct flex child of the product container with
             * min-width:auto (the default for flex items), which means
             * it refuses to shrink below the image's intrinsic width.
             * Image at ~510px intrinsic = gallery locked at 510px or
             * whatever its content forces.
             *
             * Fix: target .woocommerce-product-gallery directly with
             * min-width:0 to unblock flex shrinking, max-width:100% to
             * bound to parent. Plus images max-width:100% height:auto
             * to scale them responsively. */
            .woocommerce-product-gallery,
            .product .woocommerce-product-gallery,
            .product div.images,
            .product .images {
                max-width: 100% !important;
                width: auto !important;
                min-width: 0 !important;
                box-sizing: border-box !important;
            }
            .woocommerce-product-gallery img,
            .woocommerce-product-gallery .wp-post-image,
            .product div.images img,
            .product div.images .wp-post-image {
                max-width: 100% !important;
                height: auto !important;
            }
            /* FlexSlider viewport — WC's gallery wraps slides in this.
             * Without min-width:0 it inherits the same flex-shrink:auto
             * problem and the slide wrapper inside (with width:400% for
             * slide count) magnifies it. */
            .woocommerce-product-gallery .flex-viewport {
                max-width: 100% !important;
                min-width: 0 !important;
                box-sizing: border-box !important;
            }

            /* Product container — ensure direct children are
             * shrinkable so flex distribution works correctly. */
            [id^="product-"].product {
                max-width: 100% !important;
                box-sizing: border-box !important;
            }
            [id^="product-"].product > * {
                min-width: 0;
                max-width: 100%;
                box-sizing: border-box;
            }


            /* Variation-add-to-cart wrapper — the QC's grand-parent.
             * Same flex-shrink unblock so its children can size to
             * available width rather than to content intrinsic width. */
            .woocommerce-variation-add-to-cart,
            .variations_button,
            .variations_form,
            .single_variation_wrap {
                max-width: 100% !important;
                min-width: 0 !important;
                box-sizing: border-box !important;
            }

            /* === v4.20.8 — Frame-scoped overrides (kept for pages where
             *     the relocator does create a .flowla-gallery-frame) === */
            .flowla-gallery-frame,
            .flowla-gallery-frame > .woocommerce-product-gallery,
            .flowla-gallery-frame > div.images,
            .flowla-gallery-frame .woocommerce-product-gallery,
            .flowla-gallery-frame .images {
                max-width: 100% !important;
                width: auto !important;
                min-width: 0 !important;
                box-sizing: border-box !important;
            }
            .flowla-gallery-frame img,
            .flowla-gallery-frame .wp-post-image {
                max-width: 100% !important;
                width: auto !important;
                height: auto !important;
            }

            /* Body-level overflow safety net. */
            html, body {
                max-width: 100vw !important;
                overflow-x: clip !important;
                overflow-x: hidden !important; /* fallback chain */
            }
            @supports (overflow-x: clip) {
                html, body { overflow-x: clip !important; }
            }
        }

        .fx-eor-wrap { max-width: 1180px; margin: 30px auto; padding: 0 24px; font-family: 'Jost', system-ui, -apple-system, sans-serif; color: #1A1A1A; }
        /* v4.7.15: when the relocator has placed the wrapper inside .fbf-seo-copy
           or the gallery frame, drop the auto-margins + max-width so the wrapper
           fills its container naturally. The relocator adds a marker class. */
        .fx-eor-wrap.fx-eor-wrap--inline { max-width: none; margin: 0 0 24px 0; padding: 0; }
        /* v4.18.5 — gallery frame defensive clamps. The relocator wraps the
         * WC product gallery in .flowla-gallery-frame and freezes it at the
         * pre-wrap width. If the freeze step ever fails (offsetWidth=0 at
         * freeze time — the trait-checkout-angel.php abort-on-zero-width
         * fix is the primary defence), these rules ensure the gallery and
         * its image stay clamped to the frame width regardless.
         * Low specificity so themes that intentionally want a wider gallery
         * can still win. */
        .flowla-gallery-frame {
            max-width: 100%;
            box-sizing: border-box;
        }
        .flowla-gallery-frame .woocommerce-product-gallery,
        .flowla-gallery-frame > div.images {
            max-width: 100%;
            box-sizing: border-box;
        }
        .flowla-gallery-frame .woocommerce-product-gallery img,
        .flowla-gallery-frame .woocommerce-product-gallery .wp-post-image,
        .flowla-gallery-frame > div.images img {
            max-width: 100%;
            height: auto;
        }
        /* Anti-flash: hidden until the relocator finishes placing it. */
        .fx-eor-wrap--anchoring { visibility: hidden; }
        /* v4.7.25: diagnostic panel — visible on-page after Add to Basket click. */
        .fx-eor-diag { margin: 14px 0; background: #1F3A24; color: #E8F7D5; border-radius: 6px; overflow: hidden; font-family: 'Jost', system-ui, sans-serif; box-shadow: 0 4px 14px -6px rgba(31, 58, 36, 0.4); }
        .fx-eor-diag-header { padding: 10px 14px; background: rgba(0,0,0,0.18); display: flex; justify-content: space-between; align-items: center; gap: 10px; font-size: 13px; }
        .fx-eor-diag-header strong { font-weight: 600; }
        .fx-eor-diag-copy { background: #85C727; color: #1F3A24; border: 0; padding: 6px 14px; font-size: 11px; font-weight: 600; letter-spacing: 1px; text-transform: uppercase; cursor: pointer; border-radius: 3px; font-family: inherit; }
        .fx-eor-diag-copy:hover { background: #95D837; }
        .fx-eor-diag-copy:active { background: #75B717; }
        .fx-eor-diag-close { background: transparent; color: #fff; border: 1px solid rgba(255,255,255,0.3); width: 26px; height: 26px; cursor: pointer; border-radius: 3px; font-size: 16px; line-height: 1; padding: 0; font-family: inherit; }
        .fx-eor-diag-close:hover { background: rgba(255,255,255,0.1); }
        .fx-eor-diag-body { padding: 12px 14px; margin: 0; font-family: 'Courier New', monospace; font-size: 11px; line-height: 1.4; color: #E8F7D5; white-space: pre-wrap; word-break: break-word; max-height: 400px; overflow-y: auto; background: rgba(0,0,0,0.1); }
        .fx-eor-diag--error { background: #5C1F1F; }
        .fx-eor-diag--error .fx-eor-diag-body { color: #FFD3B3; }
        .fx-eor-diag--success { background: #1F4A24; }
        .fx-eor-accordion { background: #FAFAF8; border: 1px solid #C8DEC0; border-radius: 6px; overflow: hidden; transition: all 0.2s; }
        /* v4.25.79 — SPEED (industry best practice): skip layout + paint of any
         * EOR section that is off-screen, so the browser doesn't have to render
         * all the below-the-fold content (especially the eager custom panes)
         * up front. The section renders the moment it nears the viewport, so
         * every product is still shown when scrolled to. contain-intrinsic-size
         * reserves an estimated height (auto = remember the real size after the
         * first render) to keep the scrollbar stable. This restores the
         * "only render what's needed" discipline and fixes the mobile scroll
         * hang caused by heavy off-screen sections. */
        /* v0.2.36 — THE PHANTOM SPACE CURED (owner, 15 Aug: mobile "took
         * ages and didn't load properly"). The Guardian's v4.25.79 rule
         * above put content-visibility on the WHOLE section with a 600px
         * estimate — but the common case is a COLLAPSED section whose real
         * height is ~90px, so nine sections reserved ~3,600px of blank,
         * scroll-snapping space on every product page, both viewports
         * (measured live: wrap 5,515px reserved vs 1,885px real; the fix
         * measured live at 2,091px — 3,424px reclaimed). The optimisation
         * MOVES to the section BODY: a collapsed body is display:none and
         * costs nothing, an expanded off-screen body still skips layout/
         * paint exactly as v4.25.79 intended for the heavy panes. */
        .fx-eor-acc-body { content-visibility: auto; contain-intrinsic-size: auto 500px; }
        /* v0.2.57 — RENDER ONCE, THEN STAY: a body seen once is held visible (eor-render-once.php marks fx-eor-seen) so images never vanish on scroll-back. RE-APPLIED (v0.2.70). */
        .fx-eor-acc-body.fx-eor-seen { content-visibility: visible; contain-intrinsic-size: auto; }
        /* v4.7.33: spacing between stacked accordions when multiple sections present. */
        .fx-eor-accordion + .fx-eor-accordion { margin-top: 12px; }
        .fx-eor-accordion.open { border-color: #85C727; box-shadow: 0 4px 14px -6px rgba(31, 58, 36, 0.12); }
        .fx-eor-acc-header { padding: 16px 22px; display: flex; align-items: center; gap: 16px; cursor: pointer; user-select: none; transition: background 0.15s; }
        .fx-eor-acc-header:hover { background: #F0F7E5; }
        /* v4.7.31: gradient flows cream → mint so it visually pours into the
         * mint body below. Eliminates the abrupt color shift James flagged. */
        .fx-eor-accordion.open .fx-eor-acc-header { background: linear-gradient(180deg, #FAFAF8, #E8F7D5); border-bottom: 1px solid #C8DEC0; }
        /* v4.7.40: direct-link tab variant — visually matches the accordions
         * but the entire row is a navigation anchor. No dropdown body, no
         * chevron rotation. Arrow → replaces chevron ▼ as the affordance
         * indicator. Hover state mirrors accordion behaviour for consistency. */
        a.fx-eor-accordion--direct { display: block; text-decoration: none; color: inherit; }
        a.fx-eor-accordion--direct:hover { border-color: #85C727; box-shadow: 0 4px 14px -6px rgba(31, 58, 36, 0.12); transform: translateY(-1px); }
        a.fx-eor-accordion--direct:hover .fx-eor-acc-header { background: linear-gradient(180deg, #FAFAF8, #E8F7D5); }
        a.fx-eor-accordion--direct:hover .fx-eor-acc-title h3 { color: #2A6132; }
        a.fx-eor-accordion--direct:hover .fx-eor-chevron--arrow { transform: translateX(4px); color: #2A6132; }
        .fx-eor-chevron--arrow { transition: transform 0.15s, color 0.15s; }
        .fx-eor-pill { background: #1F3A24; color: #85C727; font-size: 9px; padding: 4px 10px; border-radius: 14px; letter-spacing: 1.5px; text-transform: uppercase; font-weight: 600; flex-shrink: 0; }

        /* v4.20.1 — In Season accordion pill + heading + items.
         *
         * The In Season pill uses a warm amber/gold tone (#C68B3A on cream)
         * to distinguish it from the sage-green pill family used by
         * Siblings / Floral Bunches / By Colour. Customers reading the
         * column register four distinct accordion "kinds":
         *   ★    Siblings        — sage pill (this product's variants)
         *   (amber) In Season Now — amber pill (what's at peak THIS month)
         *   ★★   Floral Bunches  — sage pill (all varieties index)
         *   ★★★  By Colour       — sage pill (colour-axis collections)
         *
         * The amber tone signals "special, premium, time-limited" — same
         * language as the "Currently in season" copy in the order-received
         * card. The accordion also gets a faint amber top border so it
         * doesn't visually merge with the adjacent sage accordions when
         * collapsed. */
        .fx-eor-pill--inseason {
            background: #C68B3A;
            color: #FFF8EC;
            letter-spacing: 1px;
            font-size: 10px;
            padding: 5px 11px;
        }
        .fx-eor-accordion--inseason {
            border-top: 2px solid #C68B3A;
        }
        .fx-eor-accordion--inseason.open {
            border-color: #C68B3A;
            box-shadow: 0 4px 14px -6px rgba(198, 139, 58, 0.20);
        }
        .fx-eor-accordion--inseason .fx-eor-acc-header:hover {
            background: #FFF8EC;
        }
        .fx-eor-accordion--inseason.open .fx-eor-acc-header {
            background: linear-gradient(180deg, #FAFAF8, #FFE8C5);
            border-bottom: 1px solid #E0C088;
        }

        /* Variety list — In Season variant. Star-marked items (peak bloom
         * this month) get a subtle amber background, bolder name, and
         * a star prefix that pulses gently on hover.
         *
         * v4.20.7 — Star items now span the FULL WIDTH of the accordion
         * body (grid-column: 1 / -1). The narrow 1/3 column was cramping
         * the blurb and forcing the sourcing line into a 3-column flex
         * wrap. Going full-width gives the star bloom room to breathe
         * and lets the sourcing line flow horizontally as a single
         * paragraph beneath the blurb. */
        /* v4.20.18 — Star variety panel background.
         *
         * Was: linear-gradient(90deg, #FFF8EC 0%, transparent 60%) —
         * cream/gold fading right. James (2026-05-19): "the blended
         * gold on the Peonies one — just have the gold at the edge
         * as is and green for the rest". The gold border-left stays
         * (it's the only gold accent now); the inner panel switches
         * to FBF mint #E8F7D5 — same colour as .fx-eor-acc-body so
         * the star panel reads as a slightly-bordered subdivision
         * of the accordion rather than a separately-toned card. */
        .fx-eor-variety-list--inseason .fx-eor-variety-item--peak {
            background: #E8F7D5;
            border-left: 3px solid #C68B3A;
            grid-column: 1 / -1;
            margin-bottom: 8px;
            border-radius: 0 4px 4px 0;
        }
        .fx-eor-variety-list--inseason .fx-eor-variety-item--peak .fx-eor-variety-name {
            font-weight: 600;
            color: #1F3A24;
        }
        .fx-eor-variety-peak-badge {
            display: inline-flex;
            align-items: center;
            justify-content: center;
            width: 18px;
            height: 18px;
            background: #C68B3A;
            color: #fff;
            border-radius: 50%;
            font-size: 11px;
            line-height: 1;
            margin-right: 10px;
            flex-shrink: 0;
            box-shadow: 0 1px 3px rgba(198, 139, 58, 0.3);
        }
        .fx-eor-variety-list--inseason .fx-eor-variety-link:hover .fx-eor-variety-peak-badge {
            transform: scale(1.12);
            transition: transform 0.15s;
        }

        /* v4.20.2 — Variety BLURB display.
         *
         * Star variety: blurb shown permanently beneath the name in
         * small italic grey. This is the month's headline flower so it
         * deserves a sentence of romance front-and-centre.
         *
         * Supporting cast: blurbs hide by default and reveal on hover
         * (desktop) — keeps the list scannable. On mobile, where hover
         * doesn't exist, all blurbs show inline because the list is
         * already vertically expanded so the extra height is fine.
         *
         * The .fx-eor-variety-row wrapper groups badge + name + arrow
         * into a single flex line so the blurb wraps neatly below the
         * name row, not inline with it. */
        .fx-eor-variety-list--inseason .fx-eor-variety-link {
            display: flex;
            flex-direction: column;
            align-items: stretch;
            gap: 4px;
            padding: 12px 16px;
        }
        .fx-eor-variety-list--inseason .fx-eor-variety-row {
            display: flex;
            align-items: center;
            justify-content: space-between;
            gap: 0;
        }
        /* v4.20.7 — Star variety: the row's first cluster (star + name)
         * sits left, the arrow pushes to the far right via space-between.
         * The blurb and sourcing then flow as full-width block paragraphs
         * below, aligned under the name (margin-left compensates for the
         * star badge so the text indents under "PEONIES" not under "★"). */
        .fx-eor-variety-list--inseason .fx-eor-variety-item--peak .fx-eor-variety-row {
            justify-content: space-between;
        }
        .fx-eor-variety-list--inseason .fx-eor-variety-item--peak .fx-eor-variety-blurb {
            margin: 6px 0 0 28px;
            max-width: 100%;
        }
        .fx-eor-variety-list--inseason .fx-eor-variety-item--peak .fx-eor-variety-sourcing {
            margin: 4px 0 0 28px;
            max-width: 100%;
        }
        .fx-eor-variety-blurb {
            display: none;
            font-size: 12px;
            color: #4A5F4F;
            font-style: italic;
            line-height: 1.45;
            margin: 2px 0 0 28px;
            font-family: 'Jost', sans-serif;
        }
        /* Star variety: blurb always visible. */
        .fx-eor-variety-list--inseason .fx-eor-variety-item--peak .fx-eor-variety-blurb {
            display: block;
            color: #2A6132;
            font-size: 12.5px;
        }
        /* Hover on any item reveals its blurb (desktop). */
        @media (hover: hover) and (pointer: fine) {
            .fx-eor-variety-list--inseason .fx-eor-variety-link:hover .fx-eor-variety-blurb {
                display: block;
            }
            .fx-eor-variety-list--inseason .fx-eor-variety-link:hover .fx-eor-variety-sourcing {
                display: block;
            }
        }
        /* Mobile / coarse pointer: always show all blurbs. */
        @media (hover: none), (pointer: coarse) {
            .fx-eor-variety-list--inseason .fx-eor-variety-blurb {
                display: block;
                font-size: 11.5px;
                margin-left: 0;
            }
            .fx-eor-variety-list--inseason .fx-eor-variety-item--peak .fx-eor-variety-blurb {
                margin-left: 0;
            }
            .fx-eor-variety-list--inseason .fx-eor-variety-sourcing {
                display: block;
                margin-left: 0;
            }
        }

        /* v4.20.5/7 — Sourcing line ("This month from: Netherlands + France...").
         * v4.20.7 — Changed from display:flex (which created 3 stacked
         * mini-columns when squeezed into a narrow card) to display:block
         * with inline children. Now flows as one horizontal paragraph
         * that wraps naturally like body text. Star items get this at
         * full accordion width since they span the whole grid row. */
        .fx-eor-variety-sourcing {
            display: none;
            font-size: 11.5px;
            color: #4A5F4F;
            margin: 4px 0 0 28px;
            font-family: 'Jost', sans-serif;
            line-height: 1.5;
            max-width: 100%;
        }
        .fx-eor-variety-sourcing-icon {
            display: inline;
            font-size: 12px;
            opacity: 0.7;
            margin-right: 4px;
        }
        .fx-eor-variety-sourcing-label {
            display: inline;
            font-weight: 500;
            color: #2A6132;
            margin-right: 4px;
        }
        .fx-eor-variety-sourcing-text {
            display: inline;
            font-style: italic;
            color: #4A5F4F;
        }
        /* Star variety: sourcing always visible (same as blurb). */
        .fx-eor-variety-list--inseason .fx-eor-variety-item--peak .fx-eor-variety-sourcing {
            display: block;
        }

        /* ─────────────────────────────────────────────────────────────
         * v4.20.18 — Desktop layout overhaul for In Season Now accordion
         * (James 2026-05-19 image: 3-column variety grid + cramped Also
         * Available footer were rendering "terribly" inside the narrow
         * left column of the order-pay product page).
         *
         * v4.20.20 — Specificity bug fix + always-visible blurb/sourcing.
         *
         * Bug in v4.20.18: the single-column override `grid-template-
         * columns: 1fr` used selector `.fx-eor-variety-list--inseason`
         * (specificity 0,1,0). The base rule at line ~10873 uses
         * `.fx-eor-variety-list { ... grid-template-columns: repeat(3,
         * 1fr) }` — also (0,1,0). At equal specificity, the LATER rule
         * wins; base sits 1490 lines further down, so it won. The
         * in-season list stayed 3-column. Fix: chain both classes —
         * `.fx-eor-variety-list.fx-eor-variety-list--inseason` —
         * specificity (0,2,0), beats the base cleanly without needing
         * !important.
         *
         * Always-visible blurb + sourcing (NEW in v4.20.20). James
         * 2026-05-19 image IMG_2348: "I don't like the hover element
         * to it ... the text in the green section should look like
         * the PEONIES title and text section". Previously only the
         * star variety (PEONIES) showed its blurb + sourcing inline;
         * supporting varieties (Freesia, Iris, Lilies, Lisianthus,
         * Ranunculus, Stocks, Sweet Peas) only revealed theirs on
         * desktop hover via @media (hover: hover) rule at line ~9277.
         * On a touch device that pattern degrades fine (the
         * hover-none media query at line ~9286 shows everything) —
         * but James saw it on desktop and found the hover reveal
         * jumpy. v4.20.20 makes blurb + sourcing visible on ALL
         * in-season list items, on all viewports, no hover required.
         * The @media (hover: hover) rules below become no-ops (same
         * display:block they would have applied) — left in place so
         * the cascade is explicit if anyone reads it.
         *
         * Three changes wrapped together:
         *
         *   (a) Variety list = single-column scrollable on every
         *       viewport (was 3-column grid on desktop, 1-col on
         *       mobile). Chained-class selector wins specificity.
         *       Max-height keeps the accordion compact even when
         *       many varieties peak.
         *
         *   (b) text-decoration:none !important on the in-season
         *       variety link AND on all its descendants. The theme's
         *       a:link underline was bleeding through the plugin's
         *       text-decoration:none from line 10775.
         *
         *   (c) .fx-eor-also-available-list becomes a 3-column CSS
         *       grid (was inline flow with " · " separators).
         *       Separator dots display:none. 2 columns on mobile.
         *
         *   (d) Blurb + sourcing visible on ALL in-season items,
         *       styled to match PEONIES typography (green #2A6132,
         *       12.5px, italic). Left margin reset to 0 on supporting
         *       items (no star badge so the 28px indent doesn't
         *       align with anything).
         * ───────────────────────────────────────────────────────────── */
        .fx-eor-variety-list.fx-eor-variety-list--inseason {
            grid-template-columns: 1fr;
            gap: 0;
            max-height: 380px;
            overflow-y: auto;
            scrollbar-width: thin;
            scrollbar-color: #C8DEC0 transparent;
            padding-right: 4px; /* breathing room for scrollbar */
        }
        .fx-eor-variety-list--inseason::-webkit-scrollbar {
            width: 6px;
        }
        .fx-eor-variety-list--inseason::-webkit-scrollbar-track {
            background: transparent;
        }
        .fx-eor-variety-list--inseason::-webkit-scrollbar-thumb {
            background: #C8DEC0;
            border-radius: 3px;
        }
        .fx-eor-variety-list--inseason::-webkit-scrollbar-thumb:hover {
            background: #A8C8A0;
        }
        .fx-eor-variety-list--inseason .fx-eor-variety-link,
        .fx-eor-variety-list--inseason .fx-eor-variety-link:link,
        .fx-eor-variety-list--inseason .fx-eor-variety-link:visited,
        .fx-eor-variety-list--inseason .fx-eor-variety-link:hover,
        .fx-eor-variety-list--inseason .fx-eor-variety-link:active {
            text-decoration: none !important;
        }
        .fx-eor-variety-list--inseason .fx-eor-variety-link *,
        .fx-eor-variety-list--inseason .fx-eor-variety-blurb,
        .fx-eor-variety-list--inseason .fx-eor-variety-sourcing,
        .fx-eor-variety-list--inseason .fx-eor-variety-sourcing-text,
        .fx-eor-variety-list--inseason .fx-eor-variety-sourcing-label,
        .fx-eor-variety-list--inseason .fx-eor-variety-name {
            text-decoration: none !important;
        }

        /* v4.20.20 — Always-visible blurb + sourcing on ALL in-season
         * varieties. Specificity (0,2,0) beats the base (0,1,0)
         * `.fx-eor-variety-blurb { display: none }` at line ~9261.
         * Star variety's (0,3,0) peak-specific rule at line ~9271 still
         * wins for PEONIES (which keeps its larger 12.5px green
         * styling) — supporting varieties inherit the new defaults
         * here: green-italic to match PEONIES family voice but at
         * 12px so PEONIES still reads as the dominant star. */
        .fx-eor-variety-list--inseason .fx-eor-variety-blurb {
            display: block;
            color: #2A6132;
            font-size: 12px;
            font-style: italic;
            line-height: 1.45;
            font-family: 'Jost', sans-serif;
            margin: 4px 0 0 0;
            max-width: 100%;
        }
        .fx-eor-variety-list--inseason .fx-eor-variety-sourcing {
            display: block;
            font-size: 11.5px;
            color: #4A5F4F;
            margin: 3px 0 0 0;
            font-family: 'Jost', sans-serif;
            line-height: 1.5;
            max-width: 100%;
        }
        /* Per-item spacing: supporting items get a soft divider so the
         * stacked title+blurb+sourcing chunks read as separate cards
         * even without a box around each one. PEONIES already has its
         * own background + gold border treatment from line ~9198, so
         * exclude it from this rule. */
        .fx-eor-variety-list--inseason .fx-eor-variety-item:not(.fx-eor-variety-item--peak) {
            border-bottom: 1px solid #D8E8D0;
        }
        .fx-eor-variety-list--inseason .fx-eor-variety-item:not(.fx-eor-variety-item--peak):last-child {
            border-bottom: 0;
        }
        .fx-eor-variety-list--inseason .fx-eor-variety-item:not(.fx-eor-variety-item--peak) .fx-eor-variety-link {
            padding: 10px 14px;
        }
        /* Hover: NO padding-jump (James 2026-05-19 called the layout-
         * shifting hover "the hover element" — getting rid of it).
         * Subtle background tint on supporting items only — PEONIES
         * has its own green-mint box so leave it alone. Name colour
         * darkens slightly + arrow nudges right as the click cue. */
        .fx-eor-variety-list--inseason .fx-eor-variety-link:hover {
            background: transparent;
        }
        .fx-eor-variety-list--inseason .fx-eor-variety-item:not(.fx-eor-variety-item--peak) .fx-eor-variety-link:hover {
            background: #F4FAEB;
        }
        .fx-eor-variety-list--inseason .fx-eor-variety-link:hover .fx-eor-variety-name {
            color: #1F3A24;
        }
        .fx-eor-variety-list--inseason .fx-eor-variety-link:hover .fx-eor-variety-arrow {
            opacity: 1;
            color: #2A6132;
            transform: translateX(2px);
        }
        /* End v4.20.18/v4.20.20 in-season list overhaul ─────────────── */

        /* v4.20.5 — "Also available this month" footer.
         * Lives below the variety list. Year-round varieties not at peak this
         * month still get a quiet shout-out so customers know they're sourceable. */
        .fx-eor-also-available {
            margin-top: 22px;
            padding: 14px 16px;
            background: #FAFAF8;
            border-left: 3px solid #D8E8D0;
            border-radius: 0 4px 4px 0;
            font-family: 'Jost', sans-serif;
            max-width: 100%;
            box-sizing: border-box;
        }
        .fx-eor-also-available-label {
            display: block;
            font-size: 11px;
            text-transform: uppercase;
            letter-spacing: 1px;
            color: #2A6132;
            font-weight: 600;
            margin-bottom: 8px;
        }
        .fx-eor-also-available-list {
            /* v4.20.18 — 3-column CSS grid (was inline flow with " · "
             * separators). James (2026-05-19): "for the alternative
             * flower types these used to be split on three rows —
             * make that look like it does on mobile too". Mobile
             * gets 2 columns inside the @media (max-width: 700px)
             * block below. Separators (.fx-eor-also-available-sep)
             * are display:none so they don't occupy grid cells. */
            display: grid;
            grid-template-columns: repeat(3, 1fr);
            gap: 6px 14px;
            font-size: 13px;
            line-height: 1.5;
            color: #4A5F4F;
            overflow-wrap: anywhere;
        }
        .fx-eor-also-available-item {
            /* v4.20.18 — Clean text row inside the grid (was inline
             * link with dotted bottom-border on hover). Underline
             * forced off — theme a:link was bleeding through. */
            color: #2A6132;
            text-decoration: none !important;
            padding: 2px 0;
            transition: color 0.15s, background 0.15s;
            border-radius: 2px;
        }
        .fx-eor-also-available-item:hover {
            color: #1F3A24;
            background: #F4FAEB;
            padding-left: 4px;
        }
        .fx-eor-also-available-sep {
            /* v4.20.18 — Hidden in grid mode (used to be the " · "
             * separator for inline flow). Kept in markup for
             * graceful degradation if CSS fails to load. */
            display: none;
        }

        /* v4.20.5/6 — Floral Bunches accordion: peak + out-of-season indicators.
         *
         * Peak: small amber mark inline-block before the name, no flex-shrink
         * dependency. Out: reduced opacity on the whole item + a small
         * "Returns Dec" inline pill. Both elements are inline so they
         * participate in normal text flow and wrap correctly on mobile. */
        .fx-eor-variety-bunches-peak-badge {
            display: inline-block;
            font-size: 13px;
            line-height: 1;
            vertical-align: -1px;
        }
        .fx-eor-variety-item--bunches-peak .fx-eor-variety-name {
            color: #1F3A24;
            font-weight: 500;
        }
        .fx-eor-variety-item--bunches-out {
            opacity: 0.55;
        }
        .fx-eor-variety-item--bunches-out:hover {
            opacity: 0.85;
        }
        .fx-eor-variety-returns {
            display: inline-block;
            padding: 1px 7px;
            background: #F3F0EA;
            color: #806950;
            font-size: 10px;
            text-transform: uppercase;
            letter-spacing: 0.5px;
            font-weight: 500;
            border-radius: 10px;
            font-family: 'Jost', sans-serif;
            vertical-align: 1px;
            white-space: nowrap;
        }

        .fx-eor-acc-title { flex: 1; min-width: 0; }
        .fx-eor-acc-title h3 { font-family: 'Cormorant Garamond', Georgia, serif; font-size: 22px; color: #1F3A24; font-weight: 500; line-height: 1.1; margin: 0; }
        .fx-eor-preview { font-size: 11px; color: #4A5F4F; letter-spacing: 0.5px; margin-top: 1px; }
        /* v4.19.0 — Small inline count pill in header preview ("(207)" etc). */
        .fx-eor-preview-count {
            color: #2A6132; font-weight: 500;
            margin-left: 2px;
        }

        /* v4.19.96 — MULTI-SELECT INSTRUCTION CUE.
         *
         * The "tick the boxes" instruction in the accordion header needs
         * to feel like a button-shaped pill — not a sentence of body text
         * that customers skim past. Sage-green chip, leading tick glyph
         * in a contrast circle, slight letter-spacing so it reads as a
         * label rather than running into the surrounding copy.
         *
         * The pill stays inline so the line still reads naturally:
         *   "Same flower, different varieties. [✓ Tick the boxes...] (12)"
         * but the visual weight pulls the eye to the imperative.
         * ──────────────────────────────────────────────────────────────── */
        .fx-eor-tick-cue {
            display: inline-flex;
            align-items: center;
            gap: 6px;
            background: #E8F7D5;
            border: 1px solid #85C727;
            color: #1F3A24;
            font-weight: 500;
            padding: 3px 10px 3px 4px;
            border-radius: 12px;
            margin: 0 4px;
            font-size: 11px;
            letter-spacing: 0.3px;
            text-transform: none;
            white-space: nowrap;
        }
        .fx-eor-tick-cue-icon {
            display: inline-flex;
            align-items: center;
            justify-content: center;
            width: 16px;
            height: 16px;
            background: #2A6132;
            color: #fff;
            border-radius: 3px;
            font-size: 11px;
            font-weight: 700;
            line-height: 1;
            flex-shrink: 0;
        }
        /* Mobile — wrap pill onto its own line so it doesn't crush.
         * v4.20.17: also allow the text INSIDE the pill to wrap so
         * the full "Tick the boxes to add multiple varieties to your
         * order" message doesn't extend past the viewport and overlap
         * the accordion's chevron arrow (which is what James reported
         * on 2026-05-19 14:53). The base rule's white-space:nowrap is
         * the right default for desktop where the pill sits inline
         * with the description on a single wide row; on mobile the
         * pill needs to soft-wrap. align-items:flex-start keeps the
         * ✓ icon aligned to the first line of text when wrapping. */
        @media (max-width: 720px) {
            .fx-eor-tick-cue {
                display: inline-flex;
                margin: 4px 0 0 0;
                font-size: 10.5px;
                padding: 4px 10px 4px 4px;
                white-space: normal;
                max-width: 100%;
                align-items: flex-start;
                line-height: 1.35;
            }
            .fx-eor-tick-cue-icon {
                width: 14px;
                height: 14px;
                font-size: 10px;
                margin-top: 1px;
            }
        }

        /* v4.19.96 — TICK ATTENTION PULSE.
         *
         * When the accordion transitions to preview state, the ticks on
         * the visible cards pulse 3 times to teach the affordance.
         * Customers who've used the site before see one quick reminder;
         * customers who never noticed the ticks now notice them.
         *
         * Why 3 reps not infinite: an always-on pulse becomes noise.
         * 3 reps × 900ms = ~2.7s total then completely still — long
         * enough to teach, short enough not to nag.
         *
         * Animation only fires on .is-preview state (not .open). Once
         * the customer expands to full open OR ticks any card, we
         * remove the pulse class via JS so it doesn't replay.
         *
         * Pure CSS transforms + box-shadow only (cheap to animate). */
        @keyframes fx-eor-tick-pulse {
            0%   { transform: scale(1);    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08); }
            30%  { transform: scale(1.18); box-shadow: 0 0 0 8px rgba(133, 199, 39, 0.45); }
            60%  { transform: scale(1);    box-shadow: 0 0 0 0   rgba(133, 199, 39, 0); }
            100% { transform: scale(1);    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08); }
        }
        @media (prefers-reduced-motion: no-preference) {
            .fx-eor-accordion.is-preview .fx-eor-frontcard:not(.selected) .fx-eor-check-col.fx-eor-tick-attention {
                animation: fx-eor-tick-pulse 900ms ease-out 3;
            }
        }
        /* Permanent visual reinforcement on the first card's tick in
         * preview state — a sage drop-shadow halo so even after the
         * pulse stops, the eye still lands there. */
        .fx-eor-accordion.is-preview .fx-eor-frontcard:first-child:not(.selected) .fx-eor-check-col {
            box-shadow: 0 0 0 3px rgba(133, 199, 39, 0.25), 0 1px 3px rgba(0, 0, 0, 0.08);
        }

        .fx-eor-chevron { color: #4A5F4F; font-size: 14px; transition: transform 0.25s; }
        .fx-eor-accordion.open .fx-eor-chevron { transform: rotate(180deg); color: #2A6132; }
        /* v4.19.95 — Preview-state chevron: half-rotated so it sits between
         * closed (0°) and fully-open (180°), signalling tri-state cycle. */
        .fx-eor-accordion.is-preview .fx-eor-chevron { transform: rotate(90deg); color: #4A5F4F; }
        .fx-eor-acc-body { padding: 20px 22px 22px; display: none; background: #E8F7D5; }
        .fx-eor-accordion.open .fx-eor-acc-body { display: block; }

        /* v4.19.95 — TRI-STATE ACCORDION (.is-preview).
         *
         * The Explore Our Range accordion now cycles through three states
         * instead of the binary open/closed:
         *
         *   State A — collapsed (default, no class)
         *     → click expands to preview
         *   State B — preview (.is-preview class on .fx-eor-accordion)
         *     → body is visible, but only first N cards show, where N
         *       matches the grid column count. Signals to customers that
         *       there ARE more products without overwhelming them.
         *     → click expands to fully open
         *   State C — fully open (.open class on .fx-eor-accordion)
         *     → all cards visible, current behaviour
         *     → click returns to collapsed
         *
         * Implementation: .is-preview reuses the same display:block as .open
         * for the body, then a :nth-child(n+X) rule hides cards beyond the
         * first row. X = column count + 1 (single→2, double→3, triple→4).
         *
         * Filter-chip toolbar and search row remain visible in preview
         * mode — only the .fx-eor-frontcard children inside .fx-eor-grid
         * are hidden. This keeps the controls discoverable so a customer
         * who likes what they see in the preview row can immediately use
         * Sort / View / Search without having to click expand first.
         * ──────────────────────────────────────────────────────────────── */
        .fx-eor-accordion.is-preview .fx-eor-acc-body { display: block; }
        /* Single-column preview: show only the first card */
        .fx-eor-accordion.is-preview .fx-eor-grid:not(.fx-eor-grid--double):not(.fx-eor-grid--triple) .fx-eor-frontcard:nth-child(n+2) {
            display: none;
        }
        /* Double-column preview: show only the first 2 cards */
        .fx-eor-accordion.is-preview .fx-eor-grid.fx-eor-grid--double .fx-eor-frontcard:nth-child(n+3) {
            display: none;
        }
        /* Triple-column preview: show only the first 3 cards */
        .fx-eor-accordion.is-preview .fx-eor-grid.fx-eor-grid--triple .fx-eor-frontcard:nth-child(n+4) {
            display: none;
        }
        @media (max-width: 719px) {
            /* Default / 1-col: preview shows 1 card. */
            .fx-eor-accordion.is-preview .fx-eor-grid .fx-eor-frontcard:nth-child(n+2) {
                display: none;
            }
            /* v4.25.69 — preview shows one full ROW for the chosen mobile column
             * count: 2-col → first 2 cards, 3-col → first 3 cards. */
            .fx-eor-accordion.is-preview .fx-eor-grid.fx-eor-mcols-2 .fx-eor-frontcard:nth-child(-n+2) { display: flex; }
            .fx-eor-accordion.is-preview .fx-eor-grid.fx-eor-mcols-2 .fx-eor-frontcard:nth-child(n+3) { display: none; }
        }
        /* v4.19.97 — In preview state, hide every basket-related CTA.
         *
         * James's screenshot showed customers confused by the inline
         * basket bar appearing in preview state: they thought the big
         * "ADD TO BASKET" button was the way to proceed and clicked it
         * without selecting anything, OR thought they had to "complete"
         * the basket before they could browse. Preview is a discovery
         * surface, not a transaction surface. Hide all basket UI until
         * the customer commits to fully-open view.
         *
         * Hidden in preview:
         *   .fx-eor-cta            — inline white basket bar with "Show basket" toggle + ADD TO BASKET btn
         *   .fx-eor-basket-bar     — fixed-position sticky bar at viewport bottom (sibling, body-level)
         *   .fx-eor-basket-modal   — popup viewer (hidden-by-default anyway, defensive)
         *
         * The card ticks themselves still respond (.fx-eor-check-col not
         * hidden) — they just don't surface a basket bar. State accrues
         * silently and the bars reveal as soon as the customer expands
         * to fully-open view. */
        .fx-eor-accordion.is-preview .fx-eor-cta {
            display: none !important;
        }
        /* Sticky bar + modal sit OUTSIDE the accordion in the DOM, so use
         * a body-level flag written by JS in sync with accordion state. */
        body.fx-eor-preview-active .fx-eor-basket-bar,
        body.fx-eor-preview-active .fx-eor-basket-modal {
            display: none !important;
        }

        /* When in preview, the bottom of the body shows a clickable
         * "Click here to Explore Our Range" button. This was a CSS-only
         * ::after pseudo-element in v4.19.95 — but pseudo-elements can't
         * be clicked, so the line looked like a link and did nothing,
         * which was its own confusion. v4.19.97 replaced it with a real
         * <button> injected via JS into the body — but the body is the
         * lazy-load AJAX target, so when cards arrived the body's
         * innerHTML was replaced and the button got wiped.
         *
         * v4.19.99 fix: render the button SERVER-SIDE as a SIBLING of
         * .fx-eor-acc-body (not inside it). The button survives lazy-
         * load because it's not inside the lazy-load target. CSS just
         * shows/hides based on the accordion's state class.
         *
         * Two button variants:
         *   .fx-eor-preview-expand-btn--inline  — server-rendered,
         *     persists across lazy-load. Default hidden, visible only
         *     when accordion has .is-preview class.
         *   (legacy) JS-injected button without the --inline modifier
         *     was used in v4.19.97; removed in v4.19.99 since the
         *     server-rendered button covers all states. */
        .fx-eor-accordion.is-preview .fx-eor-acc-body {
            position: relative;
        }
        /* v0.2.237 — ONE LIME BUTTON (the owner: "please make that link a lime green button"): the same lime as the cards' ADD TO BASKET, the count of varieties in its text; the status box above it ("Showing 8 of 16", "✓ All 16 varieties shown") leaves — one button says it all. */
        .fx-eor-preview-expand-btn {
            display: block;
            width: 100%;
            text-align: center;
            font-size: 14px;
            color: #1F3A24;
            font-weight: 700;
            letter-spacing: 0.3px;
            margin-top: 14px;
            padding: 13px 16px;
            min-height: 48px; /* v0.2.430 (his words 1 Oct: "better tap zone") - the whole lime button is the press, at least 48px tall */
            line-height: 1.25;
            touch-action: manipulation;
            position: relative;
            z-index: 1;
            border: 0;
            border-radius: 9px;
            background: #85C727;
            text-transform: uppercase;
            text-decoration: none;
            cursor: pointer;
            font-family: 'Jost', sans-serif;
            box-sizing: border-box;
            transition: background 0.15s;
        }
        .fx-eor-preview-expand-btn:hover {
            color: #1F3A24;
            background: #95D837;
        }
        .fx-eor-preview-expand-btn:active { background: #75B717; }
        .fx-eor-preview-expand-btn:focus-visible {
            outline: 2px solid #2A6132;
            outline-offset: 2px;
            border-radius: 9px;
        }
        .fx-eor-accordion .fx-eor-pagination-status { display: none; }
        .fx-eor-accordion .fx-eor-pagination[data-fx-eor-done] { display: none; }

        /* v4.19.99 — The server-rendered (--inline) button is hidden by
         * default. The accordion's .is-preview state class promotes it
         * to visible. When the accordion transitions to .open (full) or
         * back to closed, the button disappears via this rule, without
         * needing JS to add/remove the element. */
        .fx-eor-preview-expand-btn--inline {
            display: none;
        }
        .fx-eor-accordion.is-preview .fx-eor-preview-expand-btn--inline {
            display: block;
        }
        /* v0.2.430 - CLEAR SPACE (his words 1 Oct: "too close to expand the reviews the tap zone is compromised"): the button is the last thing in the preview accordion, so the gap to the NEXT accordion header (the reviews) is the accordion's own bottom margin: at least 20px (the 12px rule between stacked accordions collapses into it, never adds to it), so a press on one never lands on the other, phones and desktop. */
        .fx-eor-accordion.is-preview { margin-bottom: 20px; }
        .fx-eor-intro { color: #1F3A24; font-size: 12px; margin-bottom: 16px; font-weight: 500; }
        /* v4.7.50: desktop grid is now 1 card per row, matching mobile.
         * Previously repeat(2, 1fr) meant each image was only 50% of a half-row
         * card — half the absolute width James wanted. Now image is 50% of the
         * FULL row width on desktop, matching mobile's measurement. */
        .fx-eor-grid { display: grid; grid-template-columns: 1fr; gap: 14px; }
        .fx-eor-grid { display: grid; grid-template-columns: 1fr; gap: 14px; align-items: stretch; }
        /* v4.16.2 — 2-column grid modifier. Only kicks in at >=720px viewport
         * so mobile stays single-column where 2-col would crush cards too
         * narrow for the 50/50 image-text internal layout. The cards themselves
         * keep their existing image-left text-right shape; with half the width,
         * each card is ~half as tall (image-driven height), so ~2.5x more
         * cards become visible in the same scroll area. */
        @media (min-width: 720px) {
            .fx-eor-grid--double { grid-template-columns: repeat(2, 1fr); gap: 10px; }
            /* v4.25.69 — narrower 2-col cards: shrink the title to fit so long
             * names (e.g. "ANNIVERSARY BOUQUET — CREAMS & PURPLES") stay whole-
             * worded. Words never break mid-character (word-break:normal on the
             * base h4). */
            .fx-eor-grid--double .fx-eor-body h4 { font-size: 14px; padding-right: 30px; }
            /* v4.19.0 — 3-col image-only grid (desktop only).
             * Cards become a third of the available width and the body
             * (name/pills/price/buy) is hidden — pure visual browsing.
             * Card-main becomes single-column so the image takes the full
             * card width. Click handlers on the image-link still route
             * to the product page. Mobile falls back to 1-col regardless. */
            .fx-eor-grid--triple { grid-template-columns: repeat(3, 1fr); gap: 8px; }
            .fx-eor-grid--triple .fx-eor-card-main { grid-template-columns: 1fr; }
            .fx-eor-grid--triple .fx-eor-body,
            .fx-eor-grid--triple .fx-eor-card-top { display: none; }
            /* Uniform square crop so the gallery feels tidy. */
            .fx-eor-grid--triple .fx-eor-img-link { aspect-ratio: 1 / 1; }
            .fx-eor-grid--triple .fx-eor-img-link img { width: 100%; height: 100%; object-fit: cover; }
            /* Hide check-col tick overlay and Add-to-Basket in 3-col —
             * pure image gallery, customer goes to product page for actions. */
            .fx-eor-grid--triple .fx-eor-check-col,
            .fx-eor-grid--triple .fx-eor-card-add { display: none; }
        }
        /* v4.19.18 — Hover-to-reveal row expansion for triple-column view.
         *
         * JAMES 2026-05-16: "when you hover over these cards in this triple
         * column view the variations pop up on hover ... they could expand
         * downwards below the images for all three cards on that row".
         *
         * Implementation:
         *  - Only kicks in for hover-capable devices (@media hover: hover)
         *  - Touch devices keep the gallery-only behavior above
         *  - Override the display:none rules with a collapsed state
         *    (max-height: 0 / opacity: 0 / overflow: hidden) so we can
         *    animate to an expanded state
         *  - JS adds class fx-eor-row-hover to ALL cards in the same row
         *    when one is hovered, so the variation/qty/add UI appears for
         *    every sibling in the row simultaneously
         *  - This avoids jagged layout (rows expand uniformly, not just
         *    the hovered card)
         */
        @media (hover: hover) and (pointer: fine) {
            .fx-eor-grid--triple .fx-eor-body,
            .fx-eor-grid--triple .fx-eor-card-top,
            .fx-eor-grid--triple .fx-eor-card-add {
                display: block;
                max-height: 0;
                opacity: 0;
                overflow: hidden;
                padding-top: 0;
                padding-bottom: 0;
                margin: 0;
                transition: max-height 0.22s ease-out, opacity 0.16s ease-out, padding 0.22s ease-out;
            }
            .fx-eor-grid--triple .fx-eor-check-col {
                display: flex;
                max-width: 0;
                opacity: 0;
                overflow: hidden;
                transition: max-width 0.22s ease-out, opacity 0.16s ease-out;
            }
            /* Expanded state — applied by JS to all cards in the hovered row. */
            .fx-eor-grid--triple .fx-eor-frontcard.fx-eor-row-hover .fx-eor-body {
                max-height: 280px;
                opacity: 1;
                padding-top: 8px;
                padding-bottom: 8px;
            }
            .fx-eor-grid--triple .fx-eor-frontcard.fx-eor-row-hover .fx-eor-card-top {
                max-height: 60px;
                opacity: 1;
            }
            .fx-eor-grid--triple .fx-eor-frontcard.fx-eor-row-hover .fx-eor-card-add {
                max-height: 80px;
                opacity: 1;
                padding-bottom: 8px;
            }
            .fx-eor-grid--triple .fx-eor-frontcard.fx-eor-row-hover .fx-eor-check-col {
                max-width: 50px;
                opacity: 1;
            }
            /* Subtle hover ring on the hovered row so the visual grouping is clear. */
            .fx-eor-grid--triple .fx-eor-frontcard.fx-eor-row-hover {
                box-shadow: 0 2px 12px rgba(31, 58, 36, 0.08);
                background: #fafff8;
                transition: box-shadow 0.18s ease, background 0.18s ease;
            }
        }
        /* ═══════════════════════════════════════════════════════════════
         * v4.20.21 — Per-view-mode polish on the Siblings/EOR product
         * cards. James 2026-05-19 (3 screenshots: 1-col/2-col/3-col):
         *
         *   1-col view → fine, no changes.
         *
         *   2-col view → tick checkbox currently at top-right of card
         *   encroaches on the title. Move to bottom-LEFT corner. Add a
         *   small explanatory note ("Tick to add to order") next to it
         *   so the multi-select UI is clearer to customers (we have no
         *   data yet on whether tick+button combo confuses; this is
         *   defensive copy).
         *
         *   3-col view → three changes:
         *     (a) Hide the "★ Currently viewing" top strip in 3-col —
         *         redundant with the lower badge that the body::before
         *         pseudo at line ~10614 already renders. James: "well
         *         located where it is lower down".
         *     (b) Pin Add-to-Basket to the bottom of the card with a
         *         2px gap from the frame. Was margin-top:10px in the
         *         flow; now margin:auto 0 2px 0 so flexbox pushes it
         *         to the bottom regardless of how many variation pills
         *         the body contains.
         *     (c) Slide-up animation replaces v4.19.18's max-height
         *         expand-below pattern. Card stays its original size;
         *         on hover the image translates UP and out of frame
         *         while the body slides UP into view from below. This
         *         keeps card heights uniform across the row and gives
         *         the "image rolls out the top of the box" effect.
         *
         * Implementation note: v4.19.18 rules (lines 9920-9966) used
         * `display: block; max-height: 0; opacity: 0` for the body and
         * card-add, then expanded max-height/opacity on .fx-eor-row-
         * hover. I replace that mechanism here for 3-col only — body
         * becomes position:absolute filling the card-main viewport,
         * translateY(100%) initially, translateY(0) on row-hover.
         * Image follows the inverse — translateY(0) → translateY(-100%).
         * Both transitions are 0.35s for a smooth slide-card feel.
         * The earlier max-height/opacity rules become no-ops because
         * mine have higher source-order priority at equal specificity
         * (0,2,0 vs 0,2,0 → last in source wins → mine win).
         * ─────────────────────────────────────────────────────────── */

        /* ─── 2-COL VIEW: tick moves to bottom-left + explanatory note
         *
         * v4.20.24 — DISABLED. James 2026-05-19: "we are going to remove
         * the tick box entirely and the pill instruction at the top of
         * the column and the little nudges". The multi-select pattern is
         * being retired in favour of single-add-to-basket → mini-basket
         * flow. Rules below kept as a "tombstone" so they're visible in
         * the cascade history; the v4.20.24 block at the end of this
         * file hides the underlying elements (tick + cue + note) with
         * display:none !important regardless of view mode. */
        @media (min-width: 720px) {
            .fx-eor-grid--double .fx-eor-check-col {
                top: auto;
                right: auto;
                bottom: 10px;
                left: 10px;
            }
        }

        /* ─── 3-COL VIEW: v4.20.21 slide-up — STRIPPED in v4.20.43
         *
         * Original v4.20.21 attempt repositioned .fx-eor-body to
         * position:absolute, translateY(100%), with the image sliding
         * up out of frame on .fx-eor-row-hover. James rejected the
         * pattern outright after testing: "it needs to scroll slowly
         * with the mouse and not jump back if the user moves out of
         * the box" → bumped to 1.5s → "auto scroll is useless from
         * too fast to slow uncontrollable" → final verdict 2026-05-19:
         * "you invented rocket scrolling we had scrolling before —
         * find out where that code went".
         *
         * v4.20.43 restores the v4.19.18 max-height expand-down (still
         * intact at lines 9920–9966 above). The trigger is rewired
         * from .fx-eor-row-hover (JS-added row-wide) to per-card
         * :hover and .fx-eor-in-cart (lock-open) — see the v4.20.43
         * block ~150 lines below.
         * ─────────────────────────────────────────────────────────── */

        /* ═══════════════════════════════════════════════════════════════
         * v4.20.24 — RETIRE THE MULTI-SELECT UI
         *
         * James 2026-05-19 (this thread): "we are going to remove the
         * tick box entirely and the pill instruction at the top of the
         * column and the little nudges. WHAT WE ARE GOING TO DO IS THIS
         * WE ARE GOING TO KEEP ADD TO BASKET. WHEN THE USER CLICKS IT
         * THE PRODUCT GOES INTO THE BASKET THE ADD TO BASKET BUTTON
         * CHANGED TO ADDED. THE USER STAYS ON THE PAGE AND AT THAT POINT
         * THE MINI BASKET APPEARS AND THE USER CAN CONTINUE SHOPPING."
         *
         * Strategy: HIDE the underlying elements via CSS, don't rip out
         * the HTML or the JS that powers them. Two reasons:
         *
         *   (1) Reversibility — if user testing shows the tick model was
         *       actually working for some customer cohort and only
         *       confusing others, we can re-enable per-segment / per-
         *       category by removing the display:none rules. The whole
         *       tick subsystem (selected[] state, .selected class, qty
         *       sync, bulk-add AJAX) stays intact in the DOM.
         *
         *   (2) Bulb support — the user said this functionality may
         *       come back when bulb categories are added. Hiding the UI
         *       leaves the working multi-select code in place ready
         *       for a per-category re-enable.
         *
         * Hidden elements:
         *   - .fx-eor-check-col       — the tick checkbox on each card
         *   - .fx-eor-tick-cue        — top-of-accordion "Tick the boxes
         *                                 to add multiple varieties" pill
         *   - .fx-eor-cta-summary     — "0 items selected · £0.00" line
         *                                 (mini-basket subtotal stays
         *                                 inside the panel; this top-line
         *                                 summary was tick-state)
         *   - The 2-col bottom-left "TICK TO MULTI-SELECT" pseudo note
         *     (the v4.20.21 ::after rule was already removed in this
         *     version's earlier edit)
         *
         * The mini-basket panel itself stays — it's the new primary
         * cart-state surface. Already configured to be expanded by
         * default (v4.19.44), so when the customer clicks Add to Basket
         * the new item appears in it immediately.
         * ─────────────────────────────────────────────────────────── */
        .fx-eor-check-col,
        .fx-eor-tick-cue,
        .fx-eor-cta-summary {
            display: none !important;
        }

        /* v4.20.24 — Sticky "✓ ADDED" button state. The .is-added class
         * is added by addSingleCard() on successful AJAX add (see
         * function at line ~13963). Visual treatment: sage tone
         * (#5C8F4F → flat green) instead of the bright #85C727 primary,
         * white text instead of dark, so the button reads as a "done"
         * confirmation rather than a "primary action waiting to be
         * clicked". Button stays clickable so a customer can add
         * another unit if they want (each click = +1 to cart). */
        .fx-eor-card-add.is-added {
            background: #5C8F4F !important;
            color: #fff !important;
            cursor: pointer;
        }
        .fx-eor-card-add.is-added:hover {
            background: #4F7F44 !important;
        }
        .fx-eor-card-add.is-added:active {
            background: #406932 !important;
        }
        /* End v4.20.24 retire-multi-select block ─────────────────────── */

        /* ═══════════════════════════════════════════════════════════════
         * v4.20.43 — RESTORE THE v4.19.18 EXPAND-DOWN PATTERN
         *
         * James 2026-05-19 (this thread, after rejecting v4.20.21
         * through v4.20.27 in succession): "YOU INVENTED ROCKET
         * SCROLLING WE HAD SCROLLING BEFORE — FIND OUT WHERE THAT
         * CODE WENT".
         *
         * The original v4.19.18 max-height expand-down code is still
         * in place at lines 9920–9966. This block REWIRES it for the
         * per-card spec James approved in-thread (v9 of the inline
         * demo):
         *
         *   1. Default state    → body collapsed (max-height:0),
         *                         image visible above.
         *   2. Per-card hover   → body expands DOWNWARD over 1.5s.
         *                         Only the hovered card opens —
         *                         siblings stay closed. Image stays
         *                         put. No translation, no transform,
         *                         no slide.
         *   3. After Add to     → card gets .fx-eor-in-cart, body
         *      Basket             stays expanded indefinitely (lock-
         *                         open). Image blurs (filter:blur
         *                         2.5px + saturate 0.85) as a basket-
         *                         state cue. Pills and qty stepper
         *                         remain interactive so the customer
         *                         can change variation / qty without
         *                         needing to re-hover.
         *   4. Remove from      → .fx-eor-in-cart removed, body
         *      basket             returns to default hover-only
         *                         behaviour, image un-blurs.
         *
         * Trigger replaces v4.19.18's .fx-eor-row-hover class (added
         * by setupTripleHover JS, row-wide reveal) with CSS-only
         * :hover on each card individually. setupTripleHover stays
         * neutered (return; at line ~15670) — pure CSS does it all
         * now. No JS row-shuffling, no grace timers, no auto-trigger.
         *
         * Currently Viewing pill: rendered via .fx-eor-body::before
         * (line ~11011) — appears at the top of the expanded body for
         * data-current="1" cards. Visible whenever the body is open
         * (hover OR .fx-eor-in-cart lock-open).
         * ─────────────────────────────────────────────────────────── */
        @media (min-width: 720px) and (hover: hover) and (pointer: fine) {
            /* v4.20.43 — Override the global .fx-eor-grid { align-items:
             * stretch; } at line 9875 for 3-col view. Stretch makes every
             * cell in a row grow to match the tallest cell's height. With
             * per-card hover/in-cart expand, the OTHER cards in the row
             * were stretching with empty white space below their images
             * to match the expanded card's height. align-items: start
             * lets each card size to its own content. James reported
             * "stop the other cells in the column expanding at the same
             * time" 2026-05-19 — this is the wiring. */
            .fx-eor-grid--triple {
                align-items: start;
            }

            /* Override v4.19.18 collapsed-state transitions (0.22s)
             * with the demo-approved 1.5s ease. Applies to both
             * reveal (collapse → expand) and revert (expand → collapse)
             * because CSS transitions are defined on the base state. */
            .fx-eor-grid--triple .fx-eor-body,
            .fx-eor-grid--triple .fx-eor-card-top,
            .fx-eor-grid--triple .fx-eor-card-add {
                transition: max-height 1.5s ease, opacity 1.2s ease, padding 1.5s ease !important;
            }
            .fx-eor-grid--triple .fx-eor-check-col {
                transition: max-width 1.5s ease, opacity 1.2s ease !important;
            }

            /* Per-card hover expand-down. Same expanded-state CSS
             * also applies to .fx-eor-in-cart so cards stay locked
             * open once the customer has added them to the basket. */
            .fx-eor-grid--triple .fx-eor-frontcard:hover .fx-eor-body,
            .fx-eor-grid--triple .fx-eor-frontcard.fx-eor-in-cart .fx-eor-body {
                max-height: 360px;
                opacity: 1;
                padding-top: 10px;
                padding-bottom: 12px;
            }
            .fx-eor-grid--triple .fx-eor-frontcard:hover .fx-eor-card-add,
            .fx-eor-grid--triple .fx-eor-frontcard.fx-eor-in-cart .fx-eor-card-add {
                max-height: 100px;
                opacity: 1;
                /* v4.20.43 — Taller button with proper top padding. James
                 * (2026-05-19): "I want the nice padding on the button
                 * just a few more pixels of button on the top of it".
                 * padding-top makes the button itself taller (not just
                 * space above it). margin-top kept small for slight
                 * breathing room from the price row above. */
                padding-top: 14px;
                padding-bottom: 12px;
                margin-top: 8px;
            }
            /* v4.20.24 retired the multi-select tick via display:none
             * on .fx-eor-check-col. The expanded-state max-width
             * rule below is kept for symmetry in case future bulb
             * categories re-enable the tick UI per-segment. */
            .fx-eor-grid--triple .fx-eor-frontcard:hover .fx-eor-check-col,
            .fx-eor-grid--triple .fx-eor-frontcard.fx-eor-in-cart .fx-eor-check-col {
                max-width: 50px;
                opacity: 1;
            }

            /* Subtle hover / in-cart hint — same styling as v4.19.18
             * row-hover but now per-card. */
            .fx-eor-grid--triple .fx-eor-frontcard:hover,
            .fx-eor-grid--triple .fx-eor-frontcard.fx-eor-in-cart {
                box-shadow: 0 2px 12px rgba(31, 58, 36, 0.08);
                background: #fafff8;
                transition: box-shadow 0.18s ease, background 0.18s ease;
            }

            /* Image blur on cards that are in the basket — visual cue
             * the product has already been added. Demo-approved
             * values: 2.5px blur + 0.85 saturation. Filter applies to
             * the <img> inside .fx-eor-img-link so the link wrapper
             * stays sharp (badges / overlays not affected). */
            .fx-eor-grid--triple .fx-eor-frontcard.fx-eor-in-cart .fx-eor-img-link img {
                filter: blur(2.5px) saturate(0.85);
                transition: filter 0.35s ease;
            }

            /* v0.2.372, row 23c35 — EVERY CARD OPEN ON DESKTOP (the owner: "on desktop these expanding boxes are no good so just
             * have them all expanded i think that will look better and default on desktop this setting" · "it looks better than the
             * smaller setting"). Under .fx-eor-wrap--open (the switch fx_range_open_desktop, ON by default) every card in the
             * three-column grid wears the hover state from first paint — the SAME values the hover rules above paint, nothing new —
             * and nothing waits for the pointer. 1024px and up only: tablets and phones keep their own rules. */
            @media (min-width: 1024px) {
                .fx-eor-wrap--open .fx-eor-grid--triple .fx-eor-frontcard .fx-eor-body { max-height: 360px; opacity: 1; padding-top: 10px; padding-bottom: 12px; transition: none !important; }
                .fx-eor-wrap--open .fx-eor-grid--triple .fx-eor-frontcard .fx-eor-card-add { max-height: 100px; opacity: 1; padding-top: 14px; padding-bottom: 12px; margin-top: 8px; transition: none !important; }
                .fx-eor-wrap--open .fx-eor-grid--triple .fx-eor-frontcard { box-shadow: 0 2px 12px rgba(31, 58, 36, 0.08); background: #fafff8; }
                /* v0.2.373, row 23c44 — THE TILE LAW on the open cards (the owner: "make these pills line up neatly and the box sizes and the
                 * buttons need to be lined up"): every card in a row stretches to one height; the card and its main column are flex columns;
                 * the name is held to two lines; the pills band has one height and shows every pill; the price row and the Add button are
                 * pinned to the foot, so the buttons of a row sit on one line. */
                .fx-eor-wrap--open .fx-eor-grid--triple { align-items: stretch; }
                .fx-eor-wrap--open .fx-eor-grid--triple .fx-eor-frontcard { display: flex; flex-direction: column; }
                .fx-eor-wrap--open .fx-eor-grid--triple .fx-eor-card-main { display: flex; flex-direction: column; flex: 1 1 auto; }
                .fx-eor-wrap--open .fx-eor-grid--triple .fx-eor-body { display: flex; flex-direction: column; flex: 1 1 auto; max-height: none; overflow: visible; }
                .fx-eor-wrap--open .fx-eor-grid--triple .fx-eor-body > .fx-eor-name-link { display: block; min-height: 2.6em; }
                /* v0.2.374, row 23c53 — "what is happening with these images? they are all wonky now": v0.2.373 made the card's main column a flex
                 * column and left the picture link with no flex rule, so the body beneath squashed it (every picture a different height, the
                 * square gone). The picture link is a fixed child at full width; its square aspect ratio rules its height again. */
                .fx-eor-wrap--open .fx-eor-grid--triple .fx-eor-card-main > .fx-eor-img-link { flex: 0 0 auto; width: 100%; align-self: stretch; }
                .fx-eor-wrap--open .fx-eor-grid--triple .fx-eor-card-main > .fx-eor-check-col { flex: 0 0 auto; }
                /* v0.2.373, row 23c45 — "the scroll function is jumpy and glitchy": the pills band was a 72px scroll box of its own, so a wheel
                 * over it scrolled the band before the page, card after card. In the open mode the band shows every pill and owns no scroll;
                 * and the accordion body holding the open grid is never size-estimated while scrolling. */
                .fx-eor-wrap--open .fx-eor-grid--triple .fx-eor-variations { height: auto; min-height: 58px; overflow: visible; }
                .fx-eor-wrap--open .fx-eor-grid--triple .fx-eor-bottom { margin-top: auto; }
                .fx-eor-wrap--open .fx-eor-grid--triple .fx-eor-card-add { flex: 0 0 auto; }
                .fx-eor-wrap--open .fx-eor-acc-body { content-visibility: visible; contain-intrinsic-size: auto; }
            }
            /* The .fx-eor-card-top top-strip stays hidden in 3-col.
             * Currently Viewing is handled by .fx-eor-body::before
             * on data-current="1" cards (line ~11011). */
            .fx-eor-grid--triple .fx-eor-card-top {
                display: none !important;
            }
        }
        /* End v4.20.43 expand-down restoration block ─────────────────── */

        /* v4.15.0 — Filter chip row above the Siblings grid.
         * v4.16.1 — Was changed to horizontal scroll.
         * v4.19.0 — REPLACED horizontal scroll with wrap (per James).
         * Chips wrap onto multiple rows naturally. No scroll, no clipping,
         * no More/Less toggle. Customer sees every category at a glance.
         * Simple, no JS measurement, just flex-wrap. */
        .fx-eor-chiprow {
            display: flex; gap: 8px;
            flex-wrap: wrap;
            margin: 0 0 14px;
            font-family: 'Jost', system-ui, sans-serif;
        }
        .fx-eor-chip {
            flex: 0 0 auto;
            display: inline-flex; align-items: center; gap: 4px;
            padding: 6px 14px; background: #FAFAF8;
            border: 1.5px solid #D8E8D0; border-radius: 999px;
            color: #1F3A24; font-size: 13px; line-height: 1;
            cursor: pointer; font-family: inherit;
            transition: background 0.12s, border-color 0.12s, color 0.12s;
        }
        .fx-eor-chip:hover { background: #E8F7D5; border-color: #85C727; }
        .fx-eor-chip.is-active {
            background: #2A6132; border-color: #2A6132; color: #fff;
            font-weight: 500;
        }
        .fx-eor-chip-count { font-size: 11px; opacity: 0.7; }
        .fx-eor-chip.is-active .fx-eor-chip-count { opacity: 0.9; }
        .fx-eor-frontcard.is-filtered-out,
        .fx-eor-frontcard.is-search-hidden { display: none; }
        @media (max-width: 600px) {
            .fx-eor-chiprow { gap: 6px; }
            .fx-eor-chip { padding: 5px 11px; font-size: 12px; }
        }
        /* ─────────────────────────────────────────────────────────────────
         * v4.16.0 — Customer toolbar (search + sort) above the chip row.
         * Search filters by product name as the customer types (debounced
         * 120ms in JS). Sort reorders DOM cards; "Featured" restores admin
         * order via data-default-order. ───────────────────────────────── */
        .fx-eor-toolbar {
            display: flex; justify-content: space-between; align-items: center;
            flex-wrap: wrap; gap: 12px; margin: 0 0 12px;
            font-family: 'Jost', system-ui, sans-serif;
        }
        .fx-eor-search-wrap {
            position: relative; flex: 1 1 220px; min-width: 180px; max-width: 360px;
        }
        .fx-eor-search {
            width: 100%; padding: 8px 30px 8px 12px;
            border: 1.5px solid #D8E8D0; border-radius: 999px;
            background: #FAFAF8; color: #1F3A24;
            font-family: inherit; font-size: 13px; line-height: 1.2;
            transition: border-color 0.12s, background 0.12s;
        }
        .fx-eor-search::placeholder { color: #8aa291; }
        .fx-eor-search:focus {
            outline: none; border-color: #85C727; background: #fff;
        }
        .fx-eor-search-clear {
            position: absolute; right: 10px; top: 50%;
            transform: translateY(-50%);
            color: #2A6132; font-size: 18px; line-height: 1;
            cursor: pointer; padding: 2px 6px; border-radius: 50%;
        }
        .fx-eor-search-clear:hover { background: #E8F7D5; }
        .fx-eor-sort-wrap {
            display: flex; align-items: center; gap: 6px;
            font-family: inherit;
        }
        /* v4.18.4 — Sort + View live inside this single flex group so they
         * wrap as a unit, not independently. Gap between the two sub-clusters
         * matches the toolbar gap. */
        .fx-eor-sortview-group {
            display: flex; align-items: center;
            flex-wrap: wrap; gap: 6px 12px;
        }
        .fx-eor-sort-label {
            font-size: 12px; color: #5a7261; font-weight: 500;
            margin-right: 2px;
        }
        .fx-eor-sort-btn {
            background: #FAFAF8; border: 1.5px solid #D8E8D0;
            color: #1F3A24; padding: 6px 12px; border-radius: 999px;
            font-family: inherit; font-size: 12px; line-height: 1;
            cursor: pointer;
            transition: background 0.12s, border-color 0.12s, color 0.12s;
        }
        .fx-eor-sort-btn:hover { background: #E8F7D5; border-color: #85C727; }
        .fx-eor-sort-btn.is-active {
            background: #2A6132; border-color: #2A6132; color: #fff; font-weight: 500;
        }
        /* v4.18.2 — View (column) toggle. Two icon-only buttons mirroring the
         * Sort cluster's pill style. The icons are pure CSS bars (1 wide bar /
         * 2 narrow bars) so no font or SVG dependency. Hidden on narrow
         * viewports because the 2-col grid only activates at >=720px anyway.
         *
         * v4.18.4 — Visual fix: buttons now match Sort button height/padding
         * exactly (padding:6px 12px, no min-width override) so the cluster
         * looks cohesive instead of orphaned. Icons enlarged from 12px to
         * 16px and redrawn with the recognisable list-rows / 2x2-grid
         * metaphors so they read clearly at desktop viewing distance. */
        .fx-eor-view-wrap {
            display: flex; align-items: center; gap: 6px;
            font-family: inherit;
        }
        /* v4.25.70 — mobile column selector: hidden on desktop, shown ≤700px. */
        .fx-eor-mview-wrap { display: none; }
        .fx-eor-view-btn {
            background: #FAFAF8; border: 1.5px solid #D8E8D0;
            color: #1F3A24; padding: 6px 12px; border-radius: 999px;
            font-family: inherit; line-height: 1; cursor: pointer;
            display: inline-flex; align-items: center; justify-content: center;
            transition: background 0.12s, border-color 0.12s;
            height: 28px;
            box-sizing: border-box;
        }
        .fx-eor-view-btn:hover { background: #E8F7D5; border-color: #85C727; }
        .fx-eor-view-btn.is-active { background: #2A6132; border-color: #2A6132; }
        .fx-eor-view-icon {
            display: inline-block; position: relative;
            width: 16px; height: 12px;
        }
        /* 1-col icon: three stacked horizontal rows — universal "list view"
         * metaphor. Three rows render as solid dark-green bars; turn white on
         * the active button. */
        .fx-eor-view-icon--1col::before,
        .fx-eor-view-icon--1col {
            background: transparent;
        }
        .fx-eor-view-icon--1col::before {
            content: '';
            position: absolute; inset: 0;
            background-image: linear-gradient(
                to bottom,
                #1F3A24 0, #1F3A24 2px,
                transparent 2px, transparent 5px,
                #1F3A24 5px, #1F3A24 7px,
                transparent 7px, transparent 10px,
                #1F3A24 10px, #1F3A24 12px
            );
            border-radius: 1px;
        }
        .fx-eor-view-btn.is-active .fx-eor-view-icon--1col::before {
            background-image: linear-gradient(
                to bottom,
                #fff 0, #fff 2px,
                transparent 2px, transparent 5px,
                #fff 5px, #fff 7px,
                transparent 7px, transparent 10px,
                #fff 10px, #fff 12px
            );
        }
        /* 2-col icon: 2x2 grid of small filled squares — universal "grid view"
         * metaphor. Stronger visual presence than the two-bars approach. */
        .fx-eor-view-icon--2col::before,
        .fx-eor-view-icon--2col::after {
            content: '';
            position: absolute;
            width: 6px; height: 5px;
            background: #1F3A24;
            border-radius: 1px;
        }
        .fx-eor-view-icon--2col::before {
            top: 0; left: 0;
            box-shadow:
                10px 0   0 0 #1F3A24,
                0    7px 0 0 #1F3A24,
                10px 7px 0 0 #1F3A24;
        }
        .fx-eor-view-icon--2col::after { display: none; }
        .fx-eor-view-btn.is-active .fx-eor-view-icon--2col::before {
            background: #fff;
            box-shadow:
                10px 0   0 0 #fff,
                0    7px 0 0 #fff,
                10px 7px 0 0 #fff;
        }
        /* v4.19.0 — 3-col icon: 3 small filled squares in two rows (3x2 grid).
         * Visually denser than the 2x2 of the 2-col icon so the difference
         * reads immediately. */
        .fx-eor-view-icon--3col::before,
        .fx-eor-view-icon--3col::after {
            content: '';
            position: absolute;
            width: 4px; height: 5px;
            background: #1F3A24;
            border-radius: 1px;
        }
        .fx-eor-view-icon--3col::before {
            top: 0; left: 0;
            box-shadow:
                6px  0   0 0 #1F3A24,
                12px 0   0 0 #1F3A24,
                0    7px 0 0 #1F3A24,
                6px  7px 0 0 #1F3A24,
                12px 7px 0 0 #1F3A24;
        }
        .fx-eor-view-icon--3col::after { display: none; }
        .fx-eor-view-btn.is-active .fx-eor-view-icon--3col::before {
            background: #fff;
            box-shadow:
                6px  0   0 0 #fff,
                12px 0   0 0 #fff,
                0    7px 0 0 #fff,
                6px  7px 0 0 #fff,
                12px 7px 0 0 #fff;
        }
        @media (max-width: 520px) {
            /* Hide on narrow viewports — 2-col gate is at 720px so toggle is
             * meaningless here. Keeps the toolbar from feeling crowded. */
            .fx-eor-view-wrap { display: none; }
        }
        /* v4.19.1 — Skeleton loading state for the AJAX-loaded Siblings body.
         * Shown briefly between initial paint and AJAX response. Subtle
         * pulse animation gives the customer a visual cue that content is
         * coming. Once AJAX returns, the whole skeleton is replaced
         * wholesale with the real body content. */
        @keyframes fx-eor-skel-pulse {
            0%, 100% { opacity: 0.55; }
            50%      { opacity: 1; }
        }
        .fx-eor-skeleton {
            animation: fx-eor-skel-pulse 1.4s ease-in-out infinite;
            display: flex; flex-direction: column; gap: 12px;
        }
        .fx-eor-skel-toolbar {
            height: 36px; background: #D8E8D0; border-radius: 6px;
        }
        .fx-eor-skel-chiprow {
            display: flex; flex-wrap: wrap; gap: 6px;
        }
        .fx-eor-skel-chip {
            display: inline-block;
            width: 80px; height: 26px;
            background: #D8E8D0; border-radius: 999px;
        }
        .fx-eor-skel-chip:nth-child(2) { width: 110px; }
        .fx-eor-skel-chip:nth-child(3) { width: 70px; }
        .fx-eor-skel-chip:nth-child(4) { width: 95px; }
        .fx-eor-skel-card {
            height: 220px; background: #D8E8D0; border-radius: 5px;
            border: 1px solid #C8DEC0;
        }
        @media (max-width: 600px) {
            .fx-eor-skel-card { height: 180px; }
        }
        .fx-eor-no-matches {
            padding: 18px; text-align: center; color: #5a7261;
            font-size: 13px; font-family: 'Jost', system-ui, sans-serif;
            background: #FAFAF8; border: 1px dashed #D8E8D0; border-radius: 6px;
            margin-bottom: 12px;
        }
        .fx-eor-reset-link {
            background: none; border: none; color: #2A6132;
            text-decoration: underline; cursor: pointer; font-family: inherit;
            font-size: 13px; padding: 0;
        }
        .fx-eor-reset-link:hover { color: #1F3A24; }
        /* ─────────────────────────────────────────────────────────────────
         * v4.16.0 — Out-of-stock card styling. Cards stay visible but with
         * faded image + "Sold out" badge overlay + disabled buy controls.
         * Image link remains clickable (sends customer to product page).
         * Notify-me UI lands in v4.16.1. ──────────────────────────────── */
        .fx-eor-frontcard--oos .fx-eor-img { opacity: 0.55; filter: grayscale(0.4); }
        .fx-eor-frontcard--oos .fx-eor-img-link {
            position: relative; display: block;
        }
        .fx-eor-frontcard--oos .fx-eor-img-link::after {
            content: "Sold out";
            position: absolute; top: 10px; right: 10px;
            background: #1F3A24; color: #fff;
            font-family: 'Jost', system-ui, sans-serif;
            font-size: 11px; font-weight: 600; letter-spacing: 0.6px;
            text-transform: uppercase;
            padding: 5px 10px; border-radius: 3px;
            pointer-events: none; z-index: 2;
            box-shadow: 0 1px 3px rgba(0,0,0,0.2);
        }
        .fx-eor-frontcard--oos .fx-eor-check-col,
        .fx-eor-frontcard--oos .fx-eor-variations,
        .fx-eor-frontcard--oos .fx-eor-qty,
        .fx-eor-frontcard--oos .fx-eor-card-add {
            opacity: 0.4; pointer-events: none; filter: grayscale(1);
        }
        .fx-eor-frontcard--oos .fx-eor-name-link,
        .fx-eor-frontcard--oos .fx-eor-price { opacity: 0.7; }
        .fx-eor-frontcard--oos .fx-eor-card-add {
            background: #b8b8b8 !important; cursor: not-allowed;
        }
        /* v4.18.3 — notify-me UI on OOS cards. Replaces the greyed-out Add to
         * Basket button. Three states managed inline:
         *   1. Default: "✉ Notify me when back" trigger button (full width).
         *   2. After click: trigger hides, email input + Submit button show.
         *   3. After successful submit: form hides, success message shows.
         * Critical: this wrap sits INSIDE .fx-eor-frontcard--oos, so it
         * inherits pointer-events:none from earlier rules — override to
         * pointer-events:auto so clicks register. */
        .fx-eor-frontcard--oos .fx-eor-notify-wrap {
            opacity: 1;
            filter: none;
            pointer-events: auto;
            margin-top: 4px;
        }
        .fx-eor-notify-wrap { font-family: 'Jost', sans-serif; }
        .fx-eor-notify-trigger {
            display: block;
            width: 100%;
            background: #2D6A4F;
            color: #fff;
            border: 0;
            padding: 9px 12px;
            font-size: 12px;
            font-weight: 500;
            font-family: inherit;
            letter-spacing: 0.3px;
            border-radius: 3px;
            cursor: pointer;
            text-align: center;
            transition: background 0.12s;
        }
        .fx-eor-notify-trigger:hover { background: #1F3A24; }
        .fx-eor-notify-form {
            display: flex;
            gap: 4px;
            align-items: stretch;
        }
        .fx-eor-notify-email {
            flex: 1 1 auto;
            min-width: 0;
            padding: 7px 9px;
            border: 1px solid #2D6A4F;
            border-radius: 3px;
            font-size: 12px;
            font-family: inherit;
            color: #1F3A24;
            background: #fff;
        }
        .fx-eor-notify-email:focus { outline: none; border-color: #85C727; box-shadow: 0 0 0 2px rgba(133,199,39,0.15); }
        .fx-eor-notify-submit {
            background: #2D6A4F;
            color: #fff;
            border: 0;
            padding: 7px 14px;
            font-size: 12px;
            font-weight: 500;
            font-family: inherit;
            border-radius: 3px;
            cursor: pointer;
            white-space: nowrap;
        }
        .fx-eor-notify-submit:hover { background: #1F3A24; }
        .fx-eor-notify-submit:disabled { background: #888; cursor: wait; }
        .fx-eor-notify-success {
            padding: 8px 10px;
            background: #E8F7D5;
            border: 1px solid #85C727;
            color: #2D6A4F;
            border-radius: 3px;
            font-size: 11px;
            font-weight: 500;
            text-align: center;
            line-height: 1.3;
        }
        .fx-eor-notify-error {
            padding: 6px 10px;
            background: #FBE9E9;
            border: 1px solid #d99c9c;
            color: #b03030;
            border-radius: 3px;
            font-size: 11px;
            text-align: center;
            line-height: 1.3;
        }
        @media (max-width: 600px) {
            .fx-eor-toolbar { gap: 8px; }
            .fx-eor-search-wrap { flex: 1 1 100%; max-width: none; }
            .fx-eor-sort-btn { padding: 5px 10px; font-size: 11px; }
            .fx-eor-frontcard--oos .fx-eor-img-link::after {
                top: 6px; right: 6px; font-size: 10px; padding: 4px 8px;
            }
        }
        /* v4.7.38: Hopewiser-style internal scroll viewport. Caps visible
         * cards at 6 (3 rows × 2 cols on desktop) — beyond that the user
         * scrolls within the section rather than the page. Keeps EOR
         * visually compact while preserving access to all cards. Same
         * mechanism on mobile, smaller viewport (3 cards visible).
         *
         * max-height naturally collapses when fewer than 6 cards present —
         * the container shrinks to fit content with no scrollbar shown. */
        .fx-eor-grid {
            max-height: 920px;
            overflow-y: auto;
            padding-right: 6px;
            scrollbar-width: thin;
            scrollbar-color: #85C727 #F0F4E8;
        }
        .fx-eor-grid::-webkit-scrollbar { width: 8px; }
        .fx-eor-grid::-webkit-scrollbar-track { background: #F0F4E8; border-radius: 4px; }
        .fx-eor-grid::-webkit-scrollbar-thumb { background: #85C727; border-radius: 4px; }
        .fx-eor-grid::-webkit-scrollbar-thumb:hover { background: #2A6132; }
        /* v4.7.22: card is now a vertical flex container — top strip above, main row below.
         * Both cards in a grid row stretch to equal height. The top strip is present on
         * every card (same height) so cards align consistently at top and bottom. */
        /* v4.7.30: Cards mirror the billing panel structure — white body
         * (like the address field), green border (like the field border),
         * sitting inside a cream accordion (like the panel container).
         * Visual hierarchy: page mint → cream accordion → white cards.
         * v4.7.32: card border now matches address field border colour (sage). */
        /* v4.19.42 — Was `transition: all 0.15s`. James reported tick
         * "is not immediate, takes about 2 seconds" — v4.19.41 had
         * already pulled transitions off .fx-eor-check-col and
         * .fx-eor-check, but the parent card was STILL transitioning
         * border-color, background, and box-shadow over 150ms on
         * every .selected toggle. That's the green border + sage
         * fill the user sees ease in/out — visually it reads as
         * the tick "settling" slowly even though the tick glyph
         * itself flipped instantly.
         *
         * v4.19.43 — Further narrowing. v4.19.42 had `transition:
         * transform 0.15s, box-shadow 0.15s` to keep the hover
         * lift's box-shadow animating. BUT `.fx-eor-frontcard--current.selected`
         * adds `box-shadow: 0 0 0 2px #2A6132 inset` — a 2px green
         * inset that ALSO transitioned over 150ms because
         * box-shadow was in the transition list. That's the
         * remaining "tick settles slowly" feel on the current
         * product card.
         *
         * Drop box-shadow from the transition. Now ONLY transform
         * animates — the :hover lift (translateY(-1px)) still feels
         * smooth, and the hover box-shadow appears instantly (a
         * minor regression that's barely visible). The .selected
         * 2px inset flips instantly. The tick is finally instant
         * on the current product card. */
        .fx-eor-frontcard { background: #fff; border: 1px solid #85C727; border-radius: 5px; display: flex; flex-direction: column; overflow: hidden; cursor: pointer; transition: transform 0.15s; position: relative; }
        .fx-eor-frontcard:hover { border-color: #2A6132; transform: translateY(-1px); box-shadow: 0 4px 12px -6px rgba(31, 58, 36, 0.15); }
        .fx-eor-frontcard.selected { border-color: #2A6132; background: #F8FCF0; box-shadow: 0 0 0 1px #2A6132 inset; }

        /* ═══════════════════════════════════════════════════════════════
           v4.19.23 — "In Basket" indicator.

           When a product is already in the WC cart, mark its EOR card and
           slider card with a discreet "✓ In basket" badge in the top-right
           corner + a subtle sage tint. So if customer has already added a
           product on a previous page, when they navigate to a NEW product
           page where that product appears as a sibling, they immediately
           see it's already in their basket and don't accidentally re-add.

           Independent of the .selected state (which is the EOR tick/staging
           system). A card can be both — selected (about to add more) AND
           in-basket (already has one).

           v4.19.34 — Removed the "✓ IN BASKET" pill. James: "I think the
           pill is over engineered and all we need is the tick". Cards that
           are in the WC cart now simply show the same ✓ that selected
           cards show, via a CSS rule that opacity-1's the .fx-eor-check
           ::after pseudo-element. The green border is preserved as a
           subtle in-cart indicator without the noisy pill.
           ═══════════════════════════════════════════════════════════════ */
        .fx-eor-frontcard.fx-eor-in-cart {
            border-color: #85C727;
        }
        /* v4.19.34 — Show the same checkmark as ticked/staged cards when
         * a card is in the WC cart. Reuses the existing ::after content
         * (defined on .fx-eor-check below) — just makes it visible. */
        .fx-eor-frontcard.fx-eor-in-cart .fx-eor-check::after { opacity: 1; }
        /* Current product card — green outline reinforced via inset shadow. */
        .fx-eor-frontcard--current { border-color: #2A6132; }
        .fx-eor-frontcard--current.selected { border-color: #2A6132; box-shadow: 0 0 0 2px #2A6132 inset; }
        /* Top strip: v4.7.32 — mint matching the accordion body (eliminates
         * the "cream empty space" James flagged). Strip is effectively invisible
         * on non-current, non-selected cards — clean card top edge. Only the
         * current product strip stays bold dark green for the badge. */
        /* v4.7.47: Top strip hidden everywhere — "Currently viewing" badge is
         * now rendered via .fx-eor-frontcard[data-current="1"] .fx-eor-body::before
         * (see below). Strip rules retained below as no-op for safety, but the
         * display:none here is authoritative across all viewports. */
        .fx-eor-card-top { display: none; }
        .fx-eor-frontcard--current .fx-eor-card-top { background: #2A6132; border-bottom-color: #2A6132; }
        .fx-eor-frontcard.selected .fx-eor-card-top { background: #D8E8D0; border-bottom-color: #2A6132; }
        .fx-eor-frontcard--current.selected .fx-eor-card-top { background: #2A6132; }
        .fx-eor-current-badge-text { color: #fff; font-size: 9px; font-weight: 600; letter-spacing: 1px; text-transform: uppercase; font-family: 'Jost', sans-serif; }
        /* v4.7.47: Card-main is now 50/50 horizontal split everywhere.
         * Image left half, body right half. The .fx-eor-check-col is
         * display:none below and drops out of layout, leaving two grid
         * children. The padding-top:100% trick on .fx-eor-img-link
         * (further below) locks the image to a square baseline that can
         * never exceed its 1fr track width. */
        .fx-eor-card-main { display: grid; grid-template-columns: 1fr 1fr; flex: 1 1 auto; }
        /* v4.18.1 — Mobile/constrained-width fix.
         *
         * The v4.7.65 fix (min-width:0 on card-main children) was scoped only
         * to #fx-eor-top-slider .fx-eor-card-main > *. Accordion cards never
         * needed it because they always sat in a full-width product-page
         * context where image min-content fit comfortably under 1fr.
         *
         * In a constrained-width context (one-page checkout sidebar, or
         * any container narrower than ~600px in mobile portrait), the
         * image's intrinsic natural width was forcing the first 1fr grid
         * track to grow beyond 50% of card width — eating the body column
         * entirely on the worst products (large source images). Result:
         * the card rendered as just a big image with no name/pills/price
         * visible. James reported this from mobile on the live site.
         *
         * The fix is the same as v4.7.65: tell each grid child it can shrink
         * below its min-content. The 1fr/1fr distribution then wins and the
         * image's width:100% inside its track stays at exactly 50% of card. */
        .fx-eor-card-main > * {
            min-width: 0;
        }
        /* v4.7.20: Subscription card — small "subscription" hint badge bottom-right of card body. */
        .fx-eor-frontcard--sub .fx-eor-body::after { content: '↻ Subscription'; display: inline-block; font-size: 9px; color: #4A5F4F; letter-spacing: 0.4px; text-transform: uppercase; margin-top: 2px; }
        /* v4.7.29: variation pills — small selectable chips inside each card.
         * Lets customers pick stem count (or any variation axis) without
         * leaving EOR. Active pill = filled forest green; inactive = cream
         * with mint border. Pills wrap to multiple lines if many variations. */
        /* v0.2.352, row 23b34 — THE CHIPS' OWN SCROLL BOX (the owner: a card with fifteen "£20.00 ·
         * Weekly" chips grew taller than a card with three — the row's bottoms never levelled, THE TILE
         * LAW). Bounded to about three rows of these small pills (21px pill + 4px gap, three rows ≈
         * 71px) whatever the count; overflow scrolls inside the card instead of stretching it; the house
         * scrollbar (the same tokens the skin's own scrolling boxes use — #85C727 on #F4FFEA, thin). The
         * chosen chip is scrolled into view on paint (the script just above this style block). */
        .fx-eor-variations { display: flex; flex-wrap: wrap; align-content: flex-start; gap: 4px; margin: 4px 0 8px; height: 72px; overflow-y: auto; scrollbar-width: thin; scrollbar-color: #85C727 #F4FFEA; } /* v0.2.352 — a FIXED height, not a ceiling: a card with three chips and a card with fifteen must be the SAME height (THE TILE LAW), so a short list leaves quiet space below it rather than shrinking the box; align-content keeps a short list's row pinned to the top, not stretched down the box */
        .fx-eor-variations::-webkit-scrollbar { width: 6px; }
        .fx-eor-variations::-webkit-scrollbar-track { background: #F4FFEA; border-radius: 3px; }
        .fx-eor-variations::-webkit-scrollbar-thumb { background: #85C727; border-radius: 3px; }
        .fx-eor-var-pill { background: #F4F7EF; border: 1px solid #C8DEC0; color: #1F3A24; font-size: 10px; padding: 3px 9px; border-radius: 12px; cursor: pointer; font-family: 'Jost', sans-serif; letter-spacing: 0.3px; font-weight: 500; transition: all 0.12s; line-height: 1.3; }
        .fx-eor-var-pill:hover { background: #E8F7D5; border-color: #85C727; }
        .fx-eor-var-pill.active { background: #2A6132; color: #fff; border-color: #2A6132; }
        .fx-eor-var-pill.active:hover { background: #1F3A24; border-color: #1F3A24; }
        /* v0.2.79 — PHONE-SIZED PILLS (the owner: "those tiny pills" on mobile): on a touch device a pill grows to a comfortable tap target — taller, more side room, 12px text — desktop unchanged. The active (dark) state outranks the sticky post-tap hover by declaration order above. KEEP IN STEP with eor-landing-skin.php. */
        @media (hover: none), (pointer: coarse) { .fx-eor-var-pill { font-size: 12px; padding: 7px 13px; min-height: 32px; line-height: 1.2; } .fx-eor-var-pill:hover:not(.active) { background: #F4F7EF; border-color: #C8DEC0; } }
        /* v4.7.48: Check column is RE-VISIBLE but absolutely positioned at the
         * card's top-right corner as an overlay tick. The existing click handler
         * (line ~2947: checkCol.addEventListener('click', ...) with stopPropagation)
         * carries the toggle — no JS changes.
         *
         * Why not a ::after pseudo (as in v4.7.47)? Pseudo-elements can't receive
         * click events. With pointer-events:none, taps on the tick fell through
         * to the .fx-eor-name-link <a> behind it (which wraps the h4 across the
         * full row including the padding-right reserved for the tick), and the
         * browser navigated to that product page instead of selecting it. */
        .fx-eor-check-col {
            position: absolute;
            top: 8px;
            right: 8px;
            width: 28px;
            height: 28px;
            background: rgba(255, 255, 255, 0.96);
            border: 1.5px solid #2A6132;
            border-bottom: 1.5px solid #2A6132;
            border-right: 1.5px solid #2A6132;
            border-radius: 4px;
            z-index: 5;
            box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
            cursor: pointer;
            display: flex;
            align-items: center;
            justify-content: center;
            padding: 0;
            box-sizing: border-box;
            /* v4.19.41 — Was `transition: background 0.15s, border-color 0.15s`.
             * James reported tick "takes about 2 seconds" perceptually.
             * Root cause was two combined: heavy synchronous JS after the
             * click (see toggle() rAF wrap below) AND a 150ms CSS fade on
             * the box colour + glyph opacity. Combined with browser repaint
             * delay on a JS-heavy page the box flip felt sluggish. The user
             * wants the tick to feel like a native checkbox: click, pop.
             * Set to none — colour change is instant on class toggle. */
            transition: none;
        }
        .fx-eor-frontcard.selected .fx-eor-check-col {
            background: #85C727;
            border-color: #85C727;
        }
        /* Inner .fx-eor-check now fills its overlay parent (was a 19x19 nested
         * box on the old left-column design). The existing ::after rule below
         * still renders the ✓ on .selected — no change there. */
        .fx-eor-check {
            width: 100%;
            height: 100%;
            border: 0;
            background: transparent;
        }
        .fx-eor-frontcard.selected .fx-eor-check {
            background: transparent;
            border: 0;
        }
        /* v4.7.48: Original 19x19 nested-box .fx-eor-check is now no-op —
         * the inner element fills its absolutely-positioned parent (see new
         * .fx-eor-check-col styling above). The ::after ✓ checkmark logic
         * is retained: opacity 0/1 driven by .selected. Font-size bumped to
         * suit the larger 28x28 overlay. Mobile @media tightens to 13px.
         *
         * v4.19.41 — `transition: all 0.15s` removed (was fading the
         * ::after ✓ glyph opacity 0→1 over 150ms). Pseudo-elements use
         * their host's transition rules, so this declaration was the
         * direct cause of the tick fade. With it gone the glyph pops on
         * the same frame the .selected class is added. Combined with the
         * rAF defer in toggle() (search "v4.19.41 — Yield to paint")
         * the tick now feels native-checkbox responsive. */
        .fx-eor-check { width: 100%; height: 100%; border: 0; background: transparent; display: flex; align-items: center; justify-content: center; transition: none; }
        .fx-eor-frontcard.selected .fx-eor-check { background: transparent; border: 0; }
        .fx-eor-check::after { content: '\2713'; color: #1F3A24; font-size: 15px; font-weight: 700; opacity: 0; line-height: 1; font-family: 'Jost', sans-serif; }
        .fx-eor-frontcard.selected .fx-eor-check::after { opacity: 1; }
        /* v4.7.49: align-self:start — image-link sits at the TOP of its grid cell
         * and refuses to stretch when the body cell grows taller. Long titles /
         * many variations leave blank space BELOW the image inside the card. */
        /* v4.7.50: dropped padding-top:100% pseudo. The image now drives its own
         * height via natural aspect ratio: tall portrait photos (house plants)
         * render as taller boxes, square photos (peonies) stay square. The
         * placeholder div has its own aspect-ratio:1/1 fallback below. */
        .fx-eor-img-link { display: block; text-decoration: none; line-height: 0; position: relative; align-self: start; }
        /* v4.7.17: real <img> tag instead of background-image div. Bypasses WP
         * Rocket's CSS background-image lazy loader (which was stripping the
         * inline style for lazy-load and never restoring it because the
         * relocator moves the wrapper after Rocket's scan). object-fit:cover
         * replicates the previous background-size:cover/center behaviour. */
        /* v4.7.50: <img> renders at its natural aspect ratio.
         *  - width:100% pins the image to the 1fr grid track width (50% of card)
         *  - height:auto lets the browser preserve the image's intrinsic ratio
         *  - Tall portrait photos render as taller cells, square stay square,
         *    landscape photos render shorter (with blank below via align-self:start)
         * Placeholder (no image src) gets aspect-ratio:1/1 so it doesn't collapse
         * to zero height when no image is loaded. */
        img.fx-eor-img { display: block; width: 100%; height: auto; object-fit: cover; object-position: center; background-color: #F4F7EF; }
        .fx-eor-img-placeholder { display: block; width: 100%; aspect-ratio: 1 / 1; background: linear-gradient(135deg, #E8F7D5, #85C727); }
        .fx-eor-body { padding: 10px 13px; display: flex; flex-direction: column; justify-content: space-between; }
        .fx-eor-name-link { text-decoration: none; color: inherit; }
        /* v4.25.70 — the mobile-2col "View" toggle is injected into grid cards
         * by JS; hidden everywhere except the mobile 2-column view. */
        .fx-eor-mview { display: none; }
        /* v4.7.47+: padding-right reserves space for the tick overlay at the
         * card's top-right corner (the repositioned .fx-eor-check-col element
         * from v4.7.48) so the title doesn't run under it. Mobile @media
         * tightens this to 30px for the smaller tick. */
        .fx-eor-body h4 { font-family: 'Cormorant Garamond', Georgia, serif; font-weight: 500; font-size: 16px; color: #1F3A24; margin: 0 0 4px; line-height: 1.1; padding-right: 38px; }
        /* v4.25.69 — title text rules for GRID cards only (NOT the slider, which
         * is .fx-eor-top-slider-track and keeps its own h4 rule). Keeps whole
         * words: wraps at spaces, only splits a single word if it genuinely
         * cannot fit; never mid-word from the theme's global word-break. */
        .fx-eor-grid .fx-eor-body h4 { overflow-wrap: break-word; word-break: normal; hyphens: none; padding-right: 30px; }
        .fx-eor-bottom { display: flex; justify-content: space-between; align-items: center; gap: 6px; }
        .fx-eor-price { font-size: 13px; color: #1F3A24; font-weight: 500; }
        .fx-eor-price .from { color: #4A5F4F; font-size: 9px; letter-spacing: 0.5px; text-transform: uppercase; }
        .fx-eor-qty { display: flex; align-items: center; border: 1px solid #2A6132; border-radius: 3px; overflow: hidden; height: 24px; background: #fff; }
        .fx-eor-qty button { width: 22px; height: 22px; background: #F4F7EF; border: 0; cursor: pointer; color: #2A6132; font-size: 13px; font-weight: 600; padding: 0; line-height: 1; transition: background 0.12s; }
        .fx-eor-qty button:hover { background: #E8F7D5; }
        .fx-eor-qty .fx-eor-q-input { width: 24px; text-align: center; border: 0; background: #fff; color: #1F3A24; font-size: 12px; font-weight: 600; font-family: inherit; }
        .fx-eor-qty.disabled { opacity: 0.35; pointer-events: none; }
        /* v4.7.32: per-card Add to Basket button — sage green matching the
         * FBF action button style. Single-product add path: adds this card's
         * product + chosen variation + current qty (defaulting to 1 if untiсked)
         * then redirects to /basket/. Independent of the master button. */
        .fx-eor-card-add { display: block; width: 100%; margin-top: 10px; background: #85C727; color: #1F3A24; border: 0; padding: 9px 12px; font-size: 11px; font-weight: 600; letter-spacing: 1px; text-transform: uppercase; cursor: pointer; border-radius: 3px; font-family: 'Jost', sans-serif; transition: all 0.12s; }
        .fx-eor-card-add:hover { background: #95D837; }
        .fx-eor-card-add:active { background: #75B717; }
        .fx-eor-card-add:disabled { opacity: 0.55; cursor: wait; background: #6B8B6F; color: #fff; }
        /* ═══════════════════════════════════════════════════════════════
         * v4.7.48: Currently-viewing badge — rendered via ::before on the
         * body when the wrapper carries data-current="1" (attribute set in
         * HTML at line 2066). Sits at the top of the writing column above
         * the title. The image is never touched.
         *
         * The previous-version (v4.7.47) tick overlay via .fx-eor-frontcard::after
         * has been removed — pseudo-elements can't receive clicks and
         * pointer-events:none made taps fall through to the title link.
         * Tick is now the real .fx-eor-check-col element repositioned as
         * an absolute overlay (see above). */
        .fx-eor-frontcard[data-current="1"] .fx-eor-body::before {
            content: "\2605 Currently viewing";
            display: inline-block;
            background: #2A6132;
            color: #fff;
            font-size: 10px;
            letter-spacing: 1px;
            text-transform: uppercase;
            padding: 4px 10px;
            border-radius: 3px;
            font-weight: 600;
            font-family: 'Jost', sans-serif;
            align-self: flex-start;
            margin-bottom: 4px;
        }
        /* v4.19.9 — Pagination controls. Sits between the grid and the CTA.
         * Counter + Load More button + invisible IntersectionObserver sentinel. */
        .fx-eor-pagination { margin: 18px 0 14px 0; padding: 16px 20px; background: #FAFEF5; border: 1px solid #D8E8D0; border-radius: 5px; text-align: center; font-family: 'Jost', sans-serif; }
        .fx-eor-pagination[data-fx-eor-done="1"] { background: #f9fafb; border-color: #e5e7eb; }
        .fx-eor-pagination-status { font-size: 12px; color: #4A5F4F; margin-bottom: 10px; letter-spacing: 0.4px; }
        .fx-eor-pagination-status strong { color: #1F3A24; font-weight: 600; }
        /* v0.2.70 — ONE BUTTON: the pagination box's own button is retired from view; the Explore control drives loading (mirror above). */
        .fx-eor-pagination .fx-eor-pagination-button { display: none !important; }
        .fx-eor-preview-expand-btn.is-loading { opacity: .7; pointer-events: none; }
        .fx-eor-pagination-button { display: inline-block; background: #fff; color: #2A6132; border: 1.5px solid #2A6132; padding: 10px 24px; font-size: 12px; font-weight: 600; letter-spacing: 1.2px; text-transform: uppercase; cursor: pointer; border-radius: 4px; font-family: 'Jost', sans-serif; transition: background 0.15s, color 0.15s, transform 0.1s; }
        .fx-eor-pagination-button:hover:not(:disabled) { background: #2A6132; color: #fff; }
        .fx-eor-pagination-button:active:not(:disabled) { transform: translateY(1px); }
        .fx-eor-pagination-button:disabled { opacity: 0.55; cursor: wait; }
        .fx-eor-pagination-button.is-loading::after { content: ' ⏳'; }
        /* Sentinel: small invisible div the IntersectionObserver watches. Sized
         * so it has measurable height but isn't visible. */
        .fx-eor-pagination-sentinel { height: 1px; width: 100%; margin-top: 10px; visibility: hidden; }
        /* v4.7.31: inline CTA block — appears at the bottom of the EOR section
         * itself (not just the sticky bottom bar). Matches PROCEED TO CHECKOUT
         * button style for visual consistency with the rest of FBF checkout. */
        .fx-eor-cta { margin-top: 18px; padding: 18px 20px; background: #fff; border: 1px solid #C8DEC0; border-radius: 5px; text-align: center; }
        .fx-eor-cta-summary { display: inline-flex; align-items: center; gap: 12px; margin-bottom: 14px; font-family: 'Jost', sans-serif; font-size: 13px; color: #1F3A24; }
        .fx-eor-cta-count-pill { background: #2A6132; color: #fff; min-width: 28px; height: 28px; padding: 0 8px; border-radius: 14px; display: inline-flex; align-items: center; justify-content: center; font-weight: 700; font-size: 13px; font-family: 'Jost', sans-serif; }
        .fx-eor-cta-text strong { color: #2A6132; font-weight: 600; }
        .fx-eor-cta-btn { display: block; width: 100%; background: #2A6132; color: #fff; border: 0; padding: 16px 36px; font-size: 13px; font-weight: 600; letter-spacing: 1.5px; text-transform: uppercase; cursor: pointer; border-radius: 4px; font-family: 'Jost', sans-serif; transition: background 0.15s; }
        .fx-eor-cta-btn:hover:not(:disabled) { background: #1F3A24; }
        .fx-eor-cta-btn:disabled { opacity: 0.4; cursor: not-allowed; background: #6B8B6F; }

        /* ═══════════════════════════════════════════════════════════════
           v4.19.21 — Mini-basket panel inside the inline CTA card.
           Mirrors WC cart contents with edit controls. Default-collapsed;
           toggled via "Show basket ▾" button + auto-expanded by JS on
           page load when the cart isn't empty.
           ═══════════════════════════════════════════════════════════════ */
        .fx-eor-mini-basket-toggle {
            margin-left: auto;
            background: transparent;
            border: 1px solid #C8DEC0;
            color: #2A6132;
            font-family: 'Jost', sans-serif;
            font-size: 11px;
            font-weight: 600;
            letter-spacing: 0.4px;
            padding: 5px 12px;
            border-radius: 12px;
            cursor: pointer;
            transition: all 0.15s;
        }
        .fx-eor-mini-basket-toggle:hover { background: #E8F7D5; border-color: #85C727; }
        .fx-eor-mini-basket-toggle .fx-eor-mini-basket-toggle-hide { display: none; }
        .fx-eor-mini-basket-toggle[aria-expanded="true"] .fx-eor-mini-basket-toggle-show { display: none; }
        .fx-eor-mini-basket-toggle[aria-expanded="true"] .fx-eor-mini-basket-toggle-hide { display: inline; }

        .fx-eor-mini-basket {
            background: #FAFFF8;
            border: 1px solid #D8E8D0;
            border-radius: 6px;
            padding: 4px 0 0;
            margin: 10px 0 14px;
            font-family: 'Jost', sans-serif;
        }
        .fx-eor-mini-basket[hidden] { display: none; }

        .fx-eor-mini-basket-section { padding: 8px 14px 4px; }
        .fx-eor-mini-basket-section + .fx-eor-mini-basket-section { border-top: 1px dashed #D8E8D0; padding-top: 10px; margin-top: 4px; }

        .fx-eor-mini-basket-heading {
            display: flex;
            justify-content: space-between;
            align-items: baseline;
            font-size: 10px;
            font-weight: 700;
            letter-spacing: 1.2px;
            text-transform: uppercase;
            color: #1F3A24;
            margin-bottom: 8px;
        }
        .fx-eor-mini-basket-heading-count {
            background: #2A6132;
            color: #fff;
            border-radius: 8px;
            padding: 1px 8px;
            font-size: 10px;
            font-weight: 700;
            letter-spacing: 0.5px;
        }

        .fx-eor-mini-basket-list { display: flex; flex-direction: column; gap: 8px; }

        .fx-eor-mini-basket-row {
            display: grid;
            grid-template-columns: 48px 1fr auto;
            gap: 10px;
            align-items: center;
            background: #fff;
            border: 1px solid #E8F0E0;
            border-radius: 4px;
            padding: 8px 10px;
            transition: opacity 0.18s, transform 0.18s;
        }
        .fx-eor-mini-basket-row.is-pending { background: #FFFBED; border-color: #F0E5C8; }
        .fx-eor-mini-basket-row.is-removing { opacity: 0; transform: translateX(20px); pointer-events: none; }
        .fx-eor-mini-basket-row.is-busy { opacity: 0.6; pointer-events: none; }

        .fx-eor-mini-basket-row-img {
            width: 48px;
            height: 48px;
            border-radius: 3px;
            background: #f5f5f0;
            overflow: hidden;
            display: block;
        }
        .fx-eor-mini-basket-row-img img { width: 100%; height: 100%; object-fit: cover; display: block; }

        .fx-eor-mini-basket-row-body { min-width: 0; }
        .fx-eor-mini-basket-row-name {
            display: block;
            color: #1F3A24;
            font-size: 13px;
            font-weight: 500;
            line-height: 1.25;
            text-decoration: none;
            margin-bottom: 2px;
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
        }
        .fx-eor-mini-basket-row-name:hover { color: #2A6132; }
        .fx-eor-mini-basket-row-variation {
            display: block;
            color: #6B8B6F;
            font-size: 10px;
            letter-spacing: 0.3px;
            margin-bottom: 4px;
        }
        .fx-eor-mini-basket-row-controls {
            display: flex;
            align-items: center;
            gap: 8px;
        }
        .fx-eor-mini-basket-qty {
            display: inline-flex;
            align-items: center;
            border: 1px solid #C8DEC0;
            border-radius: 3px;
            background: #F4F7EF;
            overflow: hidden;
        }
        .fx-eor-mini-basket-qty button {
            background: transparent;
            border: 0;
            width: 24px;
            height: 22px;
            cursor: pointer;
            color: #1F3A24;
            font-size: 14px;
            font-weight: 700;
            line-height: 1;
            padding: 0;
            font-family: 'Jost', sans-serif;
            transition: background 0.12s;
        }
        .fx-eor-mini-basket-qty button:hover:not(:disabled) { background: #E8F7D5; }
        .fx-eor-mini-basket-qty button:disabled { opacity: 0.3; cursor: not-allowed; }
        .fx-eor-mini-basket-qty-input {
            width: 32px;
            text-align: center;
            border: 0;
            border-left: 1px solid #C8DEC0;
            border-right: 1px solid #C8DEC0;
            background: #fff;
            font-family: 'Jost', sans-serif;
            font-size: 12px;
            font-weight: 600;
            color: #1F3A24;
            padding: 4px 0;
            -moz-appearance: textfield;
        }
        .fx-eor-mini-basket-qty-input::-webkit-outer-spin-button,
        .fx-eor-mini-basket-qty-input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
        .fx-eor-mini-basket-row-subtotal {
            color: #1F3A24;
            font-size: 13px;
            font-weight: 600;
            min-width: 50px;
            text-align: right;
        }
        .fx-eor-mini-basket-remove {
            background: transparent;
            border: 0;
            width: 22px;
            height: 22px;
            cursor: pointer;
            color: #C03030;
            font-size: 16px;
            font-weight: 700;
            line-height: 1;
            border-radius: 11px;
            transition: background 0.12s;
            padding: 0;
        }
        .fx-eor-mini-basket-remove:hover { background: #FFEAEA; }

        .fx-eor-mini-basket-empty {
            color: #6B8B6F;
            font-size: 12px;
            font-style: italic;
            padding: 6px 0 4px;
        }

        .fx-eor-mini-basket-footer {
            background: #F4F7EF;
            border-top: 1px solid #D8E8D0;
            padding: 10px 14px;
            display: flex;
            justify-content: space-between;
            align-items: center;
            border-radius: 0 0 5px 5px;
            margin-top: 8px;
        }
        .fx-eor-mini-basket-totals { font-size: 12px; color: #1F3A24; }
        .fx-eor-mini-basket-totals strong { font-size: 14px; margin-left: 6px; }
        .fx-eor-mini-basket-link {
            font-size: 11px;
            font-weight: 600;
            letter-spacing: 0.5px;
            color: #2A6132;
            text-decoration: none;
            text-transform: uppercase;
        }
        .fx-eor-mini-basket-link:hover { color: #1F3A24; text-decoration: underline; }
        /* v4.19.46 — Clear all button + actions wrapper. The
         * actions container holds the Clear All button + the View
         * basket link on the right side of the footer. Stacks
         * vertically on small viewports so the link doesn't get
         * crammed against the total. */
        .fx-eor-mini-basket-actions {
            display: flex;
            align-items: center;
            gap: 10px;
        }
        .fx-eor-mini-basket-clear-all {
            background: transparent;
            border: 0;
            color: #B85F5F;
            font-size: 11px;
            font-weight: 600;
            letter-spacing: 0.5px;
            text-transform: uppercase;
            cursor: pointer;
            padding: 4px 6px;
            font-family: inherit;
            border-radius: 3px;
            transition: background 0.12s, color 0.12s;
        }
        .fx-eor-mini-basket-clear-all:hover {
            background: #FFEAEA;
            color: #8B3F3F;
        }
        /* v4.19.57 F-16 — in-popup Add to Basket commit button. Uses
         * #2A6132 sage-green (brand "PAY NOW" / primary CTA colour) so
         * it visually claims the primary action role inside the popup.
         * Sized smaller than the page-level CTA at L7196 because it
         * sits inline next to Clear all + View basket links rather than
         * being the page's hero action. */
        .fx-eor-mini-basket-add {
            background: #2A6132;
            border: 0;
            color: #fff;
            font-size: 11px;
            font-weight: 600;
            letter-spacing: 0.5px;
            text-transform: uppercase;
            cursor: pointer;
            padding: 8px 14px;
            font-family: 'Jost', sans-serif;
            border-radius: 3px;
            transition: background 0.12s;
        }
        .fx-eor-mini-basket-add:hover:not(:disabled) {
            background: #1F3A24;
        }
        .fx-eor-mini-basket-add:disabled {
            opacity: 0.4;
            cursor: not-allowed;
            background: #6B8B6F;
        }
        /* v4.19.65 — Hide the small "Add to Basket →" commit button in the
         * INLINE mini-basket position (on the product page). The inline
         * basket already has a page-level CTA (#fx-eor-cta-btn at L7732)
         * that does the same job and is the visual primary action, so the
         * small button next to "Clear all / View basket" is redundant there
         * and clutters the row.
         *
         * Inside the View & Edit MODAL (#fx-eor-basket-modal-body), the
         * page-level CTA isn't visible — the modal covers it — so the small
         * button IS the user's commit action and needs to remain. The same
         * mini-basket DOM gets teleported between the two positions
         * (v4.19.35), so a location-aware CSS rule is the cleanest split:
         * one rule, no JS changes, no extra state to maintain.
         *
         * The :not([hidden]) selector honours the existing JS toggle at
         * L12275/L12282 (button hidden when there are no pending items,
         * shown when there are). So the full behaviour matrix is:
         *   - Inline + pending items     → hidden (this rule)
         *   - Inline + no pending items  → hidden (browser default for [hidden])
         *   - Modal + pending items      → visible (modal rule below)
         *   - Modal + no pending items   → hidden (browser default for [hidden]) */
        .fx-eor-mini-basket-add { display: none; }
        #fx-eor-basket-modal-body .fx-eor-mini-basket-add:not([hidden]) {
            display: inline-block;
        }
        @media (max-width: 600px) {
            .fx-eor-mini-basket-actions { flex-direction: column; align-items: flex-end; gap: 4px; }
        }

        @media (max-width: 600px) {
            .fx-eor-mini-basket-row { grid-template-columns: 40px 1fr auto; gap: 8px; padding: 6px 8px; }
            .fx-eor-mini-basket-row-img { width: 40px; height: 40px; }
            .fx-eor-mini-basket-row-name { font-size: 12px; }
            .fx-eor-mini-basket-row-subtotal { font-size: 12px; min-width: 42px; }
        }
        .fx-eor-cta-hint { font-size: 10px; color: #4A5F4F; margin-top: 10px; letter-spacing: 0.8px; text-transform: uppercase; }
        /* v4.7.33: placeholder content for sections not yet populated.
         * Clean, calm "coming soon" treatment — sets expectation without
         * looking broken. Centred icon + message + sub-text. */
        .fx-eor-placeholder { padding: 36px 24px; text-align: center; background: #fff; border: 1px dashed #85C727; border-radius: 5px; }
        .fx-eor-placeholder-icon { font-size: 18px; color: #85C727; letter-spacing: 4px; margin-bottom: 10px; }
        .fx-eor-placeholder-msg { font-family: 'Cormorant Garamond', Georgia, serif; font-size: 20px; color: #1F3A24; margin: 0 0 6px; font-weight: 500; }
        .fx-eor-placeholder-sub { font-size: 11px; color: #4A5F4F; letter-spacing: 0.5px; margin: 0; font-family: 'Jost', sans-serif; }
        /* v4.7.37: Floral Bunches variety menu — text-link navigation index.
         * Mirrors the FBF mega menu styling: 3-column grid, uppercase items
         * with letter-spacing, sage hairline dividers, dark-green hover state.
         * Mobile drops to 1 column. No images, no cards — pure navigation. */
        .fx-eor-variety-list { list-style: none; padding: 0; margin: 0; display: grid; grid-template-columns: repeat(3, 1fr); gap: 0 24px; }
        /* v4.25.51 — "Choose Your Flowers By Variety" image gallery. Overrides
         * the text-list layout when .fx-eor-variety-gallery is present: a
         * responsive tile grid (auto-fill, min 150px → ~3 cols desktop, 2 on
         * tablet, 1 on narrow mobile, matching the EOR card feel). Each tile is
         * a best-seller image + a serif (Cormorant Garamond) title in the same
         * style as product titles. Links unchanged — the whole tile is the
         * existing <a> to the correct variety URL. */
        .fx-eor-variety-gallery { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 16px; }
        .fx-eor-variety-gallery .fx-eor-variety-item { border-bottom: 0; }
        .fx-eor-variety-gallery .fx-eor-variety-tile {
            flex-direction: column; align-items: stretch; justify-content: flex-start;
            padding: 0; gap: 0; border: 1px solid #C8DEC0; border-radius: 8px; overflow: hidden;
            background: #fff; text-transform: none; letter-spacing: normal;
        }
        .fx-eor-variety-gallery .fx-eor-variety-tile:hover { border-color: #85C727; box-shadow: 0 2px 10px rgba(31,58,36,0.10); transform: translateY(-2px); }
        .fx-eor-variety-thumb { position: relative; display: block; width: 100%; aspect-ratio: 1 / 1; background: #F4F7EF; overflow: hidden; }
        .fx-eor-variety-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
        .fx-eor-variety-thumb .fx-eor-variety-bunches-peak-badge { position: absolute; top: 6px; left: 6px; font-size: 16px; }
        .fx-eor-variety-caption { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px; padding: 10px 12px; text-align: center; width: 100%; }
        .fx-eor-variety-gallery .fx-eor-variety-tile,
        .fx-eor-variety-gallery .fx-eor-variety-tile:hover,
        .fx-eor-variety-gallery .fx-eor-variety-name,
        .fx-eor-variety-gallery .fx-eor-variety-link { text-decoration: none !important; }
        .fx-eor-variety-gallery .fx-eor-variety-name {
            display: block; flex: none; width: 100%;
            font-family: 'Cinzel', 'Cormorant Garamond', Georgia, serif;
            font-weight: 500; font-size: 15px;
            color: #1F3A24; line-height: 1.2;
            text-transform: uppercase; letter-spacing: 0.5px;
            text-align: center; text-decoration: none;
            /* Wrap at SPACES/word boundaries first (so "CARNATIONS - RED" breaks
             * cleanly between words, never mid-word). overflow-wrap only splits a
             * single word if it genuinely can't fit (e.g. CHRYSANTHEMUMS, which
             * has no break point). NB: do NOT use word-break:break-word or
             * hyphens here — they force ugly mid-word breaks like "CARNATI/ONS". */
            overflow-wrap: break-word;
            word-break: normal;
        }
        .fx-eor-variety-gallery .fx-eor-variety-arrow { display: none; }
        .fx-eor-variety-gallery .fx-eor-variety-returns { display: block; font-family: 'Jost', sans-serif; font-size: 10px; font-weight: 500; color: #9a6a00; letter-spacing: 0.3px; margin-top: 2px; }
        /* v4.25.51 — cap the gallery at 30 tiles for load speed (matches the
         * EOR 30-rule); tiles beyond the cap are hidden until "Show all". */
        .fx-eor-variety-gallery.is-capped .fx-eor-variety-item--beyond-cap { display: none; }
        .fx-eor-variety-pagination { margin-top: 16px; text-align: center; }
        .fx-eor-variety-item { border-bottom: 1px solid #C8DEC0; }
        .fx-eor-variety-link { display: flex; align-items: center; justify-content: space-between; padding: 11px 4px; color: #1F3A24; text-decoration: none; font-family: 'Jost', sans-serif; font-size: 12px; font-weight: 500; letter-spacing: 1.2px; text-transform: uppercase; transition: all 0.12s; gap: 8px; }
        .fx-eor-variety-link:hover { color: #2A6132; padding-left: 10px; padding-right: 10px; background: linear-gradient(90deg, transparent 0%, #E8F7D5 50%, transparent 100%); }
        .fx-eor-variety-name { flex: 1; }
        .fx-eor-variety-arrow { color: #C8DEC0; font-size: 14px; opacity: 0; transform: translateX(-4px); transition: all 0.15s; }
        .fx-eor-variety-link:hover .fx-eor-variety-arrow { opacity: 1; transform: translateX(0); color: #2A6132; }
        /* v4.7.39: colour swatch dot for the By Colour section. Small filled
         * circle with a soft mint border so even white sits visible against
         * the white card body. Sits to the left of the name. */
        .fx-eor-colour-dot {
            display: inline-block;
            width: 16px;
            height: 16px;
            border-radius: 50%;
            border: 1px solid #C8DEC0;
            box-shadow: 0 1px 2px rgba(31, 58, 36, 0.08);
            flex-shrink: 0;
            margin-right: 12px;
            vertical-align: middle;
            transition: transform 0.15s;
        }
        .fx-eor-variety-link:hover .fx-eor-colour-dot { transform: scale(1.12); border-color: #2A6132; }
        .fx-eor-basket-bar { position: fixed; bottom: 0; left: 0; right: 0; background: #1F3A24; color: #fff; padding: 12px 28px; display: flex; align-items: center; justify-content: space-between; box-shadow: 0 -8px 24px -10px rgba(0,0,0,0.2); z-index: 99999; transform: translateY(110%); transition: transform 0.3s ease-out; font-family: 'Jost', system-ui, sans-serif; }
        .fx-eor-basket-bar.visible { transform: translateY(0); }
        .fx-eor-bb-summary { display: flex; align-items: center; gap: 14px; }
        .fx-eor-bb-count { background: #85C727; color: #1F3A24; width: 32px; height: 32px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-weight: 700; font-size: 14px; }
        .fx-eor-bb-text { font-size: 13px; }
        .fx-eor-bb-text strong { color: #85C727; font-weight: 500; }
        .fx-eor-bb-text .fx-eor-bb-sub { font-size: 11px; color: rgba(255,255,255,0.65); margin-top: 2px; }
        .fx-eor-bb-actions { display: flex; gap: 10px; align-items: center; }
        .fx-eor-bb-clear { color: rgba(255,255,255,0.6); background: transparent; border: 0; cursor: pointer; font-size: 12px; padding: 6px 10px; font-family: inherit; }
        /* v4.19.35 — View & Edit button. Outline style to sit between the
         * subtle "Clear" link and the prominent green "Add to Basket". */
        .fx-eor-bb-view {
            background: transparent;
            color: #fff;
            border: 1px solid rgba(255,255,255,0.45);
            padding: 9px 16px;
            font-size: 12px;
            font-weight: 500;
            letter-spacing: 0.8px;
            text-transform: uppercase;
            cursor: pointer;
            border-radius: 3px;
            font-family: inherit;
            transition: background 0.15s, border-color 0.15s;
        }
        .fx-eor-bb-view:hover {
            background: rgba(255,255,255,0.1);
            border-color: rgba(255,255,255,0.75);
        }
        /* v4.19.35 — Basket modal (View & Edit popup). The mini-basket DOM
         * teleports in/out, so the modal panel itself only styles the
         * surround (backdrop, header, scroll container). */
        .fx-eor-basket-modal {
            position: fixed;
            inset: 0;
            z-index: 100000;
            display: flex;
            align-items: center;
            justify-content: center;
            padding: 24px;
            box-sizing: border-box;
            font-family: 'Jost', system-ui, -apple-system, sans-serif;
        }
        .fx-eor-basket-modal[hidden] { display: none; }
        .fx-eor-basket-modal-backdrop {
            position: absolute;
            inset: 0;
            background: rgba(31, 58, 36, 0.55);
            backdrop-filter: blur(2px);
            -webkit-backdrop-filter: blur(2px);
            cursor: pointer;
        }
        .fx-eor-basket-modal-panel {
            position: relative;
            background: #fff;
            border-radius: 8px;
            box-shadow: 0 12px 48px -8px rgba(0,0,0,0.35);
            width: 100%;
            max-width: 560px;
            max-height: 90vh;
            display: flex;
            flex-direction: column;
            overflow: hidden;
            animation: fx-eor-basket-modal-in 0.18s ease-out;
        }
        @keyframes fx-eor-basket-modal-in {
            from { transform: scale(0.96); opacity: 0; }
            to   { transform: scale(1);    opacity: 1; }
        }
        .fx-eor-basket-modal-header {
            display: flex;
            align-items: center;
            justify-content: space-between;
            padding: 16px 22px;
            border-bottom: 1px solid #E8F0E0;
            background: linear-gradient(180deg, #FAFFF8 0%, #F4F7EF 100%);
        }
        .fx-eor-basket-modal-title {
            font-size: 16px;
            font-weight: 600;
            color: #1F3A24;
            margin: 0;
            font-family: 'Cormorant Garamond', serif;
            letter-spacing: 0.3px;
        }
        .fx-eor-basket-modal-close {
            background: transparent;
            border: 0;
            color: #1F3A24;
            font-size: 26px;
            line-height: 1;
            cursor: pointer;
            padding: 4px 10px;
            border-radius: 3px;
            transition: background 0.15s;
        }
        .fx-eor-basket-modal-close:hover { background: #E8F7D5; }
        .fx-eor-basket-modal-body {
            padding: 16px 22px;
            overflow-y: auto;
            flex: 1;
            min-height: 0;
        }
        /* While the mini-basket is teleported into the modal, override its
         * inline-collapse styling so it shows fully expanded. */
        .fx-eor-basket-modal-body .fx-eor-mini-basket {
            border: 0;
            padding: 0;
            margin: 0;
            background: transparent;
        }
        /* Hide the show/hide toggle when mini-basket is inside the modal —
         * the modal IS the open state. */
        .fx-eor-basket-modal-body .fx-eor-mini-basket-toggle { display: none; }
        @media (max-width: 600px) {
            .fx-eor-basket-modal { padding: 12px; }
            .fx-eor-basket-modal-panel { max-height: 96vh; }
            .fx-eor-basket-modal-header { padding: 12px 16px; }
            .fx-eor-basket-modal-body { padding: 12px 16px; }
            /* Hide View button label in favour of compact icon on small screens. */
            .fx-eor-bb-view { padding: 9px 12px; font-size: 11px; letter-spacing: 0.4px; }
        }
        .fx-eor-bb-add { background: #85C727; color: #1F3A24; border: 0; padding: 12px 26px; font-size: 13px; font-weight: 600; letter-spacing: 1px; text-transform: uppercase; cursor: pointer; border-radius: 3px; font-family: inherit; }
        .fx-eor-bb-add:hover { background: #95D837; }
        .fx-eor-bb-add:disabled { opacity: 0.6; cursor: wait; }

        /* v4.7.67: close button on basket bar — dismisses the bar from view.
         * Absolute-positioned at top-right of the bar (bar is position: fixed
         * so this anchors within it). Works on both desktop and mobile
         * layouts (mobile stacks summary + actions vertically; close button
         * floats above both).
         *
         * Clicking removes .visible class from the bar → bar slides down via
         * the existing transform: translateY(110%) default state. Accordion's
         * updateBasketBar() will re-add .visible on next user interaction
         * because barCommitted is still true — so the bar comes back when
         * the user ticks/unticks something. */
        .fx-eor-bb-close {
            position: absolute;
            top: 6px;
            right: 8px;
            background: transparent;
            border: 0;
            color: rgba(255,255,255,0.55);
            font-size: 22px;
            cursor: pointer;
            width: 32px;
            height: 32px;
            display: flex;
            align-items: center;
            justify-content: center;
            line-height: 1;
            border-radius: 50%;
            transition: all 0.12s;
            padding: 0;
            font-family: inherit;
            z-index: 1;
            -webkit-tap-highlight-color: transparent;
        }
        .fx-eor-bb-close:hover {
            color: #fff;
            background: rgba(255,255,255,0.12);
        }
        .fx-eor-bb-close:active {
            background: rgba(255,255,255,0.2);
        }
        @media (max-width: 700px) {
            /* ═══════════════════════════════════════════════════════════════
             * v4.7.47: Mobile @media — the structural 50/50 redesign now
             * lives in the base styles (applied desktop + mobile alike).
             * This block only tightens sizes/spacing for narrow viewports:
             * full-width cards, smaller fonts, smaller tick + badge, denser
             * stack. Card layout itself is shared with desktop. */

            .fx-eor-wrap { padding: 0 14px; margin: 20px auto; }
            /* v0.2.67 — THE STACK FITS EVERY PHONE (RE-APPLIED on the Friday base, v0.2.70; CSS only, belt over the enforcer): measured 375px — the wrap grew to 502px inside the theme's flex row (min-width:auto) and 1fr tracks could not shrink; these let two columns always divide the real width. Proven live 320/375/430. */
            .fx-eor-wrap, #fx-eor-wrap { display: block; width: 100%; max-width: 100%; min-width: 0; flex: 1 1 100%; box-sizing: border-box; overflow-x: hidden; }
            .fx-eor-accordion, .fx-eor-acc-body, .fx-eor-grid { min-width: 0; max-width: 100%; box-sizing: border-box; }
            .fx-eor-grid.fx-eor-mcols-2, .fx-eor-grid--double { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
            .fx-eor-frontcard, .fx-eor-card-main, .fx-eor-body, .fx-eor-img-link, .fx-eor-variations, .fx-eor-bottom { min-width: 0; max-width: 100%; box-sizing: border-box; }
            .fx-eor-frontcard .fx-eor-img { max-width: 100%; height: auto; }
            .fx-eor-preview-expand-btn.fx-eor-preview-expand-btn--inline { width: 100%; max-width: 100%; margin-left: 0; margin-right: 0; box-sizing: border-box; }
            /* v4.25.70 — show the mobile 1/2 column selector at the top of the
             * EOR; hide the desktop View cluster on mobile so only one shows. */
            .fx-eor-view-wrap { display: none; }
            .fx-eor-mview-wrap {
                display: flex; align-items: center; gap: 6px;
                justify-content: flex-end; margin: 0 0 12px; font-family: inherit;
            }
            .fx-eor-mview-btn {
                background: #FAFAF8; border: 1.5px solid #D8E8D0; color: #1F3A24;
                padding: 6px 12px; border-radius: 999px; line-height: 1; cursor: pointer;
                display: inline-flex; align-items: center; justify-content: center;
                height: 28px; box-sizing: border-box; transition: background 0.12s, border-color 0.12s;
            }
            .fx-eor-mview-btn:hover { background: #E8F7D5; border-color: #85C727; }
            .fx-eor-mview-btn.is-active { background: #2A6132; border-color: #2A6132; }
            .fx-eor-mview-btn.is-active .fx-eor-view-icon--1col::before,
            .fx-eor-mview-btn.is-active .fx-eor-view-icon--2col::before { background: #fff; }
            .fx-eor-grid { grid-template-columns: 1fr; gap: 10px; max-height: 760px; }
            /* v4.25.69 — mobile column count for ALL EOR card grids, driven by
             * the operator setting (wrap class). Default 2. The slider
             * (.fx-eor-top-slider-track) is NOT a .fx-eor-grid, so it's
             * untouched. The title text rules (whole words, shrink to fit) are
             * applied for the narrower 2/3-col cards. */
            /* v4.25.70 — mobile column views: 1 or 2.
             *   mcols-1 = original layout, untouched (image left / text right).
             *   mcols-2 = vertical card: image fills the column on top, then the
             *             title + a "View" button; the variations + price + Add
             *             button stay hidden until the customer taps View
             *             (.fx-eor-mexpanded), so the grid stays tidy.
             * Scoped to .fx-eor-grid — the slider (.fx-eor-top-slider-track)
             * is never matched. The mcols-1 default keeps the proven layout. */
            .fx-eor-grid.fx-eor-mcols-1 { grid-template-columns: 1fr; }

            /* v4.25.72 — cleaner 2-col: a single thin lime-lined grid. The grid
             * background is lime and the 1px gaps show through as gridlines;
             * each card is a flush white cell with no own border/radius, so the
             * frame-wrapping + padding is gone and products slot neatly in. */
            .fx-eor-grid.fx-eor-mcols-2 {
                grid-template-columns: repeat(2, 1fr);
                gap: 1px; background: #85C727;
                border: 0; border-radius: 6px;
                overflow: hidden; padding: 1px; max-height: none;
            }
            .fx-eor-grid.fx-eor-mcols-2 .fx-eor-frontcard {
                border: 0; border-radius: 0; background: #fff;
                box-shadow: none; transition: none;
            }
            /* v4.25.76 — no green fill in empty space: if the last row has a
             * single (odd) card, span it across both columns so the lime grid
             * background never shows through an empty cell. */
            .fx-eor-grid.fx-eor-mcols-2 > .fx-eor-frontcard:last-child:nth-child(odd) { grid-column: 1 / -1; }
            .fx-eor-grid.fx-eor-mcols-2 .fx-eor-frontcard:hover { transform: none; box-shadow: none; }
            /* image on top, content stacked below (reuses the card-main grid) */
            .fx-eor-grid.fx-eor-mcols-2 .fx-eor-card-main { grid-template-columns: 1fr; }
            .fx-eor-grid.fx-eor-mcols-2 .fx-eor-img-link { display: block; width: 100%; }
            .fx-eor-grid.fx-eor-mcols-2 img.fx-eor-img { width: 100%; height: auto; aspect-ratio: 1 / 1; object-fit: cover; display: block; }
            .fx-eor-grid.fx-eor-mcols-2 .fx-eor-body { padding: 6px 8px 8px; gap: 5px; }
            .fx-eor-grid.fx-eor-mcols-2 .fx-eor-body h4 { font-size: 14px; padding-right: 4px; text-align: center; }
            /* collapsed: hide variations, price/qty row and the Add button */
            .fx-eor-grid.fx-eor-mcols-2 .fx-eor-variations,
            .fx-eor-grid.fx-eor-mcols-2 .fx-eor-bottom,
            .fx-eor-grid.fx-eor-mcols-2 .fx-eor-card-add,
            .fx-eor-grid.fx-eor-mcols-2 .fx-eor-notify-wrap { display: none; }
            /* the View toggle — mid green (midpoint of mint + lime), instant.
             * touch-action removes the mobile tap delay so it opens at once. */
            .fx-eor-grid.fx-eor-mcols-2 .fx-eor-mview {
                display: block; width: 100%; margin-top: 1px; padding: 7px 0;
                background: #B6DF7E; color: #1F3A24; border: 0;
                border-radius: 5px; font-family: 'Jost', sans-serif; font-size: 12px;
                font-weight: 600; letter-spacing: 0.4px; text-transform: uppercase;
                cursor: pointer; touch-action: manipulation; transition: none;
            }
            .fx-eor-grid.fx-eor-mcols-2 .fx-eor-mview:hover { background: #A6D466; }
            /* v4.25.73 — once expanded, the View button is gone (no Close/Hide). */
            .fx-eor-grid.fx-eor-mcols-2 .fx-eor-frontcard.fx-eor-mexpanded .fx-eor-mview { display: none; }
            /* expanded: reveal variations + price + Add (button stays mid-green) */
            .fx-eor-grid.fx-eor-mcols-2 .fx-eor-frontcard.fx-eor-mexpanded .fx-eor-variations,
            .fx-eor-grid.fx-eor-mcols-2 .fx-eor-frontcard.fx-eor-mexpanded .fx-eor-bottom,
            .fx-eor-grid.fx-eor-mcols-2 .fx-eor-frontcard.fx-eor-mexpanded .fx-eor-card-add,
            .fx-eor-grid.fx-eor-mcols-2 .fx-eor-frontcard.fx-eor-mexpanded .fx-eor-notify-wrap { display: flex; }
            .fx-eor-grid.fx-eor-mcols-2 .fx-eor-frontcard.fx-eor-mexpanded .fx-eor-variations { flex-wrap: wrap; }
/* v0.2.445, row 23j47 (A) - the opened card's pill box stops at about three rows of the touch-sized pills (3 x 32px + gaps) and scrolls inside itself (the drawn 3px line); it was a fixed 72px, two rows, and on a card with eleven sizes the rest was out of sight; a few pills take no more room than they need. The pills' own look and size are untouched. */            .fx-eor-grid.fx-eor-mcols-2 .fx-eor-frontcard.fx-eor-mexpanded .fx-eor-variations { height: auto; max-height: 106px; overflow-y: auto; overflow-x: hidden; }
            .fx-eor-grid.fx-eor-mcols-2 .fx-eor-frontcard.fx-eor-mexpanded .fx-eor-card-add { display: block; }

            /* v4.20.6 — defensive mobile overflow safety net.
             *
             * Forces the EOR wrap to never exceed its parent on mobile,
             * regardless of whether it's in standalone or --inline mode.
             * Then ensures every direct child container has box-sizing
             * border-box + max-width 100% so padded children fit. The
             * .fx-eor-acc-title gets min-width: 0 (the classic flex-item
             * overflow fix) and h3 gets overflow-wrap anywhere so the
             * long accordion headings wrap rather than push the container
             * wider than the viewport. */
            .fx-eor-wrap,
            .fx-eor-wrap--inline {
                max-width: 100%;
                box-sizing: border-box;
            }
            .fx-eor-accordion,
            .fx-eor-acc-header,
            .fx-eor-acc-body {
                max-width: 100%;
                box-sizing: border-box;
            }
            .fx-eor-acc-title {
                min-width: 0;
                flex: 1 1 auto;
            }
            /* v4.20.17 — Prefer word-boundary wraps over mid-word
             * breaks. James reported headings like "Flower Subscripti
             * ons" / "Plant Subscriptio ns" breaking mid-syllable on
             * mobile (image 2026-05-19 14:37). The pre-v4.20.17 rules
             * used `word-break: break-word` + `overflow-wrap: anywhere`
             * which let the browser break inside words AT THE FIRST
             * AVAILABLE POSITION even when the word would otherwise
             * fit on the next line. Switched to `word-break: normal`
             * (only break at word boundaries — spaces, hyphens) +
             * `overflow-wrap: break-word` (allow mid-word break ONLY
             * as a last resort when the word is wider than the
             * container). Result: "Subscriptions" wraps onto its own
             * line as a whole word instead of breaking mid-syllable. */
            .fx-eor-acc-title h3 {
                overflow-wrap: break-word;
                word-break: normal;
                hyphens: none;
            }
            .fx-eor-preview {
                overflow-wrap: break-word;
                word-break: normal;
            }
            /* v4.20.17 — Hide pills on mobile.
             *
             * James (2026-05-19 14:54): "remove those pills on mobile
             * view. They just repeat the title." Several pills are
             * identical to their adjacent heading (INDOOR PLANTS pill →
             * "Indoor Plants" h3; FLOWER SUBSCRIPTIONS pill → "Flower
             * Subscriptions" h3; PLANT SUBSCRIPTIONS pill → "Plant
             * Subscriptions" h3). Others closely paraphrase (BY COLOUR
             * pill → "Choose Your Bouquets By Colour"). On desktop the
             * pills work as visual category markers, but on mobile —
             * where everything stacks vertically — they're redundant
             * noise eating ~30% of the header row width.
             *
             * display:none !important so the heading + preview text
             * gets the full row to wrap into. Reverts cleanly on
             * desktop because the rule is inside a 700px media query.
             *
             * Supersedes the v4.20.15 wrap-the-pill rules — those
             * preserved the pill but made it narrower; James decided
             * the pill is unnecessary on mobile altogether. */
            .fx-eor-pill {
                display: none !important;
            }
            /* v4.20.5 elements — keep content within viewport. */
            .fx-eor-variety-list--inseason .fx-eor-variety-link {
                max-width: 100%;
                box-sizing: border-box;
            }
            .fx-eor-variety-list--inseason .fx-eor-variety-row {
                min-width: 0;
                max-width: 100%;
            }
            .fx-eor-variety-list--inseason .fx-eor-variety-name {
                min-width: 0;
                overflow-wrap: anywhere;
                word-break: break-word;
            }
            .fx-eor-variety-blurb,
            .fx-eor-variety-sourcing,
            .fx-eor-variety-sourcing-text {
                max-width: 100%;
                overflow-wrap: anywhere;
                word-break: break-word;
            }
            .fx-eor-also-available,
            .fx-eor-also-available-list {
                max-width: 100%;
                box-sizing: border-box;
                overflow-wrap: anywhere;
                word-break: break-word;
            }
            /* v4.20.18 — Also-available drops from 3-col (desktop) to
             * 2-col on mobile so Phalaenopsis Orchids / Chrysanthemums
             * and other long variety names breathe. Inherits all other
             * styling from the base .fx-eor-also-available-list rule. */
            .fx-eor-also-available-list {
                grid-template-columns: repeat(2, 1fr);
                gap: 4px 10px;
            }
            /* Floral Bunches: ensure peak emoji + returns pill don't push
             * the link wider than its container. */
            .fx-eor-variety-item {
                max-width: 100%;
                box-sizing: border-box;
            }
            .fx-eor-variety-item .fx-eor-variety-name {
                min-width: 0;
                overflow-wrap: anywhere;
                word-break: break-word;
            }

            /* Accordion shell — drop horizontal padding so cards run flush */
            .fx-eor-acc-header { padding: 14px 16px; gap: 10px; }
            .fx-eor-acc-title h3 { font-size: 18px; }
            .fx-eor-acc-body { padding: 16px 0 18px; }
            .fx-eor-intro { margin-left: 14px; margin-right: 14px; }

            /* Body density */
            .fx-eor-body { padding: 6px 9px 9px; gap: 4px; }
            .fx-eor-body h4 { font-size: 15px; padding-right: 30px; margin: 0 0 4px; }

            /* Smaller currently-viewing badge */
            .fx-eor-frontcard[data-current="1"] .fx-eor-body::before {
                font-size: 9px;
                padding: 3px 7px;
                margin-bottom: 3px;
            }

            /* Smaller tick overlay — targets the .fx-eor-check-col real element
             * (was the ::after pseudo before v4.7.48) */
            .fx-eor-check-col {
                top: 6px;
                right: 6px;
                width: 24px;
                height: 24px;
            }
            /* v4.7.51: invisible ::before pseudo extends the CLICK area without
             * changing the visible tick. With -12px inset on each side, the
             * tappable zone becomes 48x48 (4× the area) while the rendered
             * sage-bordered box stays 24x24. Pseudo lives inside the check-col's
             * box, so taps anywhere on the 48x48 area register on the parent
             * .fx-eor-check-col element and trigger the existing click handler
             * (line ~2964: checkCol.addEventListener with stopPropagation).
             * z-index:5 on the check-col puts the pseudo above the title's
             * <a class="fx-eor-name-link"> link beneath, so near-misses with
             * fat thumbs select the card instead of navigating to the product. */
            .fx-eor-check-col::before {
                content: "";
                position: absolute;
                top: -12px;
                right: -12px;
                bottom: -12px;
                left: -12px;
                background: transparent;
            }
            .fx-eor-check::after {
                font-size: 13px;
            }

            /* Variation pills + price row + qty stepper tightened */
            .fx-eor-variations { gap: 3px; margin: 4px 0 6px; }
            .fx-eor-var-pill { font-size: 10px; padding: 2px 7px; }
            .fx-eor-bottom { gap: 4px; margin-top: 4px; }
            .fx-eor-price { font-size: 13px; }
            .fx-eor-qty { height: 22px; }
            .fx-eor-qty button { width: 20px; height: 20px; font-size: 12px; }
            .fx-eor-qty .fx-eor-q-input { width: 22px; font-size: 11px; }
            .fx-eor-card-add { padding: 8px 6px; font-size: 10px; margin-top: 6px; }

            /* Bottom basket bar / CTA / variety list — existing mobile overrides */
            .fx-eor-basket-bar { padding: 10px 14px; flex-direction: column; gap: 8px; align-items: stretch; }
            .fx-eor-bb-add { width: 100%; }
            .fx-eor-cta { padding: 14px 14px; margin-top: 14px; }
            .fx-eor-cta-btn { padding: 14px 24px; font-size: 12px; }
            /* v4.7.37: variety list collapses to single column on mobile. */
            .fx-eor-variety-list { grid-template-columns: 1fr; gap: 0; }
            .fx-eor-variety-gallery { grid-template-columns: repeat(2, 1fr); gap: 12px; }
            .fx-eor-variety-gallery .fx-eor-variety-name { font-size: 14px; letter-spacing: 0.5px; }
            .fx-eor-variety-link { padding: 13px 4px; font-size: 13px; }
        }

        /* ═══ TOP SLIDER CSS — v4.7.64 (ACCORDION MARKUP, SCOPED OVERRIDES) ═
         *
         * The slider cards reuse accordion's `.fx-eor-frontcard` markup
         * verbatim (same class names, same structure). All accordion CSS
         * rules — card visuals, tick check column, variation pills, qty
         * stepper, Add to Basket button — apply unchanged.
         *
         * This block defines only:
         *   1. The slider's OUTER container (wrap, header, track) — these
         *      have unique `.fx-eor-top-slider-*` classes, no conflict with
         *      accordion.
         *   2. Slider-specific OVERRIDES of card behaviour via
         *      `#fx-eor-top-slider .fx-eor-frontcard` selectors. These add:
         *        - card width clamping (calc(100vw - 56px))
         *        - scroll-snap alignment
         *        - card-main aspect-ratio (locks height to image's natural aspect)
         *        - body overflow-y: auto (vertical scroll for many-variation cards)
         *        - hide empty card-top on non-current cards (no white space)
         *      These overrides cascade only over cards INSIDE the slider —
         *      accordion cards remain untouched.
         *
         * v4.7.58 width disaster is prevented by:
         *   .fx-eor-top-slider-wrap { width: 100%; overflow: hidden; padding: 0 14px; }
         *   #fx-eor-top-slider .fx-eor-frontcard { flex: 0 0 calc(100vw - 56px); }
         * The wrap clamps; cards use viewport-anchored widths; the track scrolls
         * horizontally within the clamped wrap. */
        .fx-eor-top-slider-wrap {
            display: none;
            width: 100%;
            box-sizing: border-box;
            margin: 14px 0 18px;
            padding: 0 10px;
            overflow: hidden;
            font-family: 'Jost', system-ui, -apple-system, sans-serif;
            color: #1A1A1A;
        }
        .fx-eor-top-slider-header {
            display: flex;
            align-items: baseline;
            justify-content: space-between;
            padding: 0 0 8px;
        }
        .fx-eor-top-slider-title {
            font-family: 'Cormorant Garamond', Georgia, serif;
            font-weight: 500;
            font-size: 18px;
            color: #1F3A24;
        }
        .fx-eor-top-slider-hint {
            font-size: 10px;
            color: #4A5F4F;
            letter-spacing: 0.8px;
            text-transform: uppercase;
            font-family: 'Jost', sans-serif;
        }
        .fx-eor-top-slider-track {
            display: flex;
            gap: 10px;
            overflow-x: auto;
            overflow-y: hidden;
            scroll-snap-type: x mandatory;
            -webkit-overflow-scrolling: touch;
            scrollbar-width: none;
            padding: 6px 0 14px;
            align-items: stretch;
            /* v4.16.1 — touch-action: pan-x tells the browser horizontal
             * motion on the track is for scrolling. Without this, taps
             * landing on variation pills / qty buttons / Add-to-Basket
             * inside cards were consumed as taps before the browser
             * recognised the horizontal pan gesture, so users could only
             * swipe by starting their finger on the image area. With
             * pan-x set on the parent, the browser commits to "this
             * touch is a scroll" once horizontal motion exceeds its
             * native threshold (~5px on iOS/Android), cancelling any
             * pending tap on the child. Stationary touches still fire
             * clicks normally so buttons remain tappable.
             * v0.2.408, row 23f98 — THE FROZEN-SCROLL VIRUS: pan-x ALONE
             * tells the phone a finger landing on this strip may ONLY
             * move sideways, so a vertical scroll that STARTS on the strip
             * is refused and the page reads as frozen (the same-day page
             * prints its two rails with this very class, as a grid that
             * fills the screen). The same cure as v4.20.43 below: pan-y
             * pan-x — the browser routes by dominant direction, sideways
             * to this track, up and down to the page. The contract card is
             * docs/contracts/flowla-explores/sameday-touch-and-scroll.md. */
            touch-action: pan-y pan-x;
            /* v4.7.68: scroll-padding ensures snap landing position respects
             * the wrap's outer padding. Without this, cards snap with their
             * left edge at the track's content-box left (which is at the
             * wrap's padding-left position) but subpixel rounding can
             * leave the card's right edge slightly past the visible area,
             * chopping a few pixels off. Setting scroll-padding-left: 0
             * explicitly anchors the snap point. */
            scroll-padding: 0;
        }
        .fx-eor-top-slider-track::-webkit-scrollbar { display: none; }
        /* v0.2.73 — THE ONE VIEW ALL: button + expanded grid + chunk law shared with the landing slider (includes/eor-viewall.php). */
        /* ── THE ONE VIEW ALL (eor-viewall.php) ── */
.fx-eor-ts-viewall { display: block; margin: 8px auto 4px; background: #2A6132 !important; color: #fff !important; /* v0.2.104 — the forest-green sweep */ border: none !important; border-radius: 8px; font-family: 'Jost', system-ui, sans-serif; font-size: 15px; font-weight: 600; letter-spacing: 1.2px; text-transform: uppercase; padding: 12px 34px; cursor: pointer; text-align: center; transition: background .15s; }
.fx-eor-ts-viewall:hover { background: #1F3A24 !important; color: #fff !important; }
.fx-eor-ts-viewall.is-loading { opacity: .7; pointer-events: none; }
@media (min-width: 701px) { .fx-eor-ts-va--mobile-only { display: none; } }
.fx-eor-ts-hidden { display: none !important; }
.fx-eor-ts-sentinel { display: none; text-align: center; font-family: 'Jost', system-ui, sans-serif; font-size: 12px; color: #4A5F4F; letter-spacing: .4px; padding: 10px 0 2px; }
#fx-eor-top-slider.fx-eor-ts-expanded .fx-eor-ts-sentinel { display: block; }
#fx-eor-top-slider.fx-eor-ts-expanded { height: auto !important; max-height: none !important; overflow: visible !important; }
#fx-eor-top-slider.fx-eor-ts-expanded .fx-eor-top-slider-hint, #fx-eor-top-slider.fx-eor-ts-expanded .fx-ls-arrow { display: none !important; }
#fx-eor-top-slider.fx-eor-ts-expanded .fx-ls-viewport { height: auto !important; max-height: none !important; overflow: visible !important; }
#fx-eor-top-slider.fx-eor-ts-expanded .fx-eor-top-slider-track { display: grid !important; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 1px; background: #85C727; padding: 1px; border-radius: 6px; overflow: hidden !important; transform: none !important; scroll-snap-type: none !important; height: auto !important; max-height: none !important; touch-action: auto !important; }
#fx-eor-top-slider.fx-eor-ts-expanded .fx-eor-top-slider-track * { touch-action: auto !important; }
#fx-eor-top-slider.fx-eor-ts-expanded .fx-eor-frontcard { flex: none !important; width: auto !important; max-width: none !important; min-width: 0 !important; margin: 0 !important; height: auto !important; scroll-snap-align: none !important; border: 0 !important; border-radius: 0 !important; background: #fff; box-shadow: none !important; transform: none !important; content-visibility: visible; contain-intrinsic-size: auto; }
#fx-eor-top-slider.fx-eor-ts-expanded .fx-eor-top-slider-track > .fx-eor-frontcard:not(.fx-eor-ts-hidden):last-of-type:nth-of-type(odd) { grid-column: 1 / -1; }
#fx-eor-top-slider.fx-eor-ts-expanded .fx-eor-card-main { grid-template-columns: 1fr; grid-template-rows: auto; height: auto !important; max-height: none !important; overflow: visible !important; }
#fx-eor-top-slider.fx-eor-ts-expanded .fx-eor-img-link { display: block; width: 100%; height: auto; }
#fx-eor-top-slider.fx-eor-ts-expanded img.fx-eor-img { width: 100%; height: auto; aspect-ratio: 1 / 1; object-fit: cover; display: block; }
#fx-eor-top-slider.fx-eor-ts-expanded .fx-eor-body { padding: 6px 8px 8px; gap: 5px; overflow: visible !important; height: auto !important; max-height: none !important; min-height: 0 !important; }
#fx-eor-top-slider.fx-eor-ts-expanded .fx-eor-slider-scroll { overflow: visible !important; height: auto !important; max-height: none !important; min-height: 0 !important; flex: 0 0 auto; }
#fx-eor-top-slider.fx-eor-ts-expanded .fx-eor-slider-scroll::after { display: none; }
#fx-eor-top-slider.fx-eor-ts-expanded .fx-eor-name-link { padding-right: 0; }
#fx-eor-top-slider.fx-eor-ts-expanded .fx-eor-body h4 { font-size: 14px; padding-right: 0; text-align: center; }
#fx-eor-top-slider.fx-eor-ts-expanded .fx-eor-mview { display: block; width: 100%; margin-top: 1px; padding: 7px 0; background: #B6DF7E; color: #1F3A24; border: 0; border-radius: 5px; font-family: 'Jost', sans-serif; font-size: 12px; font-weight: 600; letter-spacing: 0.4px; text-transform: uppercase; cursor: pointer; touch-action: manipulation; transition: none; }
#fx-eor-top-slider.fx-eor-ts-expanded .fx-eor-mview:hover { background: #A6D466; }
#fx-eor-top-slider.fx-eor-ts-expanded .fx-eor-frontcard.fx-eor-mexpanded .fx-eor-mview { display: none; }
#fx-eor-top-slider:not(.fx-eor-ts-expanded) .fx-eor-mview { display: none !important; }
@media (max-width: 700px) {
#fx-eor-top-slider.fx-eor-ts-expanded .fx-eor-frontcard:not(.fx-eor-mexpanded) .fx-eor-variations,
#fx-eor-top-slider.fx-eor-ts-expanded .fx-eor-frontcard:not(.fx-eor-mexpanded) .fx-eor-slider-footer,
#fx-eor-top-slider.fx-eor-ts-expanded .fx-eor-frontcard:not(.fx-eor-mexpanded) .fx-eor-bottom,
#fx-eor-top-slider.fx-eor-ts-expanded .fx-eor-frontcard:not(.fx-eor-mexpanded) .fx-eor-card-add,
#fx-eor-top-slider.fx-eor-ts-expanded .fx-eor-frontcard:not(.fx-eor-mexpanded) .fx-eor-notify-wrap { display: none !important; }
#fx-eor-top-slider.fx-eor-ts-expanded .fx-eor-frontcard.fx-eor-mexpanded .fx-eor-variations { display: flex; flex-wrap: wrap; }
#fx-eor-top-slider.fx-eor-ts-expanded .fx-eor-frontcard.fx-eor-mexpanded .fx-eor-slider-footer { display: flex; }
/* v0.2.437, row 23i69 — THE VIEW BUTTONS SIT ON ONE LINE (the owner, 2 Oct: "LINE THE VIEW BUTTONS AT THE BOTTOM TO RESPECT LONG TITLES ON EACH ROW"; THE TILE LAW). The two cards of a row already share one height (the grid row stretches them); what varied was WHERE the View button sat inside it - a card whose title wrapped to three lines put its button lower than its neighbour's, the neighbour's button floating up with a gap under it. Now each card is a column top to bottom, the body grows to fill it, and the View button (and, once a pair is opened, the footer) takes margin-top:auto, so it rests on the floor of the card and every View in a row sits on one line whatever the title's length. Nothing is cut, resized or added. */
#fx-eor-top-slider.fx-eor-ts-expanded .fx-eor-frontcard { display: flex; flex-direction: column; }
#fx-eor-top-slider.fx-eor-ts-expanded .fx-eor-card-main { flex: 1 1 auto; display: flex; flex-direction: column; }
#fx-eor-top-slider.fx-eor-ts-expanded .fx-eor-img-link { flex: 0 0 auto; }
#fx-eor-top-slider.fx-eor-ts-expanded .fx-eor-body { flex: 1 1 auto; display: flex; flex-direction: column; }
#fx-eor-top-slider.fx-eor-ts-expanded .fx-eor-mview { margin-top: auto; flex: 0 0 auto; }
#fx-eor-top-slider.fx-eor-ts-expanded .fx-eor-frontcard.fx-eor-mexpanded .fx-eor-slider-footer { margin-top: auto; }
}
@media (min-width: 701px) {
#fx-eor-top-slider.fx-eor-ts-expanded .fx-eor-top-slider-track { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 12px; background: transparent; padding: 0; }
/* v0.2.81 — THE LAST ROW KEEPS ITS COLUMNS (the owner, 19 Aug: the seventh card became a banner — "to match the others you would just have the three products on the same row justified to the left with a blank 1/4 in the fourth column"). The phone rule that lets a last odd card span its 2-column row is cancelled on desktop: every card keeps one column, left-justified, the rest of the row blank. */
#fx-eor-top-slider.fx-eor-ts-expanded .fx-eor-top-slider-track > .fx-eor-frontcard:not(.fx-eor-ts-hidden):last-of-type:nth-of-type(odd) { grid-column: auto; }
#fx-eor-top-slider.fx-eor-ts-expanded .fx-eor-frontcard { border: 1px solid #C2E29A !important; border-radius: 8px !important; }
#fx-eor-top-slider.fx-eor-ts-expanded .fx-eor-mview { display: none !important; }
#fx-eor-top-slider.fx-eor-ts-expanded .fx-eor-variations { display: flex; flex-wrap: wrap; }
#fx-eor-top-slider.fx-eor-ts-expanded .fx-eor-slider-footer { display: flex; }
}
/* v0.2.445, row 23j47 (A + B, the owner's phone pictures, 4 Oct 2026) - THE OPEN CARD, LAID OUT AS HE DREW IT, AND THE PILLS THAT SCROLL IN THEIR OWN BOX.
 * HIS WORDS: "why is there a big white area here ... the right hand scroll is too fat and the pills are too cramped ... the pills could display the length of the image and the add to basket elements
 * could be underneath the image and the pills - i thought we were having forest green buttons". The card an open phone shopper sees - a card in the swipe rail, and a card opened by View in the expanded
 * grid - is now ONE shape: the title across the top, the PHOTO on the left with the SIZE PILLS beside it running the photo's full height (they scroll inside their own box, the drawn 3px line, when they are
 * more than fit), and UNDER both, across the card, the price, the - 1 + quantity and ADD TO BASKET in one row (forest fill #2F5D29, white text, 9px corners; the quantity in the lime outline on the pale ground,
 * law 17). An opened card takes the whole row (it was half a row beside its partner, which is where the white area came from: the pair shared one height, the footer was pinned to the floor, and the card with fewer
 * pills was left with a gap between its pills and its price - row 23i69's pin, v0.2.437). The pills keep their v0.2.437 look and size: no pill rule is touched. Phones only (700px and under). */
@media (max-width: 700px) {
#fx-eor-top-slider.fx-eor-ts-expanded .fx-eor-frontcard.fx-eor-mexpanded { grid-column: 1 / -1; }
/* v0.2.461, row 23k60 (the owner, 07/10/2026: "same function for expand as quick view so stack and make product full width one by one just as in quick view"): the Explore Our Range grid's opened card takes the whole row, one card per row (the View button opens both cards of a row, so both stack). */
.fx-eor-grid.fx-eor-mcols-2 .fx-eor-frontcard.fx-eor-mexpanded { grid-column: 1 / -1; }
:is(#fx-eor-top-slider:not(.fx-eor-ts-expanded) .fx-eor-frontcard, #fx-eor-top-slider.fx-eor-ts-expanded .fx-eor-frontcard.fx-eor-mexpanded, .fx-eor-grid.fx-eor-mcols-2 .fx-eor-frontcard.fx-eor-mexpanded) { display: flex; flex-direction: column; }
:is(#fx-eor-top-slider:not(.fx-eor-ts-expanded) .fx-eor-frontcard, #fx-eor-top-slider.fx-eor-ts-expanded .fx-eor-frontcard.fx-eor-mexpanded, .fx-eor-grid.fx-eor-mcols-2 .fx-eor-frontcard.fx-eor-mexpanded) .fx-eor-card-main { display: grid; grid-template-columns: 60% minmax(0, 1fr); grid-template-areas: "badge badge" "title title" "img pills" "foot foot"; grid-template-rows: auto auto auto auto; column-gap: 8px; row-gap: 0; height: auto; max-height: none; overflow: visible; flex: 1 1 auto; padding: 6px 9px 9px; box-sizing: border-box; }
:is(#fx-eor-top-slider:not(.fx-eor-ts-expanded) .fx-eor-frontcard, #fx-eor-top-slider.fx-eor-ts-expanded .fx-eor-frontcard.fx-eor-mexpanded, .fx-eor-grid.fx-eor-mcols-2 .fx-eor-frontcard.fx-eor-mexpanded) .fx-eor-body, :is(#fx-eor-top-slider:not(.fx-eor-ts-expanded) .fx-eor-frontcard, #fx-eor-top-slider.fx-eor-ts-expanded .fx-eor-frontcard.fx-eor-mexpanded, .fx-eor-grid.fx-eor-mcols-2 .fx-eor-frontcard.fx-eor-mexpanded) .fx-eor-slider-scroll { display: contents; }
:is(#fx-eor-top-slider:not(.fx-eor-ts-expanded) .fx-eor-frontcard, #fx-eor-top-slider.fx-eor-ts-expanded .fx-eor-frontcard.fx-eor-mexpanded, .fx-eor-grid.fx-eor-mcols-2 .fx-eor-frontcard.fx-eor-mexpanded) .fx-eor-slider-scroll::after { display: none; }
:is(#fx-eor-top-slider:not(.fx-eor-ts-expanded) .fx-eor-frontcard, #fx-eor-top-slider.fx-eor-ts-expanded .fx-eor-frontcard.fx-eor-mexpanded, .fx-eor-grid.fx-eor-mcols-2 .fx-eor-frontcard.fx-eor-mexpanded) .fx-eor-slider-scroll::before { grid-area: badge; justify-self: start; }
:is(#fx-eor-top-slider:not(.fx-eor-ts-expanded) .fx-eor-frontcard, #fx-eor-top-slider.fx-eor-ts-expanded .fx-eor-frontcard.fx-eor-mexpanded, .fx-eor-grid.fx-eor-mcols-2 .fx-eor-frontcard.fx-eor-mexpanded) .fx-eor-img-link { grid-area: img; width: 100%; height: auto; aspect-ratio: 1 / 1; align-self: start; overflow: hidden; border-radius: 8px; }
:is(#fx-eor-top-slider:not(.fx-eor-ts-expanded) .fx-eor-frontcard, #fx-eor-top-slider.fx-eor-ts-expanded .fx-eor-frontcard.fx-eor-mexpanded, .fx-eor-grid.fx-eor-mcols-2 .fx-eor-frontcard.fx-eor-mexpanded) img.fx-eor-img { width: 100%; height: 100%; aspect-ratio: auto; object-fit: cover; display: block; }
:is(#fx-eor-top-slider:not(.fx-eor-ts-expanded) .fx-eor-frontcard, #fx-eor-top-slider.fx-eor-ts-expanded .fx-eor-frontcard.fx-eor-mexpanded, .fx-eor-grid.fx-eor-mcols-2 .fx-eor-frontcard.fx-eor-mexpanded) .fx-eor-name-link { grid-area: title; display: block; min-width: 0; overflow: hidden; align-self: start; padding: 0 !important; margin: 0 0 6px; text-align: center; }
:is(#fx-eor-top-slider:not(.fx-eor-ts-expanded) .fx-eor-frontcard, #fx-eor-top-slider.fx-eor-ts-expanded .fx-eor-frontcard.fx-eor-mexpanded, .fx-eor-grid.fx-eor-mcols-2 .fx-eor-frontcard.fx-eor-mexpanded) .fx-eor-body h4 { display: block; font-size: 14px; line-height: 16px; text-align: center; white-space: nowrap; text-wrap: nowrap; overflow: hidden; text-overflow: ellipsis; margin: 0; padding: 0 !important; }
:is(#fx-eor-top-slider:not(.fx-eor-ts-expanded) .fx-eor-frontcard, #fx-eor-top-slider.fx-eor-ts-expanded .fx-eor-frontcard.fx-eor-mexpanded, .fx-eor-grid.fx-eor-mcols-2 .fx-eor-frontcard.fx-eor-mexpanded) .fx-eor-variations { grid-area: pills; align-self: stretch; contain: size; display: flex; flex-direction: column; flex-wrap: nowrap; align-items: stretch; align-content: flex-start; gap: 6px; margin: 0; padding: 0 7px 0 0; height: auto; max-height: none; overflow-x: hidden; overflow-y: auto; touch-action: pan-y; scrollbar-width: none; }
:is(#fx-eor-top-slider:not(.fx-eor-ts-expanded) .fx-eor-frontcard, #fx-eor-top-slider.fx-eor-ts-expanded .fx-eor-frontcard.fx-eor-mexpanded, .fx-eor-grid.fx-eor-mcols-2 .fx-eor-frontcard.fx-eor-mexpanded) .fx-eor-variations::-webkit-scrollbar { display: none; }
/* v0.2.447, row 23j64 (the owner, 4 Oct 2026, on his phone: "NOW WE HAVE 1 COLUN OF PILLS CENTRE THEM AND MAKE THEM ALL FULL WIDTH FOR THAT WHITE SECTION AND CENTRE THE TEXT") - every size pill fills the pill column (up to the 3px scroll line's gutter) with its words centred; the height and the type size are the pills' own, untouched. */
:is(#fx-eor-top-slider:not(.fx-eor-ts-expanded) .fx-eor-frontcard, #fx-eor-top-slider.fx-eor-ts-expanded .fx-eor-frontcard.fx-eor-mexpanded, .fx-eor-grid.fx-eor-mcols-2 .fx-eor-frontcard.fx-eor-mexpanded) .fx-eor-var-pill { width: 100%; box-sizing: border-box; text-align: center; justify-content: center; flex: 0 0 auto; }
/* v0.2.447, row 23j65 (the owner, 4 Oct 2026: "I THINK PUT THE QUANTITY UNDER THE PRICE AND TRY AND FIT A VIEW BUTTON INBETWEEN THAT AND THE ADD TO BASKET BUTTON") - THE PHONE BOTTOM ROW: on the LEFT the price with the - 1 + quantity directly under it, in the MIDDLE the lime-outline VIEW link to the product page (the card's ONE a.fx-eor-dview, re-seated here by grid areas - no second View element), on the RIGHT the forest ADD TO BASKET at its v0.2.446 size. .fx-eor-bottom steps aside (display: contents) so its price and quantity become the footer's own grid items. */
:is(#fx-eor-top-slider:not(.fx-eor-ts-expanded) .fx-eor-frontcard, #fx-eor-top-slider.fx-eor-ts-expanded .fx-eor-frontcard.fx-eor-mexpanded, .fx-eor-grid.fx-eor-mcols-2 .fx-eor-frontcard.fx-eor-mexpanded) .fx-eor-slider-footer, :is(#fx-eor-top-slider:not(.fx-eor-ts-expanded) .fx-eor-frontcard, #fx-eor-top-slider.fx-eor-ts-expanded .fx-eor-frontcard.fx-eor-mexpanded, .fx-eor-grid.fx-eor-mcols-2 .fx-eor-frontcard.fx-eor-mexpanded) .fx-eor-grid-foot { grid-area: foot; align-self: end; display: grid; grid-template-columns: auto auto minmax(0, 1fr); grid-template-areas: "price view add" "qty view add"; align-items: center; column-gap: 8px; row-gap: 4px; margin: 0; padding: 6px 0 0; background: transparent; }
:is(#fx-eor-top-slider:not(.fx-eor-ts-expanded) .fx-eor-frontcard, #fx-eor-top-slider.fx-eor-ts-expanded .fx-eor-frontcard.fx-eor-mexpanded, .fx-eor-grid.fx-eor-mcols-2 .fx-eor-frontcard.fx-eor-mexpanded) .fx-eor-bottom { display: contents; }
:is(#fx-eor-top-slider:not(.fx-eor-ts-expanded) .fx-eor-frontcard, #fx-eor-top-slider.fx-eor-ts-expanded .fx-eor-frontcard.fx-eor-mexpanded, .fx-eor-grid.fx-eor-mcols-2 .fx-eor-frontcard.fx-eor-mexpanded) .fx-eor-price { grid-area: price; justify-self: start; }
:is(#fx-eor-top-slider:not(.fx-eor-ts-expanded) .fx-eor-frontcard, #fx-eor-top-slider.fx-eor-ts-expanded .fx-eor-frontcard.fx-eor-mexpanded, .fx-eor-grid.fx-eor-mcols-2 .fx-eor-frontcard.fx-eor-mexpanded) .fx-eor-qty { grid-area: qty; justify-self: start; }
:is(#fx-eor-top-slider:not(.fx-eor-ts-expanded) .fx-eor-frontcard, #fx-eor-top-slider.fx-eor-ts-expanded .fx-eor-frontcard.fx-eor-mexpanded, .fx-eor-grid.fx-eor-mcols-2 .fx-eor-frontcard.fx-eor-mexpanded) .fx-eor-dview { grid-area: view; display: inline-flex; align-items: center; justify-content: center; align-self: center; min-height: 34px; padding: 0 12px; background: #F4FFEA; border: 1.5px solid #85C727; border-radius: 9px; color: #1F3A24; font-family: 'Jost', sans-serif; font-size: 12px; font-weight: 600; letter-spacing: .08em; text-transform: uppercase; text-decoration: none; white-space: nowrap; line-height: 1.2; box-sizing: border-box; }
:is(#fx-eor-top-slider:not(.fx-eor-ts-expanded) .fx-eor-frontcard, #fx-eor-top-slider.fx-eor-ts-expanded .fx-eor-frontcard.fx-eor-mexpanded, .fx-eor-grid.fx-eor-mcols-2 .fx-eor-frontcard.fx-eor-mexpanded) .fx-eor-dview:hover { background: #E8F7D5; color: #1F3A24; }
:is(#fx-eor-top-slider:not(.fx-eor-ts-expanded) .fx-eor-frontcard, #fx-eor-top-slider.fx-eor-ts-expanded .fx-eor-frontcard.fx-eor-mexpanded, .fx-eor-grid.fx-eor-mcols-2 .fx-eor-frontcard.fx-eor-mexpanded).fx-eor-frontcard--oos .fx-eor-dview { display: none; }
:is(#fx-eor-top-slider:not(.fx-eor-ts-expanded) .fx-eor-frontcard, #fx-eor-top-slider.fx-eor-ts-expanded .fx-eor-frontcard.fx-eor-mexpanded, .fx-eor-grid.fx-eor-mcols-2 .fx-eor-frontcard.fx-eor-mexpanded) .fx-eor-price, :is(#fx-eor-top-slider:not(.fx-eor-ts-expanded) .fx-eor-frontcard, #fx-eor-top-slider.fx-eor-ts-expanded .fx-eor-frontcard.fx-eor-mexpanded, .fx-eor-grid.fx-eor-mcols-2 .fx-eor-frontcard.fx-eor-mexpanded) .fx-eor-price .price-amt { font-size: 15px; white-space: nowrap; }
:is(#fx-eor-top-slider:not(.fx-eor-ts-expanded) .fx-eor-frontcard, #fx-eor-top-slider.fx-eor-ts-expanded .fx-eor-frontcard.fx-eor-mexpanded, .fx-eor-grid.fx-eor-mcols-2 .fx-eor-frontcard.fx-eor-mexpanded) .fx-eor-card-add { grid-area: add; position: relative; width: auto; margin: 0; padding: 10px 14px; font-size: 12px; letter-spacing: .08em; border-radius: 9px; background: #2F5D29; color: #fff; text-align: center; text-decoration: none; box-sizing: border-box; white-space: nowrap; }
:is(#fx-eor-top-slider:not(.fx-eor-ts-expanded) .fx-eor-frontcard, #fx-eor-top-slider.fx-eor-ts-expanded .fx-eor-frontcard.fx-eor-mexpanded, .fx-eor-grid.fx-eor-mcols-2 .fx-eor-frontcard.fx-eor-mexpanded) .fx-eor-card-add::after { content: ""; position: absolute; left: 0; right: 0; top: -3px; bottom: -3px; }
:is(#fx-eor-top-slider:not(.fx-eor-ts-expanded) .fx-eor-frontcard, #fx-eor-top-slider.fx-eor-ts-expanded .fx-eor-frontcard.fx-eor-mexpanded, .fx-eor-grid.fx-eor-mcols-2 .fx-eor-frontcard.fx-eor-mexpanded) .fx-eor-card-add:hover { background: #264d21; color: #fff; }
:is(#fx-eor-top-slider:not(.fx-eor-ts-expanded) .fx-eor-frontcard, #fx-eor-top-slider.fx-eor-ts-expanded .fx-eor-frontcard.fx-eor-mexpanded, .fx-eor-grid.fx-eor-mcols-2 .fx-eor-frontcard.fx-eor-mexpanded) .fx-eor-qty { border: 1.5px solid #85C727; border-radius: 9px; background: #F4FFEA; }
:is(#fx-eor-top-slider:not(.fx-eor-ts-expanded) .fx-eor-frontcard, #fx-eor-top-slider.fx-eor-ts-expanded .fx-eor-frontcard.fx-eor-mexpanded, .fx-eor-grid.fx-eor-mcols-2 .fx-eor-frontcard.fx-eor-mexpanded) .fx-eor-qty button, :is(#fx-eor-top-slider:not(.fx-eor-ts-expanded) .fx-eor-frontcard, #fx-eor-top-slider.fx-eor-ts-expanded .fx-eor-frontcard.fx-eor-mexpanded, .fx-eor-grid.fx-eor-mcols-2 .fx-eor-frontcard.fx-eor-mexpanded) .fx-eor-qty .fx-eor-q-input { background: #F4FFEA; color: #1F3A24; }
}
/* v0.2.445, row 23j47 (A) - THE PILL BOX SCROLLS IN ITSELF: on a computer a Best Sellers or product-page slider card whose size pills run past about three rows (a product with eleven sizes, 6 stems to 200 stems)
 * stops there and the pills scroll inside the box, with the same thin lime line - the card never stretches, and a card with a few pills takes no more room than its pills. */
@media (min-width: 701px) {
#fx-eor-top-slider .fx-eor-frontcard .fx-eor-variations { max-height: 82px; overflow-y: auto; overflow-x: hidden; scrollbar-width: thin; scrollbar-color: #85C727 transparent; }
}
/* the forest ADD and the lime-outline quantity (rows 23e90, law 17) on every Best Sellers card, both widths: the engine's bright-lime bar is the theme's, not the house's. */
#fx-eor-top-slider .fx-eor-frontcard:not(.fx-eor-frontcard--oos) .fx-eor-card-add { background: #2F5D29; color: #fff; border-radius: 9px; }
#fx-eor-top-slider .fx-eor-frontcard:not(.fx-eor-frontcard--oos) .fx-eor-card-add:hover { background: #264d21; color: #fff; }
#fx-eor-top-slider .fx-eor-qty { border: 1.5px solid #85C727; background: #F4FFEA; }
#fx-eor-top-slider .fx-eor-qty button, #fx-eor-top-slider .fx-eor-qty .fx-eor-q-input { background: #F4FFEA; color: #1F3A24; }
/* v0.2.446, row 23j61 - THE VIEW BUTTON ON A COMPUTER, between the price and the quantity, in the lime outline on the pale ground (law 17). Shown from 1024px: on a tablet (768) the four-up card is about 160px wide and the rig read the quantity box crushed to 2px beside it, so tablets and phones keep their title link (and phones their own View). */
#fx-eor-top-slider .fx-eor-dview { display: none; }
/* v0.2.461, row 23k60 - the Explore Our Range grid's card gets, from the page's own script (fxEorInjectMobileView), the same two pieces the Quick Shop card is printed with: a footer wrapper around the price / quantity / ADD, and a View link to the product. Outside an opened phone card the link is hidden and the wrapper takes no box, so the grid looks and works exactly as before. */
.fx-eor-grid .fx-eor-dview { display: none; }
.fx-eor-grid .fx-eor-grid-foot { display: contents; }
@media (min-width: 1024px) {
#fx-eor-top-slider .fx-eor-bottom .fx-eor-dview { display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto; padding: 4px 9px; background: #F4FFEA; border: 1.5px solid #85C727; border-radius: 9px; color: #1F3A24; font-family: 'Jost', sans-serif; font-size: 11px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; text-decoration: none; white-space: nowrap; line-height: 1.2; box-sizing: border-box; }
#fx-eor-top-slider .fx-eor-bottom .fx-eor-dview:hover { background: #E8F7D5; color: #1F3A24; }
#fx-eor-top-slider .fx-eor-bottom:has(.fx-eor-dview) .fx-eor-qty { flex-shrink: 0; }
}
        /* ── Scoped overrides for cards inside the slider only ──────────── */

        /* v4.7.65/68: Card sizing with HARD CONSTRAINTS to prevent the flex
         * item (the card) from growing past its flex-basis due to content
         * min-content. Without `min-width: 0`, flex items default to
         * `min-width: auto` which means content min-content size becomes the
         * floor — long product titles or wide variation pills pushed the
         * card wider than calc(...), causing badges/buttons/pills to
         * overflow off the right of the viewport.
         *
         * v4.7.68 — card width tightened from `calc(100vw - 40px)` to
         * `calc(100vw - 60px)`. The previous width left the card with
         * subpixel margin to spare (335px card in 355px track on a 375
         * viewport, with 10px gap), and iOS Safari's scroll-snap was rounding
         * the snap position so the right edge of the card was chopping a
         * few pixels at the viewport edge. The extra 20px breathing room
         * means snap landing is robust even with subpixel rounding, and
         * gives a comfortable peek of the next card on the right.
         *
         * `scroll-snap-stop: always` enforces one-card-at-a-time gestures
         * so fast swipes can't overshoot and land mid-card. */
        #fx-eor-top-slider .fx-eor-frontcard {
            flex: 0 0 calc(100vw - 60px);
            width: calc(100vw - 60px);
            max-width: calc(100vw - 60px);
            min-width: 0;
            scroll-snap-align: start;
            scroll-snap-stop: always;
            box-sizing: border-box;
        }

        /* Card-main: EXPLICIT height (not aspect-ratio which is only preferred).
         *
         * v4.7.66: changed from `aspect-ratio: 2/1` to explicit
         * `height: calc((100vw - 40px) / 2)`. The aspect-ratio approach was
         * only a PREFERRED ratio — when content (image at natural aspect ratio
         * via accordion's `img.fx-eor-img { height: auto }`, or body with
         * many variations) exceeded the calculated height, the container grew
         * to fit. Resulted in cards being 400-450px tall instead of the
         * intended ~167px, and body scroll never engaged because there was
         * always enough height for all content.
         *
         * The explicit `height` + `max-height` + `grid-template-rows` triple
         * locks the row to exactly half the card width regardless of content.
         * `flex: 0 0 auto` overrides accordion's `flex: 1 1 auto` (which
         * would otherwise let card-main grow to fill card height).
         *
         * v4.7.68: aspect changed from 2:1 (square cells = card-main width / 2)
         * to 3:2 (portrait cells = card-main width × 2/3). FBF product photos
         * are tall portrait (typical bouquet photography aspect ~3:4 or 4:5).
         * With square cells, `object-fit: cover` aggressively cropped the
         * top/bottom of each photo. With 3:4 portrait cells (card-main width
         * × 2/3) the photos display naturally without heavy cropping.
         *
         * Math: card_width = 100vw - 60. card-main width = card_width.
         * card-main height = card_width × 2/3 (= 3:2 W:H card-main aspect).
         * Each cell is (card_width / 2) × (card_width × 2/3) = 3:4 portrait. */
        #fx-eor-top-slider .fx-eor-card-main {
            display: grid;
            grid-template-columns: 1fr 1fr;
            grid-template-rows: calc((100vw - 60px) * 2 / 3);
            height: calc((100vw - 60px) * 2 / 3);
            max-height: calc((100vw - 60px) * 2 / 3);
            width: 100%;
            max-width: 100%;
            min-width: 0;
            flex: 0 0 auto;
            box-sizing: border-box;
            overflow: hidden;
        }

        /* v4.7.66: image must fill its grid cell, NOT take natural aspect.
         * Accordion's `img.fx-eor-img` has `height: auto` for the accordion's
         * intentional behaviour (tall photos render as tall cells). In the
         * slider we want uniform card height regardless of photo aspect, so
         * we override the image to fill the constrained cell with cover. */
        #fx-eor-top-slider .fx-eor-img-link {
            display: block;
            width: 100%;
            height: 100%;
            overflow: hidden;
            align-self: stretch;
        }
        #fx-eor-top-slider img.fx-eor-img {
            width: 100%;
            height: 100%;
            object-fit: cover;
            display: block;
        }
        #fx-eor-top-slider .fx-eor-img-placeholder {
            width: 100%;
            height: 100%;
            aspect-ratio: auto;
        }

        /* v4.7.65: CRITICAL — force grid cells to respect 1fr / 1fr distribution.
         * Without `min-width: 0` on grid items, CSS Grid defaults to
         * `min-width: auto` and a column can't shrink below its content's
         * min-content width. Long product titles ("Subscription Flowers -
         * Peonies Pinks & Lavender") have wide min-content that pushes the
         * body grid cell past 50% of card width, forcing the card to expand
         * (or content to overflow). Setting `min-width: 0` allows the grid to
         * enforce the 1fr/1fr distribution and any overflow within body is
         * then clipped/scrolled by the body's own overflow rules. */
        #fx-eor-top-slider .fx-eor-card-main > * {
            min-width: 0;
        }

        /* Hide the empty card-top strip on non-current cards in the slider
         * (per James: "too much white because of the selected product
         * element bar"). The strip stays on the current product card to
         * show the "Currently viewing" badge. */
        #fx-eor-top-slider .fx-eor-frontcard:not(.fx-eor-frontcard--current) .fx-eor-card-top {
            display: none;
        }

        /* v4.7.65: Pad the title in slider so it doesn't run into the
         * absolute-positioned `.fx-eor-check-col` overlay in the top-right
         * corner. Accordion cards are full-width on mobile so titles have
         * room before reaching the corner; slider cards are narrower so we
         * pad explicitly. */
        #fx-eor-top-slider .fx-eor-name-link {
            padding-right: 32px;
            box-sizing: border-box;
            display: block;
        }

        /* v4.7.70: title line-clamp + word-break for the slider only.
         *
         * Problem: long product titles like "Subscription Flowers - Peonies
         * Pinks & Lavender" wrap to 3-5 lines in the narrow slider body
         * cell, eating vertical space and creating inconsistent layouts.
         *
         * Solution: clamp at 2 lines with "..." ellipsis. `overflow-wrap:
         * break-word` ensures ultra-long single words break cleanly rather
         * than overflowing. `text-wrap: balance` (modern browsers — Chrome
         * 114+, Firefox 121+, Safari 17.4+) distributes line breaks evenly
         * so a 3-word title splits like "Lovely / Spring Subscription"
         * rather than "Lovely Spring / Subscription" — falls back
         * gracefully on older browsers.
         *
         * Why not shrink-to-fit:
         *  - Requires JS measurement per card (adds layout cost)
         *  - Long titles shrunk to one line become illegible at ~7-8px
         *  - Variable font sizes across cards look chaotic
         *  - Line-clamp is the e-commerce industry standard
         *    (Amazon/Etsy/ASOS/Wayfair all use this pattern)
         *
         * Scoped to slider only — accordion titles unchanged.
         *
         * v4.20.43 — Clamp REMOVED per James (2026-05-19): "allow the
         * title to show in full". The clamp was hiding the full product
         * name on the slider. Title now wraps to as many lines as the
         * name needs; the body's overflow-y:auto handles vertical
         * scrolling so the user can roll the title and variations up
         * the card if they exceed the visible area. */
        #fx-eor-top-slider .fx-eor-body h4 {
            display: block;
            -webkit-line-clamp: unset;
            -webkit-box-orient: unset;
            overflow: visible;
            text-overflow: clip;
            overflow-wrap: break-word;
            text-wrap: balance;
        }

        /* v4.20.43 — Slider footer: position:sticky pins the price/qty
         * row + the Add-to-Basket button to the bottom of the body
         * while the upper content (title + variations) scrolls behind
         * it. James (2026-05-19): "Fix the add to basket button to the
         * bottom of the box with 2px of white between the button and
         * the border. Then fix the quantity row above that then the
         * slider element that is there rolls the full title and
         * variations up the page".
         *
         * Layout mechanism:
         *  - Body is the scroll container (overflow-y:auto, defined
         *    height from grid-template-rows on card-main, see line
         *    11800-ish).
         *  - .fx-eor-slider-footer is the LAST child of the body.
         *    position:sticky + bottom:2px sticks it 2px from the
         *    body's visible bottom edge as the user scrolls.
         *  - .fx-eor-bottom (price + qty) sits at the top of the
         *    footer; .fx-eor-card-add sits below it. Both pinned
         *    together at the bottom.
         *  - background:#fff ensures scrolling content above renders
         *    cleanly behind the footer (no see-through).
         *  - margin-top:auto pushes the footer to the bottom of the
         *    flex column even when content is short (so footer doesn't
         *    sit awkwardly mid-card).
         *
         * Why position:sticky not flex margin-top:auto alone: when
         * content exceeds body height, the body scrolls. Without
         * sticky, the footer scrolls out of view along with content.
         * Sticky pins it visually at the bottom regardless of scroll.
         *
         * Why the v4.7.71 sticky-removal doesn't apply here: that
         * removal was tied to padding-bottom interaction. The current
         * body has no padding-bottom (replaced by the ::after spacer
         * in v4.7.72). The footer wrapper sticks cleanly.
         *
         * The 2px white gap to the card border comes from:
         *  - bottom: 2px (footer leaves 2px below itself)
         *  - The body's ::after spacer (14px) provides scroll buffer
         *    above the footer, not below — body extends to the card
         *    edge, so the 2px below the footer IS the gap to the
         *    card's outer border. */
        /* v4.20.43 — Slider two-zone flex layout per James (2026-05-19):
         * "WHEN YOU SCROLL UP THE BUTTON IS NOT FIXED TO THE BOTTOM AND YOU
         * CAN SEE IN THE GAP THE VARIATIONS SCROLLING. IT JUMPS UP".
         *
         * v4.20.33's approach: body has overflow-y:auto, footer has
         * position:sticky bottom:2px with a mask gradient.
         * Two problems with that:
         *   (a) The mask gradient (linear-gradient transparent → black
         *       over 4px) made the top 4px of the footer SEE-THROUGH.
         *       Variations scrolling past in the body showed through
         *       that fade — exactly the "you can see in the gap"
         *       behaviour James reported.
         *   (b) position:sticky inside an overflow-y:auto flex item on
         *       iOS Safari is the same scenario v4.7.71 abandoned. The
         *       footer doesn't reliably pin; it can "jump" as scroll
         *       momentum settles.
         *
         * v4.20.43 fix: body is now the flex container with
         * overflow:hidden (no scrolling on the body itself). A new inner
         * wrapper .fx-eor-slider-scroll holds title + variations and
         * IS the scroll container. .fx-eor-slider-footer is a natural
         * flex-item at the bottom (flex: 0 0 auto, NO sticky, NO mask,
         * fully opaque white). The 2px white gap to the card border
         * comes from padding-bottom: 2px on the footer.
         *
         * This is the v4.7.71 "natural flex-flow positioning" idea —
         * but applied at the right level. The body no longer scrolls;
         * only the upper zone does. The footer can never "jump" because
         * it isn't part of any scrolling context. The iOS Safari sticky
         * quirks don't apply. The ::after spacer that v4.7.72 added for
         * iOS scroll buffer moves from the body to the scroll wrapper.
         *
         * Working logic preserved:
         *   - v4.20.34 qty stepper unconditional enable
         *   - v4.20.34 visual qty fallback in addSingleCard
         *   - v4.20.34 bulletproofed slider redirect to /basket/
         *   - v4.20.33 .fx-eor-slider-footer wrapper (CSS approach changed)
         *   - v4.7.72 ::after scroll buffer (moved to scroll wrapper)
         *   - All horizontal swipe gesture handling on the track
         *
         * Working logic DELETED: none. Only the v4.20.33 sticky+mask
         * approach (which never worked) is removed. */
        #fx-eor-top-slider .fx-eor-slider-scroll {
            flex: 1 1 auto;
            min-height: 0;
            overflow-y: auto;
            overflow-x: hidden;
            overscroll-behavior: contain;
            -webkit-overflow-scrolling: touch;
            scrollbar-width: thin;
            scrollbar-color: #85C727 transparent;
            /* v4.20.43 — Was pan-y. James (2026-05-20) reported swipe
             * gestures on the right side of the card didn't trigger
             * slider scroll. pan-y BLOCKED horizontal pan; the !important
             * rule below also covers this, but updating inline keeps
             * the declarations consistent. */
            touch-action: pan-y pan-x;
            display: flex;
            flex-direction: column;
        }
        #fx-eor-top-slider .fx-eor-slider-scroll::after {
            content: '';
            display: block;
            height: 6px;
            flex-shrink: 0;
        }
        #fx-eor-top-slider .fx-eor-slider-scroll::-webkit-scrollbar { width: 4px; }
        #fx-eor-top-slider .fx-eor-slider-scroll::-webkit-scrollbar-track { background: transparent; }
        #fx-eor-top-slider .fx-eor-slider-scroll::-webkit-scrollbar-thumb { background: #85C727; border-radius: 2px; }

        #fx-eor-top-slider .fx-eor-slider-footer {
            flex: 0 0 auto;
            background: #ffffff;
            display: flex;
            flex-direction: column;
            gap: 6px;
            padding-top: 6px;
            padding-bottom: 2px;
            /* 2px padding-bottom = the white gap between the Add button
             * and the card's outer border (the box edge) — exactly
             * what James asked for. */
        }
        #fx-eor-top-slider .fx-eor-slider-footer .fx-eor-bottom {
            margin: 0;
        }
        #fx-eor-top-slider .fx-eor-slider-footer .fx-eor-card-add {
            margin: 0;
        }

        /* v4.20.43 — CURRENTLY VIEWING strip slides up with the title.
         * James (2026-05-20): "make the currently viewing strip slide up
         * when you slide that mini product. The problem with that scroll
         * is when the top of the frame doesn't move up it gets right in
         * the way of selecting the pills".
         *
         * Background: the strip is rendered via CSS ::before pseudo on
         * .fx-eor-body (line 10942) so the same render works for grid /
         * accordion / slider WITHOUT needing the strip in HTML.
         * v4.20.35 moved the slider's scrollable content into a NEW
         * inner wrapper .fx-eor-slider-scroll. The ::before sits on the
         * BODY, not the scroll wrapper — so it stayed pinned at the top
         * while title + variations scrolled away. Result: when the user
         * scrolled to reach lower pills, the strip remained right where
         * the pills used to be — exactly the obstruction James reported.
         *
         * Fix: slider-only override — hide the original body::before
         * for slider cards, and emit the SAME strip as a ::before on
         * .fx-eor-slider-scroll instead. Since the scroll wrapper IS
         * the vertical scroll container, its ::before becomes the first
         * flex-item inside the scrolling region and scrolls up with the
         * rest of the upper content.
         *
         * Grid + accordion render paths are UNTOUCHED — they don't have
         * .fx-eor-slider-scroll, so the original body::before continues
         * to fire there. Only #fx-eor-top-slider scope changes. */
        #fx-eor-top-slider .fx-eor-frontcard[data-current="1"] .fx-eor-body::before {
            display: none !important;
        }
        #fx-eor-top-slider .fx-eor-frontcard[data-current="1"] .fx-eor-slider-scroll::before {
            content: "\2605 Currently viewing";
            display: inline-block;
            background: #2A6132;
            color: #fff;
            font-size: 10px;
            letter-spacing: 1px;
            text-transform: uppercase;
            padding: 4px 10px;
            border-radius: 3px;
            font-weight: 600;
            font-family: 'Jost', sans-serif;
            align-self: flex-start;
            margin-bottom: 6px;
            flex-shrink: 0;
        }

        /* v4.20.43 — Swipe detection on the full right side of slider
         * cards. James (2026-05-20): "add slide detection onto the whole
         * of the righthand side of the slider product so that it detects
         * slide when you are focussed on the pills titles or add to cart
         * button or quantity. So that side of the pane needs to have
         * both slide and click detection on mobile".
         *
         * Background: .fx-eor-slider-scroll had touch-action: pan-y
         * (v4.20.35) and .fx-eor-body had touch-action: pan-y (v4.7.72).
         * Both EXPLICITLY BLOCK horizontal pan gestures. When the user's
         * finger lands on the inner wrapper or any of its descendants
         * (pills, qty buttons, Add button, qty input, title), the
         * browser sees pan-y and DROPS the horizontal pan entirely —
         * even though the parent track has overflow-x:auto + pan-x and
         * could have scrolled.
         *
         * Native browser scroll-chaining requires touch-action on EACH
         * intermediate element to ALLOW the gesture direction. pan-y
         * means "only vertical" — horizontal motion is forbidden.
         *
         * Fix: change pan-y to "pan-y pan-x" on both .fx-eor-body and
         * .fx-eor-slider-scroll. The browser routes by DOMINANT motion
         * direction: vertical-dominant pan → inner scroll wrapper
         * (overflow-y:auto wins); horizontal-dominant pan → bubbles up
         * to the track (overflow-x:auto wins). Stationary taps still
         * fire click events on pills/buttons normally — the threshold
         * is ~5px of movement before the browser commits to "scroll".
         *
         * Also explicit pan-y pan-x on interactive children. Buttons
         * default to touch-action: auto which already allows panning,
         * but being explicit removes any ambiguity from older browsers
         * (or future CSS resets that might set touch-action: manipulation
         * on buttons globally). */
        #fx-eor-top-slider .fx-eor-body,
        #fx-eor-top-slider .fx-eor-slider-scroll,
        #fx-eor-top-slider .fx-eor-slider-footer,
        #fx-eor-top-slider .fx-eor-var-pill,
        #fx-eor-top-slider .fx-eor-card-add,
        #fx-eor-top-slider .fx-eor-q-up,
        #fx-eor-top-slider .fx-eor-q-down,
        #fx-eor-top-slider .fx-eor-q-input,
        #fx-eor-top-slider .fx-eor-name-link,
        #fx-eor-top-slider .fx-eor-name-link h4,
        #fx-eor-top-slider .fx-eor-variations,
        #fx-eor-top-slider .fx-eor-bottom,
        #fx-eor-top-slider .fx-eor-price,
        #fx-eor-top-slider .fx-eor-qty {
            touch-action: pan-y pan-x !important;
        }

        /* Title full-width on slider — v4.20.24 retired the multi-select
         * tick column (.fx-eor-check-col display:none), so the
         * padding-right:38px (global, line 10907) + padding-right:32px
         * (slider scope below, line 11877) that reserved space for the
         * absolute-positioned tick overlay are obsolete. James
         * (2026-05-19): "THE TEXT IS WRAPPPED EARLY IN THE TITLE AND IT
         * SHOULD BE FULL WIDTH NOW THE TICK BOX HAS BEEN REMOVED". Zero
         * both for the slider so the title gets the full body width to
         * wrap into. Grid + accordion scopes untouched — those layouts
         * may want the right padding for their own reasons. */
        #fx-eor-top-slider .fx-eor-body h4 {
            padding-right: 0 !important;
        }
        #fx-eor-top-slider .fx-eor-name-link {
            padding-right: 0 !important;
        }

        /* v4.7.65: Tighten "ADD TO BASKET" button so the text fits inside the
         * narrower slider body cell. Accordion's button has generous padding
         * suitable for full-width body; slider body is ~half width so we
         * reduce padding + font slightly. white-space: nowrap + width: 100%
         * keep the button predictable.
         *
         * v4.7.71: position: sticky removed (was added in v4.7.69, removed
         * per James). On iOS Safari the sticky bottom: 0 anchor interacted
         * badly with the body's padding-bottom (content-box bottom anchor
         * vs padding-box rendering caused the bottom half of the button
         * to be visually clipped). Reverted to natural flex-flow positioning
         * — button is the last child in the body, stacks at the bottom of
         * content for short cards, scrolls naturally into view at max-scroll
         * for long-content cards. */
        #fx-eor-top-slider .fx-eor-card-add {
            padding: 10px 6px;
            font-size: 10px;
            letter-spacing: 0.5px;
            width: 100%;
            box-sizing: border-box;
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
        }

        /* v4.7.65: Tighten the "★ CURRENTLY VIEWING" badge font so it fits in
         * the narrower slider card-top strip alongside the check-col overlay. */
        #fx-eor-top-slider .fx-eor-current-badge-text {
            font-size: 9px;
            letter-spacing: 0.4px;
        }

        /* Body becomes a vertical scroll viewport — content above the
         * fold is name + variations + price/qty, with Add to Basket
         * appearing as the user scrolls the body up (for products with
         * many variations). min-width: 0 lets the body grid cell shrink
         * to its 1fr allocation regardless of content min-content.
         *
         * v4.7.66: added `height: 100%` + `max-height: 100%` so the body
         * fills the grid cell (now explicitly sized in card-main) and
         * scroll engages when content > cell height. Previously the body
         * was content-sized which meant scroll never triggered.
         *
         * v4.7.68: `justify-content: flex-start` overrides accordion's
         * `justify-content: space-between` (set on `.fx-eor-body` in the
         * shared CSS at line ~2700). Space-between distributes empty
         * vertical space between children — for SHORT body content (simple
         * product with no variations) the title pinned to the top + button
         * pinned to the bottom of the cell looked unbalanced with a huge
         * gap in the middle. Flex-start stacks title/pills/price/button
         * with consistent 4px gap (from mobile media query rule), button
         * sits right below the price row. Cleaner, more predictable. */
        #fx-eor-top-slider .fx-eor-body {
            /* v4.20.43 — Body is now the non-scrolling flex container.
             * Scroll moved to inner .fx-eor-slider-scroll wrapper (see
             * v4.20.43 block above). The body's job is to host two
             * vertically stacked flex items: the scroll wrapper (flex:1)
             * and the footer (flex:0 0 auto). The previous
             * overflow-y:auto on the body is GONE — that role is now the
             * inner wrapper's. This eliminates the v4.20.33 sticky+mask
             * problems described in detail in the v4.20.43 comment
             * above; the footer can never "jump" because it isn't in any
             * scrolling context, and there's no mask gradient leaking
             * variations behind the footer.
             *
             * touch-action: pan-y retained — the inner scroll wrapper
             * also has touch-action:pan-y; nesting them is fine and
             * doubly ensures iOS Safari commits vertical gestures to
             * the scroll wrapper rather than the parent horizontal
             * track. */
            overflow: hidden;
            min-height: 0;
            min-width: 0;
            height: 100%;
            max-height: 100%;
            box-sizing: border-box;
            justify-content: flex-start;
            /* v4.20.43 — Was pan-y. See v4.20.43 swipe-detection comment
             * above the touch-action !important rule for full reasoning.
             * pan-y pan-x lets the browser route both vertical (to the
             * inner scroll wrapper) and horizontal (to the parent
             * track) pan gestures depending on dominant motion direction. */
            touch-action: pan-y pan-x;
        }
        /* v4.20.43 — body::after spacer REMOVED. The 14px scroll buffer
         * that v4.7.72 added for the iOS Safari padding-bottom bug now
         * lives on .fx-eor-slider-scroll::after (6px is enough since
         * the footer is fully visible and no longer needs to be scrolled
         * past). The body itself doesn't scroll anymore so it doesn't
         * need the buffer. */
        /* Slider body's own webkit-scrollbar rules removed — no scroll
         * on the body now. Scrollbar styling moved to
         * .fx-eor-slider-scroll above. */

        /* Mobile-only display (slider hidden on desktop where accordion is enough) */
        @media (max-width: 700px) {
            .fx-eor-top-slider-wrap { display: block; }
        }

        /* v4.19.32 — REVERTED v4.19.22 mobile slider tap-to-expand.
         * The collapse-to-image-only + tap-to-reveal pattern was breaking
         * the mobile experience (controls invisible, expand didn't restore
         * them reliably). Restored the pre-v4.19.22 behaviour where slider
         * cards show every control by default — matching how accordion
         * cards render. setupCard() wires the same behaviours for both
         * slider and accordion cards, so the slider gets tick / pills /
         * qty / Add automatically without needing the expand mechanism.
         * The variation-sync multi-current-card fix from v4.19.22 is
         * preserved (that lives in applyVariationToAllCurrentCards). */
        