/* BookSesh CPT-single polish — editorial layout/rhythm, Nova-aligned. No font override. Scoped. */
body.bks-single-polish{
  --bks-shadow: 0 10px 34px rgba(9,7,17,.10);
  --bks-shadow-hover: 0 16px 44px rgba(9,7,17,.15);
  --bks-radius: 20px;
  --bks-radius-img: 18px;
  --bks-coral: #EB666D;
}
/* NOTE: heading typography is OWNER-OWNED in Elementor (owner directive 2026-09-21). Layout only.
   Exception (owner 2026-10-02): PHONE-ONLY size/line-height cap on the About/section headings, see section 8. */

/* 1. Content + sidebar cards (JS-tagged). */
body.bks-single-polish .bks-card{
  border: 0 !important; border-radius: var(--bks-radius) !important;
  box-shadow: var(--bks-shadow) !important; background: #ffffff !important;
  margin-bottom: 22px !important; transition: box-shadow .2s ease, transform .2s ease;
}
body.bks-single-polish .bks-card:hover{ box-shadow: var(--bks-shadow-hover) !important; }
body.bks-single-polish .bks-card--roomy{ padding: 34px !important; }

/* 2. Image radius — hero/gallery + related-card images. */
body.bks-single-polish .ts-gallery-grid img,
body.bks-single-polish .ts-gallery img{ border-radius: var(--bks-radius-img) !important; }
body.bks-single-polish .ts-preview img{ border-radius: 14px !important; }

/* 3. Related-listing cards — softer, visible hover lift. */
body.bks-single-polish .ts-preview{ border-radius: 16px !important; transition: transform .18s ease, box-shadow .18s ease; }
body.bks-single-polish .ts-preview:hover{ transform: translateY(-3px); box-shadow: var(--bks-shadow) !important; }
/* 3b. "More like this" / related cards — inset the TEXT rows so nothing sits flush to the card edge, while the
   main photo + BOOK NOW button stay FULL-BLEED. GENERIC selectors so it works for BOTH the session AND event
   card templates. Pad the flex CONTAINER (not each widget) so no row gets squeezed; titles wrap to 2 lines
   instead of hard-truncating (kills the "chopped" look). */
body.bks-single-polish .ts-preview{ overflow: hidden; }
body.bks-single-polish .ts-preview .e-con-inner{ padding: 12px !important; }
body.bks-single-polish .ts-preview h3,
body.bks-single-polish .ts-preview h3 a{ white-space: normal !important; display: -webkit-box !important; -webkit-line-clamp: 2 !important; -webkit-box-orient: vertical !important; overflow: hidden !important; }

/* 4. Description rhythm. */
body.bks-single-polish .elementor-widget-text-editor{ line-height: 1.78; }
body.bks-single-polish .elementor-widget-text-editor p{ margin-bottom: 1.15em; }

/* 5. Read-more clamp (full text stays in DOM -> SEO-safe). */
body.bks-single-polish .bks-clamp{ position: relative; max-height: 15.5em; overflow: hidden;
  -webkit-mask-image: linear-gradient(180deg,#000 72%,transparent); mask-image: linear-gradient(180deg,#000 72%,transparent); }
body.bks-single-polish .bks-clamp.is-open{ max-height: none; -webkit-mask-image: none; mask-image: none; }
body.bks-single-polish .bks-readmore{ display: inline-block; margin-top: .7em; font-size: .9rem; font-weight: 600;
  background: none; border: 0; padding: .2em 0; cursor: pointer; text-decoration: underline; text-underline-offset: 3px; }

/* 6. HERO CROSSFADE — same gentle dissolve as the /session/ cards, on the big hero. */
body.bks-single-polish .bks-hero{ position: relative !important; overflow: hidden; border-radius: var(--bks-radius-img); touch-action: pan-y; }
body.bks-single-polish .bks-hero-slide{
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover;
  opacity: 0 !important; transition: opacity 1300ms ease-in-out !important; will-change: opacity;
  transform: translateZ(0); backface-visibility: hidden; -webkit-backface-visibility: hidden; pointer-events: none;
}
body.bks-single-polish .bks-hero-slide.is-active{ opacity: 1 !important; }
/* hero dot navigation (auto-rotating + click, like /session/) */
body.bks-single-polish .bks-hero-dots{ position: absolute; left: auto; right: 16px; bottom: 14px; z-index: 4;
  display: flex; gap: 6px; justify-content: flex-end; pointer-events: none; }
/* owner 2026-10-03: shrunk 9px->7px (closer to Airbnb's ~6px reference, still tappable). Visual size/colour/
   opacity/transition untouched; a 24x24 ::before hit area (transparent, absolute-centered) keeps the tap
   target comfortable on mobile without enlarging what's drawn. */
body.bks-single-polish .bks-hero-dot{ position: relative; width: 7px; height: 7px; padding: 0; border: 0; border-radius: 50%; cursor: pointer;
  pointer-events: auto; background: rgba(255,255,255,.55); box-shadow: 0 1px 3px rgba(0,0,0,.35);
  transition: background .2s ease, transform .2s ease; }
body.bks-single-polish .bks-hero-dot::before{ content: ""; position: absolute; top: 50%; left: 50%;
  width: 13px; height: 24px; transform: translate(-50%,-50%); background: transparent; } /* width = dot pitch (7+6) so neighbours never overlap */
body.bks-single-polish .elementor-element-12db055{ pointer-events: none; }
body.bks-single-polish .elementor-element-12db055 a,
body.bks-single-polish .elementor-element-12db055 img{ pointer-events: auto; }
body.bks-single-polish .bks-hero-dot:hover{ transform: scale(1.18); }
body.bks-single-polish .bks-hero-dot.is-active{ background: #fff; transform: scale(1.18); }

/* 7. Nova baseline-bar HIGHLIGHT on one H1 word — BookSesh coral (root brand), not a tenant colour. */
body.bks-single-polish .bk-hl{ position: relative; display: inline-block; padding: 0 .05em; }
body.bks-single-polish .bk-hl::before{ content: ""; position: absolute; z-index: -1; left: -.05em; right: -.05em;
  bottom: .06em; height: .32em; border-radius: 2px;
  background-image: linear-gradient(90deg, var(--bks-coral) 0%, var(--bks-coral) 65%, transparent 100%); }

/* 7b. FAQ-style accordion on the About body sub-sections (Nova-style). CLIENT-SIDE ONLY — the served
      HTML is unchanged, so the crawlable text is byte-identical; this just collapses it in the browser. */
body.bks-single-polish .bks-acc-head{ cursor: pointer; position: relative; padding-right: 30px !important;
  border-top: 1px solid rgba(9,7,17,.09); padding-top: .7em; margin-top: .7em; user-select: none;
  /* owner 2026-09-21: UNIFORM toggle size across mixed h3/h4 (SEO tag levels stay in the DOM; only the visual
     size is unified), responsive so mobile isn't oversized. font-family stays Elementor-owned (not set here). */
  font-size: 1.15rem !important; font-weight: 600 !important; line-height: 1.32 !important; margin-bottom: 0 !important; }
body.bks-single-polish .bks-acc-head::after{ content:""; position: absolute; right: 6px; top: 1.05em; width: 8px; height: 8px;
  border-right: 2px solid currentColor; border-bottom: 2px solid currentColor; transform: rotate(45deg); opacity: .5; transition: transform .25s ease; }
body.bks-single-polish .bks-acc-head.is-open::after{ transform: rotate(-135deg); }
body.bks-single-polish .bks-acc-panel{ max-height: 0; overflow: hidden; transition: max-height .35s ease; }
/* content-less structural label (e.g. "Frequently Asked Questions") — hidden visually, stays in served HTML (SEO) */
body.bks-single-polish .bks-acc-empty{ display: none !important; }

/* 7c. About-body READ MORE (owner 2026-10-02) — same clamp as the author-page bio. CSS-only clamp; the full
      text stays in the served HTML (SEO-safe). Places + events (JS-gated; events added 2026-10-02). */
body.bks-single-polish .bks-sp-clamp{ position: relative; max-height: 15em; overflow: hidden;
  -webkit-mask-image: linear-gradient(180deg,#000 62%,transparent); mask-image: linear-gradient(180deg,#000 62%,transparent); }
body.bks-single-polish .bks-sp-clamp.is-open{ max-height: none; -webkit-mask-image: none; mask-image: none; }
body.bks-single-polish .bks-sp-readmore{ position: relative; z-index: 1; display: block; width: 100%; text-align: center; margin-top: .6em; font-weight: 600;
  font-size: .95rem; line-height: 1; color: inherit; background: none; border: 0; padding: .3em 0; cursor: pointer;
  text-decoration: underline; text-underline-offset: 3px; }

/* 9. Host bio — restore the tenant's own paragraph/line breaks. The bio text sits raw (no <p>) inside the
      template's bio text-editor widget (dd3f8c7); the source newlines already exist but collapse by default.
      pre-line honours them WITHOUT touching the DOM/text (served HTML byte-identical -> SEO-safe). */
body.bks-single-polish .elementor-element-dd3f8c7 .elementor-widget-container{ white-space: pre-line; }

/* 8. Mobile. */
@media (max-width: 767px){
  body.bks-single-polish .bks-card{ border-radius: 16px !important; margin-bottom: 16px !important; }
  body.bks-single-polish .bks-card--roomy{ padding: 22px !important; }
  body.bks-single-polish .ts-preview{ border-radius: 14px !important; }
  body.bks-single-polish .elementor-widget-text-editor{ line-height: 1.72; }
  /* dots sit bottom-RIGHT (clears the centred profile logo on mobile too). owner 2026-10-03: no longer
     up-sized visually on mobile (that was the old tap-target workaround) — the base 7px dot's own ::before
     24x24 hit area now covers the tap target on every breakpoint, so mobile keeps the same small visual size. */
  /* uniform FAQ toggles, smaller on phones so they don't dominate */
  body.bks-single-polish .bks-acc-head{ font-size: 1rem !important; }
  body.bks-single-polish .bks-sp-clamp{ max-height: 13em; }
  body.bks-single-polish .bks-sp-readmore{ margin-top: -14px; }
  body.bks-single-polish .bks-sp-clamp--bio{ max-height: 8.6em; }   /* host bio: same clamp as the author-page bio */
  /* Owner 2026-10-02: "About {service}" H2 (5034f27) was 24px/1.0 on phones and read too tall; it now sits just
     under the first in-body H2 ("{service}", 22.5px/25.5px). Section titles that were LARGER than it on phones
     ("Sessions/Events held by", "More like this" at 24px) are capped to the same value so none outranks it.
     Desktop untouched. Font family/weight untouched (owner-owned in Elementor).
     Partial removal (2026-10-03, owner directive): 5034f27 is now linked to the Elementor global "BKS Section
     Heading" (kit 11923, id afb14e8) and no longer needs this cap, so it has been removed from the selector
     list below. d7c07b7 (12434 "Sessions held by"), 17f66b3 (12434 "More like this"), 6afa517 and 4ff595e
     (12411) are still on their OWN typography (36/35/24, mobile 24px) — not linked to the global — so they
     stay capped at 22px; without the cap they would jump to 24px on phones. */
  body.bks-single-polish .elementor-element-d7c07b7 .elementor-heading-title,
  body.bks-single-polish .elementor-element-6afa517 .elementor-heading-title,
  body.bks-single-polish .elementor-element-17f66b3 .elementor-heading-title,
  body.bks-single-polish .elementor-element-4ff595e .elementor-heading-title{ font-size: 22px !important; line-height: 1.15 !important; }
}

/* ---------- 10-pre. Card-gallery crossfade/dots — safety default (ALL breakpoints). The JS
   (single-polish.js buildCardGalleries) only ever creates these elements when
   matchMedia('(max-width:767px)') matches, but this belt-and-braces default keeps any extra
   slide <img>/dot elements fully inert (no layout box) at any width that isn't covered by the
   mobile-only rules in section 10h below — desktop stays byte-for-byte unaffected even in an
   edge case (e.g. a resize race) where the elements briefly exist above the breakpoint. */
body.bks-single-polish .bks-sp-cgal-slide:not(.bks-sp-cgal-base),
body.bks-single-polish .bks-sp-cgal-dots{ display: none; }

/* ---------- 10. Single-page feed skin — MOBILE-ONLY v2 proposal (2026-10-03) ----------
   Supersedes the rolled-back build. Desktop gets ZERO rules from this block (no body class,
   no discovery-skin.css enqueue, nothing outside this @media guard). Everything below is
   scoped to @media (max-width: 767px) and uses the REAL element IDs confirmed live via
   Playwright DOM inspection on 13044's "More like this" feed (card #3, "Cacao Ceremony..."):
     050809c = title container (flex)      8f23438 = rating/review-count
     bksesh-qv = teaser+indicators+quickview block (plugin-owned, order untouched below
                 except the sentinel needed for the toggle itself — see 10d)
     b6b2133 = photo widget                9ccb512 = BOOK NOW + venue row (final row)
     22a8d2b = host-avatar badge (native Elementor `elementor-absolute`, position:absolute
               relative to `.ts-preview` itself — NOT relative to the photo, because the
               archive's `session-discovery.js` reparent script (which makes the avatar a
               DOM child of b6b2133 so its absolute coordinates track the photo) is never
               enqueued on singles. That script is a hard dependency for this exact visual
               — see 10c below for why it is NOT ported here.
   EVENTS template 12412 (745d0c3/ce7b3c5/d62c038/3fa1342/a7b2e5f/db3de79/843ce2f) carries no
   avatar widget at all, so it has none of 10c's problem; included for the same title fix only. */

@media (max-width: 767px) {

/* 10a. Card box — same lavender-wash box as the desktop design, mobile only. No change from
   the rolled-back build's version; this part was never reported as broken. */
body.bks-single-polish .elementor-widget-ts-post-feed .ts-preview {
  box-sizing: border-box;
  border: 1px solid rgba(122,90,240,.16) !important;
  border-radius: 14px !important;
  padding: 18px !important;
  background: linear-gradient(180deg,#EBE6FD 0%,#FFFFFF 78%) !important;
  box-shadow: 0 6px 20px rgba(122,90,240,.14), 0 2px 6px rgba(9,7,17,.07) !important;
}

/* 10b. Reorder: title -> rating -> teaser/quick-view -> photo -> BOOK NOW+venue.
   Uses the CONFIRMED real session-card IDs (050809c/8f23438/bksesh-qv/b6b2133/9ccb512),
   not the archive's own id set (which doesn't fully match this template's container ids
   for every field, per 10c's history) — verified matching live via computed `order`. */
body.bks-single-polish .elementor-widget-ts-post-feed .ts-preview .elementor-element-050809c { order: 1; }
body.bks-single-polish .elementor-widget-ts-post-feed .ts-preview .elementor-element-8f23438 { order: 2; }
body.bks-single-polish .elementor-widget-ts-post-feed .ts-preview .bksesh-qv                 { order: 3; }
body.bks-single-polish .elementor-widget-ts-post-feed .ts-preview .elementor-element-b6b2133 { order: 4; position: relative; margin-bottom: 12px; }
body.bks-single-polish .elementor-widget-ts-post-feed .ts-preview .elementor-element-9ccb512 { order: 5; }

/* 10c. Avatar badge — ROOT CAUSE OF THE "MESSY TITLES" BUG, FIXED BY REMOVAL, NOT REPOSITIONING.
   22a8d2b is `position:absolute` relative to `.ts-preview` (the whole card), with a top/left
   offset Elementor computed assuming the ORIGINAL (photo-first) layout, where that offset
   happens to land on the photo. Once 10b promotes the title to the first visual slot, that
   SAME fixed offset instead lands on the title — confirmed live: pre-reorder the avatar's
   rect top (2995.6) sits within 8px of the photo's rect top (2987.6, correct, avatar-on-photo);
   post-reorder with no other change, the avatar's rect top (3052.6) sits within 7px of the
   NEW title rect top (3045.6) instead — the avatar physically overlaps the first word of the
   title ("Cacao" partly hidden under the circular badge in the broken screenshot).
   A correct fix needs the avatar to be a DOM child of the photo widget (so its absolute
   coordinates track the photo, not the card) — that reparenting is done by a companion script,
   `session-discovery.js`, on the /session archive; it is NOT enqueued for single-page feeds in
   this build (CSS-only port) and enqueuing + testing it is a separate change, not a CSS fix.
   Hiding the badge on the mobile feed-card skin is the safe, zero-JS-risk, zero-regression-risk
   option for this preview — the host name is already shown via other text on the page (listing
   title/page header), so no information is lost, only the small circular photo. If the owner
   wants the avatar-on-photo look restored, that is a follow-up task to enqueue+verify the
   reparent script, flagged in the report, not applied here. */
body.bks-single-polish .elementor-widget-ts-post-feed .ts-preview .elementor-element-22a8d2b { display: none !important; }

/* 10d. Quick-view toggle — needs a flex `order` since it is an injected DOM sibling with no
   native one (same sentinel used in the rolled-back build); UNLIKE the rolled-back build this
   proposal does NOT touch `.bksesh-qv-panel`'s own collapse mechanism at all (see 10g). */
body.bks-single-polish .elementor-widget-ts-post-feed .ts-preview .bksesh-qv { order: 99; }

/* 10e. Title typography fix (the actual owner ask) — Plus Jakarta Sans 600 (already loaded
   site-wide, same stack used by booksesh-wfh-badge.php), ~17-18px, ~1.3 line-height, left-
   aligned, clamped to 2 lines with an ellipsis so a long title never collides with whatever
   sits below it (stars row, 8px margin given explicitly rather than relying on the clamp
   alone). Also sets the brand-blue title colour + removes any inherited center-align/gradient-
   text leftovers from the module styling. */
body.bks-single-polish .elementor-widget-ts-post-feed .ts-preview .elementor-element-050809c .elementor-heading-title,
body.bks-single-polish .elementor-widget-ts-post-feed .ts-preview .elementor-element-050809c .elementor-heading-title a {
  font-family: "Plus Jakarta Sans", sans-serif !important;
  font-weight: 600 !important;
  font-size: 17.5px !important;
  line-height: 1.3 !important;
  text-align: left !important;
  color: #0F40FF !important;
  background: none !important;
  -webkit-text-fill-color: #0F40FF !important;
  display: -webkit-box !important;
  -webkit-box-orient: vertical !important;
  -webkit-line-clamp: 2 !important;
  overflow: hidden !important;
  text-overflow: ellipsis !important;
  margin: 0 0 8px !important;
}
/* Same title fix for the EVENTS card (template 12412, id 3fa1342) — this template has no
   avatar widget, so 10c does not apply here; included for visual parity between the two
   card types. */
body.bks-single-polish .elementor-widget-ts-post-feed .ts-preview .elementor-element-3fa1342 .elementor-heading-title,
body.bks-single-polish .elementor-widget-ts-post-feed .ts-preview .elementor-element-3fa1342 .elementor-heading-title a {
  font-family: "Plus Jakarta Sans", sans-serif !important;
  font-weight: 600 !important;
  font-size: 17.5px !important;
  line-height: 1.3 !important;
  text-align: left !important;
  color: #0F40FF !important;
  background: none !important;
  -webkit-text-fill-color: #0F40FF !important;
  display: -webkit-box !important;
  -webkit-box-orient: vertical !important;
  -webkit-line-clamp: 2 !important;
  overflow: hidden !important;
  text-overflow: ellipsis !important;
  margin: 0 0 8px !important;
}
body.bks-single-polish .elementor-widget-ts-post-feed .ts-preview .elementor-element-db3de79 { order: 0; position: relative; margin: 0 0 13px !important; }
body.bks-single-polish .elementor-widget-ts-post-feed .ts-preview .elementor-element-843ce2f { order: 1; }
body.bks-single-polish .elementor-widget-ts-post-feed .ts-preview .elementor-element-a7b2e5f { order: 2; margin: 1px 0 1px !important; }
body.bks-single-polish .elementor-widget-ts-post-feed .ts-preview .elementor-element-745d0c3 { order: 3; }

/* 10f. BOOK NOW pill + WFH-chip gradients — cosmetic only, no DOM/order dependency, no bug
   reported against these; carried over unchanged, mobile-scoped.
   Size reduced 20% (owner directive 2026-10-03, "reduce the book now pills by 20%" — these FEED
   CARD pills only, mobile only; the sticky booking card's own "Book now" pill is a completely
   separate rule (#bookseshStickyCta .booksesh-btn, booksesh-sticky-booking-card.php) and is not
   touched by this selector at all, and desktop carries zero rules from this file.
   BEFORE (native .booksesh-btn, wp-content/plugins/booksesh-listing-button.old): font-size:18px,
   padding:10px 20px (no explicit height — natural box ≈ 18*1.2 + 10+10 ≈ 41.6px tall).
   AFTER (x0.8): font-size:14.4px, padding:8px 16px (natural box ≈ 14.4*1.2 + 8+8 ≈ 33.3px); an
   explicit min-height:34px is added so the tap target never drops under the 32px floor even if
   line-height/font metrics round down slightly on a given device. Gradient/radius/shadow/
   animation are all unchanged. */
body.bks-single-polish .elementor-widget-ts-post-feed .ts-preview .booksesh-btn {
  border-radius: 999px !important; border: 0 !important; color: #fff !important;
  background-color: #0F40FF !important;
  background-image: linear-gradient(90deg, #0F40FF 0%, #7A5AF0 25%, #EB666D 50%, #7A5AF0 75%, #0F40FF 100%) !important;
  background-size: 280% 100% !important;
  box-shadow: 0 4px 14px rgba(122, 90, 240, .35) !important;
  animation: bksV2Grad 11s ease-in-out infinite !important;
  font-size: 14.4px !important;
  padding: 8px 16px !important;
  min-height: 34px !important;
}
@keyframes bksV2Grad { 0% { background-position: 0% 50%; } 50% { background-position: 100% 50%; } 100% { background-position: 0% 50%; } }
body.bks-single-polish .elementor-widget-ts-post-feed .ts-preview .bksesh-wfh-chip--card .bksesh-wfh-txt {
  background: linear-gradient(90deg, #0F40FF 0%, #7A5AF0 100%) !important;
  -webkit-background-clip: text !important; background-clip: text !important;
  -webkit-text-fill-color: transparent !important; color: transparent !important;
}
body.bks-single-polish .elementor-widget-ts-post-feed .ts-preview .bksesh-wfh-chip--card .bksesh-wfh-ico { color: #0F40FF !important; stroke: #0F40FF !important; }

/* 10g. DELIBERATELY OMITTED from this proposal: the rolled-back build's ".bksesh-qv-panel"
   grid-reveal override (display:grid; grid-template-rows:0fr -> 1fr). Diagnosed independently
   during this preview (not an owner-reported item, found live): that override replaces the
   quick-view plugin's own working max-height collapse with a single-row CSS-grid trick that
   needs `min-height:0` on `.bksesh-qv-panel-inner` to collapse to zero height; that rule was
   never added, so EVERY quick-view panel rendered ~460-480px tall at all times (opacity
   ~0.18, not fully invisible) regardless of toggle state — nearly doubling every card's
   height. Confirmed live via computed style: grid-template-rows resolved to ~458-478px, not
   0px, with no `.is-open` class present. This is the single biggest contributor to "desktop
   gone horribly wrong" (visually, a tall near-blank gradient gap in every card) and it is
   NOT scoped by any media query in the rolled-back build, so it hit mobile too (same
   ballooned-gap screenshot). Leaving `.bksesh-qv-panel` completely untouched avoids
   reintroducing this bug; the plugin's existing open/close animation is unaffected by
   anything in this block. */

/* 10h. Card photo CROSSFADE + swipe + dots (owner 2026-10-03: "images don't fade and missing
   nav dots like in /session"; same day clarification: swipe is mandatory, dots optional —
   included here because they come "for free" with the reused mechanics and match /session's
   own look exactly). Values/selectors are ported 1:1 from the SAME code already live on the
   /session archive (booksesh-card-gallery-preview/assets/card-gallery-preview.css) — same
   5px dot, same bottom:8px/gap:5px position, same 1300ms ease-in-out two-layer dissolve, same
   !important fight against the card template's own `transition-duration:.2s` longhand (see that
   file's §"ROOT-CAUSE FIX" comment for why !important is required here too), same GPU-layer
   promotion for a smooth mobile fade. touch-action:pan-y on the container is the OTHER half of
   the "don't block vertical scroll" requirement (single-polish.js's attachSwipe only ever calls
   preventDefault once a real horizontal drag is confirmed — this CSS property is the browser-
   native backstop so even the first few pixels of a vertical drag are never hijacked). */
body.bks-single-polish .elementor-widget-ts-post-feed .ts-preview .bks-sp-cgal {
  position: relative; touch-action: pan-y;
}
body.bks-single-polish .elementor-widget-ts-post-feed .ts-preview .bks-sp-cgal-slide {
  transition: opacity 1300ms ease-in-out !important;
  will-change: opacity; transform: translateZ(0);
  backface-visibility: hidden; -webkit-backface-visibility: hidden;
}
body.bks-single-polish .elementor-widget-ts-post-feed .ts-preview .bks-sp-cgal-slide:not(.bks-sp-cgal-base) {
  display: block; position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; opacity: 0 !important; pointer-events: none; z-index: 1;
}
body.bks-single-polish .elementor-widget-ts-post-feed .ts-preview .bks-sp-cgal-slide.bks-sp-cgal-base { opacity: 1 !important; }
body.bks-single-polish .elementor-widget-ts-post-feed .ts-preview .bks-sp-cgal-slide.bks-sp-cgal-base:not(.is-active) { opacity: 0 !important; }
body.bks-single-polish .elementor-widget-ts-post-feed .ts-preview .bks-sp-cgal-slide:not(.bks-sp-cgal-base).is-active { opacity: 1 !important; }
body.bks-single-polish .elementor-widget-ts-post-feed .ts-preview .bks-sp-cgal-dots {
  display: flex; position: absolute; left: 0; right: 0; bottom: 8px;
  justify-content: center; align-items: center; gap: 5px; z-index: 3; pointer-events: none;
}
body.bks-single-polish .elementor-widget-ts-post-feed .ts-preview .bks-sp-cgal-dot {
  width: 5px; height: 5px; border-radius: 50%;
  background: rgba(255,255,255,.55); box-shadow: 0 0 0 1px rgba(0,0,0,.15);
  transition: background 200ms ease, transform 200ms ease; transform: scale(1);
}
body.bks-single-polish .elementor-widget-ts-post-feed .ts-preview .bks-sp-cgal-dot.is-active { background: #ffffff; transform: scale(1.35); }

} /* end @media (max-width: 767px) */

/* 10i. Reduced motion (combined with the same mobile gate — these elements never exist above
   767px anyway): static first image, dissolve collapses to an effectively instant swap instead
   of the 1300ms fade. The dots stay visible as plain static indicators (not clickable either
   way — see single-polish.js comment on bksCardGalEnhance). */
@media (max-width: 767px) and (prefers-reduced-motion: reduce) {
  body.bks-single-polish .elementor-widget-ts-post-feed .ts-preview .bks-sp-cgal-slide {
    transition: opacity 1ms linear !important;
  }
}

/* ---------- 11. Category/"Browse more" term tiles — lavender gradient box (owner 2026-10-03:
   "the categories boxes should have the gradient fades as we did in the broken version — I
   liked that"). Context: the 2026-10-03 21:33 rolled-back build applied this exact box rule to
   a BARE `.ts-preview` selector, which leaked onto these term tiles (template 12442,
   `.ts-preview[data-term-id]`, "Browse more" → "Categories", e.g. "Holistic Treatments" /
   "13 places") as an unintended side effect — the rolled-back build's REAL bug was unrelated
   (the `.bksesh-qv-panel` grid-reveal ballooning every POST-feed card's height, see section 10g
   above); the owner saw this tile look in that broken screenshot and liked it independently of
   that bug. Re-created here DELIBERATELY, scoped ONLY to term-feed tiles
   (`[data-term-id]`, never `[data-post-id]`) so it can never again touch the "held by"/"More
   like this" POST-feed cards, the hero, or the sticky card. Applied at ALL breakpoints per
   owner's explicit instruction (not mobile-gated) — exact values copied verbatim from the
   broken backup (`single-polish.css.bak-feedskin-broken-20261003-215407`). */
body.bks-single-polish .ts-preview[data-term-id] {
  box-sizing: border-box; border: 1px solid rgba(122,90,240,.16) !important; border-radius: 14px !important;
  padding: 18px !important; background: linear-gradient(180deg,#EBE6FD 0%,#FFFFFF 78%) !important;
  box-shadow: 0 6px 20px rgba(122,90,240,.14), 0 2px 6px rgba(9,7,17,.07) !important;
  transition: transform .18s ease, box-shadow .18s ease;
}
body.bks-single-polish .ts-preview[data-term-id]:hover {
  transform: translateY(-3px); box-shadow: 0 14px 34px rgba(122,90,240,.20), 0 3px 8px rgba(9,7,17,.08) !important;
}
