/* JBH Color Mode System */
/* ================================================================
   JBH Starter Blocks — Frontend Styles
   Self-contained CSS for the 10 starter blocks.
   No build step required.  |  v1.0.9
   ================================================================ */

/* ── Global CSS Custom Properties ────────────────────────────── */
/* Brand palette exposed as CSS custom properties so child themes and
   user-authored CSS can tap into the JBH palette with
   `var(--jbh-teal-light)` / `var(--jbh-coral-light)` for subtle tinted
   surfaces. The plugin currently inlines the literal rgba values at
   ~30 spots because those values rarely need to retint per-site; the
   variables remain as public API contract for extenders. */
:root {
	--jbh-teal: #2A9D8F;
	--jbh-teal-dark: #1F5F5B;
	--jbh-teal-light: rgba(42, 157, 143, 0.10);
	--jbh-coral: #D64F42;
	--jbh-coral-light: rgba(214, 79, 66, 0.10);
	/* Brighter coral used by the studio modal submit-button hover state
	   (modal.css L1119-1121) and the recommended-card CTA hover (line 1171
	   below). Defined HERE rather than only in class-jbh-starter-blocksy-compat.php
	   so the live frontend has it too — the editor previewed correctly via
	   the Blocksy-compat injection but the published page resolved the
	   var() to its initial value, making the modal submit button's
	   background flash transparent on hover whenever the user hadn't
	   set a hover-bg picker. Same hex as the Blocksy-compat definition
	   (#E76F51) so the editor preview and live page are pixel-identical. */
	--jbh-coral-hover: #E76F51;
	--jbh-bg: #121212;
	--jbh-card: #1A1A1A;
	--jbh-creme: #F0EAD6;
	--jbh-slate: #9CA3AF;
	--jbh-border: rgba(31, 95, 91, 0.20);
	--jbh-font-sans: Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
	--jbh-font-serif: "Playfair Display", Georgia, serif;
	--jbh-font-mono: "Fira Code", monospace;
	--jbh-gap: 20px;
	--jbh-card-radius: 4px;
	--jbh-transition: 0.3s cubic-bezier(0.4, 0, 0.2, 1);
	--jbh-heading-color: #F0EAD6;
	--jbh-text-color: #9CA3AF;
	--jbh-card-heading: #ffffff;

	/* ── Ambience Tokens — Mode-Reactive Shadows, Backdrops & Decorations
	   These handle the "light-mode feels wrong" class of UX bugs where a
	   design decision tuned for dark mode (aggressive black shadows, heavy
	   near-opaque backdrops, near-invisible teal watermarks on light cards)
	   reads as sloppy when the site toggles light.

	   The defaults here are the dark-mode values the plugin has always
	   shipped (so nothing visually regresses on dark-mode sites). The
	   light-mode overrides live under html[data-theme="light"] / .light /
	   [data-color-mode="light"] / body[data-ct-color-mode="light"] + an
	   OS-level prefers-color-scheme fallback, so they react in lock-step
	   with Blocksy Pro's Colour Mode Switch, JBH Platform, and system
	   preference without any JS.

	   Because tokens are declared at :root (or body for Blocksy), they
	   cascade through the DOM into every descendant — including #jbh-modal-
	   overlay which is rendered in wp_footer outside any block wrapper. */
	--jbh-modal-backdrop:      rgba(0, 0, 0, 0.65);
	--jbh-modal-panel-shadow:  -8px 0 48px rgba(0, 0, 0, 0.5), -2px 0 8px rgba(0, 0, 0, 0.2);
	--jbh-modal-popup-shadow:  0 24px 80px rgba(0, 0, 0, 0.5);
	--jbh-pm-backdrop:         rgba(0, 0, 0, 0.80);
	--jbh-pm-shadow:           0 20px 60px rgba(0, 0, 0, 0.5);
	--jbh-watermark-color:        rgba(42, 157, 143, 0.05);
	--jbh-watermark-color-hover:  rgba(42, 157, 143, 0.10);
	--jbh-card-shadow-subtle:  0 4px 20px rgba(0, 0, 0, 0.08);
	--jbh-card-shadow-hover:   0 8px 30px rgba(0, 0, 0, 0.14);

	/* ── Dual-palette token defaults — see §"Dual-Palette Color Resolver" below.
	   These -dk / -lt slots are written inline by render.php ONLY when the
	   admin picks an explicit colour in the block inspector. Without these
	   :root defaults, an unset slot makes the alias `--jbh-filter-text:
	   var(--jbh-filter-text-dk)` resolve to invalid, which IACVT-poisons
	   every consumer (color/background/border) on the toolbar — the
	   inline fallback in `var(--jbh-filter-text, var(--jbh-text-color))`
	   does NOT kick in because the outer custom property IS defined,
	   just defined to invalid (CSS Custom Properties §3.2). The consumer
	   reverts to `unset`, color inherits the body's color (white on most
	   light themes) and renders white-on-white. Defining these defaults
	   here makes the alias chain resolve at use site to the mode-specific
	   global token (substitution is lazy / cascade-aware), so the toolbar
	   text/border are always visible regardless of admin overrides.

	   Only filter / sort / search toolbar tokens need this treatment —
	   every other dual-palette token is unconditionally written inline by
	   its block's render.php (it always has a base value to fall back
	   on, even with no admin override). */
	--jbh-filter-bg-dk:          var(--jbh-card);
	--jbh-filter-bg-lt:          var(--jbh-card);
	/* Toolbar text defaults — LITERAL slate values, not `var(--jbh-text-color)`.
	   Rationale: in `selfPalette:false` blocks, `--jbh-text-color` is mapped
	   to Blocksy `--theme-palette-color-3` (body text). When a `.jbh-light`
	   block lives on a Blocksy site whose colour-mode toggle is set to dark,
	   palette-3 holds a LIGHT cream-grey value while `.jbh-light` paints the
	   card #FFFFFF — net effect: invisible white-on-white search text /
	   placeholder. Same trap fires under Chrome's "Auto Dark" experiment,
	   where browser-applied colour transformations leak through any chain
	   that doesn't break free of `--jbh-text-color`.
	   The Inspector pickers (`filterText` / `filterTextLight`) still
	   override these literals via render.php inline writes, so editors
	   keep full retint freedom. */
	--jbh-filter-text-dk:        #9CA3AF;
	--jbh-filter-text-lt:        #4B5563;
	--jbh-filter-border-dk:      var(--jbh-border);
	/* Light-mode default bumped above the global `--jbh-border` (rgba 0/0/0/0.12)
	   because a 12 %% black border on a #FFFFFF card reads as essentially
	   white in real-world lighting — the toolbar / search bar / sort dropdown
	   all silently lost their outline in light mode while dark mode still got
	   the teal-tinted line at 20 %% opacity. 22 %% black gives a clean visible
	   neutral that mirrors the dark-mode line’s perceived weight without
	   pulling in a brand colour the editor may not want on light surfaces.
	   Editors who do want a different tint can still override it via the
	   block’s `filterBorderLight` Inspector picker. */
	--jbh-filter-border-lt:      rgba(0, 0, 0, 0.22);
	--jbh-filter-active-bg-dk:   var(--jbh-teal);
	--jbh-filter-active-bg-lt:   var(--jbh-teal);
	--jbh-filter-active-text-dk: #ffffff;
	--jbh-filter-active-text-lt: #ffffff;
}

/* ── Dark / Light Mode — Block-level classes ────────────────── */
.jbh-dark {
	--jbh-bg: #121212; --jbh-card: #1A1A1A; --jbh-creme: #F0EAD6;
	--jbh-slate: #9CA3AF; --jbh-heading-color: #F0EAD6;
	--jbh-text-color: #9CA3AF; --jbh-card-heading: #ffffff;
	--jbh-border: rgba(31, 95, 91, 0.20);
}
.jbh-light {
	--jbh-bg: #F9F8F6; --jbh-card: #FFFFFF; --jbh-creme: #121212;
	--jbh-slate: #4B5563; --jbh-heading-color: #121212;
	--jbh-text-color: #4B5563; --jbh-card-heading: #121212;
	--jbh-border: rgba(0, 0, 0, 0.12);
}

/* ── Dual-Palette Color Resolver ────────────────────────────────
   render.php outputs -dk (dark) and -lt (light) suffixed custom
   property variants. The active .jbh-dark / .jbh-light class on
   each block resolves them into the mode-agnostic variable that
   the rest of the CSS already consumes via var(--jbh-custom-*, …).

   IMPORTANT: when a -dk / -lt slot is NOT defined inline by render.php,
   the alias chain `--jbh-X: var(--jbh-X-dk)` resolves to the guaranteed-
   invalid value, which IACVT-poisons every consumer property per
   CSS Custom Properties §3.2 — the inline fallback in
   `var(--jbh-X, fallback)` is NOT used because the outer custom
   property IS defined (just defined to invalid). Two strategies in
   this stylesheet keep that from breaking real pages:

   1. For tokens that render.php ALWAYS writes inline (every grid /
      hero / CTA / about / insights / page-intro / section-header
      colour pair), the inline write itself is the safety net — the
      slot is never undefined in practice.
   2. For tokens render.php writes CONDITIONALLY (only when the admin
      explicitly picks a toolbar colour: the five filter / sort /
      search slots), the slot has a `:root` default above that points
      at the corresponding mode-agnostic global token (`--jbh-text-color`,
      `--jbh-card`, `--jbh-border`, etc.). Substitution is lazy, so the
      default resolves to the active mode's value at the consumer's
      use site, regardless of which `.jbh-dark` / `.jbh-light` block
      is in scope. */
.jbh-dark {
	/* Grid blocks shared */
	--jbh-custom-header: var(--jbh-custom-header-dk);
	--jbh-custom-price: var(--jbh-custom-price-dk);
	--jbh-custom-desc: var(--jbh-custom-desc-dk);
	--jbh-custom-icon: var(--jbh-custom-icon-dk);
	--jbh-custom-btn: var(--jbh-custom-btn-dk);
	--jbh-custom-btn-text: var(--jbh-custom-btn-text-dk);
	--jbh-custom-card-bg: var(--jbh-custom-card-bg-dk);
	--jbh-custom-card-border: var(--jbh-custom-card-border-dk);
	--jbh-custom-btn-hover: var(--jbh-custom-btn-hover-dk);
	--jbh-custom-btn-hover-text: var(--jbh-custom-btn-hover-text-dk);
	--jbh-custom-badge: var(--jbh-custom-badge-dk);
	--jbh-custom-target: var(--jbh-custom-target-dk);
	--jbh-custom-tag: var(--jbh-custom-tag-dk);
	--jbh-custom-block-bg: var(--jbh-custom-block-bg-dk);
	/* Studio grid — Target band text + price/timeline footer text.
	   Previously these elements had no independent customisation
	   path, so user-picked Target Band / Timeline / Price Label
	   colours could only affect the *label* and not the *text*.
	   Adding dedicated aliases fixes that asymmetry end-to-end. */
	--jbh-custom-target-text:    var(--jbh-custom-target-text-dk);
	--jbh-custom-timeline-label: var(--jbh-custom-timeline-label-dk);
	--jbh-custom-timeline-value: var(--jbh-custom-timeline-value-dk);
	--jbh-custom-price-label:    var(--jbh-custom-price-label-dk);
	/* Studio grid — Card header / icon-box / target-band surfaces. */
	--jbh-custom-card-header-bg: var(--jbh-custom-card-header-bg-dk);
	--jbh-custom-icon-box-bg:    var(--jbh-custom-icon-box-bg-dk);
	--jbh-custom-target-band-bg: var(--jbh-custom-target-band-bg-dk);
	/* Studio grid — Includes section */
	--jbh-custom-includes-label: var(--jbh-custom-includes-label-dk);
	--jbh-custom-includes-text:  var(--jbh-custom-includes-text-dk);
	--jbh-custom-includes-icon:  var(--jbh-custom-includes-icon-dk);
	/* Studio grid — Add-ons section */
	--jbh-custom-addons-label:   var(--jbh-custom-addons-label-dk);
	--jbh-custom-addons-pill-bg: var(--jbh-custom-addons-pill-bg-dk);
	--jbh-custom-addons-pill-bd: var(--jbh-custom-addons-pill-bd-dk);
	--jbh-custom-addons-pill-tx: var(--jbh-custom-addons-pill-tx-dk);
	--jbh-custom-addons-price:   var(--jbh-custom-addons-price-dk);
	/* Studio grid — Card footer tint (behind the CTA button) */
	--jbh-custom-card-footer-bg: var(--jbh-custom-card-footer-bg-dk);
	/* Pricing plans — Billing-period toggle (track off / track on / dot).
	   Lets users retint the tiny switch that flips Monthly ↔ Yearly so
	   it matches the rest of the block's palette in either mode. */
	--jbh-custom-toggle-track:        var(--jbh-custom-toggle-track-dk);
	--jbh-custom-toggle-track-active: var(--jbh-custom-toggle-track-active-dk);
	--jbh-custom-toggle-dot:          var(--jbh-custom-toggle-dot-dk);
	/* Store grid — Product badge ("NEW" etc.) colours */
	--jbh-custom-badge-bg:   var(--jbh-custom-badge-bg-dk);
	--jbh-custom-badge-text: var(--jbh-custom-badge-text-dk);
	/* Store grid — Featured-product outline picker */
	--jbh-featured-outline:  var(--jbh-featured-outline-dk);
	/* Store grid — Filter / sort / search toolbar colours */
	--jbh-filter-bg:          var(--jbh-filter-bg-dk);
	--jbh-filter-text:        var(--jbh-filter-text-dk);
	--jbh-filter-border:      var(--jbh-filter-border-dk);
	--jbh-filter-active-bg:   var(--jbh-filter-active-bg-dk);
	--jbh-filter-active-text: var(--jbh-filter-active-text-dk);
	/* Hero section */
	--jbh-hero-heading-color: var(--jbh-hero-heading-dk);
	--jbh-hero-heading2-color: var(--jbh-hero-heading2-dk);
	--jbh-hero-subtitle-color: var(--jbh-hero-subtitle-dk);
	--jbh-hero-badge-color: var(--jbh-hero-badge-dk);
	--jbh-hero-btn-bg: var(--jbh-hero-btn-dk);
	--jbh-hero-btn-text: var(--jbh-hero-btn-text-dk);
	--jbh-hero-btn-hover-bg: var(--jbh-hero-btn-hover-dk);
	--jbh-hero-btn-hover-text: var(--jbh-hero-btn-hover-text-dk);
	--jbh-hero-sec-btn-bg: var(--jbh-hero-sec-btn-dk);
	--jbh-hero-sec-btn-text: var(--jbh-hero-sec-btn-text-dk);
	--jbh-hero-feat-card-bg: var(--jbh-hero-feat-card-bg-dk);
	--jbh-hero-feat-heading: var(--jbh-hero-feat-heading-dk);
	--jbh-hero-feat-desc: var(--jbh-hero-feat-desc-dk);
	--jbh-hero-feat-icon: var(--jbh-hero-feat-icon-dk);
	--jbh-hero-feat-eyebrow: var(--jbh-hero-feat-eyebrow-dk);
	/* Section header */
	--jbh-sh-heading-color: var(--jbh-sh-heading-dk);
	--jbh-sh-subtitle-color: var(--jbh-sh-subtitle-dk);
	--jbh-sh-badge-color: var(--jbh-sh-badge-dk);
	/* Page intro */
	--jbh-pi-heading-color: var(--jbh-pi-heading-dk);
	--jbh-pi-subtitle-color: var(--jbh-pi-subtitle-dk);
	--jbh-pi-label-color: var(--jbh-pi-label-dk);
	--jbh-pi-callout-text-color: var(--jbh-pi-callout-text-dk);
	--jbh-pi-status-text-color: var(--jbh-pi-status-text-dk);
	--jbh-pi-callout-border: var(--jbh-pi-callout-border-dk);
	/* CTA banner */
	--jbh-cta-heading-color: var(--jbh-cta-heading-dk);
	--jbh-cta-subtitle-color: var(--jbh-cta-subtitle-dk);
	--jbh-cta-badge-color: var(--jbh-cta-badge-dk);
	--jbh-cta-btn-bg: var(--jbh-cta-btn-dk);
	--jbh-cta-btn-text: var(--jbh-cta-btn-text-dk);
	--jbh-cta-btn-hover-bg: var(--jbh-cta-btn-hover-dk);
	--jbh-cta-btn-hover-text: var(--jbh-cta-btn-hover-text-dk);
	/* About section */
	--jbh-about-heading-color: var(--jbh-about-heading-dk);
	--jbh-about-bio-color: var(--jbh-about-bio-dk);
	--jbh-about-label-color: var(--jbh-about-label-dk);
	--jbh-about-card-bg: var(--jbh-about-card-bg-dk);
	/* Insights grid */
	--jbh-ig-heading-color: var(--jbh-ig-heading-dk);
	--jbh-ig-excerpt-color: var(--jbh-ig-excerpt-dk);
	--jbh-ig-category-color: var(--jbh-ig-category-dk);
	--jbh-ig-link-color: var(--jbh-ig-link-dk);
	--jbh-ig-date-color: var(--jbh-ig-date-dk);
	--jbh-ig-tag-color: var(--jbh-ig-tag-dk);
	--jbh-ig-author-color: var(--jbh-ig-author-dk);
	--jbh-ig-link-hover-color: var(--jbh-ig-link-hover-dk);
	--jbh-ig-meta-bg: var(--jbh-ig-meta-bg-dk);
	--jbh-ig-card-bg: var(--jbh-ig-card-bg-dk);
	--jbh-ig-card-border: var(--jbh-ig-card-border-dk);
	--jbh-ig-icon-color: var(--jbh-ig-icon-dk);
	/* Portfolio grid */
	--jbh-pf-subtitle-color: var(--jbh-pf-subtitle-dk);
	--jbh-pf-meta-color: var(--jbh-pf-meta-dk);
	--jbh-pf-icon-label-color: var(--jbh-pf-icon-label-dk);
}
.jbh-light {
	/* Grid blocks shared */
	--jbh-custom-header: var(--jbh-custom-header-lt);
	--jbh-custom-price: var(--jbh-custom-price-lt);
	--jbh-custom-desc: var(--jbh-custom-desc-lt);
	--jbh-custom-icon: var(--jbh-custom-icon-lt);
	--jbh-custom-btn: var(--jbh-custom-btn-lt);
	--jbh-custom-btn-text: var(--jbh-custom-btn-text-lt);
	--jbh-custom-card-bg: var(--jbh-custom-card-bg-lt);
	--jbh-custom-card-border: var(--jbh-custom-card-border-lt);
	--jbh-custom-btn-hover: var(--jbh-custom-btn-hover-lt);
	--jbh-custom-btn-hover-text: var(--jbh-custom-btn-hover-text-lt);
	--jbh-custom-badge: var(--jbh-custom-badge-lt);
	--jbh-custom-target: var(--jbh-custom-target-lt);
	--jbh-custom-tag: var(--jbh-custom-tag-lt);
	--jbh-custom-block-bg: var(--jbh-custom-block-bg-lt);
	/* Studio grid — Target band text + price/timeline footer text. */
	--jbh-custom-target-text:    var(--jbh-custom-target-text-lt);
	--jbh-custom-timeline-label: var(--jbh-custom-timeline-label-lt);
	--jbh-custom-timeline-value: var(--jbh-custom-timeline-value-lt);
	--jbh-custom-price-label:    var(--jbh-custom-price-label-lt);
	/* Studio grid — Card header / icon-box / target-band surfaces. */
	--jbh-custom-card-header-bg: var(--jbh-custom-card-header-bg-lt);
	--jbh-custom-icon-box-bg:    var(--jbh-custom-icon-box-bg-lt);
	--jbh-custom-target-band-bg: var(--jbh-custom-target-band-bg-lt);
	/* Studio grid — Includes section */
	--jbh-custom-includes-label: var(--jbh-custom-includes-label-lt);
	--jbh-custom-includes-text:  var(--jbh-custom-includes-text-lt);
	--jbh-custom-includes-icon:  var(--jbh-custom-includes-icon-lt);
	/* Studio grid — Add-ons section */
	--jbh-custom-addons-label:   var(--jbh-custom-addons-label-lt);
	--jbh-custom-addons-pill-bg: var(--jbh-custom-addons-pill-bg-lt);
	--jbh-custom-addons-pill-bd: var(--jbh-custom-addons-pill-bd-lt);
	--jbh-custom-addons-pill-tx: var(--jbh-custom-addons-pill-tx-lt);
	--jbh-custom-addons-price:   var(--jbh-custom-addons-price-lt);
	/* Studio grid — Card footer tint (behind the CTA button) */
	--jbh-custom-card-footer-bg: var(--jbh-custom-card-footer-bg-lt);
	/* Pricing plans — Billing-period toggle (light-mode aliases). */
	--jbh-custom-toggle-track:        var(--jbh-custom-toggle-track-lt);
	--jbh-custom-toggle-track-active: var(--jbh-custom-toggle-track-active-lt);
	--jbh-custom-toggle-dot:          var(--jbh-custom-toggle-dot-lt);
	/* Store grid — Product badge (light-mode aliases). */
	--jbh-custom-badge-bg:   var(--jbh-custom-badge-bg-lt);
	--jbh-custom-badge-text: var(--jbh-custom-badge-text-lt);
	/* Store grid — Featured-product outline (light-mode alias). */
	--jbh-featured-outline:  var(--jbh-featured-outline-lt);
	/* Store grid — Filter / sort / search toolbar (light-mode aliases). */
	--jbh-filter-bg:          var(--jbh-filter-bg-lt);
	--jbh-filter-text:        var(--jbh-filter-text-lt);
	--jbh-filter-border:      var(--jbh-filter-border-lt);
	--jbh-filter-active-bg:   var(--jbh-filter-active-bg-lt);
	--jbh-filter-active-text: var(--jbh-filter-active-text-lt);
	/* Hero section */
	--jbh-hero-heading-color: var(--jbh-hero-heading-lt);
	--jbh-hero-heading2-color: var(--jbh-hero-heading2-lt);
	--jbh-hero-subtitle-color: var(--jbh-hero-subtitle-lt);
	--jbh-hero-badge-color: var(--jbh-hero-badge-lt);
	--jbh-hero-btn-bg: var(--jbh-hero-btn-lt);
	--jbh-hero-btn-text: var(--jbh-hero-btn-text-lt);
	--jbh-hero-btn-hover-bg: var(--jbh-hero-btn-hover-lt);
	--jbh-hero-btn-hover-text: var(--jbh-hero-btn-hover-text-lt);
	--jbh-hero-sec-btn-bg: var(--jbh-hero-sec-btn-lt);
	--jbh-hero-sec-btn-text: var(--jbh-hero-sec-btn-text-lt);
	--jbh-hero-feat-card-bg: var(--jbh-hero-feat-card-bg-lt);
	--jbh-hero-feat-heading: var(--jbh-hero-feat-heading-lt);
	--jbh-hero-feat-desc: var(--jbh-hero-feat-desc-lt);
	--jbh-hero-feat-icon: var(--jbh-hero-feat-icon-lt);
	--jbh-hero-feat-eyebrow: var(--jbh-hero-feat-eyebrow-lt);
	/* Section header */
	--jbh-sh-heading-color: var(--jbh-sh-heading-lt);
	--jbh-sh-subtitle-color: var(--jbh-sh-subtitle-lt);
	--jbh-sh-badge-color: var(--jbh-sh-badge-lt);
	/* Page intro */
	--jbh-pi-heading-color: var(--jbh-pi-heading-lt);
	--jbh-pi-subtitle-color: var(--jbh-pi-subtitle-lt);
	--jbh-pi-label-color: var(--jbh-pi-label-lt);
	--jbh-pi-callout-text-color: var(--jbh-pi-callout-text-lt);
	--jbh-pi-status-text-color: var(--jbh-pi-status-text-lt);
	--jbh-pi-callout-border: var(--jbh-pi-callout-border-lt);
	/* CTA banner */
	--jbh-cta-heading-color: var(--jbh-cta-heading-lt);
	--jbh-cta-subtitle-color: var(--jbh-cta-subtitle-lt);
	--jbh-cta-badge-color: var(--jbh-cta-badge-lt);
	--jbh-cta-btn-bg: var(--jbh-cta-btn-lt);
	--jbh-cta-btn-text: var(--jbh-cta-btn-text-lt);
	--jbh-cta-btn-hover-bg: var(--jbh-cta-btn-hover-lt);
	--jbh-cta-btn-hover-text: var(--jbh-cta-btn-hover-text-lt);
	/* About section */
	--jbh-about-heading-color: var(--jbh-about-heading-lt);
	--jbh-about-bio-color: var(--jbh-about-bio-lt);
	--jbh-about-label-color: var(--jbh-about-label-lt);
	--jbh-about-card-bg: var(--jbh-about-card-bg-lt);
	/* Insights grid */
	--jbh-ig-heading-color: var(--jbh-ig-heading-lt);
	--jbh-ig-excerpt-color: var(--jbh-ig-excerpt-lt);
	--jbh-ig-category-color: var(--jbh-ig-category-lt);
	--jbh-ig-link-color: var(--jbh-ig-link-lt);
	--jbh-ig-date-color: var(--jbh-ig-date-lt);
	--jbh-ig-tag-color: var(--jbh-ig-tag-lt);
	--jbh-ig-author-color: var(--jbh-ig-author-lt);
	--jbh-ig-link-hover-color: var(--jbh-ig-link-hover-lt);
	--jbh-ig-meta-bg: var(--jbh-ig-meta-bg-lt);
	--jbh-ig-card-bg: var(--jbh-ig-card-bg-lt);
	--jbh-ig-card-border: var(--jbh-ig-card-border-lt);
	--jbh-ig-icon-color: var(--jbh-ig-icon-lt);
	/* Portfolio grid */
	--jbh-pf-subtitle-color: var(--jbh-pf-subtitle-lt);
	--jbh-pf-meta-color: var(--jbh-pf-meta-lt);
	--jbh-pf-icon-label-color: var(--jbh-pf-icon-label-lt);
}

/* ── Auto Mode — Follows site-wide color-mode switch ────────────
   Blocks with colorMode="auto" emit `.jbh-auto` instead of
   `.jbh-dark` / `.jbh-light`. Unlike those, `.jbh-auto` deliberately
   does NOT declare the base surface vars (--jbh-bg, --jbh-card, …)
   — those cascade down naturally from the html-level cascade at
   lines 182-207, which already reacts to Blocksy's Colour Mode
   Switch, JBH Platform's data-theme, and OS prefers-color-scheme.
   Leaving them unset means the block's base palette follows the
   site in real-time with zero extra JS.

   What `.jbh-auto` DOES define is the dual-palette custom-var
   resolver, because those aliases only exist at block scope and
   can't cascade from html. Default branch aliases the `-dk`
   variants (matching :root's dark seed); the three selector sets
   below flip them to `-lt` when any of the four recognised
   light-mode site signals are active. ────────────────────── */
.jbh-auto {
	/* Grid blocks shared — dark aliases (default branch) */
	--jbh-custom-header: var(--jbh-custom-header-dk);
	--jbh-custom-price: var(--jbh-custom-price-dk);
	--jbh-custom-desc: var(--jbh-custom-desc-dk);
	--jbh-custom-icon: var(--jbh-custom-icon-dk);
	--jbh-custom-btn: var(--jbh-custom-btn-dk);
	--jbh-custom-btn-text: var(--jbh-custom-btn-text-dk);
	--jbh-custom-card-bg: var(--jbh-custom-card-bg-dk);
	--jbh-custom-card-border: var(--jbh-custom-card-border-dk);
	--jbh-custom-btn-hover: var(--jbh-custom-btn-hover-dk);
	--jbh-custom-btn-hover-text: var(--jbh-custom-btn-hover-text-dk);
	--jbh-custom-badge: var(--jbh-custom-badge-dk);
	--jbh-custom-target: var(--jbh-custom-target-dk);
	--jbh-custom-tag: var(--jbh-custom-tag-dk);
	--jbh-custom-block-bg: var(--jbh-custom-block-bg-dk);
	/* Studio grid — Target band text + price/timeline footer text. */
	--jbh-custom-target-text:    var(--jbh-custom-target-text-dk);
	--jbh-custom-timeline-label: var(--jbh-custom-timeline-label-dk);
	--jbh-custom-timeline-value: var(--jbh-custom-timeline-value-dk);
	--jbh-custom-price-label:    var(--jbh-custom-price-label-dk);
	/* Studio grid — Card header / icon-box / target-band surfaces. */
	--jbh-custom-card-header-bg: var(--jbh-custom-card-header-bg-dk);
	--jbh-custom-icon-box-bg:    var(--jbh-custom-icon-box-bg-dk);
	--jbh-custom-target-band-bg: var(--jbh-custom-target-band-bg-dk);
	/* Studio grid — Includes section */
	--jbh-custom-includes-label: var(--jbh-custom-includes-label-dk);
	--jbh-custom-includes-text:  var(--jbh-custom-includes-text-dk);
	--jbh-custom-includes-icon:  var(--jbh-custom-includes-icon-dk);
	/* Studio grid — Add-ons section */
	--jbh-custom-addons-label:   var(--jbh-custom-addons-label-dk);
	--jbh-custom-addons-pill-bg: var(--jbh-custom-addons-pill-bg-dk);
	--jbh-custom-addons-pill-bd: var(--jbh-custom-addons-pill-bd-dk);
	--jbh-custom-addons-pill-tx: var(--jbh-custom-addons-pill-tx-dk);
	--jbh-custom-addons-price:   var(--jbh-custom-addons-price-dk);
	/* Studio grid — Card footer tint */
	--jbh-custom-card-footer-bg: var(--jbh-custom-card-footer-bg-dk);
	/* Pricing plans — Billing-period toggle (dark-mode aliases). */
	--jbh-custom-toggle-track:        var(--jbh-custom-toggle-track-dk);
	--jbh-custom-toggle-track-active: var(--jbh-custom-toggle-track-active-dk);
	--jbh-custom-toggle-dot:          var(--jbh-custom-toggle-dot-dk);
	/* Store grid — Product badge */
	--jbh-custom-badge-bg:   var(--jbh-custom-badge-bg-dk);
	--jbh-custom-badge-text: var(--jbh-custom-badge-text-dk);
	/* Store grid — Featured-product outline */
	--jbh-featured-outline:  var(--jbh-featured-outline-dk);
	/* Store grid — Filter / sort / search toolbar */
	--jbh-filter-bg:          var(--jbh-filter-bg-dk);
	--jbh-filter-text:        var(--jbh-filter-text-dk);
	--jbh-filter-border:      var(--jbh-filter-border-dk);
	--jbh-filter-active-bg:   var(--jbh-filter-active-bg-dk);
	--jbh-filter-active-text: var(--jbh-filter-active-text-dk);
	/* Hero section */
	--jbh-hero-heading-color: var(--jbh-hero-heading-dk);
	--jbh-hero-heading2-color: var(--jbh-hero-heading2-dk);
	--jbh-hero-subtitle-color: var(--jbh-hero-subtitle-dk);
	--jbh-hero-badge-color: var(--jbh-hero-badge-dk);
	--jbh-hero-btn-bg: var(--jbh-hero-btn-dk);
	--jbh-hero-btn-text: var(--jbh-hero-btn-text-dk);
	--jbh-hero-btn-hover-bg: var(--jbh-hero-btn-hover-dk);
	--jbh-hero-btn-hover-text: var(--jbh-hero-btn-hover-text-dk);
	--jbh-hero-sec-btn-bg: var(--jbh-hero-sec-btn-dk);
	--jbh-hero-sec-btn-text: var(--jbh-hero-sec-btn-text-dk);
	--jbh-hero-feat-card-bg: var(--jbh-hero-feat-card-bg-dk);
	--jbh-hero-feat-heading: var(--jbh-hero-feat-heading-dk);
	--jbh-hero-feat-desc: var(--jbh-hero-feat-desc-dk);
	--jbh-hero-feat-icon: var(--jbh-hero-feat-icon-dk);
	--jbh-hero-feat-eyebrow: var(--jbh-hero-feat-eyebrow-dk);
	/* Section header */
	--jbh-sh-heading-color: var(--jbh-sh-heading-dk);
	--jbh-sh-subtitle-color: var(--jbh-sh-subtitle-dk);
	--jbh-sh-badge-color: var(--jbh-sh-badge-dk);
	/* Page intro */
	--jbh-pi-heading-color: var(--jbh-pi-heading-dk);
	--jbh-pi-subtitle-color: var(--jbh-pi-subtitle-dk);
	--jbh-pi-label-color: var(--jbh-pi-label-dk);
	--jbh-pi-callout-text-color: var(--jbh-pi-callout-text-dk);
	--jbh-pi-status-text-color: var(--jbh-pi-status-text-dk);
	--jbh-pi-callout-border: var(--jbh-pi-callout-border-dk);
	/* CTA banner */
	--jbh-cta-heading-color: var(--jbh-cta-heading-dk);
	--jbh-cta-subtitle-color: var(--jbh-cta-subtitle-dk);
	--jbh-cta-badge-color: var(--jbh-cta-badge-dk);
	--jbh-cta-btn-bg: var(--jbh-cta-btn-dk);
	--jbh-cta-btn-text: var(--jbh-cta-btn-text-dk);
	--jbh-cta-btn-hover-bg: var(--jbh-cta-btn-hover-dk);
	--jbh-cta-btn-hover-text: var(--jbh-cta-btn-hover-text-dk);
	/* About section */
	--jbh-about-heading-color: var(--jbh-about-heading-dk);
	--jbh-about-bio-color: var(--jbh-about-bio-dk);
	--jbh-about-label-color: var(--jbh-about-label-dk);
	--jbh-about-card-bg: var(--jbh-about-card-bg-dk);
	/* Insights grid */
	--jbh-ig-heading-color: var(--jbh-ig-heading-dk);
	--jbh-ig-excerpt-color: var(--jbh-ig-excerpt-dk);
	--jbh-ig-category-color: var(--jbh-ig-category-dk);
	--jbh-ig-link-color: var(--jbh-ig-link-dk);
	--jbh-ig-date-color: var(--jbh-ig-date-dk);
	--jbh-ig-tag-color: var(--jbh-ig-tag-dk);
	--jbh-ig-author-color: var(--jbh-ig-author-dk);
	--jbh-ig-link-hover-color: var(--jbh-ig-link-hover-dk);
	--jbh-ig-meta-bg: var(--jbh-ig-meta-bg-dk);
	--jbh-ig-card-bg: var(--jbh-ig-card-bg-dk);
	--jbh-ig-card-border: var(--jbh-ig-card-border-dk);
	--jbh-ig-icon-color: var(--jbh-ig-icon-dk);
	/* Portfolio grid */
	--jbh-pf-subtitle-color: var(--jbh-pf-subtitle-dk);
	--jbh-pf-meta-color: var(--jbh-pf-meta-dk);
	--jbh-pf-icon-label-color: var(--jbh-pf-icon-label-dk);
}

/* Site signalled LIGHT mode → flip auto-block custom-var aliases
   to the -lt variants. Four selector families cover the supported
   toggles:
     · html[data-theme="light"]      (JBH Platform / WP core convention)
     · html.light                    (class-based convention)
     · html[data-color-mode="light"] (some custom themes)
     · body[data-ct-color-mode="light"] (Blocksy Pro Colour Mode Switch) */
html[data-theme="light"] .jbh-auto,
html.light .jbh-auto,
html[data-color-mode="light"] .jbh-auto,
body[data-ct-color-mode="light"] .jbh-auto {
	/* Grid blocks shared */
	--jbh-custom-header: var(--jbh-custom-header-lt);
	--jbh-custom-price: var(--jbh-custom-price-lt);
	--jbh-custom-desc: var(--jbh-custom-desc-lt);
	--jbh-custom-icon: var(--jbh-custom-icon-lt);
	--jbh-custom-btn: var(--jbh-custom-btn-lt);
	--jbh-custom-btn-text: var(--jbh-custom-btn-text-lt);
	--jbh-custom-card-bg: var(--jbh-custom-card-bg-lt);
	--jbh-custom-card-border: var(--jbh-custom-card-border-lt);
	--jbh-custom-btn-hover: var(--jbh-custom-btn-hover-lt);
	--jbh-custom-btn-hover-text: var(--jbh-custom-btn-hover-text-lt);
	--jbh-custom-badge: var(--jbh-custom-badge-lt);
	--jbh-custom-target: var(--jbh-custom-target-lt);
	--jbh-custom-tag: var(--jbh-custom-tag-lt);
	--jbh-custom-block-bg: var(--jbh-custom-block-bg-lt);
	/* Studio grid — Target band text + price/timeline footer text. */
	--jbh-custom-target-text:    var(--jbh-custom-target-text-lt);
	--jbh-custom-timeline-label: var(--jbh-custom-timeline-label-lt);
	--jbh-custom-timeline-value: var(--jbh-custom-timeline-value-lt);
	--jbh-custom-price-label:    var(--jbh-custom-price-label-lt);
	/* Studio grid — Card header / icon-box / target-band surfaces. */
	--jbh-custom-card-header-bg: var(--jbh-custom-card-header-bg-lt);
	--jbh-custom-icon-box-bg:    var(--jbh-custom-icon-box-bg-lt);
	--jbh-custom-target-band-bg: var(--jbh-custom-target-band-bg-lt);
	/* Studio grid — Includes section */
	--jbh-custom-includes-label: var(--jbh-custom-includes-label-lt);
	--jbh-custom-includes-text:  var(--jbh-custom-includes-text-lt);
	--jbh-custom-includes-icon:  var(--jbh-custom-includes-icon-lt);
	/* Studio grid — Add-ons section */
	--jbh-custom-addons-label:   var(--jbh-custom-addons-label-lt);
	--jbh-custom-addons-pill-bg: var(--jbh-custom-addons-pill-bg-lt);
	--jbh-custom-addons-pill-bd: var(--jbh-custom-addons-pill-bd-lt);
	--jbh-custom-addons-pill-tx: var(--jbh-custom-addons-pill-tx-lt);
	--jbh-custom-addons-price:   var(--jbh-custom-addons-price-lt);
	/* Studio grid — Card footer tint */
	--jbh-custom-card-footer-bg: var(--jbh-custom-card-footer-bg-lt);
	/* Pricing plans — Billing-period toggle (light-mode aliases). */
	--jbh-custom-toggle-track:        var(--jbh-custom-toggle-track-lt);
	--jbh-custom-toggle-track-active: var(--jbh-custom-toggle-track-active-lt);
	--jbh-custom-toggle-dot:          var(--jbh-custom-toggle-dot-lt);
	/* Store grid — Product badge */
	--jbh-custom-badge-bg:   var(--jbh-custom-badge-bg-lt);
	--jbh-custom-badge-text: var(--jbh-custom-badge-text-lt);
	/* Store grid — Featured-product outline */
	--jbh-featured-outline:  var(--jbh-featured-outline-lt);
	/* Store grid — Filter / sort / search toolbar */
	--jbh-filter-bg:          var(--jbh-filter-bg-lt);
	--jbh-filter-text:        var(--jbh-filter-text-lt);
	--jbh-filter-border:      var(--jbh-filter-border-lt);
	--jbh-filter-active-bg:   var(--jbh-filter-active-bg-lt);
	--jbh-filter-active-text: var(--jbh-filter-active-text-lt);
	/* Hero section */
	--jbh-hero-heading-color: var(--jbh-hero-heading-lt);
	--jbh-hero-heading2-color: var(--jbh-hero-heading2-lt);
	--jbh-hero-subtitle-color: var(--jbh-hero-subtitle-lt);
	--jbh-hero-badge-color: var(--jbh-hero-badge-lt);
	--jbh-hero-btn-bg: var(--jbh-hero-btn-lt);
	--jbh-hero-btn-text: var(--jbh-hero-btn-text-lt);
	--jbh-hero-btn-hover-bg: var(--jbh-hero-btn-hover-lt);
	--jbh-hero-btn-hover-text: var(--jbh-hero-btn-hover-text-lt);
	--jbh-hero-sec-btn-bg: var(--jbh-hero-sec-btn-lt);
	--jbh-hero-sec-btn-text: var(--jbh-hero-sec-btn-text-lt);
	--jbh-hero-feat-card-bg: var(--jbh-hero-feat-card-bg-lt);
	--jbh-hero-feat-heading: var(--jbh-hero-feat-heading-lt);
	--jbh-hero-feat-desc: var(--jbh-hero-feat-desc-lt);
	--jbh-hero-feat-icon: var(--jbh-hero-feat-icon-lt);
	--jbh-hero-feat-eyebrow: var(--jbh-hero-feat-eyebrow-lt);
	/* Section header */
	--jbh-sh-heading-color: var(--jbh-sh-heading-lt);
	--jbh-sh-subtitle-color: var(--jbh-sh-subtitle-lt);
	--jbh-sh-badge-color: var(--jbh-sh-badge-lt);
	/* Page intro */
	--jbh-pi-heading-color: var(--jbh-pi-heading-lt);
	--jbh-pi-subtitle-color: var(--jbh-pi-subtitle-lt);
	--jbh-pi-label-color: var(--jbh-pi-label-lt);
	--jbh-pi-callout-text-color: var(--jbh-pi-callout-text-lt);
	--jbh-pi-status-text-color: var(--jbh-pi-status-text-lt);
	--jbh-pi-callout-border: var(--jbh-pi-callout-border-lt);
	/* CTA banner */
	--jbh-cta-heading-color: var(--jbh-cta-heading-lt);
	--jbh-cta-subtitle-color: var(--jbh-cta-subtitle-lt);
	--jbh-cta-badge-color: var(--jbh-cta-badge-lt);
	--jbh-cta-btn-bg: var(--jbh-cta-btn-lt);
	--jbh-cta-btn-text: var(--jbh-cta-btn-text-lt);
	--jbh-cta-btn-hover-bg: var(--jbh-cta-btn-hover-lt);
	--jbh-cta-btn-hover-text: var(--jbh-cta-btn-hover-text-lt);
	/* About section */
	--jbh-about-heading-color: var(--jbh-about-heading-lt);
	--jbh-about-bio-color: var(--jbh-about-bio-lt);
	--jbh-about-label-color: var(--jbh-about-label-lt);
	--jbh-about-card-bg: var(--jbh-about-card-bg-lt);
	/* Insights grid */
	--jbh-ig-heading-color: var(--jbh-ig-heading-lt);
	--jbh-ig-excerpt-color: var(--jbh-ig-excerpt-lt);
	--jbh-ig-category-color: var(--jbh-ig-category-lt);
	--jbh-ig-link-color: var(--jbh-ig-link-lt);
	--jbh-ig-date-color: var(--jbh-ig-date-lt);
	--jbh-ig-tag-color: var(--jbh-ig-tag-lt);
	--jbh-ig-author-color: var(--jbh-ig-author-lt);
	--jbh-ig-link-hover-color: var(--jbh-ig-link-hover-lt);
	--jbh-ig-meta-bg: var(--jbh-ig-meta-bg-lt);
	--jbh-ig-card-bg: var(--jbh-ig-card-bg-lt);
	--jbh-ig-card-border: var(--jbh-ig-card-border-lt);
	--jbh-ig-icon-color: var(--jbh-ig-icon-lt);
	/* Portfolio grid */
	--jbh-pf-subtitle-color: var(--jbh-pf-subtitle-lt);
	--jbh-pf-meta-color: var(--jbh-pf-meta-lt);
	--jbh-pf-icon-label-color: var(--jbh-pf-icon-label-lt);
}

/* OS-level preference fallback — only when no explicit site mode
   signal is present. Must match the same "no explicit toggle"
   predicate used at line 202 so both cascades stay in lock-step. */
@media (prefers-color-scheme: light) {
	html:not([data-theme]):not(.dark):not(.light):not([data-color-mode]) .jbh-auto {
		/* Grid blocks shared */
		--jbh-custom-header: var(--jbh-custom-header-lt);
		--jbh-custom-price: var(--jbh-custom-price-lt);
		--jbh-custom-desc: var(--jbh-custom-desc-lt);
		--jbh-custom-icon: var(--jbh-custom-icon-lt);
		--jbh-custom-btn: var(--jbh-custom-btn-lt);
		--jbh-custom-btn-text: var(--jbh-custom-btn-text-lt);
		--jbh-custom-card-bg: var(--jbh-custom-card-bg-lt);
		--jbh-custom-card-border: var(--jbh-custom-card-border-lt);
		--jbh-custom-btn-hover: var(--jbh-custom-btn-hover-lt);
		--jbh-custom-btn-hover-text: var(--jbh-custom-btn-hover-text-lt);
		--jbh-custom-badge: var(--jbh-custom-badge-lt);
		--jbh-custom-target: var(--jbh-custom-target-lt);
		--jbh-custom-tag: var(--jbh-custom-tag-lt);
		--jbh-custom-block-bg: var(--jbh-custom-block-bg-lt);
		/* Studio grid — Target band text + price/timeline footer text. */
		--jbh-custom-target-text:    var(--jbh-custom-target-text-lt);
		--jbh-custom-timeline-label: var(--jbh-custom-timeline-label-lt);
		--jbh-custom-timeline-value: var(--jbh-custom-timeline-value-lt);
		--jbh-custom-price-label:    var(--jbh-custom-price-label-lt);
		/* Studio grid — Card header / icon-box / target-band surfaces. */
		--jbh-custom-card-header-bg: var(--jbh-custom-card-header-bg-lt);
		--jbh-custom-icon-box-bg:    var(--jbh-custom-icon-box-bg-lt);
		--jbh-custom-target-band-bg: var(--jbh-custom-target-band-bg-lt);
		/* Studio grid — Includes section */
		--jbh-custom-includes-label: var(--jbh-custom-includes-label-lt);
		--jbh-custom-includes-text:  var(--jbh-custom-includes-text-lt);
		--jbh-custom-includes-icon:  var(--jbh-custom-includes-icon-lt);
		/* Studio grid — Add-ons section */
		--jbh-custom-addons-label:   var(--jbh-custom-addons-label-lt);
		--jbh-custom-addons-pill-bg: var(--jbh-custom-addons-pill-bg-lt);
		--jbh-custom-addons-pill-bd: var(--jbh-custom-addons-pill-bd-lt);
		--jbh-custom-addons-pill-tx: var(--jbh-custom-addons-pill-tx-lt);
		--jbh-custom-addons-price:   var(--jbh-custom-addons-price-lt);
		/* Studio grid — Card footer tint */
		--jbh-custom-card-footer-bg: var(--jbh-custom-card-footer-bg-lt);
		/* Pricing plans — Billing-period toggle (light-mode aliases). */
		--jbh-custom-toggle-track:        var(--jbh-custom-toggle-track-lt);
		--jbh-custom-toggle-track-active: var(--jbh-custom-toggle-track-active-lt);
		--jbh-custom-toggle-dot:          var(--jbh-custom-toggle-dot-lt);
		/* Store grid — Product badge */
		--jbh-custom-badge-bg:   var(--jbh-custom-badge-bg-lt);
		--jbh-custom-badge-text: var(--jbh-custom-badge-text-lt);
		/* Store grid — Featured-product outline */
		--jbh-featured-outline:  var(--jbh-featured-outline-lt);
		/* Store grid — Filter / sort / search toolbar */
		--jbh-filter-bg:          var(--jbh-filter-bg-lt);
		--jbh-filter-text:        var(--jbh-filter-text-lt);
		--jbh-filter-border:      var(--jbh-filter-border-lt);
		--jbh-filter-active-bg:   var(--jbh-filter-active-bg-lt);
		--jbh-filter-active-text: var(--jbh-filter-active-text-lt);
		/* Hero section */
		--jbh-hero-heading-color: var(--jbh-hero-heading-lt);
		--jbh-hero-heading2-color: var(--jbh-hero-heading2-lt);
		--jbh-hero-subtitle-color: var(--jbh-hero-subtitle-lt);
		--jbh-hero-badge-color: var(--jbh-hero-badge-lt);
		--jbh-hero-btn-bg: var(--jbh-hero-btn-lt);
		--jbh-hero-btn-text: var(--jbh-hero-btn-text-lt);
		--jbh-hero-btn-hover-bg: var(--jbh-hero-btn-hover-lt);
		--jbh-hero-btn-hover-text: var(--jbh-hero-btn-hover-text-lt);
		--jbh-hero-sec-btn-bg: var(--jbh-hero-sec-btn-lt);
		--jbh-hero-sec-btn-text: var(--jbh-hero-sec-btn-text-lt);
		--jbh-hero-feat-card-bg: var(--jbh-hero-feat-card-bg-lt);
		--jbh-hero-feat-heading: var(--jbh-hero-feat-heading-lt);
		--jbh-hero-feat-desc: var(--jbh-hero-feat-desc-lt);
		--jbh-hero-feat-icon: var(--jbh-hero-feat-icon-lt);
		--jbh-hero-feat-eyebrow: var(--jbh-hero-feat-eyebrow-lt);
		/* Section header */
		--jbh-sh-heading-color: var(--jbh-sh-heading-lt);
		--jbh-sh-subtitle-color: var(--jbh-sh-subtitle-lt);
		--jbh-sh-badge-color: var(--jbh-sh-badge-lt);
		/* Page intro */
		--jbh-pi-heading-color: var(--jbh-pi-heading-lt);
		--jbh-pi-subtitle-color: var(--jbh-pi-subtitle-lt);
		--jbh-pi-label-color: var(--jbh-pi-label-lt);
		--jbh-pi-callout-text-color: var(--jbh-pi-callout-text-lt);
		--jbh-pi-status-text-color: var(--jbh-pi-status-text-lt);
		--jbh-pi-callout-border: var(--jbh-pi-callout-border-lt);
		/* CTA banner */
		--jbh-cta-heading-color: var(--jbh-cta-heading-lt);
		--jbh-cta-subtitle-color: var(--jbh-cta-subtitle-lt);
		--jbh-cta-badge-color: var(--jbh-cta-badge-lt);
		--jbh-cta-btn-bg: var(--jbh-cta-btn-lt);
		--jbh-cta-btn-text: var(--jbh-cta-btn-text-lt);
		--jbh-cta-btn-hover-bg: var(--jbh-cta-btn-hover-lt);
		--jbh-cta-btn-hover-text: var(--jbh-cta-btn-hover-text-lt);
		/* About section */
		--jbh-about-heading-color: var(--jbh-about-heading-lt);
		--jbh-about-bio-color: var(--jbh-about-bio-lt);
		--jbh-about-label-color: var(--jbh-about-label-lt);
		--jbh-about-card-bg: var(--jbh-about-card-bg-lt);
		/* Insights grid */
		--jbh-ig-heading-color: var(--jbh-ig-heading-lt);
		--jbh-ig-excerpt-color: var(--jbh-ig-excerpt-lt);
		--jbh-ig-category-color: var(--jbh-ig-category-lt);
		--jbh-ig-link-color: var(--jbh-ig-link-lt);
		--jbh-ig-date-color: var(--jbh-ig-date-lt);
		--jbh-ig-tag-color: var(--jbh-ig-tag-lt);
		--jbh-ig-author-color: var(--jbh-ig-author-lt);
		--jbh-ig-link-hover-color: var(--jbh-ig-link-hover-lt);
		--jbh-ig-meta-bg: var(--jbh-ig-meta-bg-lt);
		--jbh-ig-card-bg: var(--jbh-ig-card-bg-lt);
		--jbh-ig-card-border: var(--jbh-ig-card-border-lt);
		--jbh-ig-icon-color: var(--jbh-ig-icon-lt);
		/* Portfolio grid */
		--jbh-pf-subtitle-color: var(--jbh-pf-subtitle-lt);
		--jbh-pf-meta-color: var(--jbh-pf-meta-lt);
		--jbh-pf-icon-label-color: var(--jbh-pf-icon-label-lt);
	}
}

/* ── Global Dark / Light Mode — html-level selectors ────────── */
/* Supports: JBH Platform toggle (data-theme / .dark / .light),
   Blocksy Colour Mode Switch (palette var swap + [data-color-mode]),
   and OS-level prefers-color-scheme auto-detection.                */

/* ── INVERTED: site dark → plugin light ──────────────────────── */
html[data-jbh-invert][data-theme="dark"],
html[data-jbh-invert].dark,
html[data-jbh-invert][data-color-mode="dark"] {
	--jbh-bg: #F9F8F6; --jbh-card: #FFFFFF; --jbh-creme: #121212;
	--jbh-slate: #4B5563; --jbh-heading-color: #121212;
	--jbh-text-color: #4B5563; --jbh-card-heading: #121212;
	--jbh-border: rgba(0, 0, 0, 0.12);

	/* Ambience tokens flip to "soft" variants. Rationale:
	   · Backdrops tuned to #0F172A (slate-900) at lower opacity feel
	     like premium modal dimming rather than the heavy black curtain
	     a dark-mode backdrop imposes on a light page.
	   · Panel/content shadows soften dramatically — light cards need
	     only a hint of shadow to read as elevated; keeping the dark
	     rgba(0,0,0,0.5) looks like a mistake on an off-white surface.
	   · Watermark opacity bumps ~1.5× so the teal decoration stays
	     perceptible against a white card (0.05 teal on white is
	     practically invisible; 0.08 reads like intentional texture).
	   · Card shadows pick up slightly so hover affordance survives
	     on light backgrounds. */
	--jbh-modal-backdrop:      rgba(15, 23, 42, 0.40);
	--jbh-modal-panel-shadow:  -8px 0 40px rgba(15, 23, 42, 0.18), -2px 0 6px rgba(15, 23, 42, 0.08);
	--jbh-modal-popup-shadow:  0 24px 72px rgba(15, 23, 42, 0.18);
	--jbh-pm-backdrop:         rgba(15, 23, 42, 0.50);
	--jbh-pm-shadow:           0 20px 60px rgba(15, 23, 42, 0.20);
	--jbh-watermark-color:        rgba(42, 157, 143, 0.08);
	--jbh-watermark-color-hover:  rgba(42, 157, 143, 0.16);
	--jbh-card-shadow-subtle:  0 4px 20px rgba(15, 23, 42, 0.06);
	--jbh-card-shadow-hover:   0 8px 30px rgba(15, 23, 42, 0.10);
}
/* INVERTED: site light → plugin dark */
html[data-jbh-invert][data-theme="light"],
html[data-jbh-invert].light,
html[data-jbh-invert][data-color-mode="light"] {
	--jbh-bg: #121212; --jbh-card: #1A1A1A; --jbh-creme: #F0EAD6;
	--jbh-slate: #9CA3AF; --jbh-heading-color: #F0EAD6;
	--jbh-text-color: #9CA3AF; --jbh-card-heading: #ffffff;
	--jbh-border: rgba(31, 95, 91, 0.20);
}

/* ── STANDARD (non-inverted): site dark → plugin dark ──────── */
html:not([data-jbh-invert])[data-theme="dark"],
html:not([data-jbh-invert]).dark,
html:not([data-jbh-invert])[data-color-mode="dark"] {
	--jbh-bg: #121212; --jbh-card: #1A1A1A; --jbh-creme: #F0EAD6;
	--jbh-slate: #9CA3AF; --jbh-heading-color: #F0EAD6;
	--jbh-text-color: #9CA3AF; --jbh-card-heading: #ffffff;
	--jbh-border: rgba(31, 95, 91, 0.20);
}
/* STANDARD: site light → plugin light */
html:not([data-jbh-invert])[data-theme="light"],
html:not([data-jbh-invert]).light,
html:not([data-jbh-invert])[data-color-mode="light"] {
	--jbh-bg: #F9F8F6; --jbh-card: #FFFFFF; --jbh-creme: #121212;
	--jbh-slate: #4B5563; --jbh-heading-color: #121212;
	--jbh-text-color: #4B5563; --jbh-card-heading: #121212;
	--jbh-border: rgba(0, 0, 0, 0.12);
	--jbh-modal-backdrop:      rgba(15, 23, 42, 0.40);
	--jbh-modal-panel-shadow:  -8px 0 40px rgba(15, 23, 42, 0.18), -2px 0 6px rgba(15, 23, 42, 0.08);
	--jbh-modal-popup-shadow:  0 24px 72px rgba(15, 23, 42, 0.18);
	--jbh-pm-backdrop:         rgba(15, 23, 42, 0.50);
	--jbh-pm-shadow:           0 20px 60px rgba(15, 23, 42, 0.20);
	--jbh-watermark-color:        rgba(42, 157, 143, 0.08);
	--jbh-watermark-color-hover:  rgba(42, 157, 143, 0.16);
	--jbh-card-shadow-subtle:  0 4px 20px rgba(15, 23, 42, 0.06);
	--jbh-card-shadow-hover:   0 8px 30px rgba(15, 23, 42, 0.10);
}

/* Blocksy Pro Colour Mode Switch — writes data-ct-color-mode on body,
   not html. Must be a separate rule because :root/html-level selectors
   don't match body. Tokens still cascade into #jbh-modal-overlay via
   body → footer DOM inheritance. */
/* INVERTED Blocksy body selector */
html[data-jbh-invert] body[data-ct-color-mode="dark"] {
	--jbh-bg: #F9F8F6; --jbh-card: #FFFFFF; --jbh-creme: #121212;
	--jbh-slate: #4B5563; --jbh-heading-color: #121212;
	--jbh-text-color: #4B5563; --jbh-card-heading: #121212;
	--jbh-border: rgba(0, 0, 0, 0.12);
	--jbh-modal-backdrop:      rgba(15, 23, 42, 0.40);
	--jbh-modal-panel-shadow:  -8px 0 40px rgba(15, 23, 42, 0.18), -2px 0 6px rgba(15, 23, 42, 0.08);
	--jbh-modal-popup-shadow:  0 24px 72px rgba(15, 23, 42, 0.18);
	--jbh-pm-backdrop:         rgba(15, 23, 42, 0.50);
	--jbh-pm-shadow:           0 20px 60px rgba(15, 23, 42, 0.20);
	--jbh-watermark-color:        rgba(42, 157, 143, 0.08);
	--jbh-watermark-color-hover:  rgba(42, 157, 143, 0.16);
	--jbh-card-shadow-subtle:  0 4px 20px rgba(15, 23, 42, 0.06);
	--jbh-card-shadow-hover:   0 8px 30px rgba(15, 23, 42, 0.10);
}
/* STANDARD Blocksy body selectors */
html:not([data-jbh-invert]) body[data-ct-color-mode="dark"] {
	--jbh-bg: #121212; --jbh-card: #1A1A1A; --jbh-creme: #F0EAD6;
	--jbh-slate: #9CA3AF; --jbh-heading-color: #F0EAD6;
	--jbh-text-color: #9CA3AF; --jbh-card-heading: #ffffff;
	--jbh-border: rgba(31, 95, 91, 0.20);
}
html:not([data-jbh-invert]) body[data-ct-color-mode="light"] {
	--jbh-bg: #F9F8F6; --jbh-card: #FFFFFF; --jbh-creme: #121212;
	--jbh-slate: #4B5563; --jbh-heading-color: #121212;
	--jbh-text-color: #4B5563; --jbh-card-heading: #121212;
	--jbh-border: rgba(0, 0, 0, 0.12);
	--jbh-modal-backdrop:      rgba(15, 23, 42, 0.40);
	--jbh-modal-panel-shadow:  -8px 0 40px rgba(15, 23, 42, 0.18), -2px 0 6px rgba(15, 23, 42, 0.08);
	--jbh-modal-popup-shadow:  0 24px 72px rgba(15, 23, 42, 0.18);
	--jbh-pm-backdrop:         rgba(15, 23, 42, 0.50);
	--jbh-pm-shadow:           0 20px 60px rgba(15, 23, 42, 0.20);
	--jbh-watermark-color:        rgba(42, 157, 143, 0.08);
	--jbh-watermark-color-hover:  rgba(42, 157, 143, 0.16);
	--jbh-card-shadow-subtle:  0 4px 20px rgba(15, 23, 42, 0.06);
	--jbh-card-shadow-hover:   0 8px 30px rgba(15, 23, 42, 0.10);
}

/* Auto-detect OS preference when no explicit mode is set */
/* INVERTED: OS dark → plugin light */
@media (prefers-color-scheme: dark) {
	html[data-jbh-invert]:not([data-theme]):not(.dark):not(.light):not([data-color-mode]) {
		--jbh-bg: #F9F8F6; --jbh-card: #FFFFFF; --jbh-creme: #121212;
		--jbh-slate: #4B5563; --jbh-heading-color: #121212;
		--jbh-text-color: #4B5563; --jbh-card-heading: #121212;
		--jbh-border: rgba(0, 0, 0, 0.12);
		--jbh-modal-backdrop:      rgba(15, 23, 42, 0.40);
		--jbh-modal-panel-shadow:  -8px 0 40px rgba(15, 23, 42, 0.18), -2px 0 6px rgba(15, 23, 42, 0.08);
		--jbh-modal-popup-shadow:  0 24px 72px rgba(15, 23, 42, 0.18);
		--jbh-pm-backdrop:         rgba(15, 23, 42, 0.50);
		--jbh-pm-shadow:           0 20px 60px rgba(15, 23, 42, 0.20);
		--jbh-watermark-color:        rgba(42, 157, 143, 0.08);
		--jbh-watermark-color-hover:  rgba(42, 157, 143, 0.16);
		--jbh-card-shadow-subtle:  0 4px 20px rgba(15, 23, 42, 0.06);
		--jbh-card-shadow-hover:   0 8px 30px rgba(15, 23, 42, 0.10);
	}
}
/* STANDARD: OS dark → plugin dark (no-op, :root already seeds dark) */
/* STANDARD: OS light → plugin light */
@media (prefers-color-scheme: light) {
	html:not([data-jbh-invert]):not([data-theme]):not(.dark):not(.light):not([data-color-mode]) {
		--jbh-bg: #F9F8F6; --jbh-card: #FFFFFF; --jbh-creme: #121212;
		--jbh-slate: #4B5563; --jbh-heading-color: #121212;
		--jbh-text-color: #4B5563; --jbh-card-heading: #121212;
		--jbh-border: rgba(0, 0, 0, 0.12);
		--jbh-modal-backdrop:      rgba(15, 23, 42, 0.40);
		--jbh-modal-panel-shadow:  -8px 0 40px rgba(15, 23, 42, 0.18), -2px 0 6px rgba(15, 23, 42, 0.08);
		--jbh-modal-popup-shadow:  0 24px 72px rgba(15, 23, 42, 0.18);
		--jbh-pm-backdrop:         rgba(15, 23, 42, 0.50);
		--jbh-pm-shadow:           0 20px 60px rgba(15, 23, 42, 0.20);
		--jbh-watermark-color:        rgba(42, 157, 143, 0.08);
		--jbh-watermark-color-hover:  rgba(42, 157, 143, 0.16);
		--jbh-card-shadow-subtle:  0 4px 20px rgba(15, 23, 42, 0.06);
		--jbh-card-shadow-hover:   0 8px 30px rgba(15, 23, 42, 0.10);
	}
}

/* ── Same-Frame Site-Mode Reactivity — CSS-Only ─────────────────
   Root cause of the "dark → light feels laggy" bug before this rule
   existed: `.jbh-dark { --jbh-bg: #121212; … }` and `.jbh-light {…}`
   declared the full palette at BLOCK scope (specificity 0,1,0),
   which blocked the page-level cascade from `html[data-theme]` /
   `body[data-ct-color-mode]` (specificity 0,1,1). When Blocksy's
   Colour Mode Switch flipped body's attribute, every non-JBH
   element on the page re-resolved palette INSTANTLY — but JBH
   blocks stayed stuck on their class-level palette until the
   MutationObserver microtask fired and JS swapped `.jbh-dark` for
   `.jbh-light`. Between the paint after Blocksy's mutation and the
   paint after our class swap, one-to-two frames of laggy
   transition were visible (watermark color fading, card-header
   gradient reshuffling, etc.).

   The fix: one ancestor-qualified rule per direction that reaches
   INTO the block and re-declares palette + custom-var aliases with
   specificity 0,3,1 — higher than `.jbh-dark` / `.jbh-light`'s
   0,1,0, so it wins without `!important`. Specificity breakdown:
       :is(html[data-theme="light"], …)  → 0,1,1 (attr + element)
       :is(.jbh-dark, .jbh-light, …)      → 0,1,0 (one class)
       :not(.jbh-override-theme)          → 0,1,0 (one class)
       total                              → 0,3,1
   Because the paint triggered by Blocksy's attribute mutation
   is the SAME frame that re-resolves these rules, the block
   changes palette in lock-step with the rest of the site — zero
   JS dependency, zero observable lag.

   Opt-out: any block with `.jbh-override-theme` skips this cascade
   entirely (that class is the explicit "I want to stay in MY mode
   regardless of site mode" marker emitted by render.php when the
   Inspector's Override Site Mode toggle is on).
   ────────────────────────────────────────────────────────────── */

/* INVERTED: SITE LIGHT → blocks DARK */
:is(html[data-jbh-invert][data-theme="light"], html[data-jbh-invert].light, html[data-jbh-invert][data-color-mode="light"]) :is(.jbh-dark, .jbh-light, .jbh-auto):not(.jbh-override-theme),
html[data-jbh-invert] body[data-ct-color-mode="light"] :is(.jbh-dark, .jbh-light, .jbh-auto):not(.jbh-override-theme) {
	--jbh-bg:            #121212;
	--jbh-card:          #1A1A1A;
	--jbh-creme:         #F0EAD6;
	--jbh-slate:         #9CA3AF;
	--jbh-heading-color: #F0EAD6;
	--jbh-text-color:    #9CA3AF;
	--jbh-card-heading:  #ffffff;
	--jbh-border:        rgba(31, 95, 91, 0.20);
	/* Grid blocks shared — dark aliases */
	--jbh-custom-header:            var(--jbh-custom-header-dk);
	--jbh-custom-price:             var(--jbh-custom-price-dk);
	--jbh-custom-desc:              var(--jbh-custom-desc-dk);
	--jbh-custom-icon:              var(--jbh-custom-icon-dk);
	--jbh-custom-btn:               var(--jbh-custom-btn-dk);
	--jbh-custom-btn-text:          var(--jbh-custom-btn-text-dk);
	--jbh-custom-card-bg:           var(--jbh-custom-card-bg-dk);
	--jbh-custom-card-border:       var(--jbh-custom-card-border-dk);
	--jbh-custom-btn-hover:         var(--jbh-custom-btn-hover-dk);
	--jbh-custom-btn-hover-text:    var(--jbh-custom-btn-hover-text-dk);
	--jbh-custom-badge:             var(--jbh-custom-badge-dk);
	--jbh-custom-target:            var(--jbh-custom-target-dk);
	--jbh-custom-tag:               var(--jbh-custom-tag-dk);
	--jbh-custom-block-bg:          var(--jbh-custom-block-bg-dk);
	/* Studio grid */
	--jbh-custom-target-text:       var(--jbh-custom-target-text-dk);
	--jbh-custom-timeline-label:    var(--jbh-custom-timeline-label-dk);
	--jbh-custom-timeline-value:    var(--jbh-custom-timeline-value-dk);
	--jbh-custom-price-label:       var(--jbh-custom-price-label-dk);
	--jbh-custom-card-header-bg:    var(--jbh-custom-card-header-bg-dk);
	--jbh-custom-icon-box-bg:       var(--jbh-custom-icon-box-bg-dk);
	--jbh-custom-target-band-bg:    var(--jbh-custom-target-band-bg-dk);
	--jbh-custom-includes-label:    var(--jbh-custom-includes-label-dk);
	--jbh-custom-includes-text:     var(--jbh-custom-includes-text-dk);
	--jbh-custom-includes-icon:     var(--jbh-custom-includes-icon-dk);
	--jbh-custom-addons-label:      var(--jbh-custom-addons-label-dk);
	--jbh-custom-addons-pill-bg:    var(--jbh-custom-addons-pill-bg-dk);
	--jbh-custom-addons-pill-bd:    var(--jbh-custom-addons-pill-bd-dk);
	--jbh-custom-addons-pill-tx:    var(--jbh-custom-addons-pill-tx-dk);
	--jbh-custom-addons-price:      var(--jbh-custom-addons-price-dk);
	--jbh-custom-card-footer-bg:    var(--jbh-custom-card-footer-bg-dk);
	/* Pricing plans — billing toggle */
	--jbh-custom-toggle-track:        var(--jbh-custom-toggle-track-dk);
	--jbh-custom-toggle-track-active: var(--jbh-custom-toggle-track-active-dk);
	--jbh-custom-toggle-dot:          var(--jbh-custom-toggle-dot-dk);
	/* Store grid — Product badge */
	--jbh-custom-badge-bg:            var(--jbh-custom-badge-bg-dk);
	--jbh-custom-badge-text:          var(--jbh-custom-badge-text-dk);
	/* Store grid — Featured-product outline */
	--jbh-featured-outline:           var(--jbh-featured-outline-dk);
	/* Store grid — Filter / sort / search toolbar */
	--jbh-filter-bg:                  var(--jbh-filter-bg-dk);
	--jbh-filter-text:                var(--jbh-filter-text-dk);
	--jbh-filter-border:              var(--jbh-filter-border-dk);
	--jbh-filter-active-bg:           var(--jbh-filter-active-bg-dk);
	--jbh-filter-active-text:         var(--jbh-filter-active-text-dk);
	/* Hero section */
	--jbh-hero-heading-color:  var(--jbh-hero-heading-dk);
	--jbh-hero-heading2-color: var(--jbh-hero-heading2-dk);
	--jbh-hero-subtitle-color: var(--jbh-hero-subtitle-dk);
	--jbh-hero-badge-color:    var(--jbh-hero-badge-dk);
	--jbh-hero-btn-bg:         var(--jbh-hero-btn-dk);
	--jbh-hero-btn-text:       var(--jbh-hero-btn-text-dk);
	--jbh-hero-btn-hover-bg:   var(--jbh-hero-btn-hover-dk);
	--jbh-hero-btn-hover-text: var(--jbh-hero-btn-hover-text-dk);
	--jbh-hero-sec-btn-bg: var(--jbh-hero-sec-btn-dk);
	--jbh-hero-sec-btn-text: var(--jbh-hero-sec-btn-text-dk);
	--jbh-hero-feat-card-bg: var(--jbh-hero-feat-card-bg-dk);
	--jbh-hero-feat-heading: var(--jbh-hero-feat-heading-dk);
	--jbh-hero-feat-desc: var(--jbh-hero-feat-desc-dk);
	--jbh-hero-feat-icon: var(--jbh-hero-feat-icon-dk);
	--jbh-hero-feat-eyebrow: var(--jbh-hero-feat-eyebrow-dk);
	/* Section header */
	--jbh-sh-heading-color:  var(--jbh-sh-heading-dk);
	--jbh-sh-subtitle-color: var(--jbh-sh-subtitle-dk);
	--jbh-sh-badge-color:    var(--jbh-sh-badge-dk);
	/* Page intro */
	--jbh-pi-heading-color:      var(--jbh-pi-heading-dk);
	--jbh-pi-subtitle-color:     var(--jbh-pi-subtitle-dk);
	--jbh-pi-label-color:        var(--jbh-pi-label-dk);
	--jbh-pi-callout-text-color: var(--jbh-pi-callout-text-dk);
	--jbh-pi-status-text-color:  var(--jbh-pi-status-text-dk);
	/* CTA banner */
	--jbh-cta-heading-color:   var(--jbh-cta-heading-dk);
	--jbh-cta-subtitle-color:  var(--jbh-cta-subtitle-dk);
	--jbh-cta-badge-color:     var(--jbh-cta-badge-dk);
	--jbh-cta-btn-bg:          var(--jbh-cta-btn-dk);
	--jbh-cta-btn-text:        var(--jbh-cta-btn-text-dk);
	--jbh-cta-btn-hover-bg:    var(--jbh-cta-btn-hover-dk);
	--jbh-cta-btn-hover-text:  var(--jbh-cta-btn-hover-text-dk);
	/* About section */
	--jbh-about-heading-color: var(--jbh-about-heading-dk);
	--jbh-about-bio-color:     var(--jbh-about-bio-dk);
	--jbh-about-label-color:   var(--jbh-about-label-dk);
	--jbh-about-card-bg:       var(--jbh-about-card-bg-dk);
	/* Insights grid */
	--jbh-ig-heading-color:    var(--jbh-ig-heading-dk);
	--jbh-ig-excerpt-color:    var(--jbh-ig-excerpt-dk);
	--jbh-ig-category-color:   var(--jbh-ig-category-dk);
	--jbh-ig-link-color:       var(--jbh-ig-link-dk);
	--jbh-ig-date-color:       var(--jbh-ig-date-dk);
	--jbh-ig-tag-color:        var(--jbh-ig-tag-dk);
	--jbh-ig-author-color:     var(--jbh-ig-author-dk);
	--jbh-ig-link-hover-color: var(--jbh-ig-link-hover-dk);
	--jbh-ig-meta-bg:          var(--jbh-ig-meta-bg-dk);
	--jbh-ig-card-bg:          var(--jbh-ig-card-bg-dk);
	--jbh-ig-card-border:      var(--jbh-ig-card-border-dk);
	--jbh-ig-icon-color:       var(--jbh-ig-icon-dk);
	/* Portfolio grid */
	--jbh-pf-subtitle-color:   var(--jbh-pf-subtitle-dk);
	--jbh-pf-meta-color:       var(--jbh-pf-meta-dk);
	--jbh-pf-icon-label-color: var(--jbh-pf-icon-label-dk);
}

/* INVERTED: SITE DARK → blocks LIGHT */
:is(html[data-jbh-invert][data-theme="dark"], html[data-jbh-invert].dark, html[data-jbh-invert][data-color-mode="dark"]) :is(.jbh-dark, .jbh-light, .jbh-auto):not(.jbh-override-theme),
html[data-jbh-invert] body[data-ct-color-mode="dark"] :is(.jbh-dark, .jbh-light, .jbh-auto):not(.jbh-override-theme) {
	/* Surface tokens (mirror frontend.css:64-69 .jbh-light {}) */
	--jbh-bg:            #F9F8F6;
	--jbh-card:          #FFFFFF;
	--jbh-creme:         #121212;
	--jbh-slate:         #4B5563;
	--jbh-heading-color: #121212;
	--jbh-text-color:    #4B5563;
	--jbh-card-heading:  #121212;
	--jbh-border:        rgba(0, 0, 0, 0.12);
	/* Grid blocks shared — light aliases */
	--jbh-custom-header:            var(--jbh-custom-header-lt);
	--jbh-custom-price:             var(--jbh-custom-price-lt);
	--jbh-custom-desc:              var(--jbh-custom-desc-lt);
	--jbh-custom-icon:              var(--jbh-custom-icon-lt);
	--jbh-custom-btn:               var(--jbh-custom-btn-lt);
	--jbh-custom-btn-text:          var(--jbh-custom-btn-text-lt);
	--jbh-custom-card-bg:           var(--jbh-custom-card-bg-lt);
	--jbh-custom-card-border:       var(--jbh-custom-card-border-lt);
	--jbh-custom-btn-hover:         var(--jbh-custom-btn-hover-lt);
	--jbh-custom-btn-hover-text:    var(--jbh-custom-btn-hover-text-lt);
	--jbh-custom-badge:             var(--jbh-custom-badge-lt);
	--jbh-custom-target:            var(--jbh-custom-target-lt);
	--jbh-custom-tag:               var(--jbh-custom-tag-lt);
	--jbh-custom-block-bg:          var(--jbh-custom-block-bg-lt);
	/* Studio grid */
	--jbh-custom-target-text:       var(--jbh-custom-target-text-lt);
	--jbh-custom-timeline-label:    var(--jbh-custom-timeline-label-lt);
	--jbh-custom-timeline-value:    var(--jbh-custom-timeline-value-lt);
	--jbh-custom-price-label:       var(--jbh-custom-price-label-lt);
	--jbh-custom-card-header-bg:    var(--jbh-custom-card-header-bg-lt);
	--jbh-custom-icon-box-bg:       var(--jbh-custom-icon-box-bg-lt);
	--jbh-custom-target-band-bg:    var(--jbh-custom-target-band-bg-lt);
	--jbh-custom-includes-label:    var(--jbh-custom-includes-label-lt);
	--jbh-custom-includes-text:     var(--jbh-custom-includes-text-lt);
	--jbh-custom-includes-icon:     var(--jbh-custom-includes-icon-lt);
	--jbh-custom-addons-label:      var(--jbh-custom-addons-label-lt);
	--jbh-custom-addons-pill-bg:    var(--jbh-custom-addons-pill-bg-lt);
	--jbh-custom-addons-pill-bd:    var(--jbh-custom-addons-pill-bd-lt);
	--jbh-custom-addons-pill-tx:    var(--jbh-custom-addons-pill-tx-lt);
	--jbh-custom-addons-price:      var(--jbh-custom-addons-price-lt);
	--jbh-custom-card-footer-bg:    var(--jbh-custom-card-footer-bg-lt);
	/* Pricing plans — billing toggle */
	--jbh-custom-toggle-track:        var(--jbh-custom-toggle-track-lt);
	--jbh-custom-toggle-track-active: var(--jbh-custom-toggle-track-active-lt);
	--jbh-custom-toggle-dot:          var(--jbh-custom-toggle-dot-lt);
	/* Store grid — Product badge */
	--jbh-custom-badge-bg:            var(--jbh-custom-badge-bg-lt);
	--jbh-custom-badge-text:          var(--jbh-custom-badge-text-lt);
	/* Store grid — Featured-product outline */
	--jbh-featured-outline:           var(--jbh-featured-outline-lt);
	/* Store grid — Filter / sort / search toolbar */
	--jbh-filter-bg:                  var(--jbh-filter-bg-lt);
	--jbh-filter-text:                var(--jbh-filter-text-lt);
	--jbh-filter-border:              var(--jbh-filter-border-lt);
	--jbh-filter-active-bg:           var(--jbh-filter-active-bg-lt);
	--jbh-filter-active-text:         var(--jbh-filter-active-text-lt);
	/* Hero section */
	--jbh-hero-heading-color:  var(--jbh-hero-heading-lt);
	--jbh-hero-heading2-color: var(--jbh-hero-heading2-lt);
	--jbh-hero-subtitle-color: var(--jbh-hero-subtitle-lt);
	--jbh-hero-badge-color:    var(--jbh-hero-badge-lt);
	--jbh-hero-btn-bg:         var(--jbh-hero-btn-lt);
	--jbh-hero-btn-text:       var(--jbh-hero-btn-text-lt);
	--jbh-hero-btn-hover-bg:   var(--jbh-hero-btn-hover-lt);
	--jbh-hero-btn-hover-text: var(--jbh-hero-btn-hover-text-lt);
	--jbh-hero-sec-btn-bg: var(--jbh-hero-sec-btn-lt);
	--jbh-hero-sec-btn-text: var(--jbh-hero-sec-btn-text-lt);
	--jbh-hero-feat-card-bg: var(--jbh-hero-feat-card-bg-lt);
	--jbh-hero-feat-heading: var(--jbh-hero-feat-heading-lt);
	--jbh-hero-feat-desc: var(--jbh-hero-feat-desc-lt);
	--jbh-hero-feat-icon: var(--jbh-hero-feat-icon-lt);
	--jbh-hero-feat-eyebrow: var(--jbh-hero-feat-eyebrow-lt);
	/* Section header */
	--jbh-sh-heading-color:  var(--jbh-sh-heading-lt);
	--jbh-sh-subtitle-color: var(--jbh-sh-subtitle-lt);
	--jbh-sh-badge-color:    var(--jbh-sh-badge-lt);
	/* Page intro */
	--jbh-pi-heading-color:      var(--jbh-pi-heading-lt);
	--jbh-pi-subtitle-color:     var(--jbh-pi-subtitle-lt);
	--jbh-pi-label-color:        var(--jbh-pi-label-lt);
	--jbh-pi-callout-text-color: var(--jbh-pi-callout-text-lt);
	--jbh-pi-status-text-color:  var(--jbh-pi-status-text-lt);
	/* CTA banner */
	--jbh-cta-heading-color:   var(--jbh-cta-heading-lt);
	--jbh-cta-subtitle-color:  var(--jbh-cta-subtitle-lt);
	--jbh-cta-badge-color:     var(--jbh-cta-badge-lt);
	--jbh-cta-btn-bg:          var(--jbh-cta-btn-lt);
	--jbh-cta-btn-text:        var(--jbh-cta-btn-text-lt);
	--jbh-cta-btn-hover-bg:    var(--jbh-cta-btn-hover-lt);
	--jbh-cta-btn-hover-text:  var(--jbh-cta-btn-hover-text-lt);
	/* About section */
	--jbh-about-heading-color: var(--jbh-about-heading-lt);
	--jbh-about-bio-color:     var(--jbh-about-bio-lt);
	--jbh-about-label-color:   var(--jbh-about-label-lt);
	--jbh-about-card-bg:       var(--jbh-about-card-bg-lt);
	/* Insights grid */
	--jbh-ig-heading-color:    var(--jbh-ig-heading-lt);
	--jbh-ig-excerpt-color:    var(--jbh-ig-excerpt-lt);
	--jbh-ig-category-color:   var(--jbh-ig-category-lt);
	--jbh-ig-link-color:       var(--jbh-ig-link-lt);
	--jbh-ig-date-color:       var(--jbh-ig-date-lt);
	--jbh-ig-tag-color:        var(--jbh-ig-tag-lt);
	--jbh-ig-author-color:     var(--jbh-ig-author-lt);
	--jbh-ig-link-hover-color: var(--jbh-ig-link-hover-lt);
	--jbh-ig-meta-bg:          var(--jbh-ig-meta-bg-lt);
	--jbh-ig-card-bg:          var(--jbh-ig-card-bg-lt);
	--jbh-ig-card-border:      var(--jbh-ig-card-border-lt);
	--jbh-ig-icon-color:       var(--jbh-ig-icon-lt);
	/* Portfolio grid */
	--jbh-pf-subtitle-color:   var(--jbh-pf-subtitle-lt);
	--jbh-pf-meta-color:       var(--jbh-pf-meta-lt);
	--jbh-pf-icon-label-color: var(--jbh-pf-icon-label-lt);
}

/* ── STANDARD (non-inverted) mega-selectors ─────────────────────
   When data-jbh-invert is absent, site mode maps straight through:
   site dark → blocks dark, site light → blocks light. ────────── */

/* STANDARD: SITE LIGHT → blocks LIGHT */
:is(html:not([data-jbh-invert])[data-theme="light"], html:not([data-jbh-invert]).light, html:not([data-jbh-invert])[data-color-mode="light"]) :is(.jbh-dark, .jbh-light, .jbh-auto):not(.jbh-override-theme),
html:not([data-jbh-invert]) body[data-ct-color-mode="light"] :is(.jbh-dark, .jbh-light, .jbh-auto):not(.jbh-override-theme) {
	--jbh-bg:            #F9F8F6;
	--jbh-card:          #FFFFFF;
	--jbh-creme:         #121212;
	--jbh-slate:         #4B5563;
	--jbh-heading-color: #121212;
	--jbh-text-color:    #4B5563;
	--jbh-card-heading:  #121212;
	--jbh-border:        rgba(0, 0, 0, 0.12);
	/* Grid blocks shared — light aliases */
	--jbh-custom-header:            var(--jbh-custom-header-lt);
	--jbh-custom-price:             var(--jbh-custom-price-lt);
	--jbh-custom-desc:              var(--jbh-custom-desc-lt);
	--jbh-custom-icon:              var(--jbh-custom-icon-lt);
	--jbh-custom-btn:               var(--jbh-custom-btn-lt);
	--jbh-custom-btn-text:          var(--jbh-custom-btn-text-lt);
	--jbh-custom-card-bg:           var(--jbh-custom-card-bg-lt);
	--jbh-custom-card-border:       var(--jbh-custom-card-border-lt);
	--jbh-custom-btn-hover:         var(--jbh-custom-btn-hover-lt);
	--jbh-custom-btn-hover-text:    var(--jbh-custom-btn-hover-text-lt);
	--jbh-custom-badge:             var(--jbh-custom-badge-lt);
	--jbh-custom-target:            var(--jbh-custom-target-lt);
	--jbh-custom-tag:               var(--jbh-custom-tag-lt);
	--jbh-custom-block-bg:          var(--jbh-custom-block-bg-lt);
	/* Studio grid */
	--jbh-custom-target-text:       var(--jbh-custom-target-text-lt);
	--jbh-custom-timeline-label:    var(--jbh-custom-timeline-label-lt);
	--jbh-custom-timeline-value:    var(--jbh-custom-timeline-value-lt);
	--jbh-custom-price-label:       var(--jbh-custom-price-label-lt);
	--jbh-custom-card-header-bg:    var(--jbh-custom-card-header-bg-lt);
	--jbh-custom-icon-box-bg:       var(--jbh-custom-icon-box-bg-lt);
	--jbh-custom-target-band-bg:    var(--jbh-custom-target-band-bg-lt);
	--jbh-custom-includes-label:    var(--jbh-custom-includes-label-lt);
	--jbh-custom-includes-text:     var(--jbh-custom-includes-text-lt);
	--jbh-custom-includes-icon:     var(--jbh-custom-includes-icon-lt);
	--jbh-custom-addons-label:      var(--jbh-custom-addons-label-lt);
	--jbh-custom-addons-pill-bg:    var(--jbh-custom-addons-pill-bg-lt);
	--jbh-custom-addons-pill-bd:    var(--jbh-custom-addons-pill-bd-lt);
	--jbh-custom-addons-pill-tx:    var(--jbh-custom-addons-pill-tx-lt);
	--jbh-custom-addons-price:      var(--jbh-custom-addons-price-lt);
	--jbh-custom-card-footer-bg:    var(--jbh-custom-card-footer-bg-lt);
	/* Pricing plans — billing toggle */
	--jbh-custom-toggle-track:        var(--jbh-custom-toggle-track-lt);
	--jbh-custom-toggle-track-active: var(--jbh-custom-toggle-track-active-lt);
	--jbh-custom-toggle-dot:          var(--jbh-custom-toggle-dot-lt);
	/* Store grid — Product badge */
	--jbh-custom-badge-bg:            var(--jbh-custom-badge-bg-lt);
	--jbh-custom-badge-text:          var(--jbh-custom-badge-text-lt);
	/* Store grid — Featured-product outline */
	--jbh-featured-outline:           var(--jbh-featured-outline-lt);
	/* Store grid — Filter / sort / search toolbar */
	--jbh-filter-bg:                  var(--jbh-filter-bg-lt);
	--jbh-filter-text:                var(--jbh-filter-text-lt);
	--jbh-filter-border:              var(--jbh-filter-border-lt);
	--jbh-filter-active-bg:           var(--jbh-filter-active-bg-lt);
	--jbh-filter-active-text:         var(--jbh-filter-active-text-lt);
	/* Hero section */
	--jbh-hero-heading-color:  var(--jbh-hero-heading-lt);
	--jbh-hero-heading2-color: var(--jbh-hero-heading2-lt);
	--jbh-hero-subtitle-color: var(--jbh-hero-subtitle-lt);
	--jbh-hero-badge-color:    var(--jbh-hero-badge-lt);
	--jbh-hero-btn-bg:         var(--jbh-hero-btn-lt);
	--jbh-hero-btn-text:       var(--jbh-hero-btn-text-lt);
	--jbh-hero-btn-hover-bg:   var(--jbh-hero-btn-hover-lt);
	--jbh-hero-btn-hover-text: var(--jbh-hero-btn-hover-text-lt);
	--jbh-hero-sec-btn-bg: var(--jbh-hero-sec-btn-lt);
	--jbh-hero-sec-btn-text: var(--jbh-hero-sec-btn-text-lt);
	--jbh-hero-feat-card-bg: var(--jbh-hero-feat-card-bg-lt);
	--jbh-hero-feat-heading: var(--jbh-hero-feat-heading-lt);
	--jbh-hero-feat-desc: var(--jbh-hero-feat-desc-lt);
	--jbh-hero-feat-icon: var(--jbh-hero-feat-icon-lt);
	--jbh-hero-feat-eyebrow: var(--jbh-hero-feat-eyebrow-lt);
	/* Section header */
	--jbh-sh-heading-color:  var(--jbh-sh-heading-lt);
	--jbh-sh-subtitle-color: var(--jbh-sh-subtitle-lt);
	--jbh-sh-badge-color:    var(--jbh-sh-badge-lt);
	/* Page intro */
	--jbh-pi-heading-color:      var(--jbh-pi-heading-lt);
	--jbh-pi-subtitle-color:     var(--jbh-pi-subtitle-lt);
	--jbh-pi-label-color:        var(--jbh-pi-label-lt);
	--jbh-pi-callout-text-color: var(--jbh-pi-callout-text-lt);
	--jbh-pi-status-text-color:  var(--jbh-pi-status-text-lt);
	/* CTA banner */
	--jbh-cta-heading-color:   var(--jbh-cta-heading-lt);
	--jbh-cta-subtitle-color:  var(--jbh-cta-subtitle-lt);
	--jbh-cta-badge-color:     var(--jbh-cta-badge-lt);
	--jbh-cta-btn-bg:          var(--jbh-cta-btn-lt);
	--jbh-cta-btn-text:        var(--jbh-cta-btn-text-lt);
	--jbh-cta-btn-hover-bg:    var(--jbh-cta-btn-hover-lt);
	--jbh-cta-btn-hover-text:  var(--jbh-cta-btn-hover-text-lt);
	/* About section */
	--jbh-about-heading-color: var(--jbh-about-heading-lt);
	--jbh-about-bio-color:     var(--jbh-about-bio-lt);
	--jbh-about-label-color:   var(--jbh-about-label-lt);
	--jbh-about-card-bg:       var(--jbh-about-card-bg-lt);
	/* Insights grid */
	--jbh-ig-heading-color:    var(--jbh-ig-heading-lt);
	--jbh-ig-excerpt-color:    var(--jbh-ig-excerpt-lt);
	--jbh-ig-category-color:   var(--jbh-ig-category-lt);
	--jbh-ig-link-color:       var(--jbh-ig-link-lt);
	--jbh-ig-date-color:       var(--jbh-ig-date-lt);
	--jbh-ig-tag-color:        var(--jbh-ig-tag-lt);
	--jbh-ig-author-color:     var(--jbh-ig-author-lt);
	--jbh-ig-link-hover-color: var(--jbh-ig-link-hover-lt);
	--jbh-ig-meta-bg:          var(--jbh-ig-meta-bg-lt);
	--jbh-ig-card-bg:          var(--jbh-ig-card-bg-lt);
	--jbh-ig-card-border:      var(--jbh-ig-card-border-lt);
	--jbh-ig-icon-color:       var(--jbh-ig-icon-lt);
	/* Portfolio grid */
	--jbh-pf-subtitle-color:   var(--jbh-pf-subtitle-lt);
	--jbh-pf-meta-color:       var(--jbh-pf-meta-lt);
	--jbh-pf-icon-label-color: var(--jbh-pf-icon-label-lt);
}

/* STANDARD: SITE DARK → blocks DARK */
:is(html:not([data-jbh-invert])[data-theme="dark"], html:not([data-jbh-invert]).dark, html:not([data-jbh-invert])[data-color-mode="dark"]) :is(.jbh-dark, .jbh-light, .jbh-auto):not(.jbh-override-theme),
html:not([data-jbh-invert]) body[data-ct-color-mode="dark"] :is(.jbh-dark, .jbh-light, .jbh-auto):not(.jbh-override-theme) {
	--jbh-bg:            #121212;
	--jbh-card:          #1A1A1A;
	--jbh-creme:         #F0EAD6;
	--jbh-slate:         #9CA3AF;
	--jbh-heading-color: #F0EAD6;
	--jbh-text-color:    #9CA3AF;
	--jbh-card-heading:  #ffffff;
	--jbh-border:        rgba(31, 95, 91, 0.20);
	/* Grid blocks shared — dark aliases */
	--jbh-custom-header:            var(--jbh-custom-header-dk);
	--jbh-custom-price:             var(--jbh-custom-price-dk);
	--jbh-custom-desc:              var(--jbh-custom-desc-dk);
	--jbh-custom-icon:              var(--jbh-custom-icon-dk);
	--jbh-custom-btn:               var(--jbh-custom-btn-dk);
	--jbh-custom-btn-text:          var(--jbh-custom-btn-text-dk);
	--jbh-custom-card-bg:           var(--jbh-custom-card-bg-dk);
	--jbh-custom-card-border:       var(--jbh-custom-card-border-dk);
	--jbh-custom-btn-hover:         var(--jbh-custom-btn-hover-dk);
	--jbh-custom-btn-hover-text:    var(--jbh-custom-btn-hover-text-dk);
	--jbh-custom-badge:             var(--jbh-custom-badge-dk);
	--jbh-custom-target:            var(--jbh-custom-target-dk);
	--jbh-custom-tag:               var(--jbh-custom-tag-dk);
	--jbh-custom-block-bg:          var(--jbh-custom-block-bg-dk);
	/* Studio grid */
	--jbh-custom-target-text:       var(--jbh-custom-target-text-dk);
	--jbh-custom-timeline-label:    var(--jbh-custom-timeline-label-dk);
	--jbh-custom-timeline-value:    var(--jbh-custom-timeline-value-dk);
	--jbh-custom-price-label:       var(--jbh-custom-price-label-dk);
	--jbh-custom-card-header-bg:    var(--jbh-custom-card-header-bg-dk);
	--jbh-custom-icon-box-bg:       var(--jbh-custom-icon-box-bg-dk);
	--jbh-custom-target-band-bg:    var(--jbh-custom-target-band-bg-dk);
	--jbh-custom-includes-label:    var(--jbh-custom-includes-label-dk);
	--jbh-custom-includes-text:     var(--jbh-custom-includes-text-dk);
	--jbh-custom-includes-icon:     var(--jbh-custom-includes-icon-dk);
	--jbh-custom-addons-label:      var(--jbh-custom-addons-label-dk);
	--jbh-custom-addons-pill-bg:    var(--jbh-custom-addons-pill-bg-dk);
	--jbh-custom-addons-pill-bd:    var(--jbh-custom-addons-pill-bd-dk);
	--jbh-custom-addons-pill-tx:    var(--jbh-custom-addons-pill-tx-dk);
	--jbh-custom-addons-price:      var(--jbh-custom-addons-price-dk);
	--jbh-custom-card-footer-bg:    var(--jbh-custom-card-footer-bg-dk);
	/* Pricing plans — billing toggle */
	--jbh-custom-toggle-track:        var(--jbh-custom-toggle-track-dk);
	--jbh-custom-toggle-track-active: var(--jbh-custom-toggle-track-active-dk);
	--jbh-custom-toggle-dot:          var(--jbh-custom-toggle-dot-dk);
	/* Store grid — Product badge */
	--jbh-custom-badge-bg:            var(--jbh-custom-badge-bg-dk);
	--jbh-custom-badge-text:          var(--jbh-custom-badge-text-dk);
	/* Store grid — Featured-product outline */
	--jbh-featured-outline:           var(--jbh-featured-outline-dk);
	/* Store grid — Filter / sort / search toolbar */
	--jbh-filter-bg:                  var(--jbh-filter-bg-dk);
	--jbh-filter-text:                var(--jbh-filter-text-dk);
	--jbh-filter-border:              var(--jbh-filter-border-dk);
	--jbh-filter-active-bg:           var(--jbh-filter-active-bg-dk);
	--jbh-filter-active-text:         var(--jbh-filter-active-text-dk);
	/* Hero section */
	--jbh-hero-heading-color:  var(--jbh-hero-heading-dk);
	--jbh-hero-heading2-color: var(--jbh-hero-heading2-dk);
	--jbh-hero-subtitle-color: var(--jbh-hero-subtitle-dk);
	--jbh-hero-badge-color:    var(--jbh-hero-badge-dk);
	--jbh-hero-btn-bg:         var(--jbh-hero-btn-dk);
	--jbh-hero-btn-text:       var(--jbh-hero-btn-text-dk);
	--jbh-hero-btn-hover-bg:   var(--jbh-hero-btn-hover-dk);
	--jbh-hero-btn-hover-text: var(--jbh-hero-btn-hover-text-dk);
	--jbh-hero-sec-btn-bg: var(--jbh-hero-sec-btn-dk);
	--jbh-hero-sec-btn-text: var(--jbh-hero-sec-btn-text-dk);
	--jbh-hero-feat-card-bg: var(--jbh-hero-feat-card-bg-dk);
	--jbh-hero-feat-heading: var(--jbh-hero-feat-heading-dk);
	--jbh-hero-feat-desc: var(--jbh-hero-feat-desc-dk);
	--jbh-hero-feat-icon: var(--jbh-hero-feat-icon-dk);
	--jbh-hero-feat-eyebrow: var(--jbh-hero-feat-eyebrow-dk);
	/* Section header */
	--jbh-sh-heading-color:  var(--jbh-sh-heading-dk);
	--jbh-sh-subtitle-color: var(--jbh-sh-subtitle-dk);
	--jbh-sh-badge-color:    var(--jbh-sh-badge-dk);
	/* Page intro */
	--jbh-pi-heading-color:      var(--jbh-pi-heading-dk);
	--jbh-pi-subtitle-color:     var(--jbh-pi-subtitle-dk);
	--jbh-pi-label-color:        var(--jbh-pi-label-dk);
	--jbh-pi-callout-text-color: var(--jbh-pi-callout-text-dk);
	--jbh-pi-status-text-color:  var(--jbh-pi-status-text-dk);
	/* CTA banner */
	--jbh-cta-heading-color:   var(--jbh-cta-heading-dk);
	--jbh-cta-subtitle-color:  var(--jbh-cta-subtitle-dk);
	--jbh-cta-badge-color:     var(--jbh-cta-badge-dk);
	--jbh-cta-btn-bg:          var(--jbh-cta-btn-dk);
	--jbh-cta-btn-text:        var(--jbh-cta-btn-text-dk);
	--jbh-cta-btn-hover-bg:    var(--jbh-cta-btn-hover-dk);
	--jbh-cta-btn-hover-text:  var(--jbh-cta-btn-hover-text-dk);
	/* About section */
	--jbh-about-heading-color: var(--jbh-about-heading-dk);
	--jbh-about-bio-color:     var(--jbh-about-bio-dk);
	--jbh-about-label-color:   var(--jbh-about-label-dk);
	--jbh-about-card-bg:       var(--jbh-about-card-bg-dk);
	/* Insights grid */
	--jbh-ig-heading-color:    var(--jbh-ig-heading-dk);
	--jbh-ig-excerpt-color:    var(--jbh-ig-excerpt-dk);
	--jbh-ig-category-color:   var(--jbh-ig-category-dk);
	--jbh-ig-link-color:       var(--jbh-ig-link-dk);
	--jbh-ig-date-color:       var(--jbh-ig-date-dk);
	--jbh-ig-tag-color:        var(--jbh-ig-tag-dk);
	--jbh-ig-author-color:     var(--jbh-ig-author-dk);
	--jbh-ig-link-hover-color: var(--jbh-ig-link-hover-dk);
	--jbh-ig-meta-bg:          var(--jbh-ig-meta-bg-dk);
	--jbh-ig-card-bg:          var(--jbh-ig-card-bg-dk);
	--jbh-ig-card-border:      var(--jbh-ig-card-border-dk);
	--jbh-ig-icon-color:       var(--jbh-ig-icon-dk);
	/* Portfolio grid */
	--jbh-pf-subtitle-color:   var(--jbh-pf-subtitle-dk);
	--jbh-pf-meta-color:       var(--jbh-pf-meta-dk);
	--jbh-pf-icon-label-color: var(--jbh-pf-icon-label-dk);
}

/* ── Smooth Dark ↔ Light Mode Flip ──────────────────────────────
   Two historical implementations existed before the current one:

     v1 (laggy)  — added `.jbh-theme-transitioning` for 400 ms and
                   ran a 0.4s cross-fade on every palette-touching
                   property. The dark gradient on a studio-grid
                   card header (painted via `background:
                   linear-gradient(…, var(--jbh-bg), …)`) ended up
                   cross-fading with its light-mode counterpart
                   for almost half a second — the toggle felt
                   broken, not fluid.
     v2 (jarring)— added `.jbh-mode-flipping` and nuked every
                   transition to 0 s so the palette repainted
                   INSTANTLY. Solid colors snapped hard while
                   Blocksy's own site-wide UI continued fading
                   smoothly over 0.3s, so JBH blocks looked out of
                   sync with the rest of the page.

   v4 (current) — the best of both: during the flip we APPLY a
   fast 0.15s ease-out transition — but ONLY on the solid color
   properties (`background-color`, `color`, `border-color`, `fill`,
   `stroke`, `outline-color`). `background-image` is intentionally
   omitted, so any element painting a gradient (studio card header,
   hero ambience ring, CTA banner neon wash) swaps its computed
   gradient instantly — dodging the v1 cross-fade artifact entirely
   — while every flat-color element fades in lock-step with
   Blocksy Pro's default 150 ms chrome fade. v3 used 0.25s which
   visibly trailed the surrounding page; 0.15s locks JBH blocks to
   the same cadence as Blocksy's own palette swap.

   `!important` is required to beat element-level `transition:`
   shorthands that might otherwise re-specify `transition-property:
   all`. The class is only present for ~170 ms (one 0.15s
   transition cycle + a 20 ms safety margin) so hover transitions
   resume normal behavior as soon as the fade completes.

   Scope is the 13 JBH block wrappers + the two modal overlays.
   Universal selectors (`.jbh-mode-flipping *`) would interfere
   with Blocksy's own mode-switch transitions, so we stay opt-in.
   v1.2.4: added page-intro, contact-section, testimonials and
   tools-resources so the cross-fade applies uniformly to every
   block the plugin ships — previously these 4 snapped while their
   neighbours faded, which read as a glitch on multi-block pages. */
html.jbh-mode-flipping :is(
	.jbh-studio-grid,
	.jbh-store-grid,
	.jbh-pricing-plans,
	.jbh-portfolio-grid,
	.jbh-hero-section,
	.jbh-section-header,
	.jbh-about-section,
	.jbh-insights-grid,
	.jbh-cta-banner,
	.jbh-page-intro,
	.jbh-contact-section,
	.jbh-testimonials,
	.jbh-tools-resources,
	#jbh-modal-overlay,
	.jbh-portfolio-modal-overlay
),
html.jbh-mode-flipping :is(
	.jbh-studio-grid,
	.jbh-store-grid,
	.jbh-pricing-plans,
	.jbh-portfolio-grid,
	.jbh-hero-section,
	.jbh-section-header,
	.jbh-about-section,
	.jbh-insights-grid,
	.jbh-cta-banner,
	.jbh-page-intro,
	.jbh-contact-section,
	.jbh-testimonials,
	.jbh-tools-resources,
	#jbh-modal-overlay,
	.jbh-portfolio-modal-overlay
) *,
html.jbh-mode-flipping :is(
	.jbh-studio-grid,
	.jbh-store-grid,
	.jbh-pricing-plans,
	.jbh-portfolio-grid,
	.jbh-hero-section,
	.jbh-section-header,
	.jbh-about-section,
	.jbh-insights-grid,
	.jbh-cta-banner,
	.jbh-page-intro,
	.jbh-contact-section,
	.jbh-testimonials,
	.jbh-tools-resources,
	#jbh-modal-overlay,
	.jbh-portfolio-modal-overlay
) *::before,
html.jbh-mode-flipping :is(
	.jbh-studio-grid,
	.jbh-store-grid,
	.jbh-pricing-plans,
	.jbh-portfolio-grid,
	.jbh-hero-section,
	.jbh-section-header,
	.jbh-about-section,
	.jbh-insights-grid,
	.jbh-cta-banner,
	.jbh-page-intro,
	.jbh-contact-section,
	.jbh-testimonials,
	.jbh-tools-resources,
	#jbh-modal-overlay,
	.jbh-portfolio-modal-overlay
) *::after {
	transition:
		background-color 0.15s cubic-bezier(0.4, 0, 0.2, 1),
		color            0.15s cubic-bezier(0.4, 0, 0.2, 1),
		border-color     0.15s cubic-bezier(0.4, 0, 0.2, 1),
		outline-color    0.15s cubic-bezier(0.4, 0, 0.2, 1),
		fill             0.15s cubic-bezier(0.4, 0, 0.2, 1),
		stroke           0.15s cubic-bezier(0.4, 0, 0.2, 1),
		box-shadow       0.15s cubic-bezier(0.4, 0, 0.2, 1) !important;
}

/* Accessibility — honour the user's prefers-reduced-motion setting.
   When reduced motion is requested, we go back to the v2 instant
   flip so the mode swap happens without any fade whatsoever. */
@media (prefers-reduced-motion: reduce) {
	html.jbh-mode-flipping :is(
		.jbh-studio-grid,
		.jbh-store-grid,
		.jbh-pricing-plans,
		.jbh-portfolio-grid,
		.jbh-hero-section,
		.jbh-section-header,
		.jbh-about-section,
		.jbh-insights-grid,
		.jbh-cta-banner,
		.jbh-page-intro,
		.jbh-contact-section,
		.jbh-testimonials,
		.jbh-tools-resources,
		#jbh-modal-overlay,
		.jbh-portfolio-modal-overlay
	),
	html.jbh-mode-flipping :is(
		.jbh-studio-grid,
		.jbh-store-grid,
		.jbh-pricing-plans,
		.jbh-portfolio-grid,
		.jbh-hero-section,
		.jbh-section-header,
		.jbh-about-section,
		.jbh-insights-grid,
		.jbh-cta-banner,
		.jbh-page-intro,
		.jbh-contact-section,
		.jbh-testimonials,
		.jbh-tools-resources,
		#jbh-modal-overlay,
		.jbh-portfolio-modal-overlay
	) * {
		transition: none !important;
		animation-duration: 0s !important;
	}
}

/* ── Gap / Radius Variants ───────────────────────────────────── */
.jbh-gap-small  { --jbh-gap: 12px; }
.jbh-gap-medium { --jbh-gap: 20px; }
.jbh-gap-large  { --jbh-gap: 32px; }
.jbh-radius-none   { --jbh-card-radius: 0; }
.jbh-radius-small  { --jbh-card-radius: 4px; }
.jbh-radius-medium { --jbh-card-radius: 8px; }
.jbh-radius-large  { --jbh-card-radius: 16px; }

/* ================================================================
   1.  STUDIO GRID
   ================================================================ */
.jbh-studio-grid { background: var(--jbh-custom-block-bg, var(--jbh-bg)); padding: 60px 24px; font-family: var(--jbh-font-sans); }
.jbh-studio-grid .jbh-section-header { display: flex; align-items: center; gap: 12px; margin-bottom: 28px; }
.jbh-service-grid { display: grid; gap: var(--jbh-gap); grid-template-columns: repeat(var(--jbh-cols, 3), 1fr); }
.jbh-service-card { position: relative; background: var(--jbh-custom-card-bg, var(--jbh-card)); border-radius: var(--jbh-card-radius); padding: 0; display: flex; flex-direction: column; transition: transform var(--jbh-transition), box-shadow var(--jbh-transition), border-color var(--jbh-transition); overflow: hidden; border: 1px solid rgba(42,157,143,0.10); box-shadow: 0 4px 20px rgba(0,0,0,0.08); }
.jbh-service-card:hover { box-shadow: 0 8px 30px rgba(0,0,0,0.14); }
.jbh-service-card.jbh-recommended { border: 2px solid var(--jbh-custom-badge-bg, var(--jbh-teal-dark)); box-shadow: 0 8px 30px rgba(42,157,143,0.15); z-index: 10; overflow: visible !important; }
@media (min-width: 1024px) {
	.jbh-studio-grid .jbh-service-grid .jbh-service-card { margin-top: 16px; }
	.jbh-studio-grid .jbh-service-grid .jbh-service-card.jbh-recommended { margin-top: 0; transform: translateY(-16px); }
	.jbh-studio-grid .jbh-service-grid .jbh-service-card.jbh-recommended:hover { transform: translateY(-18px); }
}
.jbh-card-rec-badge { position: absolute; top: 0; left: 50%; transform: translate(-50%, -50%); background: var(--jbh-custom-badge-bg, var(--jbh-teal-dark)); color: var(--jbh-custom-badge-text, #fff); font-size: 10px; font-family: var(--jbh-font-mono); font-weight: 700; text-transform: uppercase; letter-spacing: 0.15em; padding: 6px 20px; border-radius: 999px; white-space: nowrap; z-index: 20; box-shadow: 0 2px 8px rgba(0,0,0,0.15); }
/* Card header surface. When no picker is set the background falls back
   to the original `linear-gradient(to bottom, var(--jbh-bg), transparent)`
   so existing sites keep their look. When the Inspector's "Card Header
   Background" picker is set (per mode), that value wins. This is also
   what makes the dark-mode gradient vanish instantly on mode flip —
   the user-set bg shares a single token which the cascade resolver
   swaps atomically. */
.jbh-card-header { padding: 32px 32px 24px; position: relative; overflow: hidden; border-bottom: 1px solid var(--jbh-border); background: var(--jbh-custom-card-header-bg, linear-gradient(to bottom, var(--jbh-bg), transparent)); border-radius: var(--jbh-card-radius) var(--jbh-card-radius) 0 0; }
.jbh-recommended .jbh-card-header { padding-top: 40px; }
.jbh-no-header-gradient .jbh-card-header { background: var(--jbh-custom-card-header-bg, var(--jbh-card)); }
/* Mode-reactive watermark opacity. 0.05 teal reads fine on a dark card but
   is practically invisible on white — light mode bumps to 0.08 so it stays
   perceptible as intentional texture instead of a rendering bug. */
/* Watermark color change is INSTANT on mode flip — the previous
   `transition: color 0.5s ease` was the primary visible culprit in
   the "dark → light has a lingering teal ghost" bug. Hover fade-in
   is still smooth because the transition lives on the :hover
   selector only, which means palette changes (which bypass :hover)
   skip the transition entirely and repaint at the site's new mode. */
.jbh-card-watermark { position: absolute; bottom: -40px; right: -40px; width: 192px; height: 192px; color: var(--jbh-watermark-color, rgba(42,157,143,0.05)); pointer-events: none; }
.jbh-service-card:hover .jbh-card-watermark { color: var(--jbh-watermark-color-hover, rgba(42,157,143,0.10)); transition: color 0.3s ease; }
.jbh-card-watermark svg { width: 100%; height: 100%; }
.jbh-card-header-inner { position: relative; z-index: 2; }
.jbh-card-icon-box { width: 56px; height: 56px; background: var(--jbh-custom-icon-box-bg, rgba(42,157,143,0.10)); color: var(--jbh-custom-icon, var(--jbh-teal)); border-radius: 12px; display: flex; align-items: center; justify-content: center; margin-bottom: 20px; box-shadow: inset 0 1px 2px rgba(0,0,0,0.06); }
.jbh-card-icon-box svg { width: 28px; height: 28px; }
.jbh-card-title { font-family: var(--jbh-font-serif); font-size: 22px; font-weight: 700; color: var(--jbh-card-heading); margin: 0 0 10px; }
.jbh-card-desc { color: var(--jbh-text-color); font-size: 14px; line-height: 1.7; margin: 0; font-weight: 300; }
.jbh-card-target-band { padding: 16px 32px; background: var(--jbh-custom-target-band-bg, rgba(42,157,143,0.05)); border-bottom: 1px solid var(--jbh-border); display: flex; flex-direction: column; gap: 4px; }
.jbh-card-target-label { font-size: 10px; font-family: var(--jbh-font-mono); text-transform: uppercase; letter-spacing: 0.12em; color: var(--jbh-custom-target, var(--jbh-text-color)); }
.jbh-card-target-text { font-size: 12px; font-weight: 500; color: var(--jbh-custom-target-text, var(--jbh-heading-color)); line-height: 1.4; }
.jbh-card-body { padding: 32px; flex-grow: 1; display: flex; flex-direction: column; }
.jbh-card-includes-label { font-size: 10px; font-family: var(--jbh-font-mono); text-transform: uppercase; letter-spacing: 0.12em; color: var(--jbh-custom-includes-label, var(--jbh-text-color)); margin: 0 0 16px; font-weight: 400; }
.jbh-card-includes { list-style: none; padding: 0; margin: 0 0 24px; }
.jbh-card-includes li { display: flex; align-items: flex-start; gap: 12px; font-size: 14px; color: var(--jbh-custom-includes-text, var(--jbh-heading-color)); font-weight: 300; line-height: 1.5; padding: 8px 0; }
.jbh-check-icon { width: 16px; height: 16px; min-width: 16px; margin-top: 2px; color: var(--jbh-custom-includes-icon, var(--jbh-custom-icon, var(--jbh-teal))); }
.jbh-card-addons-wrap { margin-top: auto; padding-top: 20px; border-top: 1px solid var(--jbh-border); }
.jbh-card-addons-label { font-size: 10px; font-family: var(--jbh-font-mono); text-transform: uppercase; letter-spacing: 0.12em; color: var(--jbh-custom-addons-label, var(--jbh-text-color)); margin: 0 0 12px; font-weight: 400; }
/* Vertical-stacked add-on rows. Each add-on is a full-width row with the
   label on the left (flex-grows so long names like "Key Concept Illustration"
   wrap rather than collide with the price column) and the price right-aligned.
   Switched from a horizontal pill strip because the labels are long enough
   that 2-up pills got cramped on 3-column desktop grids and every viewport on
   mobile, and because each add-on now always shows its price (boolean add-ons
   render "+$X", quantity add-ons render "$X/ea"), which makes a cleaner
   tabular reading order than wrapping pills. */
.jbh-card-addons-pills { display: flex; flex-direction: column; gap: 6px; }
.jbh-addon-pill { display: flex; align-items: center; justify-content: space-between; gap: 12px; font-size: 11px; font-family: var(--jbh-font-mono); color: var(--jbh-custom-addons-pill-tx, var(--jbh-text-color)); border: 1px solid var(--jbh-custom-addons-pill-bd, rgba(42,157,143,0.20)); background: var(--jbh-custom-addons-pill-bg, var(--jbh-bg)); padding: 8px 14px; border-radius: 8px; transition: border-color var(--jbh-transition); cursor: default; }
.jbh-service-card:hover .jbh-addon-pill { border-color: var(--jbh-custom-addons-pill-bd, rgba(42,157,143,0.40)); }
.jbh-addon-label { flex: 1 1 auto; min-width: 0; line-height: 1.4; }
.jbh-addon-price { color: var(--jbh-custom-addons-price, var(--jbh-teal)); font-weight: 700; flex-shrink: 0; white-space: nowrap; }
.jbh-card-footer { padding: 24px 32px; margin-top: auto; border-top: 1px solid var(--jbh-border); background: color-mix(in srgb, var(--jbh-bg) 50%, transparent); border-radius: 0 0 var(--jbh-card-radius) var(--jbh-card-radius); }
.jbh-card-pricing { display: flex; justify-content: space-between; align-items: flex-end; margin-bottom: 20px; }
.jbh-card-price-group, .jbh-card-timeline-group { display: flex; flex-direction: column; }
/* Price label ("Digital Product Investment" by default) inherits from
   the Timeline Label picker when its own picker is empty. This removes
   the friction of having to pick the same colour twice for what reads
   as one visual row in the card footer. Users who want independent
   control still get it by setting the Price Label Color explicitly. */
.jbh-card-price-label    { font-size: 10px; font-family: var(--jbh-font-mono); text-transform: uppercase; letter-spacing: 0.12em; color: var(--jbh-custom-price-label, var(--jbh-custom-timeline-label, var(--jbh-text-color))); margin-bottom: 4px; }
.jbh-card-timeline-label { font-size: 10px; font-family: var(--jbh-font-mono); text-transform: uppercase; letter-spacing: 0.12em; color: var(--jbh-custom-timeline-label, var(--jbh-text-color)); margin-bottom: 4px; }
.jbh-card-price { font-family: var(--jbh-font-serif); font-size: 36px; font-weight: 700; color: var(--jbh-custom-price, var(--jbh-card-heading)); line-height: 1; }
.jbh-card-timeline { font-family: var(--jbh-font-serif); font-size: 14px; font-weight: 700; color: var(--jbh-custom-timeline-value, var(--jbh-custom-icon, var(--jbh-teal))); }
.jbh-card-timeline-group { text-align: right; }
.jbh-get-started-btn { display: block; width: 100%; padding: 16px; border-radius: var(--jbh-card-radius); font-size: 14px; font-weight: 700; font-family: var(--jbh-font-serif); letter-spacing: 0.02em; cursor: pointer; transition: all var(--jbh-transition); text-align: center; background: var(--jbh-custom-btn, var(--jbh-teal)); color: var(--jbh-custom-btn-text, #ffffff); border: 2px solid var(--jbh-custom-btn, var(--jbh-teal)); }
.jbh-get-started-btn:hover, .jbh-get-started-btn:focus-visible { filter: brightness(1.1); transform: translateY(-1px); }
.jbh-get-started-btn.jbh-btn-coral { background: var(--jbh-coral); border-color: var(--jbh-coral); box-shadow: 0 4px 14px rgba(214,79,66,0.25); }
.jbh-get-started-btn.jbh-btn-coral:hover { background: var(--jbh-coral-hover, #E76F51); border-color: var(--jbh-coral-hover, #E76F51); }
.jbh-layout-list .jbh-service-grid { grid-template-columns: 1fr !important; }
.jbh-layout-list .jbh-service-card { flex-direction: row; }
.jbh-layout-list .jbh-card-header { border-bottom: none; border-right: 1px solid var(--jbh-border); min-width: 280px; border-radius: var(--jbh-card-radius) 0 0 var(--jbh-card-radius); }
.jbh-layout-list .jbh-card-footer { border-top: none; }

/* ── 4-column compact sizing for studio cards ──────────────────
   With the new four-card default (blueprint / ecosystem / acoustic /
   kinetic) each card drops to ~287px wide on a 1280px viewport.
   Tighten structural padding + icon-box so headline / target band /
   includes list / add-on pills breathe inside the narrower track.
      Desktop 4-column cards need slightly tighter title rhythm so longer
   service names fit their card width without weakening the naming.
   Scoped to min-width:1025px because the existing
   responsive rule already collapses to 2-up below that width and the
   tightening would otherwise over-shrink the 2-up layout. */
@media (min-width: 1025px) {
	.jbh-studio-grid[style*="--jbh-cols:4"] .jbh-card-header        { padding: 24px 22px 18px; }
	.jbh-studio-grid[style*="--jbh-cols:4"] .jbh-recommended .jbh-card-header { padding-top: 32px; }
	.jbh-studio-grid[style*="--jbh-cols:4"] .jbh-card-target-band   { padding: 14px 22px; }
	.jbh-studio-grid[style*="--jbh-cols:4"] .jbh-card-body          { padding: 22px; }
	.jbh-studio-grid[style*="--jbh-cols:4"] .jbh-card-footer        { padding: 20px 22px; }
	.jbh-studio-grid[style*="--jbh-cols:4"] .jbh-card-icon-box      { width: 48px; height: 48px; margin-bottom: 16px; border-radius: 10px; }
		.jbh-studio-grid[style*="--jbh-cols:4"] .jbh-card-icon-box svg  { width: 24px; height: 24px; }
	.jbh-studio-grid[style*="--jbh-cols:4"] .jbh-card-title         { font-size: clamp(17px, 1.15vw, 18.5px); line-height: 1.16; letter-spacing: -0.01em; min-height: 2.35em; text-wrap: balance; }
	.jbh-studio-grid[style*="--jbh-cols:4"] .jbh-card-desc          { min-height: 4.25em; }
	.jbh-studio-grid[style*="--jbh-cols:4"] .jbh-card-includes      { margin: 0 0 18px; }
	.jbh-studio-grid[style*="--jbh-cols:4"] .jbh-addon-pill         { padding: 8px 12px; font-size: 12px; }
	.jbh-studio-grid[style*="--jbh-cols:4"] .jbh-get-started-btn    { padding: 14px; font-size: 13px; }
}

/* ── Studio card title balance — tablet/mobile ─────────────────
   Desktop keeps the 4-column tightening above. This adds softer
   responsive title sizing for 2-column tablet and 1-column mobile
   Studio cards without touching Store, Plans, Portfolio, or modals. */
@media (max-width: 1024px) {
	.jbh-studio-grid .jbh-service-card .jbh-card-title {
		font-size: clamp(19px, 3.2vw, 21px);
		line-height: 1.18;
		letter-spacing: -0.01em;
		text-wrap: balance;
	}
}

@media (max-width: 480px) {
	.jbh-studio-grid .jbh-service-card .jbh-card-title {
		font-size: clamp(18px, 5vw, 20px);
		line-height: 1.18;
		min-height: 0;
	}
}

/* ── Container overflow — break out of parent width ────────────
   When the user enables "Break Out of Container Width" in the
   inspector the wrapper escapes its parent's `max-width` cap via
   the negative-margin recenter trick (`margin-left: calc((100% -
   breakoutWidth) / 2)`). The breakout extent is driven by the
   `--jbh-overflow-w` variable that render.php emits from the
   inspector slider value (60vw–100vw). The variable defaults to
   `100vw` so any pre-existing block saved with only the toggle
   attribute still produces a true edge-to-edge bleed. The inner
   `.jbh-service-grid` carries the user's optional max-width cap
   (--jbh-overflow-max-width) so the cards stay readable while the
   wrapper background can still bleed full-bleed — a pattern
   WP-core's `.alignfull` doesn't support out of the box.
   `box-sizing: border-box` keeps the existing 24px horizontal
   padding inside the breakout bounds (without it the wrapper
   would overflow horizontally and produce a phantom scrollbar).
   Selector specificity (0,2,0) is intentionally LOWER than the
   constraint rule's (0,4,0) at the bottom of this file — the
   constraint self-excludes via `:not(.jbh-overflow-container)` so
   the two rules cleanly partition the element space without
   relying on a specificity contest. */
.jbh-studio-grid.jbh-overflow-container {
	width: var(--jbh-overflow-w, 100vw);
	max-width: var(--jbh-overflow-w, 100vw);
	margin-left: calc((100% - var(--jbh-overflow-w, 100vw)) / 2);
	margin-right: calc((100% - var(--jbh-overflow-w, 100vw)) / 2);
	box-sizing: border-box;
}
.jbh-studio-grid.jbh-overflow-container .jbh-service-grid {
	max-width: var(--jbh-overflow-max-width, none);
	margin-left: auto;
	margin-right: auto;
}

/* ================================================================
   COMPACT CARDS — collapse card bodies; expand ALL simultaneously
   when ANY card in the grid is hovered / focused / when the user
   clicks the "Expand All" button (toggles .jbh-force-expanded on
   the wrapper).
   ================================================================ */
.jbh-compact-cards .jbh-card-body {
	max-height: 0;
	overflow: hidden;
	padding-top: 0;
	padding-bottom: 0;
	opacity: 0;
	transition: max-height 0.45s cubic-bezier(0.4,0,0.2,1),
	            padding 0.35s ease,
	            opacity 0.35s ease;
}
/* ── Hover behaviour: ALL mode (default) ─────────────────────────
   Grid-level hover/focus expands EVERY card body in lockstep so the
   visitor can compare packages without chasing the pointer
   card-by-card. .jbh-force-expanded is the persistent state toggled
   by the Expand All button (see frontend.js → initStudioExpandAll).
   The `:not(.jbh-hover-single)` guard hands control over to the
   single-card rule set further below when the editor opts in. */
.jbh-compact-cards:not(.jbh-hover-single) .jbh-service-grid:hover .jbh-card-body,
.jbh-compact-cards:not(.jbh-hover-single) .jbh-service-grid:focus-within .jbh-card-body,
.jbh-compact-cards.jbh-force-expanded .jbh-card-body {
	max-height: 1200px;
	padding-top: 32px;
	padding-bottom: 32px;
	opacity: 1;
}

/* ── Hover behaviour: SINGLE mode (.jbh-hover-single) ────────────
   Restores the classic per-card hover/focus — only the card the
   visitor is interacting with reveals its body; the rest stay
   compact. .jbh-force-expanded still wins (the rule above already
   matches because it doesn't carry the :not(.jbh-hover-single)
   guard for that branch — see the third selector). */
.jbh-compact-cards.jbh-hover-single .jbh-service-card:hover .jbh-card-body,
.jbh-compact-cards.jbh-hover-single .jbh-service-card:focus-within .jbh-card-body {
	max-height: 1200px;
	padding-top: 32px;
	padding-bottom: 32px;
	opacity: 1;
}

/* SINGLE mode compact-height balance —
   Tablet/desktop only: minimized cards share the same height.
   Mobile stays natural because cards stack vertically. */
@media (min-width: 768px) {
	.jbh-compact-cards.jbh-hover-single:not(.jbh-force-expanded)
		.jbh-service-grid:not(:hover):not(:focus-within) {
		align-items: stretch;
		grid-auto-rows: 1fr;
	}

	.jbh-compact-cards.jbh-hover-single:not(.jbh-force-expanded)
		.jbh-service-grid:not(:hover):not(:focus-within) .jbh-service-card {
		height: 100%;
	}

	/* During single-card hover/focus, keep only the active card expanding naturally. */
	.jbh-compact-cards.jbh-hover-single:not(.jbh-force-expanded) .jbh-service-grid:hover,
	.jbh-compact-cards.jbh-hover-single:not(.jbh-force-expanded) .jbh-service-grid:focus-within {
		align-items: start;
		grid-auto-rows: auto;
	}

	/* Minimized text safety: prevents long text from forcing one compact card taller. */
	.jbh-compact-cards.jbh-hover-single:not(.jbh-force-expanded)
		.jbh-service-card:not(:hover):not(:focus-within) .jbh-card-title,
	.jbh-compact-cards.jbh-hover-single:not(.jbh-force-expanded)
		.jbh-service-card:not(:hover):not(:focus-within) .jbh-card-desc,
	.jbh-compact-cards.jbh-hover-single:not(.jbh-force-expanded)
		.jbh-service-card:not(:hover):not(:focus-within) .jbh-card-target-text {
		display: -webkit-box;
		-webkit-box-orient: vertical;
		overflow: hidden;
	}

	.jbh-compact-cards.jbh-hover-single:not(.jbh-force-expanded)
		.jbh-service-card:not(:hover):not(:focus-within) .jbh-card-title {
		-webkit-line-clamp: 2;
	}

	.jbh-compact-cards.jbh-hover-single:not(.jbh-force-expanded)
		.jbh-service-card:not(:hover):not(:focus-within) .jbh-card-desc {
		-webkit-line-clamp: 3;
	}

	.jbh-compact-cards.jbh-hover-single:not(.jbh-force-expanded)
		.jbh-service-card:not(:hover):not(:focus-within) .jbh-card-target-text {
		-webkit-line-clamp: 3;
	}
}

/* Mobile: natural stacked card heights. */
@media (max-width: 767px) {
	.jbh-compact-cards.jbh-hover-single:not(.jbh-force-expanded) .jbh-service-grid {
		align-items: stretch;
		grid-auto-rows: auto;
	}

	.jbh-compact-cards.jbh-hover-single:not(.jbh-force-expanded) .jbh-service-card {
		height: auto;
	}

	.jbh-compact-cards.jbh-hover-single:not(.jbh-force-expanded) .jbh-card-title,
	.jbh-compact-cards.jbh-hover-single:not(.jbh-force-expanded) .jbh-card-desc,
	.jbh-compact-cards.jbh-hover-single:not(.jbh-force-expanded) .jbh-card-target-text {
		display: block;
		overflow: visible;
		-webkit-line-clamp: unset;
		-webkit-box-orient: initial;
	}
}
/* Belt-and-braces: also clamp `flex-grow` to 0 on non-hovered card
   bodies in SINGLE mode so even if a parent layout (theme grid
   override, FSE pattern, custom CSS) reintroduces stretching, the
   card body itself refuses to consume the extra space and won't
   create the "empty content" gap the user reported. The hovered
   card's body still keeps its expanded max-height from the rule
   above, so this only neutralises the empty-stretch bug. */
.jbh-compact-cards.jbh-hover-single:not(.jbh-force-expanded) .jbh-service-card:not(:hover):not(:focus-within) .jbh-card-body {
	flex-grow: 0;
}

/* ── Studio card description height balance ─────────────────────
   Keeps the description directly under each Studio card title aligned
   across cards even when description word counts differ. Extra text is
   line-clamped so the following "Best For" ribbon starts at the same
   vertical position in every card. */
.jbh-studio-grid .jbh-service-card .jbh-card-desc {
	display: -webkit-box;
	-webkit-box-orient: vertical;
	-webkit-line-clamp: 4;
	line-clamp: 4;
	overflow: hidden;
	min-height: calc(1.7em * 4);
	max-height: calc(1.7em * 4);
}

/* Tablet: wider cards need less reserved description space. */
@media (max-width: 1024px) {
	.jbh-studio-grid .jbh-service-card .jbh-card-desc {
		-webkit-line-clamp: 3;
		line-clamp: 3;
		min-height: calc(1.7em * 3);
		max-height: calc(1.7em * 3);
	}
}

/* Mobile: keep stacked cards consistent while preserving readability. */
@media (max-width: 480px) {
	.jbh-studio-grid .jbh-service-card .jbh-card-desc {
		-webkit-line-clamp: 4;
		line-clamp: 4;
		min-height: calc(1.7em * 4);
		max-height: calc(1.7em * 4);
	}
}

.jbh-compact-cards .jbh-card-target-band {
	transition: opacity 0.3s ease, padding 0.3s ease;
}
/* Target band — ALL mode: compress only when the grid is fully idle
   (no hover, no focus, not force-expanded) so every card looks
   consistently compact before any interaction. */
.jbh-compact-cards:not(.jbh-hover-single):not(.jbh-force-expanded)
	.jbh-service-grid:not(:hover):not(:focus-within) .jbh-card-target-band {
	padding-top: 8px;
	padding-bottom: 8px;
}
/* Target band — SINGLE mode: compress on every non-hovered card
   individually so the band only "blooms" on the active card. */
.jbh-compact-cards.jbh-hover-single:not(.jbh-force-expanded)
	.jbh-service-card:not(:hover):not(:focus-within) .jbh-card-target-band {
	padding-top: 8px;
	padding-bottom: 8px;
}

/* Subtle indicator hint — fades out when the matching card expands
   so the visitor gets feedback that the content is now live. */
.jbh-compact-cards .jbh-service-card::after {
	content: '';
	display: block;
	height: 3px;
	background: linear-gradient(90deg, transparent, var(--jbh-custom-icon, var(--jbh-teal)), transparent);
	opacity: 0.3;
	transition: opacity 0.3s ease;
}
/* ::after fade — ALL mode: fade across every card on grid hover/focus */
.jbh-compact-cards:not(.jbh-hover-single) .jbh-service-grid:hover .jbh-service-card::after,
.jbh-compact-cards:not(.jbh-hover-single) .jbh-service-grid:focus-within .jbh-service-card::after,
.jbh-compact-cards.jbh-force-expanded .jbh-service-card::after {
	opacity: 0;
}
/* ::after fade — SINGLE mode: fade only on the hovered/focused card */
.jbh-compact-cards.jbh-hover-single .jbh-service-card:hover::after,
.jbh-compact-cards.jbh-hover-single .jbh-service-card:focus-within::after {
	opacity: 0;
}
/* Honour prefers-reduced-motion — collapse/expand without the
   max-height easing curve so users on that setting don't see a
   multi-second height crawl. */
@media (prefers-reduced-motion: reduce) {
	.jbh-compact-cards .jbh-card-body {
		transition: none;
	}
}

/* ── Expand / Collapse All button ────────────────────────────────
   Customisable position (top | bottom) + style (primary | outline |
   ghost | subtle). The button toggles .jbh-force-expanded on the
   wrapper; CSS rules above handle the visual state, JS just swaps
   the class and updates aria-expanded for screen-readers. */
.jbh-expand-all-wrap {
	display: flex;
	justify-content: center;
	width: 100%;
}
.jbh-expand-all-wrap-top    { margin: 0 0 20px; }
.jbh-expand-all-wrap-bottom { margin: 24px 0 0; }

.jbh-expand-all-btn {
	display: inline-flex;
	align-items: center;
	gap: 10px;
	padding: 10px 22px;
	font-family: var(--jbh-font-sans);
	font-size: 13px;
	font-weight: 600;
	letter-spacing: 0.04em;
	text-transform: uppercase;
	border-radius: 999px;
	cursor: pointer;
	transition: background 0.25s ease, color 0.25s ease,
	            border-color 0.25s ease, box-shadow 0.25s ease,
	            transform 0.15s ease;
	border: 1.5px solid var(--jbh-custom-icon, var(--jbh-teal));
	background: transparent;
	color: var(--jbh-custom-icon, var(--jbh-teal));
}
.jbh-expand-all-btn:hover,
.jbh-expand-all-btn:focus-visible {
	background: var(--jbh-custom-icon, var(--jbh-teal));
	color: #fff;
	outline: none;
	box-shadow: 0 6px 18px color-mix(in srgb, var(--jbh-custom-icon, var(--jbh-teal)) 32%, transparent);
}
.jbh-expand-all-btn:active { transform: translateY(1px); }

/* Style variants — primary (filled), ghost (text only), subtle (low-emphasis) */
.jbh-expand-all-btn.is-primary {
	background: var(--jbh-custom-icon, var(--jbh-teal));
	color: #fff;
}
.jbh-expand-all-btn.is-primary:hover,
.jbh-expand-all-btn.is-primary:focus-visible {
	filter: brightness(1.1);
	box-shadow: 0 8px 24px color-mix(in srgb, var(--jbh-custom-icon, var(--jbh-teal)) 40%, transparent);
}
.jbh-expand-all-btn.is-ghost {
	border-color: transparent;
	padding-left: 12px;
	padding-right: 12px;
}
.jbh-expand-all-btn.is-ghost:hover,
.jbh-expand-all-btn.is-ghost:focus-visible {
	background: color-mix(in srgb, var(--jbh-custom-icon, var(--jbh-teal)) 10%, transparent);
	color: var(--jbh-custom-icon, var(--jbh-teal));
	box-shadow: none;
}
.jbh-expand-all-btn.is-subtle {
	border-color: var(--jbh-border);
	color: var(--jbh-card-desc);
	background: color-mix(in srgb, var(--jbh-custom-icon, var(--jbh-teal)) 4%, transparent);
}
.jbh-expand-all-btn.is-subtle:hover,
.jbh-expand-all-btn.is-subtle:focus-visible {
	border-color: var(--jbh-custom-icon, var(--jbh-teal));
	color: var(--jbh-custom-icon, var(--jbh-teal));
	background: color-mix(in srgb, var(--jbh-custom-icon, var(--jbh-teal)) 10%, transparent);
	box-shadow: none;
}

.jbh-expand-all-icon {
	width: 16px;
	height: 16px;
	transition: transform 0.3s ease;
}
.jbh-expand-all-btn[aria-expanded="true"] .jbh-expand-all-icon {
	transform: rotate(180deg);
}
/* Label toggle — show "Expand" label when collapsed, "Collapse" when expanded */
.jbh-expand-all-btn .jbh-expand-label-collapse { display: none; }
.jbh-expand-all-btn[aria-expanded="true"] .jbh-expand-label-expand   { display: none; }
.jbh-expand-all-btn[aria-expanded="true"] .jbh-expand-label-collapse { display: inline; }

/* ================================================================
   CAROUSEL MODE — horizontal scroll with snap
   ================================================================ */
.jbh-carousel-mode {
	position: relative;
}
.jbh-carousel-mode .jbh-service-grid {
	display: flex !important;
	overflow-x: auto;
	overflow-y: hidden;
	scroll-snap-type: x mandatory;
	scroll-behavior: smooth;
	-webkit-overflow-scrolling: touch;
	scrollbar-width: thin;
	scrollbar-color: var(--jbh-custom-icon, var(--jbh-teal)) transparent;
	padding-bottom: 8px;
	gap: var(--jbh-gap);
}
.jbh-carousel-mode .jbh-service-grid::-webkit-scrollbar { height: 6px; }
.jbh-carousel-mode .jbh-service-grid::-webkit-scrollbar-track { background: transparent; }
.jbh-carousel-mode .jbh-service-grid::-webkit-scrollbar-thumb { background: var(--jbh-custom-icon, var(--jbh-teal)); border-radius: 3px; }
.jbh-carousel-mode .jbh-service-card {
	flex: 0 0 auto;
	width: calc((100% - var(--jbh-gap) * (var(--jbh-cols, 3) - 1)) / var(--jbh-cols, 3));
	min-width: 280px;
	scroll-snap-align: start;
}
/* Carousel arrows */
.jbh-carousel-arrow {
	position: absolute;
	top: 50%;
	transform: translateY(-50%);
	z-index: 20;
	width: 44px;
	height: 44px;
	border-radius: 50%;
	border: 1px solid var(--jbh-border);
	background: var(--jbh-custom-card-bg, var(--jbh-card));
	color: var(--jbh-card-heading);
	cursor: pointer;
	display: flex;
	align-items: center;
	justify-content: center;
	box-shadow: 0 4px 12px rgba(0,0,0,0.15);
	transition: all var(--jbh-transition);
	opacity: 0.85;
}
.jbh-carousel-arrow:hover {
	opacity: 1;
	background: var(--jbh-custom-icon, var(--jbh-teal));
	color: #fff;
	border-color: var(--jbh-custom-icon, var(--jbh-teal));
}
.jbh-carousel-arrow svg { width: 20px; height: 20px; }
.jbh-carousel-prev { left: -16px; }
.jbh-carousel-next { right: -16px; }
@media (max-width: 768px) {
	.jbh-carousel-mode .jbh-service-card { min-width: 85vw; }
	.jbh-carousel-prev { left: 4px; }
	.jbh-carousel-next { right: 4px; }
	.jbh-carousel-arrow { width: 36px; height: 36px; }
}

/* ================================================================
   ROW LIMIT — cap visible rows with gradient fade + show-more
   ================================================================ */
.jbh-row-limit {
	position: relative;
}
.jbh-row-limit .jbh-service-grid {
	overflow: hidden;
	/* Each row height ≈ 1fr auto. We approximate with a generous
	   max-height per row. The transition animates the expansion. */
	max-height: calc(var(--jbh-max-rows, 2) * 520px);
	transition: max-height 0.5s cubic-bezier(0.4,0,0.2,1);
}
.jbh-row-limit.jbh-rows-expanded .jbh-service-grid {
	max-height: 9999px;
}
/* Gradient fade overlay */
.jbh-row-limit-fade {
	position: absolute;
	bottom: 52px;
	left: 0;
	right: 0;
	height: 120px;
	background: linear-gradient(to bottom, transparent, var(--jbh-custom-block-bg, var(--jbh-bg)));
	pointer-events: none;
	transition: opacity 0.4s ease;
	z-index: 5;
}
.jbh-row-limit.jbh-rows-expanded .jbh-row-limit-fade {
	opacity: 0;
}
/* Show More / Show Less button */
.jbh-show-more-btn {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 8px;
	margin: 24px auto 0;
	padding: 12px 32px;
	border: 1px solid var(--jbh-border);
	border-radius: 999px;
	background: var(--jbh-custom-card-bg, var(--jbh-card));
	color: var(--jbh-custom-icon, var(--jbh-teal));
	font-family: var(--jbh-font-mono);
	font-size: 12px;
	font-weight: 600;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	cursor: pointer;
	transition: all var(--jbh-transition);
	position: relative;
	z-index: 10;
}
.jbh-show-more-btn:hover {
	background: var(--jbh-custom-icon, var(--jbh-teal));
	color: #fff;
	border-color: var(--jbh-custom-icon, var(--jbh-teal));
}
.jbh-show-more-icon {
	width: 16px;
	height: 16px;
	transition: transform 0.3s ease;
}
.jbh-rows-expanded .jbh-show-more-icon {
	transform: rotate(180deg);
}
/* Toggle text visibility */
.jbh-show-more-btn .jbh-show-less-text { display: none; }
.jbh-rows-expanded .jbh-show-more-btn .jbh-show-more-text { display: none; }
.jbh-rows-expanded .jbh-show-more-btn .jbh-show-less-text { display: inline; }

/* ── Tooltip palette resolvers ─────────────────────────────────
   Inline `--jbh-tooltip-*-dk` / `-lt` custom properties from
   render.php get aliased into the canonical `--jbh-tooltip-*`
   slots that the global `[data-jbh-tooltip]` rendering rules
   consume. Defaults sit on the same fallback line as the
   var() consumers so tooltips render correctly even on blocks
   where the user never opens the Inspector. */
.jbh-studio-grid.jbh-dark,
.jbh-studio-grid.jbh-auto {
	--jbh-tooltip-bg:     var(--jbh-tooltip-bg-dk,     #1F2937);
	--jbh-tooltip-text:   var(--jbh-tooltip-text-dk,   #FFFFFF);
	--jbh-tooltip-border: var(--jbh-tooltip-border-dk, transparent);
}
.jbh-studio-grid.jbh-light {
	--jbh-tooltip-bg:     var(--jbh-tooltip-bg-lt,     #FFFFFF);
	--jbh-tooltip-text:   var(--jbh-tooltip-text-lt,   #1F2937);
	--jbh-tooltip-border: var(--jbh-tooltip-border-lt, rgba(0,0,0,0.10));
}
/* Same-frame site-mode reactivity \u2014 mirrors the pattern at
   line 753 / 850 so site-toggle flips swap tooltip palette
   instantly without waiting for the MutationObserver tick. */
:is(html[data-theme="light"], html.light, html[data-color-mode="light"], body[data-ct-color-mode="light"]) .jbh-studio-grid:not(.jbh-override-theme) {
	--jbh-tooltip-bg:     var(--jbh-tooltip-bg-lt,     #FFFFFF);
	--jbh-tooltip-text:   var(--jbh-tooltip-text-lt,   #1F2937);
	--jbh-tooltip-border: var(--jbh-tooltip-border-lt, rgba(0,0,0,0.10));
}
:is(html[data-theme="dark"], html.dark, html[data-color-mode="dark"], body[data-ct-color-mode="dark"]) .jbh-studio-grid:not(.jbh-override-theme) {
	--jbh-tooltip-bg:     var(--jbh-tooltip-bg-dk,     #1F2937);
	--jbh-tooltip-text:   var(--jbh-tooltip-text-dk,   #FFFFFF);
	--jbh-tooltip-border: var(--jbh-tooltip-border-dk, transparent);
}

/* ── Tooltip rendering — JBH-scoped, no JS ─────────────────────
   Pure CSS pseudo-element approach scoped to the two surfaces
   that actually emit `data-jbh-tooltip`: studio-grid block
   wrappers (cards) and the modal overlay (sections). Scoping
   avoids cross-plugin/theme bleed onto unrelated elements that
   happen to carry the attribute. The `position: relative` is
   only declared on tooltipped elements that aren't already
   positioned — established positioning contexts (e.g.
   .jbh-card-rec-badge with position:absolute) keep their
   existing context, so the tooltip pseudo-element anchors
   to the badge itself rather than sliding to the nearest
   positioned ancestor.

   Hover OR focus-visible triggers — keyboard users get the
   same help-text by tabbing to the element. Card surfaces
   inside .jbh-studio-grid that have `overflow: hidden`
   (.jbh-service-card, .jbh-card-header) get a paired override
   below to release the clip when tooltips are configured. */
.jbh-studio-grid [data-jbh-tooltip],
#jbh-modal-overlay [data-jbh-tooltip] {
	position: relative;
}
/* Tooltip body — uses ::after, with explicit resets for
   `top/height/width/border-radius` because two existing button
   styles (`.jbh-get-started-btn::after` and `.jbh-submit-btn::after`,
   defined later in source) use the same pseudo-element for the
   click-ripple animation. Without these resets the ripple's
   `top: 50%; height: 0; border-radius: 50%` would leak into the
   tooltip's box and produce a zero-height tooltip pinned to the
   button's centre. Specificity 0,3,1 (two classes + attribute +
   pseudo) beats the ripple's 0,1,1 in idle state and ties with
   the ripple's `:active` state, where the later source position
   of the ripple wins on the click — which is the intended UX
   (tooltip during hover, ripple during click). */
.jbh-studio-grid [data-jbh-tooltip]:hover::after,
.jbh-studio-grid [data-jbh-tooltip]:focus-visible::after,
#jbh-modal-overlay [data-jbh-tooltip]:hover::after,
#jbh-modal-overlay [data-jbh-tooltip]:focus-visible::after {
	content: attr(data-jbh-tooltip);
	position: absolute;
	/* Resets neutralise the ripple ::after's `top: 50%; height: 0;
	   width: 0; border-radius: 50%` legacy when the tooltipped
	   element is also a CSS-ripple button. */
	top: auto;
	height: auto;
	z-index: 99999;
	bottom: calc(100% + 10px);
	left: 50%;
	transform: translateX(-50%);
	background: var(--jbh-tooltip-bg, #1F2937);
	color: var(--jbh-tooltip-text, #FFFFFF);
	padding: 8px 12px;
	border-radius: var(--jbh-tooltip-radius, 6px);
	font-family: var(--jbh-font-sans, system-ui, sans-serif);
	font-size: var(--jbh-tooltip-font-size, 12px);
	font-weight: 500;
	line-height: 1.4;
	max-width: var(--jbh-tooltip-max-width, 280px);
	width: max-content;
	white-space: normal;
	text-align: center;
	/* Combined drop-shadow + outline so the optional border has
	   zero layout impact. Transparent default renders no outline,
	   user-customised colour renders as a sharp 1px ring. */
	box-shadow:
		0 8px 24px rgba(0, 0, 0, 0.18),
		0 0 0 1px var(--jbh-tooltip-border, transparent);
	pointer-events: none;
	animation: jbh-tooltip-fade 0.18s ease-out backwards;
}
/* Arrow — drawn as a CSS triangle so its color follows the bg
   variable automatically without extra markup or SVG. Uses
   ::before since none of our tooltip targets currently use
   ::before for anything else (verified by repo-wide audit). */
.jbh-studio-grid [data-jbh-tooltip]:hover::before,
.jbh-studio-grid [data-jbh-tooltip]:focus-visible::before,
#jbh-modal-overlay [data-jbh-tooltip]:hover::before,
#jbh-modal-overlay [data-jbh-tooltip]:focus-visible::before {
	content: '';
	position: absolute;
	top: auto;
	z-index: 99999;
	bottom: calc(100% + 4px);
	left: 50%;
	transform: translateX(-50%);
	width: 0;
	height: 0;
	border: 6px solid transparent;
	border-top-color: var(--jbh-tooltip-bg, #1F2937);
	background: transparent;
	pointer-events: none;
	animation: jbh-tooltip-fade 0.18s ease-out backwards;
}
@keyframes jbh-tooltip-fade {
	from { opacity: 0; transform: translateX(-50%) translateY(4px); }
	to   { opacity: 1; transform: translateX(-50%) translateY(0); }
}

/* Release the parent overflow:hidden clips on card and header so
   tooltip pseudo-elements can extend beyond the card box. Scoped
   to wrappers that actually have tooltips configured (render.php
   only emits `data-tooltip-position` when the tooltip map is
   non-empty), so blocks without tooltips keep their existing
   overflow behaviour and watermark clipping unchanged.

   The ripple-button selectors are scoped via `[data-jbh-tooltip]`
   directly so only buttons the user has actually configured a
   tooltip for lose their overflow clip. Side-effect on those
   buttons: the click-ripple animation circle briefly extends past
   the button border (acceptable since the ripple ends transparent
   inside half a second). All other buttons keep their ripple
   clipping intact. */
.jbh-studio-grid[data-tooltip-position] .jbh-service-card,
.jbh-studio-grid[data-tooltip-position] .jbh-card-header,
.jbh-studio-grid .jbh-get-started-btn[data-jbh-tooltip],
#jbh-modal-overlay #jbh-submit-btn[data-jbh-tooltip] {
	overflow: visible;
}

/* Position variants — driven by `data-tooltip-position` attribute
   on the studio-grid wrapper or modal overlay. Each variant
   repositions the tooltip body and rotates the arrow. */
.jbh-studio-grid[data-tooltip-position="bottom"] [data-jbh-tooltip]:hover::after,
.jbh-studio-grid[data-tooltip-position="bottom"] [data-jbh-tooltip]:focus-visible::after,
#jbh-modal-overlay[data-tooltip-position="bottom"] [data-jbh-tooltip]:hover::after,
#jbh-modal-overlay[data-tooltip-position="bottom"] [data-jbh-tooltip]:focus-visible::after {
	bottom: auto;
	top: calc(100% + 10px);
}
.jbh-studio-grid[data-tooltip-position="bottom"] [data-jbh-tooltip]:hover::before,
.jbh-studio-grid[data-tooltip-position="bottom"] [data-jbh-tooltip]:focus-visible::before,
#jbh-modal-overlay[data-tooltip-position="bottom"] [data-jbh-tooltip]:hover::before,
#jbh-modal-overlay[data-tooltip-position="bottom"] [data-jbh-tooltip]:focus-visible::before {
	bottom: auto;
	top: calc(100% + 4px);
	border-top-color: transparent;
	border-bottom-color: var(--jbh-tooltip-bg, #1F2937);
}
.jbh-studio-grid[data-tooltip-position="left"] [data-jbh-tooltip]:hover::after,
.jbh-studio-grid[data-tooltip-position="left"] [data-jbh-tooltip]:focus-visible::after,
#jbh-modal-overlay[data-tooltip-position="left"] [data-jbh-tooltip]:hover::after,
#jbh-modal-overlay[data-tooltip-position="left"] [data-jbh-tooltip]:focus-visible::after {
	bottom: 50%;
	left: auto;
	right: calc(100% + 10px);
	transform: translateY(50%);
}
.jbh-studio-grid[data-tooltip-position="left"] [data-jbh-tooltip]:hover::before,
.jbh-studio-grid[data-tooltip-position="left"] [data-jbh-tooltip]:focus-visible::before,
#jbh-modal-overlay[data-tooltip-position="left"] [data-jbh-tooltip]:hover::before,
#jbh-modal-overlay[data-tooltip-position="left"] [data-jbh-tooltip]:focus-visible::before {
	bottom: 50%;
	left: auto;
	right: calc(100% + 4px);
	transform: translateY(50%);
	border-top-color: transparent;
	border-left-color: var(--jbh-tooltip-bg, #1F2937);
}
.jbh-studio-grid[data-tooltip-position="right"] [data-jbh-tooltip]:hover::after,
.jbh-studio-grid[data-tooltip-position="right"] [data-jbh-tooltip]:focus-visible::after,
#jbh-modal-overlay[data-tooltip-position="right"] [data-jbh-tooltip]:hover::after,
#jbh-modal-overlay[data-tooltip-position="right"] [data-jbh-tooltip]:focus-visible::after {
	bottom: 50%;
	left: calc(100% + 10px);
	right: auto;
	transform: translateY(50%);
}
.jbh-studio-grid[data-tooltip-position="right"] [data-jbh-tooltip]:hover::before,
.jbh-studio-grid[data-tooltip-position="right"] [data-jbh-tooltip]:focus-visible::before,
#jbh-modal-overlay[data-tooltip-position="right"] [data-jbh-tooltip]:hover::before,
#jbh-modal-overlay[data-tooltip-position="right"] [data-jbh-tooltip]:focus-visible::before {
	bottom: 50%;
	left: calc(100% + 4px);
	right: auto;
	transform: translateY(50%);
	border-top-color: transparent;
	border-right-color: var(--jbh-tooltip-bg, #1F2937);
}

/* Reduced-motion preference — disable fade animation per OS
   accessibility setting. */
@media (prefers-reduced-motion: reduce) {
	.jbh-studio-grid [data-jbh-tooltip]:hover::after,
	.jbh-studio-grid [data-jbh-tooltip]:hover::before,
	.jbh-studio-grid [data-jbh-tooltip]:focus-visible::after,
	.jbh-studio-grid [data-jbh-tooltip]:focus-visible::before,
	#jbh-modal-overlay [data-jbh-tooltip]:hover::after,
	#jbh-modal-overlay [data-jbh-tooltip]:hover::before,
	#jbh-modal-overlay [data-jbh-tooltip]:focus-visible::after,
	#jbh-modal-overlay [data-jbh-tooltip]:focus-visible::before {
		animation: none;
	}
}

/* Editor-only cancellation — Gutenberg renders studio-grid via
   ServerSideRender inside `.editor-styles-wrapper` (post editor)
   or `.block-editor-block-list__layout` (FSE). The frontend
   breakout trick (`width: 100vw; margin: calc(50% - 50vw)`)
   resolves `100vw` against the editor iframe's viewport, which
   is wider than the visible block-list column — without this
   guard the block would visually escape into the editor sidebar
   and inspector chrome at edit time. */
.editor-styles-wrapper .jbh-studio-grid.jbh-overflow-container,
.block-editor-block-list__layout .jbh-studio-grid.jbh-overflow-container {
	width: 100%;
	max-width: 100%;
	margin-left: auto;
	margin-right: auto;
}
.editor-styles-wrapper .jbh-studio-grid.jbh-overflow-container .jbh-service-grid,
.block-editor-block-list__layout .jbh-studio-grid.jbh-overflow-container .jbh-service-grid {
	max-width: 100%;
}

/* ================================================================
   2.  STORE GRID
   ================================================================ */
.jbh-store-grid { background: var(--jbh-custom-block-bg, var(--jbh-bg)); padding: 60px 24px; font-family: var(--jbh-font-sans); }
.jbh-store-heading { margin-bottom: 40px; }
.jbh-store-tag { font-size: 14px; font-weight: 700; letter-spacing: 2px; text-transform: uppercase; color: var(--jbh-teal); margin: 0 0 8px; }
.jbh-store-title { font-family: var(--jbh-font-serif); font-size: clamp(2rem, 4vw, 3rem); font-weight: 700; color: var(--jbh-heading-color); margin: 0 0 8px; }
.jbh-store-subtitle { color: var(--jbh-text-color); font-size: 16px; line-height: 1.6; margin: 0; }
.jbh-product-grid { display: grid; gap: var(--jbh-gap); grid-template-columns: repeat(var(--jbh-cols, 2), 1fr); align-items: stretch; grid-auto-rows: 1fr; }
.jbh-product-card { background: var(--jbh-custom-card-bg, var(--jbh-card)); border-radius: var(--jbh-card-radius); padding: 40px; display: flex; flex-direction: column; transition: transform var(--jbh-transition), box-shadow var(--jbh-transition), border-color var(--jbh-transition); min-height: 0; }
/* `[hidden]` guard. When frontend.js's store-grid toolbar filters out a
   card via `card.hidden = true`, the browser's UA rule
   `[hidden] { display: none }` is *silently overridden* by author
   rules like `.jbh-product-card { display: flex }` — author wins over
   UA at equal specificity, so cards stayed visible even when matched
   as "hidden" in JS. This was the actual root cause of the reported
   "search doesn't filter products" bug.
   Scoped to every hideable card type so search + category filter work
   identically across all four grid blocks. `!important` guarantees the
   guard also beats preset rules (`.jbh-cards-glass`, `.jbh-img-left`,
   `.jbh-layout-list` etc.) that explicitly set `display: flex` on the
   card themselves. */
.jbh-service-card[hidden],
.jbh-product-card[hidden],
.jbh-plan-card[hidden],
.jbh-project-card[hidden],
.jbh-project-stacked[hidden],
.jbh-project-grid[hidden],
.jbh-project-split[hidden],
.jbh-insight-card[hidden] { display: none !important; }
.jbh-product-type { font-size: 10px; font-weight: 700; letter-spacing: 0.15em; text-transform: uppercase; color: var(--jbh-text-color); margin: 0 0 8px; opacity: 0.7; font-family: var(--jbh-font-mono); }
.jbh-product-title { font-family: var(--jbh-font-serif); font-size: 18px; font-weight: 700; color: var(--jbh-custom-header, var(--jbh-card-heading)); margin: 0 0 8px; transition: color var(--jbh-transition); overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 2; line-clamp: 2; -webkit-box-orient: vertical; }
.jbh-product-desc { color: var(--jbh-custom-desc, var(--jbh-text-color)); font-size: 14px; line-height: 1.5; margin: 0 0 16px; flex-grow: 1; font-weight: 300; overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: var(--jbh-desc-lines, 2); line-clamp: var(--jbh-desc-lines, 2); -webkit-box-orient: vertical; word-break: break-word; }
.jbh-product-price { font-size: 16px; font-weight: 700; color: var(--jbh-custom-price, var(--jbh-teal)); margin: 0; font-family: var(--jbh-font-mono); white-space: nowrap; }
.jbh-product-price del, .jbh-product-price ins { display: inline; text-decoration: inherit; background: none; color: inherit; }
.jbh-product-price del { opacity: 0.55; margin-right: 6px; }
.jbh-product-badge { display: inline-block; font-size: 10px; font-weight: 700; letter-spacing: 1px; text-transform: uppercase; background: var(--jbh-custom-badge-bg, var(--jbh-coral-light)); color: var(--jbh-custom-badge-text, var(--jbh-coral)); padding: 4px 10px; border-radius: var(--jbh-card-radius); margin-bottom: 12px; flex-shrink: 0; }
.jbh-product-btn { display: inline-block; padding: 8px 16px; font-size: 12px; font-weight: 700; text-align: center; text-decoration: none; border-radius: 8px; transition: all var(--jbh-transition); cursor: pointer; font-family: var(--jbh-font-serif); white-space: nowrap; flex-shrink: 0; }
.jbh-product-stock { display: inline-flex; align-items: center; gap: 6px; font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.1em; font-family: var(--jbh-font-mono); padding: 3px 8px; border-radius: 4px; margin: 0 0 8px; flex-shrink: 0; width: fit-content; }
.jbh-product-stock::before { content: ''; width: 6px; height: 6px; border-radius: 50%; background: currentColor; flex-shrink: 0; }
.jbh-product-stock-in { color: var(--jbh-teal); background: rgba(42, 157, 143, 0.12); }
.jbh-product-stock-low { color: #D97706; background: rgba(217, 119, 6, 0.12); }
.jbh-product-stock-out { color: var(--jbh-slate); background: rgba(156, 163, 175, 0.15); }
/* Featured badge — overlaid on the icon panel so it reads as a ribbon
   without competing with the regular .jbh-product-badge inside the
   body. Uses the accent/teal palette but can be retinted via the
   Badge Colors panel since it inherits the same custom-badge tokens.
   (position: relative is set on .jbh-product-icon-panel itself below.) */
.jbh-product-featured-badge {
	position: absolute;
	top: 10px;
	left: 10px;
	z-index: 2;
	display: inline-block;
	padding: 4px 10px;
	font-size: 10px;
	font-weight: 700;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	font-family: var(--jbh-font-mono);
	color: var(--jbh-custom-badge-text, #fff);
	background: var(--jbh-custom-badge-bg, var(--jbh-teal));
	border-radius: 999px;
	box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
	pointer-events: none;
}
/* Featured highlight outline. Gated by render.php on the `highlightFeatured`
   Inspector toggle so it no longer lights up unexpectedly on any WC product
   that the editor marked as "Featured" for unrelated purposes. Colour flows
   through `--jbh-featured-outline` (new dedicated picker slot) → falls back
   to the badge background so sites that already picked a badge colour get
   automatic outline matching → finally falls back to brand teal. */
.jbh-product-card.is-featured { outline: 1px solid var(--jbh-featured-outline, var(--jbh-custom-badge-bg, var(--jbh-teal))); outline-offset: -1px; }
/* ── Horizontal product card ──────────────────────────────── */
/* Horizontal product card — route the outer border + the icon-panel
   divider through the custom-card-border picker token so users who pick
   the horizontal layout AND set a card-border colour see both surfaces
   retint. Previous hardcoded `rgba(42,157,143,0.10)` value ignored the
   Inspector pickers on this preset. */
.jbh-product-horizontal { flex-direction: row; padding: 0; overflow: hidden; box-shadow: 0 4px 24px rgba(0,0,0,0.06); border: 1px solid var(--jbh-custom-card-border, rgba(42,157,143,0.10)); }
.jbh-product-horizontal:hover { box-shadow: 0 8px 32px rgba(0,0,0,0.14); }
.jbh-product-horizontal:hover .jbh-product-title { color: var(--jbh-custom-icon, var(--jbh-teal)); }
.jbh-product-icon-panel { position: relative; width: 33.333%; display: flex; align-items: center; justify-content: center; background: var(--jbh-bg); border-right: 1px solid var(--jbh-custom-card-border, rgba(42,157,143,0.10)); flex-shrink: 0; padding: 24px; min-height: 180px; }
.jbh-product-panel-image { max-width: 80%; max-height: 120px; object-fit: contain; }
.jbh-product-panel-icon { color: rgba(42,157,143,0.50); }
.jbh-product-panel-icon svg { width: 48px; height: 48px; }
.jbh-product-horizontal:hover .jbh-product-panel-icon { color: var(--jbh-custom-icon, var(--jbh-teal)); transition: color 0.3s ease; }
.jbh-product-horizontal .jbh-product-body { width: 66.666%; padding: 24px; display: flex; flex-direction: column; justify-content: space-between; min-height: 0; min-width: 0; }
.jbh-product-body-top { flex: 1 1 auto; min-height: 0; min-width: 0; overflow: hidden; }
.jbh-product-footer-bar { display: flex; align-items: center; justify-content: space-between; padding-top: 12px; margin-top: auto; border-top: 1px solid var(--jbh-custom-card-border, rgba(42,157,143,0.10)); gap: 8px; flex-shrink: 0; }
@media (max-width: 640px) {
	.jbh-product-horizontal { flex-direction: column; }
	.jbh-product-icon-panel { width: 100%; min-height: 100px; border-right: none; border-bottom: 1px solid var(--jbh-custom-card-border, rgba(42,157,143,0.10)); }
	.jbh-product-horizontal .jbh-product-body { width: 100%; }
}
/* ── Vertical product card (stacked: icon/image top, body below) ── */
.jbh-product-vertical { flex-direction: column; padding: 0; overflow: hidden; box-shadow: 0 4px 24px rgba(0,0,0,0.06); border: 1px solid var(--jbh-custom-card-border, rgba(42,157,143,0.10)); transition: box-shadow var(--jbh-transition), transform var(--jbh-transition); }
.jbh-product-vertical:hover { box-shadow: 0 8px 32px rgba(0,0,0,0.14); }
.jbh-product-vertical:hover .jbh-product-title { color: var(--jbh-custom-icon, var(--jbh-teal)); }
.jbh-product-vertical .jbh-product-icon-panel { width: 100%; min-height: 140px; max-height: 180px; border-right: none; border-bottom: 1px solid var(--jbh-custom-card-border, rgba(42,157,143,0.10)); padding: 32px 24px; overflow: hidden; }
.jbh-product-vertical .jbh-product-panel-image { max-width: 100%; max-height: 160px; }
.jbh-product-vertical .jbh-product-panel-icon svg { width: 56px; height: 56px; }
.jbh-product-vertical .jbh-product-body { width: 100%; padding: 24px; display: flex; flex-direction: column; justify-content: space-between; flex: 1; min-height: 0; min-width: 0; }
/* ── Uniform card height — all cards in a row share the same height
   via the grid's implicit row stretch. Content that overflows is
   clamped so cards never grow unevenly.
   The .jbh-store-height-* modifier applies a hard min/max-height
   cap so every card matches the icon-panel dimensions regardless
   of how much text its product description contains. Bodies clip
   overflow; description line-clamp + title line-clamp + footer
   flex-shrink: 0 together guarantee the CTA is always visible. */
.jbh-product-horizontal .jbh-product-icon-panel { max-height: 220px; overflow: hidden; }
.jbh-product-vertical:hover .jbh-product-panel-icon { color: var(--jbh-custom-icon, var(--jbh-teal)); }

/* Card height presets — each clamps the card to a predictable range
   matching the icon-panel footprint so long descriptions never
   stretch the card unevenly. Descriptions truncate via line-clamp;
   the footer (price + CTA) is pinned via flex-shrink: 0 and
   `margin-top: auto` so it's always visible at the bottom edge. */
.jbh-store-height-compact .jbh-product-horizontal  { min-height: 180px; max-height: 200px; }
.jbh-store-height-compact .jbh-product-horizontal .jbh-product-icon-panel { min-height: 180px; max-height: 200px; }
.jbh-store-height-compact .jbh-product-vertical    { min-height: 340px; max-height: 380px; }
.jbh-store-height-compact .jbh-product-vertical .jbh-product-icon-panel   { min-height: 120px; max-height: 140px; }

.jbh-store-height-standard .jbh-product-horizontal { min-height: 220px; max-height: 240px; }
.jbh-store-height-standard .jbh-product-horizontal .jbh-product-icon-panel { min-height: 220px; max-height: 240px; }
.jbh-store-height-standard .jbh-product-vertical   { min-height: 400px; max-height: 440px; }
.jbh-store-height-standard .jbh-product-vertical .jbh-product-icon-panel  { min-height: 160px; max-height: 180px; }

.jbh-store-height-tall .jbh-product-horizontal     { min-height: 280px; max-height: 320px; }
.jbh-store-height-tall .jbh-product-horizontal .jbh-product-icon-panel     { min-height: 280px; max-height: 320px; }
.jbh-store-height-tall .jbh-product-vertical       { min-height: 480px; max-height: 540px; }
.jbh-store-height-tall .jbh-product-vertical .jbh-product-icon-panel      { min-height: 200px; max-height: 240px; }

/* `auto` preset skips the cap so site owners who genuinely want
   "grow-to-fit" behaviour can opt out of the clamp entirely — no
   selector needed; the base card CSS already behaves that way. */

.jbh-layout-list .jbh-product-grid { grid-template-columns: 1fr !important; }
.jbh-layout-list .jbh-product-card { flex-direction: row; gap: 32px; align-items: center; }

/* ── Product image support — image position / aspect-ratio / fit
   classes are emitted on the block root by store-grid render.php
   (`jbh-img-{position}`, `jbh-img-ratio-{ratio}`, `jbh-img-{fit}`).
   The actual <img> element renders inside `.jbh-product-icon-panel`
   with class `.jbh-product-panel-image` (see L2333-2334 below for
   the responsive sizing rules). ─────────────────────────────────── */
.jbh-product-body { display: flex; flex-direction: column; flex-grow: 1; }
.jbh-has-images .jbh-product-card { padding: 0; overflow: hidden; }
.jbh-has-images .jbh-product-body { padding: 24px; }

/* ── Image position: left (horizontal card) ────────────────── */
.jbh-img-left .jbh-product-card { flex-direction: row; }
/* ── Image position: right ──────────────────────────────────── */
.jbh-img-right .jbh-product-card { flex-direction: row-reverse; }
/* ── Image position: background (overlay) ───────────────────── */
.jbh-img-background .jbh-product-card { position: relative; min-height: 280px; }
.jbh-img-background .jbh-product-body { position: relative; z-index: 2; margin-top: auto; color: #fff; padding: 24px; }
.jbh-img-background .jbh-product-title { color: #fff; }
.jbh-img-background .jbh-product-type { color: rgba(255,255,255,0.7); }
.jbh-img-background .jbh-product-desc { color: rgba(255,255,255,0.8); }
.jbh-img-background .jbh-product-price { color: #fff; }

/* ── Card padding variants ──────────────────────────────────── */
.jbh-card-pad-none .jbh-product-body { padding: 0; }
.jbh-card-pad-small .jbh-product-body { padding: 16px; }
.jbh-card-pad-medium .jbh-product-body { padding: 24px; }
.jbh-card-pad-large .jbh-product-body { padding: 40px; }

/* ── Preset: Magazine (featured first item + sidebar) ───────── */
.jbh-preset-magazine .jbh-product-grid { grid-template-columns: 1.5fr 1fr; }
.jbh-preset-magazine .jbh-product-card:first-child { grid-row: span 2; }
/* ── Preset: Compact (tight grid, smaller cards) ────────────── */
.jbh-preset-compact .jbh-product-card { padding: 0; }
.jbh-preset-compact .jbh-product-body { padding: 16px; }
.jbh-preset-compact .jbh-product-title { font-size: 15px; }
.jbh-preset-compact .jbh-product-desc { font-size: 13px; -webkit-line-clamp: 2; line-clamp: 2; display: -webkit-box; -webkit-box-orient: vertical; overflow: hidden; }
.jbh-preset-compact .jbh-product-price { font-size: 16px; margin: 12px 0 8px; }
.jbh-preset-compact .jbh-product-btn { padding: 8px 16px; font-size: 13px; }
/* ── Preset: Showcase (large images, overlay text) ──────────── */
.jbh-preset-showcase .jbh-product-card { position: relative; min-height: 320px; overflow: hidden; padding: 0; }
.jbh-preset-showcase .jbh-product-body { position: relative; z-index: 2; margin-top: auto; padding: 28px; color: #fff; }
.jbh-preset-showcase .jbh-product-title { color: #fff; font-size: 22px; }
.jbh-preset-showcase .jbh-product-type { color: rgba(255,255,255,0.65); }
.jbh-preset-showcase .jbh-product-price { color: #fff; }
/* ── Preset: Minimal (no borders, clean) ────────────────────── */
.jbh-preset-minimal .jbh-product-card { background: transparent; border: none; box-shadow: none; border-radius: 0; padding: 0; }
.jbh-preset-minimal .jbh-product-body { padding: 16px 0; }
.jbh-preset-minimal .jbh-product-btn { padding: 0; background: transparent; border: none; color: var(--jbh-teal); text-decoration: underline; text-underline-offset: 3px; }

/* ── 3+ column compact sizing — tighter padding / font so 4 cards
   fit comfortably in a single row without overflow ──────────────── */
.jbh-store-grid[style*="--jbh-cols:3"] .jbh-product-vertical .jbh-product-body,
.jbh-store-grid[style*="--jbh-cols:4"] .jbh-product-vertical .jbh-product-body { padding: 16px; }
.jbh-store-grid[style*="--jbh-cols:3"] .jbh-product-title,
.jbh-store-grid[style*="--jbh-cols:4"] .jbh-product-title { font-size: 15px; }
.jbh-store-grid[style*="--jbh-cols:3"] .jbh-product-desc,
.jbh-store-grid[style*="--jbh-cols:4"] .jbh-product-desc { font-size: 13px; -webkit-line-clamp: 2; line-clamp: 2; margin-bottom: 16px; }
.jbh-store-grid[style*="--jbh-cols:4"] .jbh-product-vertical .jbh-product-icon-panel { min-height: 100px; max-height: 140px; padding: 16px; }
.jbh-store-grid[style*="--jbh-cols:4"] .jbh-product-panel-image { max-height: 100px; }
.jbh-store-grid[style*="--jbh-cols:4"] .jbh-product-type { font-size: 9px; margin-bottom: 4px; }
.jbh-store-grid[style*="--jbh-cols:4"] .jbh-product-price { font-size: 14px; }
.jbh-store-grid[style*="--jbh-cols:4"] .jbh-product-btn { padding: 6px 12px; font-size: 11px; }

@media (max-width: 1024px) {
	.jbh-store-grid[style*="--jbh-cols:4"] .jbh-product-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 768px) {
	.jbh-img-left .jbh-product-card, .jbh-img-right .jbh-product-card { flex-direction: column; }
	.jbh-preset-magazine .jbh-product-grid { grid-template-columns: 1fr; }
	.jbh-preset-magazine .jbh-product-card:first-child { grid-row: span 1; }
	.jbh-store-grid[style*="--jbh-cols:3"] .jbh-product-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 480px) {
	.jbh-product-grid { grid-template-columns: 1fr !important; }
}

/* ── Filter / Sort / Search toolbar ──────────────────────────────
   Sits above the product grid. All controls are client-side-only —
   JS in frontend.js hides/shows cards based on data-category /
   data-title / data-price attributes rendered by render.php.

   Design tokens (--jbh-filter-bg / --jbh-filter-text /
   --jbh-filter-active-bg / --jbh-filter-active-text /
   --jbh-filter-border) resolve through the usual dual-palette chain
   (`-dk` / `-lt`) so Inspector colour overrides work in both
   modes. All sensible fallbacks degrade to the block's existing
   card/text palette so the toolbar still looks on-brand even if the
   user never opens the filter-colour panel. */
.jbh-store-toolbar {
	display: flex;
	align-items: center;
	flex-wrap: wrap;
	gap: 16px;
	margin: 0 0 32px;
	padding: 16px 20px;
	background: var(--jbh-filter-bg, var(--jbh-card));
	border: 1px solid var(--jbh-filter-border, var(--jbh-border));
	border-radius: var(--jbh-card-radius);
	color: var(--jbh-filter-text, var(--jbh-text-color));
	font-family: var(--jbh-font-sans);
}
.jbh-store-toolbar-filters {
	display: flex;
	align-items: center;
	/* `nowrap` keeps the "Filter:" label locked beside the pills on the
	   same baseline as the search input and sort dropdown. Vertical
	   wrapping here is undesirable — the pills themselves scroll
	   horizontally when there are too many to fit (see
	   `.jbh-filter-pills` below), so the filter *group* never needs
	   to break onto a new row. */
	flex-wrap: nowrap;
	gap: 8px;
	/* `1 1 0` + `min-width: 0` is the canonical "shrink-to-available"
	   recipe for flex children that contain their own overflow:
	   - `flex-grow: 1`   — claim remaining toolbar width after the
	                        side-group has taken its intrinsic size
	   - `flex-shrink: 1` — give width back when the side-group
	                        grows (e.g. long sort option text)
	   - `flex-basis: 0`  — start from zero so the filter strip
	                        never forces a reflow wider than its
	                        container
	   - `min-width: 0`   — CRITICAL: without this the intrinsic
	                        min-content width of the pills container
	                        would leak upward and push the side-group
	                        to a new row anyway, defeating the whole
	                        single-row layout. */
	flex: 1 1 0;
	min-width: 0;
}
.jbh-store-toolbar-side {
	display: flex;
	align-items: center;
	flex-wrap: wrap;
	gap: 12px;
	margin-left: auto;
}
/* Sort label + select grouped as one atomic flex unit so they NEVER
   separate when the toolbar narrows. Previously they were loose
   siblings inside `.jbh-store-toolbar-side` (which has `flex-wrap:
   wrap`), which allowed the dropdown to drop below the "Sort:" label
   on cramped widths, leaving the label orphaned on its own row.
   `flex-shrink: 0` keeps the group from being squeezed under its
   intrinsic width, and `align-items: center` aligns the label's
   baseline with the select's center for visual harmony. */
.jbh-sort-group {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	flex-shrink: 0;
}
.jbh-filter-label,
.jbh-sort-label {
	font-size: 11px;
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.12em;
	font-family: var(--jbh-font-mono);
	color: var(--jbh-filter-text, var(--jbh-text-color));
	opacity: 0.7;
	margin-right: 4px;
	flex-shrink: 0;
}

/* ── Filter style: pills (default) ─────────────────────────── */
/* Horizontally-scrolling pill strip. `nowrap` is the core of the
   single-row toolbar layout — when a shop has 10+ categories the
   pills overflow their container horizontally instead of wrapping
   downward, which would otherwise push Search / Sort to a new row.
   `overflow-x: auto` + `-webkit-overflow-scrolling: touch` gives
   mobile users inertial scroll through the pills. The UA scrollbar
   is hidden because the pills themselves are large and obvious
   scroll targets — showing a thin track below them would add
   visual clutter in the toolbar's tight vertical budget. */
.jbh-filter-pills {
	display: flex;
	flex-wrap: nowrap;
	gap: 8px;
	overflow-x: auto;
	-webkit-overflow-scrolling: touch;
	scroll-snap-type: x proximity;
	scrollbar-width: none;
	min-width: 0;
}
.jbh-filter-pills::-webkit-scrollbar { display: none; }
.jbh-filter-pills > .jbh-filter-pill { scroll-snap-align: start; flex-shrink: 0; }
.jbh-filter-pill {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	padding: 7px 14px;
	font-size: 12px;
	font-weight: 600;
	font-family: var(--jbh-font-sans);
	line-height: 1;
	border-radius: 999px;
	background: transparent;
	color: var(--jbh-filter-text, var(--jbh-text-color));
	border: 1px solid var(--jbh-filter-border, var(--jbh-border));
	cursor: pointer;
	transition: background 0.2s ease, color 0.2s ease, border-color 0.2s ease;
	white-space: nowrap;
}
.jbh-filter-pill:hover {
	border-color: var(--jbh-filter-active-bg, var(--jbh-teal));
	color: var(--jbh-filter-active-bg, var(--jbh-teal));
}
.jbh-filter-pill.is-active {
	background: var(--jbh-filter-active-bg, var(--jbh-teal));
	color: var(--jbh-filter-active-text, #fff);
	border-color: var(--jbh-filter-active-bg, var(--jbh-teal));
}
.jbh-filter-pill:focus-visible {
	outline: 2px solid var(--jbh-filter-active-bg, var(--jbh-teal));
	outline-offset: 2px;
}

/* ── Sort dropdown ──────────────────────────────────────── */
.jbh-sort-select {
	appearance: none;
	-webkit-appearance: none;
	padding: 8px 32px 8px 12px;
	font-size: 13px;
	font-family: var(--jbh-font-sans);
	font-weight: 500;
	color: var(--jbh-filter-text, var(--jbh-text-color));
	background: transparent;
	border: 1px solid var(--jbh-filter-border, var(--jbh-border));
	border-radius: 8px;
	cursor: pointer;
	transition: border-color 0.2s ease;
	/* Caret icon — default for DARK surfaces.
	   IMPORTANT: `currentColor` does NOT propagate into CSS data URLs.
	   The SVG is parsed in isolation by the browser, so `stroke='currentColor'`
	   resolves to the SVG default (black) regardless of the element’s
	   `color` property — which is exactly the bug that made the dark-mode
	   caret render dark-on-dark, invisible. Both modes now use literal
	   strokes that match `--jbh-text-color` for the active mode (dark =
	   #9CA3AF, light override below = #4B5563). */
	background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6' fill='none' stroke='%239CA3AF' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M1 1l4 4 4-4'/></svg>");
	background-repeat: no-repeat;
	background-position: right 10px center;
}
/* Light-mode caret swap. Full site-signal coverage so the caret stays
   readable regardless of which colour-mode source is active. */
.jbh-light .jbh-sort-select,
html[data-theme="light"] .jbh-sort-select,
html.light .jbh-sort-select,
html[data-color-mode="light"] .jbh-sort-select,
body[data-ct-color-mode="light"] .jbh-sort-select {
	background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6' fill='none' stroke='%234B5563' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M1 1l4 4 4-4'/></svg>");
}
.jbh-sort-select:hover { border-color: var(--jbh-filter-active-bg, var(--jbh-teal)); }
.jbh-sort-select:focus {
	outline: none;
	border-color: var(--jbh-filter-active-bg, var(--jbh-teal));
	box-shadow: 0 0 0 3px rgba(42, 157, 143, 0.15);
}
.jbh-sort-select option {
	/* Native <option> elements are rendered by the OS; we can't style
	   the dropdown panel itself, but we can at least request a
	   mode-appropriate background so the panel doesn't flash stark
	   white in dark mode on Chromium/Firefox. */
	background: var(--jbh-filter-bg, var(--jbh-card));
	color: var(--jbh-filter-text, var(--jbh-text-color));
}

/* ── Search input ─────────────────────────────────────────── */
.jbh-store-search {
	position: relative;
	display: flex;
	align-items: center;
	/* `gap` spaces the EXTERNAL search icon from the input box. The icon
	   used to be absolute-positioned INSIDE the input (with the input
	   carrying 40px of left padding to make room); we now render it as
	   a flex-sibling OUTSIDE the input so the field reads as a clean,
	   unpadded text box and the magnifier becomes a labelling icon —
	   matches the native macOS Spotlight / Linear / Stripe Dashboard
	   pattern and is easier for screen-reader users to skip. */
	gap: 8px;
	/* Shrunk to ~75 % of previous footprint (was 280px / 220px). The
	   search input no longer dominates the toolbar on medium-width
	   screens and leaves more room for filter pills beside it. */
	min-width: 165px;
	flex: 0 1 210px;
}
.jbh-store-search-input {
	/* `appearance: none` removes the UA `searchfield` chrome (iOS adds a
	   forced text-indent that pushes the placeholder under our absolutely-
	   positioned search icon; Chromium adds rounded-corner inner padding).
	   `box-sizing: border-box` keeps padding inside the declared width so
	   the field can never overflow its flex container even when a host
	   theme bumps the default `font-size` and forces the input to lay
	   out at a wider intrinsic min-content. */
	-webkit-appearance: none;
	appearance: none;
	box-sizing: border-box;
	/* `flex: 1 1 0; min-width: 0` makes the input absorb whatever space
	   is left after the (flex-sized) external icon, with `min-width:0`
	   defeating the flex spec's default `min-width: auto` that would
	   otherwise refuse to shrink the input below its placeholder's
	   intrinsic width — causing the toolbar to overflow on narrow
	   viewports when a long placeholder is set. */
	flex: 1 1 0;
	min-width: 0;
	margin: 0;
	/* Left padding dropped from 40px → 12px now that the search icon
	   lives OUTSIDE the input. Right padding stays at 36px so typed text
	   never collides with the absolutely-positioned `.jbh-store-search-clear`
	   button (which is still anchored to `right: 6px` of the relative
	   `.jbh-store-search` container — see below). */
	padding: 8px 36px 8px 12px;
	font-size: 13px;
	line-height: 1.4;
	font-family: var(--jbh-font-sans);
	color: var(--jbh-filter-text, var(--jbh-text-color));
	/* `-webkit-text-fill-color` mirrors `color` so Safari / iOS — and Chromium
	   under Auto-Dark, plus host themes (Blocksy/Astra/Twenty-Twenty-*) that
	   blanket-set `-webkit-text-fill-color` on inputs at element scope —
	   can't override the typed-character colour to white-on-white. Without
	   this, Safari ignored our `color` token entirely on iOS < 16 and most
	   Auto-Dark setups repainted the input to system-foreground (white in
	   OS dark mode) regardless of palette. `caret-color` matches so the
	   blinking cursor stays visible on light cards too. */
	-webkit-text-fill-color: var(--jbh-filter-text, var(--jbh-text-color));
	caret-color: var(--jbh-filter-text, var(--jbh-text-color));
	background: transparent;
	border: 1px solid var(--jbh-filter-border, var(--jbh-border));
	border-radius: 8px;
	transition: border-color 0.2s ease, box-shadow 0.2s ease;
}
.jbh-store-search-input::placeholder {
	color: var(--jbh-filter-text, var(--jbh-text-color));
	-webkit-text-fill-color: var(--jbh-filter-text, var(--jbh-text-color));
	/* Bumped 0.5 → 0.7. At 0.5, a `#4B5563` placeholder over `#FFFFFF` card
	   computed to ≈3.5:1 contrast — below WCAG AA's 4.5:1 floor for body
	   text and only barely meeting the 3:1 floor for UI affordances. 0.7
	   gives ≈4.6:1 on white and ≈4.4:1 on the dark card, comfortably AA
	   in both modes while still feeling subordinate to user-typed text. */
	opacity: 0.7;
}
/* Suppress browser-native clear icons.
   `<input type="search">` renders a UA-drawn X button on Chromium/
   WebKit (`::-webkit-search-cancel-button`) and an equivalent on
   legacy Edge (`::-ms-clear`). We render our own .jbh-store-search-clear
   so that both icons appeared simultaneously when the user typed
   into the field — a duplicated-X that read like a visual bug.
   Hiding the UA variants leaves only our branded clear button,
   which also matches the search-bar's aesthetic in both modes. */
.jbh-store-search-input::-webkit-search-cancel-button,
.jbh-store-search-input::-webkit-search-decoration {
	-webkit-appearance: none;
	appearance: none;
}
.jbh-store-search-input::-ms-clear,
.jbh-store-search-input::-ms-reveal {
	display: none;
	width: 0;
	height: 0;
}
/* Hover state — matches `.jbh-filter-pill:hover` and
   `.jbh-sort-select:hover` so the entire toolbar's interactive
   surfaces give the same teal-tinted hover affordance. Without this,
   the search input was the only toolbar control with no hover
   feedback at all (pills tinted teal, sort select tinted teal —
   but the search field stayed at 22 %% black border on hover).
   The teal border is then
   overridden on `:focus` below to add the matching focus ring, so
   the visual ladder reads idle → hover → focus consistently. */
.jbh-store-search-input:hover {
	border-color: var(--jbh-filter-active-bg, var(--jbh-teal));
}
.jbh-store-search-input:focus {
	outline: none;
	border-color: var(--jbh-filter-active-bg, var(--jbh-teal));
	box-shadow: 0 0 0 3px rgba(42, 157, 143, 0.15);
}
/* Belt-and-braces light-mode resolver — mirrors the same four-signal
   pattern used by `.jbh-input` in modal.css §"Light-mode placeholder
   override". Even if a host theme re-defines `--jbh-filter-text` /
   `--jbh-text-color` at a lower-specificity scope than ours, OR if
   the chain is poisoned by an IACVT (Invalid-At-Computed-Value-Time)
   condition somewhere up the cascade, this rule guarantees the
   typed-text + placeholder + caret + clear-button + result-count
   all paint a visible slate on white whenever the document is in
   light mode by ANY of the recognised signals: WP `data-theme`,
   classic `.light` body class, generic `data-color-mode` attr, or
   Blocksy's `data-ct-color-mode`. Specificity is 0,2,1 — beats every
   pure-class rule above without forcing `!important`. */
html[data-theme="light"] .jbh-store-search-input,
html.light .jbh-store-search-input,
html[data-color-mode="light"] .jbh-store-search-input,
body[data-ct-color-mode="light"] .jbh-store-search-input {
	color: #4B5563;
	-webkit-text-fill-color: #4B5563;
	caret-color: #4B5563;
	/* Light-mode "filled-input" baseline. The default border resolves to
	   `--jbh-filter-border-lt: rgba(0, 0, 0, 0.22)` which is fine for
	   filter pills + sort dropdown but renders the search input's edge
	   near-invisible on bright cards — particularly the BOTTOM line,
	   which the eye expects to "ground" the field visually. Painting
	   only the bottom border solid black gives the field the same
	   weight as Material 3 / Carbon / Polaris filled inputs without
	   darkening the rest of the box (which would feel too heavy and
	   would clash with the lighter borders used by the filter pills
	   sitting next to it). The other three sides stay at the subtle
	   `--jbh-filter-border-lt` so the field reads as a single visual
	   unit grounded by its baseline rather than a hard-edged rectangle. */
	border-bottom-color: #000000;
}
/* Override-theme block-class fallback: when the admin enables "Override
   Theme" in the Inspector, the block's own `.jbh-light` class wins
   regardless of any site-wide signal — so we can safely paint the
   filled-input baseline knowing the toolbar surface is guaranteed
   white. Without this, an explicit-light block on a no-signal /
   OS-dark host visitor would silently fall back to the 22 %% subtle
   border and the user would never see the requested filled-input look.
   We deliberately do NOT add a bare `.jbh-light` selector here because
   non-override blocks can be cross-pollinated dark by the site signal
   (see §"SITE is in DARK mode"), and a #000 bottom on a dark surface
   renders black-on-dark = invisible AND clashes with the teal-tinted
   dark border on the other three sides. */
.jbh-override-theme.jbh-light .jbh-store-search-input {
	border-bottom-color: #000000;
}
html[data-theme="light"] .jbh-store-search-input::placeholder,
html.light .jbh-store-search-input::placeholder,
html[data-color-mode="light"] .jbh-store-search-input::placeholder,
body[data-ct-color-mode="light"] .jbh-store-search-input::placeholder {
	color: #4B5563;
	-webkit-text-fill-color: #4B5563;
}
html[data-theme="light"] .jbh-store-search-clear,
html.light .jbh-store-search-clear,
html[data-color-mode="light"] .jbh-store-search-clear,
body[data-ct-color-mode="light"] .jbh-store-search-clear {
	color: #4B5563;
}
/* OS-light fallback for visitors on a host theme that ships no explicit
   colour-mode signal at all (no WP data-theme, no Blocksy toggle). Without
   this, OS-light visitors would still read the dark-mode `:root` defaults
   and get a near-invisible #9CA3AF placeholder on a white card. */
@media (prefers-color-scheme: light) {
	html:not([data-theme]):not(.dark):not(.light):not([data-color-mode]) .jbh-store-search-input {
		color: #4B5563;
		-webkit-text-fill-color: #4B5563;
		caret-color: #4B5563;
		/* OS-light parity for the filled-input baseline above. */
		border-bottom-color: #000000;
	}
	html:not([data-theme]):not(.dark):not(.light):not([data-color-mode]) .jbh-store-search-input::placeholder {
		color: #4B5563;
		-webkit-text-fill-color: #4B5563;
	}
	html:not([data-theme]):not(.dark):not(.light):not([data-color-mode]) .jbh-store-search-clear {
		color: #4B5563;
	}
}
/* Chrome / Edge autofill repaint defence. When the browser autofills a
   stored search query (or the OS does so on Mac Safari) it injects its
   own background colour AND repaints the typed text via internal
   `-webkit-text-fill-color`, defeating both `color` AND `background`
   rules. The 1000px inset shadow trick reasserts our background, the
   long transition prevents the brief yellow flash on page load, and the
   explicit `-webkit-text-fill-color` reasserts the typed-text colour. */
.jbh-store-search-input:-webkit-autofill,
.jbh-store-search-input:-webkit-autofill:hover,
.jbh-store-search-input:-webkit-autofill:focus,
.jbh-store-search-input:-webkit-autofill:active {
	-webkit-box-shadow: 0 0 0 1000px transparent inset;
	-webkit-text-fill-color: var(--jbh-filter-text, var(--jbh-text-color));
	transition: background-color 9999s ease-in-out 0s;
}
.jbh-store-search-icon {
	/* External search icon — sits OUTSIDE the input as a flex sibling.
	   `flex: 0 0 14px` locks the intrinsic 14px width so it can never
	   shrink under flex pressure (e.g. a very long placeholder pushing
	   the input to claim all the toolbar's free space). `display:block`
	   normalises browsers that render inline `<svg>` with an extra
	   half-leading bottom gap that misaligns it with the input's
	   x-height by ~1px. Bumped opacity 0.55 → 0.7 because the icon is
	   no longer floating over the input's transparent surface — it now
	   sits on the toolbar bg directly and needed a slight presence
	   bump to read as an affordance instead of a decorative ornament. */
	flex: 0 0 14px;
	display: block;
	width: 14px;
	height: 14px;
	color: var(--jbh-filter-text, var(--jbh-text-color));
	opacity: 0.7;
	pointer-events: none;
}
.jbh-store-search-clear {
	position: absolute;
	right: 6px;
	top: 50%;
	transform: translateY(-50%);
	width: 22px;
	height: 22px;
	display: none;
	align-items: center;
	justify-content: center;
	background: transparent;
	border: none;
	border-radius: 50%;
	cursor: pointer;
	color: var(--jbh-filter-text, var(--jbh-text-color));
	opacity: 0.6;
	transition: background 0.2s ease, opacity 0.2s ease;
}
.jbh-store-search-clear:hover { opacity: 1; background: rgba(127, 127, 127, 0.12); }
.jbh-store-search.is-filled .jbh-store-search-clear { display: inline-flex; }

/* ── Empty state (no products match) ───────────────────────── */
.jbh-store-empty {
	display: none;
	text-align: center;
	padding: 48px 24px;
	color: var(--jbh-text-color);
	font-family: var(--jbh-font-sans);
	font-size: 14px;
}
.jbh-store-empty strong { color: var(--jbh-heading-color); font-weight: 700; display: block; margin-bottom: 6px; font-size: 16px; }
.jbh-store-grid.is-filtered-empty .jbh-store-empty { display: block; }
.jbh-store-grid.is-filtered-empty .jbh-product-grid { display: none; }
/* Inserted by frontend.js the first time the grid enters the empty
   state. Rendered as a one-click reset that nulls search + filter +
   sort in a single action so users who over-narrow their search can
   recover without hunting for the individual clear controls. */
.jbh-store-empty-reset {
	display: inline-block;
	margin-top: 16px;
	padding: 8px 18px;
	font-size: 13px;
	font-weight: 600;
	font-family: var(--jbh-font-sans);
	color: var(--jbh-filter-active-text, #fff);
	background: var(--jbh-filter-active-bg, var(--jbh-teal));
	border: 1px solid var(--jbh-filter-active-bg, var(--jbh-teal));
	border-radius: 8px;
	cursor: pointer;
	transition: filter 0.2s ease, transform 0.2s ease;
}
.jbh-store-empty-reset:hover { filter: brightness(1.08); transform: translateY(-1px); }
.jbh-store-empty-reset:focus-visible { outline: 2px solid var(--jbh-filter-active-bg, var(--jbh-teal)); outline-offset: 2px; }

@media (max-width: 640px) {
	.jbh-store-toolbar { flex-direction: column; align-items: stretch; }
	.jbh-store-toolbar-side { margin-left: 0; }
	.jbh-store-search { flex: 1 1 100%; min-width: 0; }
	.jbh-filter-pills { overflow-x: auto; flex-wrap: nowrap; padding-bottom: 4px; -webkit-overflow-scrolling: touch; }
	/* On mobile the sort group spans the full row so the dropdown gets
	   useful tap-target width. Label keeps its intrinsic size, select
	   grows to fill the remainder — they stay side-by-side, never
	   stacked. */
	.jbh-sort-group { flex: 1 1 100%; }
	.jbh-sort-group .jbh-sort-select { flex: 1 1 auto; }
}

/* ================================================================
   3.  PRICING PLANS
   ================================================================ */
.jbh-pricing-plans { background: var(--jbh-custom-block-bg, var(--jbh-bg)); padding: 80px 24px; font-family: var(--jbh-font-sans); text-align: center; }
.jbh-plans-heading { margin-bottom: 48px; }
.jbh-plans-tag { font-size: 14px; font-weight: 700; letter-spacing: 2px; text-transform: uppercase; color: var(--jbh-teal); margin: 0 0 12px; }
.jbh-plans-title { font-family: var(--jbh-font-serif); font-size: clamp(2rem, 4vw, 3rem); font-weight: 700; color: var(--jbh-heading-color); margin: 0 0 12px; }
.jbh-plans-subtitle { color: var(--jbh-text-color); font-size: 16px; line-height: 1.6; margin: 0 auto; max-width: 600px; }
.jbh-pricing-toggle-wrap { display: flex; align-items: center; justify-content: center; gap: 12px; margin: 24px 0 40px; flex-wrap: wrap; }
.jbh-pricing-savings-pill { font-size: 10px; font-family: var(--jbh-font-mono); font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--jbh-teal); background: rgba(42,157,143,0.10); padding: 4px 10px; border-radius: 999px; margin-left: 4px; }
.jbh-pricing-savings-pill[hidden] { display: none !important; }
.jbh-pricing-toggle-label { font-size: 14px; font-weight: 600; color: var(--jbh-text-color); }
.jbh-pricing-toggle-label.is-active { color: var(--jbh-heading-color); }
/* Billing-period toggle surfaces. All three colour properties defer
   to user-set pickers when provided, with mode-aware fallbacks that
   match the previous hardcoded behaviour exactly. */
.jbh-pricing-toggle { position: relative; width: 48px; height: 26px; appearance: none; -webkit-appearance: none; background: var(--jbh-custom-toggle-track, var(--jbh-border)); border-radius: 26px; cursor: pointer; outline: none; border: none; transition: background var(--jbh-transition), box-shadow var(--jbh-transition); }
.jbh-pricing-toggle:checked { background: var(--jbh-custom-toggle-track-active, var(--jbh-teal)); }
/* WCAG 2.4.7 (Focus Visible): the UA focus ring was suppressed by
   `outline: none` above so that the track could draw its own rounded
   background. Add an explicit focus-visible ring in the brand teal so
   keyboard users can see which control has focus without the blue
   default halo clashing with the track's rounded shape. */
.jbh-pricing-toggle:focus-visible { box-shadow: 0 0 0 3px rgba(42, 157, 143, 0.35); }
.jbh-pricing-toggle::after { content: ""; position: absolute; top: 3px; left: 3px; width: 20px; height: 20px; border-radius: 50%; background: var(--jbh-custom-toggle-dot, #fff); transition: transform var(--jbh-transition), background var(--jbh-transition); }
.jbh-pricing-toggle:checked::after { transform: translateX(22px); }
.jbh-plans-grid { display: grid; grid-template-columns: repeat(var(--jbh-cols, 3), 1fr); gap: var(--jbh-gap); max-width: 1080px; margin: 0 auto; }
.jbh-plan-card { background: var(--jbh-custom-card-bg, var(--jbh-card)); border-radius: var(--jbh-card-radius); padding: 40px; text-align: left; display: flex; flex-direction: column; transition: transform var(--jbh-transition), box-shadow var(--jbh-transition), border-color var(--jbh-transition); }
.jbh-plan-card.jbh-highlighted { border-color: var(--jbh-coral) !important; border-width: 2px; border-style: solid; position: relative; overflow: visible !important; padding-top: 52px; }
.jbh-plan-badge { position: absolute; top: 0; left: 50%; transform: translate(-50%, -50%); white-space: nowrap; z-index: 3; padding: 6px 20px; border-radius: 999px; font-size: 10px; font-weight: 700; letter-spacing: 2px; text-transform: uppercase; color: var(--jbh-custom-badge-text, #fff); margin: 0; background: var(--jbh-custom-badge-bg, var(--jbh-coral)); }
.jbh-plan-name { font-family: var(--jbh-font-serif); font-size: 22px; font-weight: 600; color: var(--jbh-heading-color); margin: 0 0 4px; }
.jbh-plan-price { font-size: 40px; font-weight: 700; color: var(--jbh-card-heading); margin: 8px 0 0; line-height: 1.1; }
.jbh-plan-price span { font-size: 14px; color: var(--jbh-text-color); font-weight: 400; }
.jbh-plan-yearly-total { font-size: 13px; font-weight: 600; color: var(--jbh-text-color); opacity: 0.75; margin: 4px 0 0; font-variant-numeric: tabular-nums; font-feature-settings: "tnum"; }
.jbh-plan-yearly-total[hidden] { display: none !important; }
.jbh-plan-yearly-note { font-size: 12px; font-weight: 700; color: var(--jbh-teal); margin: 6px 0 0; }
.jbh-plan-perks { list-style: none; padding: 20px 0; margin: 16px 0; border-top: 1px solid var(--jbh-border); flex-grow: 1; }
.jbh-plan-perks li { color: var(--jbh-text-color); font-size: 14px; line-height: 2.2; padding-left: 20px; position: relative; }
.jbh-plan-perks li::before { content: "\2713"; position: absolute; left: 0; color: var(--jbh-teal); font-weight: 700; }
.jbh-plan-card.jbh-highlighted .jbh-plan-perks li::before { color: var(--jbh-coral); }
.jbh-plan-btn { display: block; width: 100%; text-align: center; padding: 14px; border-radius: var(--jbh-card-radius); font-weight: 700; font-size: 14px; cursor: pointer; text-decoration: none; transition: all var(--jbh-transition); font-family: var(--jbh-font-sans); margin-top: auto; }
.jbh-plan-btn-primary { background: var(--jbh-custom-btn, var(--jbh-coral)); color: var(--jbh-custom-btn-text, #ffffff); border: 2px solid var(--jbh-custom-btn, var(--jbh-coral)); }
/* Primary + outline hover states both now defer to --jbh-custom-btn-hover
   and --jbh-custom-btn-hover-text so the Inspector pickers actually take
   effect. Without this wiring the two hover colours were always the
   hardcoded coral / teal, regardless of picker input. */
.jbh-plan-btn-primary:hover { background: var(--jbh-custom-btn-hover, #E8665B); border-color: var(--jbh-custom-btn-hover, #E8665B); color: var(--jbh-custom-btn-hover-text, #ffffff); }
.jbh-plan-btn-outline { background: transparent; color: var(--jbh-custom-btn, var(--jbh-teal)); border: 2px solid var(--jbh-custom-btn, var(--jbh-teal)); }
.jbh-plan-btn-outline:hover { background: var(--jbh-custom-btn-hover, var(--jbh-teal)); color: var(--jbh-custom-btn-hover-text, #ffffff); border-color: var(--jbh-custom-btn-hover, var(--jbh-teal)); }

/* ================================================================
   4.  PORTFOLIO GRID
   ================================================================ */
.jbh-portfolio-grid { background: var(--jbh-custom-block-bg, var(--jbh-bg)); padding: 80px 24px; font-family: var(--jbh-font-sans); }
.jbh-portfolio-heading { margin-bottom: 48px; max-width: 700px; }
.jbh-portfolio-title { font-family: var(--jbh-font-serif); font-size: clamp(2rem, 4vw, 3rem); font-weight: 700; color: var(--jbh-heading-color); margin: 0 0 8px; }
.jbh-portfolio-subtitle { color: var(--jbh-pf-subtitle-color, var(--jbh-text-color)); font-size: 16px; line-height: 1.8; margin: 0; font-weight: 300; }
.jbh-project-list { display: flex; flex-direction: column; gap: 48px; }
/* ── Horizontal Split Card ── */
.jbh-project-split { display: flex; flex-direction: row; background: var(--jbh-custom-card-bg, var(--jbh-card)); border-radius: var(--jbh-card-radius); overflow: hidden; cursor: pointer; border: 1px solid rgba(42,157,143,0.05); box-shadow: 0 4px 24px rgba(0,0,0,0.06); transition: transform var(--jbh-transition), box-shadow var(--jbh-transition); }
.jbh-project-split:hover { box-shadow: 0 8px 32px rgba(0,0,0,0.14); transform: translateY(-2px); }
.jbh-project-icon-panel { width: 41.666%; min-height: 250px; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 12px; background: var(--jbh-bg); border-right: 1px solid rgba(42,157,143,0.10); padding: 32px; }
.jbh-project-icon-wrap { width: 48px; height: 48px; border: 1px solid rgba(42,157,143,0.30); border-radius: 50%; display: flex; align-items: center; justify-content: center; color: rgba(42,157,143,0.50); transition: color var(--jbh-transition), border-color var(--jbh-transition); }
.jbh-project-split:hover .jbh-project-icon-wrap { color: var(--jbh-custom-icon, var(--jbh-teal)); border-color: var(--jbh-custom-icon, var(--jbh-teal)); }
.jbh-project-layers-icon { width: 24px; height: 24px; }
.jbh-project-icon-label { font-size: 10px; font-family: var(--jbh-font-mono); text-transform: uppercase; letter-spacing: 0.15em; color: var(--jbh-pf-icon-label-color, var(--jbh-text-color)); }
.jbh-project-content-panel { width: 58.333%; padding: 40px; display: flex; flex-direction: column; justify-content: center; position: relative; }
.jbh-project-arrow-hover { position: absolute; top: 32px; right: 32px; width: 20px; height: 20px; color: rgba(42,157,143,0.30); transition: color var(--jbh-transition); }
.jbh-project-arrow-hover svg { width: 100%; height: 100%; }
.jbh-project-split:hover .jbh-project-arrow-hover { color: var(--jbh-custom-icon, var(--jbh-teal)); }
.jbh-project-meta { display: flex; align-items: center; gap: 12px; margin-bottom: 16px; }
.jbh-project-client { font-size: 10px; font-weight: 700; letter-spacing: 0.15em; text-transform: uppercase; color: var(--jbh-pf-meta-color, var(--jbh-teal)); background: rgba(42,157,143,0.10); padding: 4px 10px; border-radius: 6px; font-family: var(--jbh-font-mono); }
.jbh-project-sector { font-size: 10px; letter-spacing: 0.15em; text-transform: uppercase; color: var(--jbh-pf-meta-color, var(--jbh-text-color)); opacity: 0.7; font-family: var(--jbh-font-mono); }
.jbh-project-title { font-family: var(--jbh-font-serif); font-size: 22px; font-weight: 700; color: var(--jbh-card-heading); margin: 0 0 12px; line-height: 1.3; width: 92%; transition: color var(--jbh-transition); }
.jbh-project-split:hover .jbh-project-title { color: var(--jbh-custom-icon, var(--jbh-teal)); }
.jbh-project-desc { color: var(--jbh-text-color); font-size: 14px; line-height: 1.7; margin: 0 0 24px; font-weight: 300; width: 92%; }
.jbh-project-tags { display: flex; flex-wrap: wrap; gap: 8px; margin-top: auto; }
.jbh-project-cta { margin-top: var(--jbh-pf-cta-gap, 16px); margin-bottom: var(--jbh-pf-cta-mb, 0); padding-top: var(--jbh-pf-cta-pt, 0); padding-bottom: var(--jbh-pf-cta-pb, 0); padding-left: var(--jbh-pf-cta-pl, 0); padding-right: var(--jbh-pf-cta-pr, 0); }
a.jbh-project-cta { text-decoration: none; cursor: pointer; }
.jbh-project-tag { font-size: 10px; letter-spacing: 1px; color: var(--jbh-custom-tag, var(--jbh-text-color)); border: 1px solid rgba(42,157,143,0.10); border-radius: 999px; padding: 5px 14px; font-family: var(--jbh-font-mono); text-transform: uppercase; transition: border-color 0.2s ease; }
.jbh-project-tag:hover { border-color: rgba(42,157,143,0.30); }
@media (max-width: 768px) {
	.jbh-project-split { flex-direction: column; }
	.jbh-project-icon-panel { width: 100%; min-height: 120px; border-right: none; border-bottom: 1px solid rgba(42,157,143,0.10); }
	.jbh-project-content-panel { width: 100%; }
}
/* ── Stacked portfolio card (icon top, content below — single column) ── */
.jbh-project-stacked { display: flex; flex-direction: column; background: var(--jbh-custom-card-bg, var(--jbh-card)); border-radius: var(--jbh-card-radius); overflow: hidden; cursor: pointer; border: 1px solid rgba(42,157,143,0.05); box-shadow: 0 4px 24px rgba(0,0,0,0.06); transition: transform var(--jbh-transition), box-shadow var(--jbh-transition); }
.jbh-project-stacked:hover { box-shadow: 0 8px 32px rgba(0,0,0,0.14); transform: translateY(-2px); }
.jbh-project-stacked .jbh-project-icon-panel { width: 100%; min-height: 160px; border-right: none; border-bottom: 1px solid rgba(42,157,143,0.10); padding: 40px 24px; }
.jbh-project-stacked .jbh-project-content-panel { width: 100%; padding: 40px; }
.jbh-project-stacked:hover .jbh-project-icon-wrap { color: var(--jbh-custom-icon, var(--jbh-teal)); border-color: var(--jbh-custom-icon, var(--jbh-teal)); }
.jbh-project-stacked:hover .jbh-project-title { color: var(--jbh-custom-icon, var(--jbh-teal)); }
.jbh-project-stacked:hover .jbh-project-arrow-hover { color: var(--jbh-custom-icon, var(--jbh-teal)); }

/* ── Grid portfolio tiles (compact, multi-column) ──
   Honours the `Columns` Inspector slider via the shared `--jbh-cols`
   custom property (matches studio / store / pricing / insights grids).
   `minmax(0, 1fr)` clamps each track so long headlines wrap inside the
   tile instead of forcing the track wider than its share, which would
   push the right-most card past the viewport on a 3- or 4-column grid. */
.jbh-project-list-grid { display: grid; grid-template-columns: repeat(var(--jbh-cols, 3), minmax(0, 1fr)); gap: var(--jbh-gap); }
@media (max-width: 1024px) {
	.jbh-portfolio-grid[style*="--jbh-cols:4"] .jbh-project-list-grid,
	.jbh-portfolio-grid[style*="--jbh-cols:3"] .jbh-project-list-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 640px) {
	.jbh-project-list-grid { grid-template-columns: 1fr !important; }
}
.jbh-project-grid { display: flex; flex-direction: column; background: var(--jbh-custom-card-bg, var(--jbh-card)); border-radius: var(--jbh-card-radius); overflow: hidden; cursor: pointer; border: 1px solid rgba(42,157,143,0.05); box-shadow: 0 4px 24px rgba(0,0,0,0.06); transition: transform var(--jbh-transition), box-shadow var(--jbh-transition); }
.jbh-project-grid:hover { box-shadow: 0 8px 32px rgba(0,0,0,0.14); transform: translateY(-2px); }
.jbh-project-grid .jbh-project-icon-panel { width: 100%; min-height: 140px; border-right: none; border-bottom: 1px solid rgba(42,157,143,0.10); padding: 28px 18px; }
.jbh-project-grid .jbh-project-icon-wrap { width: 40px; height: 40px; }
.jbh-project-grid .jbh-project-layers-icon { width: 20px; height: 20px; }
.jbh-project-grid .jbh-project-content-panel { width: 100%; padding: 28px; }
.jbh-project-grid .jbh-project-title { font-size: 18px; width: 100%; }
.jbh-project-grid .jbh-project-desc { font-size: 13px; width: 100%; margin-bottom: 18px; }
.jbh-project-grid .jbh-project-arrow-hover { top: 20px; right: 20px; width: 16px; height: 16px; }
.jbh-project-grid:hover .jbh-project-icon-wrap { color: var(--jbh-custom-icon, var(--jbh-teal)); border-color: var(--jbh-custom-icon, var(--jbh-teal)); }
.jbh-project-grid:hover .jbh-project-title { color: var(--jbh-custom-icon, var(--jbh-teal)); }
.jbh-project-grid:hover .jbh-project-arrow-hover { color: var(--jbh-custom-icon, var(--jbh-teal)); }
/* ── Portfolio Detail Modal ── */
.jbh-portfolio-modal-overlay { position: fixed; inset: 0; z-index: 99999; display: flex; align-items: center; justify-content: center; padding: 16px; }
.jbh-portfolio-modal-overlay[hidden] { display: none; }
/* Defense-in-depth — mirrors the studio modal guard in modal.css.
   The previous Blocksy-compat bridge applied
   `.jbh-portfolio-modal-overlay:not(.alignwide):not(.alignfull) { max-width:1280px; margin:auto }`
   which collapsed the overlay into the theme's content column so the
   blurred backdrop only covered that strip. The root fix lives in
   `class-jbh-starter-blocksy-compat.php::emit_content_width_css()`
   which now excludes modal selectors; this rule is a belt-and-suspenders
   guard for third-party themes/plugins that attempt the same pattern.
   Specificity (1,2,0) on the ID selector matches the old trap exactly. */
#jbh-portfolio-modal:not(.alignwide):not(.alignfull),
#jbh-portfolio-modal.jbh-portfolio-modal-overlay { max-width: none; margin: 0; inset: 0; }
/* Mode-reactive portfolio modal ambience. Dark-mode defaults at :root stay
   heavy; light mode softens to slate-900 tints via --jbh-pm-backdrop /
   --jbh-pm-shadow in frontend.css site-mode selectors. */
.jbh-portfolio-modal-backdrop { position: absolute; inset: 0; background: var(--jbh-pm-backdrop-dk, var(--jbh-pm-backdrop, rgba(0,0,0,0.80))); backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px); }
.jbh-portfolio-modal-content { position: relative; background: var(--jbh-pm-bg-dk, var(--jbh-bg)); border: 1px solid var(--jbh-pm-border-dk, rgba(42,157,143,0.20)); border-radius: var(--jbh-pm-radius, var(--jbh-card-radius)); max-width: var(--jbh-pm-max-width, 900px); width: 100%; max-height: 90vh; overflow-y: auto; box-shadow: var(--jbh-pm-shadow-dk, var(--jbh-pm-shadow, 0 20px 60px rgba(0,0,0,0.5))); animation: jbhPortfolioModalIn 0.3s ease forwards; }
.jbh-portfolio-modal-header { position: sticky; top: 0; z-index: 10; background: var(--jbh-pm-header-bg-dk, color-mix(in srgb, var(--jbh-bg) 95%, transparent)); backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px); border-bottom: 1px solid var(--jbh-pm-border-dk, var(--jbh-border)); padding: 24px 32px; display: flex; justify-content: space-between; align-items: flex-start; gap: 16px; }
.jbh-portfolio-modal-header-text { flex: 1; min-width: 0; }
.jbh-portfolio-modal-meta { display: flex; align-items: center; gap: 12px; margin-bottom: 12px; }
.jbh-portfolio-modal-client { font-size: 10px; font-family: var(--jbh-font-mono); font-weight: 700; text-transform: uppercase; letter-spacing: 0.15em; color: var(--jbh-teal); background: var(--jbh-pm-client-bg-dk, rgba(42,157,143,0.10)); padding: 4px 10px; border-radius: 6px; }
.jbh-portfolio-modal-sector { font-size: 10px; font-family: var(--jbh-font-mono); text-transform: uppercase; letter-spacing: 0.15em; color: var(--jbh-pm-meta-dk, var(--jbh-text-color)); }
.jbh-portfolio-modal-title { font-family: var(--jbh-font-serif); font-size: clamp(1.4rem, 3vw, 1.8rem); font-weight: 700; color: var(--jbh-pm-heading-dk, var(--jbh-heading-color)); margin: 0; line-height: 1.3; }
.jbh-portfolio-modal-close { flex-shrink: 0; background: var(--jbh-pm-close-bg-dk, var(--jbh-card)); border: 1px solid rgba(42,157,143,0.10); border-radius: 8px; padding: 8px; color: var(--jbh-pm-close-dk, var(--jbh-text-color)); cursor: pointer; transition: color var(--jbh-transition), background var(--jbh-transition); }
.jbh-portfolio-modal-close:hover { color: var(--jbh-pm-close-hov-dk, var(--jbh-heading-color)); background: var(--jbh-pm-close-hov-bg-dk, rgba(42,157,143,0.10)); }
.jbh-portfolio-modal-body { padding: var(--jbh-pm-body-pad, 24px 32px 32px); }
.jbh-portfolio-modal-desc { font-size: 16px; line-height: 1.7; color: var(--jbh-pm-desc-dk, var(--jbh-text-color)); font-weight: 300; margin: 0 0 var(--jbh-pm-desc-gap, 40px); border-left: 2px solid var(--jbh-pm-desc-border-dk, var(--jbh-teal)); padding-left: 24px; padding-top: 8px; padding-bottom: 8px; }
.jbh-portfolio-modal-deliverables-heading { font-size: 12px; font-family: var(--jbh-font-mono); text-transform: uppercase; letter-spacing: 0.15em; color: var(--jbh-pm-deliv-heading-dk, var(--jbh-text-color)); margin: 0 0 24px; }
.jbh-portfolio-modal-deliverables-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: var(--jbh-pm-deliv-gap, 24px); }
.jbh-pm-deliverable-card { background: var(--jbh-pm-deliv-card-dk, var(--jbh-card)); border: 1px solid var(--jbh-pm-deliv-border-dk, rgba(42,157,143,0.10)); border-radius: var(--jbh-card-radius); padding: 24px; }
.jbh-pm-deliverable-phase { font-size: 10px; font-family: var(--jbh-font-mono); text-transform: uppercase; letter-spacing: 0.15em; color: var(--jbh-pm-phase-dk, var(--jbh-coral)); display: block; margin-bottom: 8px; }
.jbh-pm-deliverable-title { font-family: var(--jbh-font-serif); font-size: 16px; font-weight: 700; color: var(--jbh-pm-deliv-title-dk, var(--jbh-card-heading)); margin: 0 0 8px; }
.jbh-pm-deliverable-desc { font-size: 13px; color: var(--jbh-pm-deliv-desc-dk, var(--jbh-text-color)); line-height: 1.6; font-weight: 300; margin: 0; }

/* CTA push-bottom: pin CTA to the bottom of the card content panel */
.jbh-cta-push-bottom .jbh-project-content-panel { display: flex; flex-direction: column; }
.jbh-cta-push-bottom .jbh-project-cta { margin-top: auto; }

/* Modal action buttons */
.jbh-portfolio-modal-actions { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 32px; padding-top: 24px; border-top: 1px solid var(--jbh-pm-border-dk, var(--jbh-border)); }
.jbh-portfolio-modal-actions:empty { display: none; }
.jbh-pm-action-btn { display: inline-flex; align-items: center; gap: 6px; padding: 12px 24px; border-radius: var(--jbh-card-radius); font-family: var(--jbh-font-sans); font-size: 14px; font-weight: 600; text-decoration: none; cursor: pointer; transition: all var(--jbh-transition); line-height: 1.4; }
.jbh-pm-btn-primary { background: var(--jbh-pm-btn-pri-bg-dk, var(--jbh-teal)); color: var(--jbh-pm-btn-pri-text-dk, #ffffff); border: 2px solid var(--jbh-pm-btn-pri-bg-dk, var(--jbh-teal)); }
.jbh-pm-btn-primary:hover { filter: brightness(1.12); transform: translateY(-1px); }
.jbh-pm-btn-outline { background: transparent; color: var(--jbh-pm-btn-out-text-dk, var(--jbh-teal)); border: 2px solid var(--jbh-pm-btn-out-bd-dk, var(--jbh-teal)); }
.jbh-pm-btn-outline:hover { background: var(--jbh-pm-btn-out-bd-dk, var(--jbh-teal)); color: var(--jbh-pm-btn-out-hov-text-dk, #fff); }
.jbh-pm-btn-ghost { background: transparent; color: var(--jbh-pm-btn-out-text-dk, var(--jbh-teal)); border: 2px solid transparent; text-decoration: underline; text-underline-offset: 3px; }
.jbh-pm-btn-ghost:hover { color: var(--jbh-heading-color); }

/* Light-mode portfolio modal overrides — swap -dk vars to -lt */
.jbh-light .jbh-portfolio-modal-content,
html[data-theme="light"] .jbh-portfolio-modal-content,
html.light .jbh-portfolio-modal-content,
html[data-color-mode="light"] .jbh-portfolio-modal-content,
body[data-ct-color-mode="light"] .jbh-portfolio-modal-content { background: var(--jbh-pm-bg-lt, var(--jbh-bg)); }
.jbh-light .jbh-portfolio-modal-title,
html[data-theme="light"] .jbh-portfolio-modal-title,
html.light .jbh-portfolio-modal-title,
html[data-color-mode="light"] .jbh-portfolio-modal-title,
body[data-ct-color-mode="light"] .jbh-portfolio-modal-title { color: var(--jbh-pm-heading-lt, var(--jbh-heading-color)); }
.jbh-light .jbh-portfolio-modal-desc,
html[data-theme="light"] .jbh-portfolio-modal-desc,
html.light .jbh-portfolio-modal-desc,
html[data-color-mode="light"] .jbh-portfolio-modal-desc,
body[data-ct-color-mode="light"] .jbh-portfolio-modal-desc { color: var(--jbh-pm-desc-lt, var(--jbh-text-color)); }
.jbh-light .jbh-pm-deliverable-card,
html[data-theme="light"] .jbh-pm-deliverable-card,
html.light .jbh-pm-deliverable-card,
html[data-color-mode="light"] .jbh-pm-deliverable-card,
body[data-ct-color-mode="light"] .jbh-pm-deliverable-card { background: var(--jbh-pm-deliv-card-lt, var(--jbh-card)); }
.jbh-light .jbh-pm-deliverable-phase,
html[data-theme="light"] .jbh-pm-deliverable-phase,
html.light .jbh-pm-deliverable-phase,
html[data-color-mode="light"] .jbh-pm-deliverable-phase,
body[data-ct-color-mode="light"] .jbh-pm-deliverable-phase { color: var(--jbh-pm-phase-lt, var(--jbh-coral)); }
.jbh-light .jbh-pm-deliverable-title,
html[data-theme="light"] .jbh-pm-deliverable-title,
html.light .jbh-pm-deliverable-title,
html[data-color-mode="light"] .jbh-pm-deliverable-title,
body[data-ct-color-mode="light"] .jbh-pm-deliverable-title { color: var(--jbh-pm-deliv-title-lt, var(--jbh-card-heading)); }
/* Extended light-mode modal overrides */
:is(.jbh-light, html[data-theme="light"], html.light, html[data-color-mode="light"], body[data-ct-color-mode="light"]) .jbh-pm-deliverable-desc { color: var(--jbh-pm-deliv-desc-lt, var(--jbh-text-color)); }
:is(.jbh-light, html[data-theme="light"], html.light, html[data-color-mode="light"], body[data-ct-color-mode="light"]) .jbh-portfolio-modal-backdrop { background: var(--jbh-pm-backdrop-lt, var(--jbh-pm-backdrop, rgba(15,23,42,0.50))); }
:is(.jbh-light, html[data-theme="light"], html.light, html[data-color-mode="light"], body[data-ct-color-mode="light"]) .jbh-portfolio-modal-header { background: var(--jbh-pm-header-bg-lt, color-mix(in srgb, var(--jbh-bg) 95%, transparent)); }
:is(.jbh-light, html[data-theme="light"], html.light, html[data-color-mode="light"], body[data-ct-color-mode="light"]) .jbh-portfolio-modal-close { color: var(--jbh-pm-close-lt, var(--jbh-text-color)); background: var(--jbh-pm-close-bg-lt, var(--jbh-card)); }
:is(.jbh-light, html[data-theme="light"], html.light, html[data-color-mode="light"], body[data-ct-color-mode="light"]) .jbh-portfolio-modal-sector { color: var(--jbh-pm-meta-lt, var(--jbh-text-color)); }
:is(.jbh-light, html[data-theme="light"], html.light, html[data-color-mode="light"], body[data-ct-color-mode="light"]) .jbh-portfolio-modal-client { background: var(--jbh-pm-client-bg-lt, rgba(42,157,143,0.08)); }
:is(.jbh-light, html[data-theme="light"], html.light, html[data-color-mode="light"], body[data-ct-color-mode="light"]) .jbh-portfolio-modal-desc { border-left-color: var(--jbh-pm-desc-border-lt, var(--jbh-teal)); }
:is(.jbh-light, html[data-theme="light"], html.light, html[data-color-mode="light"], body[data-ct-color-mode="light"]) .jbh-pm-deliverable-card { border-color: var(--jbh-pm-deliv-border-lt, rgba(0,0,0,0.08)); }
:is(.jbh-light, html[data-theme="light"], html.light, html[data-color-mode="light"], body[data-ct-color-mode="light"]) .jbh-portfolio-modal-actions { border-top-color: var(--jbh-pm-border-lt, var(--jbh-border)); }
:is(.jbh-light, html[data-theme="light"], html.light, html[data-color-mode="light"], body[data-ct-color-mode="light"]) .jbh-pm-btn-primary { background: var(--jbh-pm-btn-pri-bg-lt, var(--jbh-teal)); color: var(--jbh-pm-btn-pri-text-lt, #ffffff); border-color: var(--jbh-pm-btn-pri-bg-lt, var(--jbh-teal)); }
:is(.jbh-light, html[data-theme="light"], html.light, html[data-color-mode="light"], body[data-ct-color-mode="light"]) .jbh-pm-btn-outline { color: var(--jbh-pm-btn-out-text-lt, var(--jbh-teal)); border-color: var(--jbh-pm-btn-out-bd-lt, var(--jbh-teal)); }
:is(.jbh-light, html[data-theme="light"], html.light, html[data-color-mode="light"], body[data-ct-color-mode="light"]) .jbh-pm-btn-ghost { color: var(--jbh-pm-btn-out-text-lt, var(--jbh-teal)); }

/* Light-mode close hover, deliverables heading, outline-button hover text, modal shadow */
:is(.jbh-light, html[data-theme="light"], html.light, html[data-color-mode="light"], body[data-ct-color-mode="light"]) .jbh-portfolio-modal-close:hover { color: var(--jbh-pm-close-hov-lt, var(--jbh-heading-color)); background: var(--jbh-pm-close-hov-bg-lt, rgba(42,157,143,0.10)); }
:is(.jbh-light, html[data-theme="light"], html.light, html[data-color-mode="light"], body[data-ct-color-mode="light"]) .jbh-portfolio-modal-deliverables-heading { color: var(--jbh-pm-deliv-heading-lt, var(--jbh-text-color)); }
:is(.jbh-light, html[data-theme="light"], html.light, html[data-color-mode="light"], body[data-ct-color-mode="light"]) .jbh-pm-btn-outline:hover { color: var(--jbh-pm-btn-out-hov-text-lt, #fff); }
:is(.jbh-light, html[data-theme="light"], html.light, html[data-color-mode="light"], body[data-ct-color-mode="light"]) .jbh-portfolio-modal-content { border-color: var(--jbh-pm-border-lt, rgba(0,0,0,0.08)); box-shadow: var(--jbh-pm-shadow-lt, var(--jbh-pm-shadow, 0 20px 60px rgba(15,23,42,0.20))); }

/* Modal animation variants. Default 'fade' uses jbhPortfolioModalIn declared
   above. The data-pm-animation attribute is set on the overlay by frontend.js
   on every open so the same shared overlay can render with different
   animations depending on which portfolio block opened it. */
@keyframes jbhPortfolioModalSlideUp { from { opacity: 0; transform: translateY( 24px ); } to { opacity: 1; transform: none; } }
@keyframes jbhPortfolioModalSlideDown { from { opacity: 0; transform: translateY( -24px ); } to { opacity: 1; transform: none; } }
@keyframes jbhPortfolioModalZoom { from { opacity: 0; transform: scale( 0.96 ); } to { opacity: 1; transform: scale( 1 ); } }
.jbh-portfolio-modal-overlay[data-pm-animation="slide-up"]   .jbh-portfolio-modal-content { animation: jbhPortfolioModalSlideUp 0.28s cubic-bezier(0.4,0,0.2,1) forwards; }
.jbh-portfolio-modal-overlay[data-pm-animation="slide-down"] .jbh-portfolio-modal-content { animation: jbhPortfolioModalSlideDown 0.28s cubic-bezier(0.4,0,0.2,1) forwards; }
.jbh-portfolio-modal-overlay[data-pm-animation="zoom"]       .jbh-portfolio-modal-content { animation: jbhPortfolioModalZoom 0.24s ease-out forwards; }
.jbh-portfolio-modal-overlay[data-pm-animation="none"]       .jbh-portfolio-modal-content { animation: none; }
@media (prefers-reduced-motion: reduce) {
	.jbh-portfolio-modal-overlay .jbh-portfolio-modal-content { animation: none !important; }
}

/* ================================================================
   5.  CARD STYLE VARIANTS
   ================================================================ */
.jbh-cards-bordered .jbh-service-card, .jbh-cards-bordered .jbh-product-card, .jbh-cards-bordered .jbh-plan-card, .jbh-cards-bordered .jbh-project-card, .jbh-cards-bordered .jbh-insight-card { border: var(--jbh-custom-card-border-w, 1px) solid var(--jbh-border); }
.jbh-cards-elevated .jbh-service-card, .jbh-cards-elevated .jbh-product-card, .jbh-cards-elevated .jbh-plan-card, .jbh-cards-elevated .jbh-project-card, .jbh-cards-elevated .jbh-insight-card { border: var(--jbh-custom-card-border-w, 1px) solid transparent; box-shadow: 0 4px 24px rgba(0,0,0,0.15); }
.jbh-cards-flat .jbh-service-card, .jbh-cards-flat .jbh-product-card, .jbh-cards-flat .jbh-plan-card, .jbh-cards-flat .jbh-project-card, .jbh-cards-flat .jbh-insight-card { border: none; box-shadow: none; }
.jbh-cards-glass .jbh-service-card, .jbh-cards-glass .jbh-product-card, .jbh-cards-glass .jbh-plan-card, .jbh-cards-glass .jbh-project-card, .jbh-cards-glass .jbh-insight-card { border: var(--jbh-custom-card-border-w, 1px) solid rgba(255,255,255,0.08); background: rgba(255,255,255,0.04); backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px); }
/* Glass preset: light-mode override. Full site-signal coverage so Blocksy
   Pro's data-ct-color-mode switch + html[data-color-mode]/html.light/
   .jbh-light/.jbh-auto all resolve to the light-glass style. */
.jbh-light .jbh-cards-glass .jbh-service-card, .jbh-light .jbh-cards-glass .jbh-product-card, .jbh-light .jbh-cards-glass .jbh-plan-card, .jbh-light .jbh-cards-glass .jbh-project-card, .jbh-light .jbh-cards-glass .jbh-insight-card,
html[data-theme="light"] .jbh-cards-glass .jbh-service-card, html[data-theme="light"] .jbh-cards-glass .jbh-product-card, html[data-theme="light"] .jbh-cards-glass .jbh-plan-card, html[data-theme="light"] .jbh-cards-glass .jbh-project-card, html[data-theme="light"] .jbh-cards-glass .jbh-insight-card,
html.light .jbh-cards-glass .jbh-service-card, html.light .jbh-cards-glass .jbh-product-card, html.light .jbh-cards-glass .jbh-plan-card, html.light .jbh-cards-glass .jbh-project-card, html.light .jbh-cards-glass .jbh-insight-card,
html[data-color-mode="light"] .jbh-cards-glass .jbh-service-card, html[data-color-mode="light"] .jbh-cards-glass .jbh-product-card, html[data-color-mode="light"] .jbh-cards-glass .jbh-plan-card, html[data-color-mode="light"] .jbh-cards-glass .jbh-project-card, html[data-color-mode="light"] .jbh-cards-glass .jbh-insight-card,
body[data-ct-color-mode="light"] .jbh-cards-glass .jbh-service-card, body[data-ct-color-mode="light"] .jbh-cards-glass .jbh-product-card, body[data-ct-color-mode="light"] .jbh-cards-glass .jbh-plan-card, body[data-ct-color-mode="light"] .jbh-cards-glass .jbh-project-card, body[data-ct-color-mode="light"] .jbh-cards-glass .jbh-insight-card { border-color: rgba(0,0,0,0.06); background: rgba(255,255,255,0.60); }
.jbh-cards-neon .jbh-service-card, .jbh-cards-neon .jbh-product-card, .jbh-cards-neon .jbh-plan-card, .jbh-cards-neon .jbh-project-card, .jbh-cards-neon .jbh-insight-card { border: 1px solid rgba(42,157,143,0.35); box-shadow: 0 0 12px rgba(42,157,143,0.12), inset 0 0 12px rgba(42,157,143,0.04); background: var(--jbh-custom-card-bg, var(--jbh-card)); }
.jbh-cards-neon .jbh-service-card:hover, .jbh-cards-neon .jbh-product-card:hover, .jbh-cards-neon .jbh-plan-card:hover, .jbh-cards-neon .jbh-project-card:hover, .jbh-cards-neon .jbh-insight-card:hover { border-color: rgba(42,157,143,0.60); box-shadow: 0 0 24px rgba(42,157,143,0.25), 0 0 48px rgba(42,157,143,0.08), inset 0 0 16px rgba(42,157,143,0.06); }
.jbh-cards-gradient .jbh-service-card, .jbh-cards-gradient .jbh-product-card, .jbh-cards-gradient .jbh-plan-card, .jbh-cards-gradient .jbh-project-card, .jbh-cards-gradient .jbh-insight-card { position: relative; border: none; background: var(--jbh-custom-card-bg, var(--jbh-card)); isolation: isolate; }
.jbh-cards-gradient .jbh-service-card::before, .jbh-cards-gradient .jbh-product-card::before, .jbh-cards-gradient .jbh-plan-card::before, .jbh-cards-gradient .jbh-project-card::before, .jbh-cards-gradient .jbh-insight-card::before { content: ""; position: absolute; inset: 0; border-radius: inherit; padding: 1px; background: linear-gradient(135deg, var(--jbh-teal), var(--jbh-coral), var(--jbh-teal)); background-size: 200% 200%; -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0); mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0); -webkit-mask-composite: xor; mask-composite: exclude; z-index: -1; transition: background-position 0.6s ease, opacity 0.3s ease; opacity: 0.6; }
.jbh-cards-gradient .jbh-service-card:hover::before, .jbh-cards-gradient .jbh-product-card:hover::before, .jbh-cards-gradient .jbh-plan-card:hover::before, .jbh-cards-gradient .jbh-project-card:hover::before, .jbh-cards-gradient .jbh-insight-card:hover::before { opacity: 1; background-position: 100% 100%; }
.jbh-cards-minimal .jbh-service-card, .jbh-cards-minimal .jbh-product-card, .jbh-cards-minimal .jbh-plan-card, .jbh-cards-minimal .jbh-project-card, .jbh-cards-minimal .jbh-insight-card { border: none; box-shadow: none; background: transparent; border-bottom: 1px solid var(--jbh-border); border-radius: 0; padding: 32px 0; }
.jbh-cards-minimal .jbh-service-card:last-child, .jbh-cards-minimal .jbh-product-card:last-child, .jbh-cards-minimal .jbh-plan-card:last-child, .jbh-cards-minimal .jbh-project-card:last-child, .jbh-cards-minimal .jbh-insight-card:last-child { border-bottom: none; }
.jbh-cards-neumorphic .jbh-service-card, .jbh-cards-neumorphic .jbh-product-card, .jbh-cards-neumorphic .jbh-plan-card, .jbh-cards-neumorphic .jbh-project-card, .jbh-cards-neumorphic .jbh-insight-card { border: none; background: var(--jbh-custom-card-bg, var(--jbh-card)); box-shadow: 6px 6px 16px rgba(0,0,0,0.25), -6px -6px 16px rgba(255,255,255,0.04); }
.jbh-cards-neumorphic .jbh-service-card:hover, .jbh-cards-neumorphic .jbh-product-card:hover, .jbh-cards-neumorphic .jbh-plan-card:hover, .jbh-cards-neumorphic .jbh-project-card:hover, .jbh-cards-neumorphic .jbh-insight-card:hover { box-shadow: 8px 8px 24px rgba(0,0,0,0.30), -8px -8px 24px rgba(255,255,255,0.06); }
/* Neumorphic preset: light-mode override. Same full site-signal coverage
   as the glass preset so Blocksy Pro + data-color-mode + auto blocks all
   get the correct light double-shadow treatment. */
.jbh-light .jbh-cards-neumorphic .jbh-service-card, .jbh-light .jbh-cards-neumorphic .jbh-product-card, .jbh-light .jbh-cards-neumorphic .jbh-plan-card, .jbh-light .jbh-cards-neumorphic .jbh-project-card, .jbh-light .jbh-cards-neumorphic .jbh-insight-card,
html[data-theme="light"] .jbh-cards-neumorphic .jbh-service-card, html[data-theme="light"] .jbh-cards-neumorphic .jbh-product-card, html[data-theme="light"] .jbh-cards-neumorphic .jbh-plan-card, html[data-theme="light"] .jbh-cards-neumorphic .jbh-project-card, html[data-theme="light"] .jbh-cards-neumorphic .jbh-insight-card,
html.light .jbh-cards-neumorphic .jbh-service-card, html.light .jbh-cards-neumorphic .jbh-product-card, html.light .jbh-cards-neumorphic .jbh-plan-card, html.light .jbh-cards-neumorphic .jbh-project-card, html.light .jbh-cards-neumorphic .jbh-insight-card,
html[data-color-mode="light"] .jbh-cards-neumorphic .jbh-service-card, html[data-color-mode="light"] .jbh-cards-neumorphic .jbh-product-card, html[data-color-mode="light"] .jbh-cards-neumorphic .jbh-plan-card, html[data-color-mode="light"] .jbh-cards-neumorphic .jbh-project-card, html[data-color-mode="light"] .jbh-cards-neumorphic .jbh-insight-card,
body[data-ct-color-mode="light"] .jbh-cards-neumorphic .jbh-service-card, body[data-ct-color-mode="light"] .jbh-cards-neumorphic .jbh-product-card, body[data-ct-color-mode="light"] .jbh-cards-neumorphic .jbh-plan-card, body[data-ct-color-mode="light"] .jbh-cards-neumorphic .jbh-project-card, body[data-ct-color-mode="light"] .jbh-cards-neumorphic .jbh-insight-card { box-shadow: 6px 6px 16px rgba(0,0,0,0.06), -6px -6px 16px rgba(255,255,255,0.50); }
.jbh-light .jbh-cards-neumorphic .jbh-service-card:hover, .jbh-light .jbh-cards-neumorphic .jbh-product-card:hover, .jbh-light .jbh-cards-neumorphic .jbh-plan-card:hover, .jbh-light .jbh-cards-neumorphic .jbh-project-card:hover, .jbh-light .jbh-cards-neumorphic .jbh-insight-card:hover,
html[data-theme="light"] .jbh-cards-neumorphic .jbh-service-card:hover, html[data-theme="light"] .jbh-cards-neumorphic .jbh-product-card:hover, html[data-theme="light"] .jbh-cards-neumorphic .jbh-plan-card:hover, html[data-theme="light"] .jbh-cards-neumorphic .jbh-project-card:hover, html[data-theme="light"] .jbh-cards-neumorphic .jbh-insight-card:hover,
html.light .jbh-cards-neumorphic .jbh-service-card:hover, html.light .jbh-cards-neumorphic .jbh-product-card:hover, html.light .jbh-cards-neumorphic .jbh-plan-card:hover, html.light .jbh-cards-neumorphic .jbh-project-card:hover, html.light .jbh-cards-neumorphic .jbh-insight-card:hover,
html[data-color-mode="light"] .jbh-cards-neumorphic .jbh-service-card:hover, html[data-color-mode="light"] .jbh-cards-neumorphic .jbh-product-card:hover, html[data-color-mode="light"] .jbh-cards-neumorphic .jbh-plan-card:hover, html[data-color-mode="light"] .jbh-cards-neumorphic .jbh-project-card:hover, html[data-color-mode="light"] .jbh-cards-neumorphic .jbh-insight-card:hover,
body[data-ct-color-mode="light"] .jbh-cards-neumorphic .jbh-service-card:hover, body[data-ct-color-mode="light"] .jbh-cards-neumorphic .jbh-product-card:hover, body[data-ct-color-mode="light"] .jbh-cards-neumorphic .jbh-plan-card:hover, body[data-ct-color-mode="light"] .jbh-cards-neumorphic .jbh-project-card:hover, body[data-ct-color-mode="light"] .jbh-cards-neumorphic .jbh-insight-card:hover { box-shadow: 8px 8px 24px rgba(0,0,0,0.08), -8px -8px 24px rgba(255,255,255,0.60); }

/* ================================================================
   6.  BUTTON STYLE VARIANTS
   ================================================================ */
.jbh-btn-filled .jbh-get-started-btn, .jbh-btn-filled .jbh-product-btn { background: var(--jbh-custom-btn, var(--jbh-coral)); color: var(--jbh-custom-btn-text, #ffffff); border: 2px solid var(--jbh-custom-btn, var(--jbh-coral)); padding: 10px 20px; border-radius: var(--jbh-card-radius); font-weight: 600; transition: background 0.2s ease, color 0.2s ease, border-color 0.2s ease, filter 0.2s ease, transform 0.2s ease; }
.jbh-btn-filled .jbh-get-started-btn:hover, .jbh-btn-filled .jbh-product-btn:hover { filter: brightness(1.08); transform: translateY(-1px); }
.jbh-btn-outline .jbh-get-started-btn, .jbh-btn-outline .jbh-product-btn { background: transparent; color: var(--jbh-custom-btn, var(--jbh-teal)); border: 2px solid var(--jbh-custom-btn, var(--jbh-teal)); padding: 10px 20px; border-radius: var(--jbh-card-radius); font-weight: 600; transition: background 0.2s ease, color 0.2s ease, border-color 0.2s ease, transform 0.2s ease; }
.jbh-btn-outline .jbh-get-started-btn:hover, .jbh-btn-outline .jbh-product-btn:hover { background: var(--jbh-custom-btn-hover, var(--jbh-custom-btn, var(--jbh-teal))); color: var(--jbh-custom-btn-hover-text, var(--jbh-custom-btn-text, #ffffff)); border-color: var(--jbh-custom-btn-hover, var(--jbh-custom-btn, var(--jbh-teal))); transform: translateY(-1px); }
.jbh-btn-ghost .jbh-get-started-btn, .jbh-btn-ghost .jbh-product-btn { background: transparent; color: var(--jbh-custom-btn, var(--jbh-teal)); border: none; padding: 10px 0; font-weight: 700; text-decoration: underline; text-underline-offset: 4px; transition: color 0.2s ease; }
.jbh-btn-ghost .jbh-get-started-btn:hover, .jbh-btn-ghost .jbh-product-btn:hover { color: var(--jbh-custom-btn-hover, var(--jbh-coral)); }
.jbh-btn-filled .jbh-plan-btn { background: var(--jbh-custom-btn, var(--jbh-coral)); color: var(--jbh-custom-btn-text, #ffffff); border: 2px solid var(--jbh-custom-btn, var(--jbh-coral)); }
.jbh-btn-filled .jbh-plan-btn:hover { filter: brightness(1.08); transform: translateY(-1px); }
.jbh-btn-outline .jbh-plan-btn { background: transparent; color: var(--jbh-custom-btn, var(--jbh-teal)); border: 2px solid var(--jbh-custom-btn, var(--jbh-teal)); }
.jbh-btn-outline .jbh-plan-btn:hover { background: var(--jbh-custom-btn-hover, var(--jbh-teal)); color: var(--jbh-custom-btn-hover-text, #ffffff); border-color: var(--jbh-custom-btn-hover, var(--jbh-teal)); transform: translateY(-1px); }
.jbh-btn-ghost .jbh-plan-btn { background: transparent; color: var(--jbh-custom-btn, var(--jbh-teal)); border: none; text-decoration: underline; text-underline-offset: 4px; }
.jbh-btn-ghost .jbh-plan-btn:hover { color: var(--jbh-custom-btn-hover, var(--jbh-coral)); }
.jbh-btn-filled .jbh-project-cta { background: var(--jbh-custom-btn, var(--jbh-coral)); color: var(--jbh-custom-btn-text, #ffffff); border: 2px solid var(--jbh-custom-btn, var(--jbh-coral)); padding: var(--jbh-pf-cta-pt, 10px) var(--jbh-pf-cta-pr, 20px) var(--jbh-pf-cta-pb, 10px) var(--jbh-pf-cta-pl, 20px); border-radius: var(--jbh-card-radius); font-weight: 600; display: inline-block; }
.jbh-btn-filled .jbh-project-cta:hover { filter: brightness(1.08); transform: translateY(-1px); }
.jbh-btn-outline .jbh-project-cta { background: transparent; color: var(--jbh-custom-btn, var(--jbh-teal)); border: 2px solid var(--jbh-custom-btn, var(--jbh-teal)); padding: var(--jbh-pf-cta-pt, 10px) var(--jbh-pf-cta-pr, 20px) var(--jbh-pf-cta-pb, 10px) var(--jbh-pf-cta-pl, 20px); border-radius: var(--jbh-card-radius); font-weight: 600; display: inline-block; }
.jbh-btn-outline .jbh-project-cta:hover { background: var(--jbh-custom-btn-hover, var(--jbh-custom-btn, var(--jbh-teal))); color: var(--jbh-custom-btn-hover-text, var(--jbh-custom-btn-text, #ffffff)); border-color: var(--jbh-custom-btn-hover, var(--jbh-custom-btn, var(--jbh-teal))); transform: translateY(-1px); }
.jbh-btn-ghost .jbh-project-cta { background: transparent; color: var(--jbh-custom-btn, var(--jbh-teal)); border: none; text-decoration: underline; text-underline-offset: 4px; display: inline-block; }
.jbh-btn-ghost .jbh-project-cta:hover { color: var(--jbh-custom-btn-hover, var(--jbh-coral)); }

/* ================================================================
   7.  HOVER / SHADOW / DIVIDER / ALIGNMENT / TITLE VARIANTS
   ================================================================ */
.jbh-hover-lift .jbh-service-card:hover, .jbh-hover-lift .jbh-product-card:hover, .jbh-hover-lift .jbh-plan-card:hover, .jbh-hover-lift .jbh-project-card:hover, .jbh-hover-lift .jbh-insight-card:hover { transform: translateY(-4px); box-shadow: 0 12px 40px rgba(0,0,0,0.18); }
.jbh-hover-glow .jbh-service-card:hover, .jbh-hover-glow .jbh-product-card:hover, .jbh-hover-glow .jbh-plan-card:hover, .jbh-hover-glow .jbh-project-card:hover, .jbh-hover-glow .jbh-insight-card:hover { box-shadow: 0 0 24px rgba(42,157,143,0.25), 0 0 48px rgba(42,157,143,0.10); }
.jbh-hover-border .jbh-service-card:hover, .jbh-hover-border .jbh-product-card:hover, .jbh-hover-border .jbh-plan-card:hover, .jbh-hover-border .jbh-project-card:hover, .jbh-hover-border .jbh-insight-card:hover { border-color: var(--jbh-custom-icon, var(--jbh-teal)) !important; }
.jbh-hover-none .jbh-service-card:hover, .jbh-hover-none .jbh-product-card:hover, .jbh-hover-none .jbh-plan-card:hover, .jbh-hover-none .jbh-project-card:hover, .jbh-hover-none .jbh-insight-card:hover { transform: none; box-shadow: none; }
.jbh-hover-scale .jbh-service-card:hover, .jbh-hover-scale .jbh-product-card:hover, .jbh-hover-scale .jbh-plan-card:hover, .jbh-hover-scale .jbh-project-card:hover, .jbh-hover-scale .jbh-insight-card:hover { transform: scale(1.03); box-shadow: 0 12px 40px rgba(0,0,0,0.18); }
.jbh-hover-tilt .jbh-service-card, .jbh-hover-tilt .jbh-product-card, .jbh-hover-tilt .jbh-plan-card, .jbh-hover-tilt .jbh-project-card, .jbh-hover-tilt .jbh-insight-card { perspective: 800px; }
.jbh-hover-tilt .jbh-service-card:hover, .jbh-hover-tilt .jbh-product-card:hover, .jbh-hover-tilt .jbh-plan-card:hover, .jbh-hover-tilt .jbh-project-card:hover, .jbh-hover-tilt .jbh-insight-card:hover { transform: rotateX(-2deg) rotateY(2deg) translateY(-2px); box-shadow: 0 16px 40px rgba(0,0,0,0.20); }
.jbh-shadow-none .jbh-service-card, .jbh-shadow-none .jbh-product-card, .jbh-shadow-none .jbh-plan-card, .jbh-shadow-none .jbh-project-card, .jbh-shadow-none .jbh-insight-card { box-shadow: none; }
.jbh-shadow-subtle .jbh-service-card, .jbh-shadow-subtle .jbh-product-card, .jbh-shadow-subtle .jbh-plan-card, .jbh-shadow-subtle .jbh-project-card, .jbh-shadow-subtle .jbh-insight-card { box-shadow: 0 2px 8px rgba(0,0,0,0.06); }
.jbh-shadow-medium .jbh-service-card, .jbh-shadow-medium .jbh-product-card, .jbh-shadow-medium .jbh-plan-card, .jbh-shadow-medium .jbh-project-card, .jbh-shadow-medium .jbh-insight-card { box-shadow: 0 4px 24px rgba(0,0,0,0.12); }
.jbh-shadow-dramatic .jbh-service-card, .jbh-shadow-dramatic .jbh-product-card, .jbh-shadow-dramatic .jbh-plan-card, .jbh-shadow-dramatic .jbh-project-card, .jbh-shadow-dramatic .jbh-insight-card { box-shadow: 0 12px 48px rgba(0,0,0,0.22), 0 4px 12px rgba(0,0,0,0.10); }
.jbh-divider-line .jbh-product-card + .jbh-product-card, .jbh-divider-line .jbh-plan-card + .jbh-plan-card, .jbh-divider-line .jbh-project-card + .jbh-project-card { border-top: 1px solid var(--jbh-border); padding-top: 40px; }
.jbh-divider-gradient .jbh-product-card + .jbh-product-card::before, .jbh-divider-gradient .jbh-plan-card + .jbh-plan-card::before, .jbh-divider-gradient .jbh-project-card + .jbh-project-card::before { content: ""; display: block; height: 1px; margin-bottom: 40px; background: linear-gradient(90deg, transparent, var(--jbh-teal), transparent); }
.jbh-divider-dots .jbh-product-card + .jbh-product-card::before, .jbh-divider-dots .jbh-plan-card + .jbh-plan-card::before, .jbh-divider-dots .jbh-project-card + .jbh-project-card::before { content: "\2022 \2022 \2022"; display: block; text-align: center; color: var(--jbh-teal); letter-spacing: 8px; font-size: 14px; margin-bottom: 40px; opacity: 0.5; }
.jbh-align-center { text-align: center; }
.jbh-align-center .jbh-section-header { justify-content: center; }
.jbh-align-center .jbh-card-footer { justify-content: center; gap: 16px; }
.jbh-align-center .jbh-project-meta { justify-content: center; }
.jbh-align-center .jbh-project-tags { justify-content: center; }
.jbh-align-center .jbh-plan-perks { list-style-position: inside; padding-left: 0; }
.jbh-align-center .jbh-plan-card { align-items: center; }
.jbh-title-small .jbh-store-title, .jbh-title-small .jbh-plans-title, .jbh-title-small .jbh-portfolio-title { font-size: clamp(1.25rem, 2.5vw, 1.75rem); }
.jbh-title-small .jbh-card-title, .jbh-title-small .jbh-product-title, .jbh-title-small .jbh-plan-name, .jbh-title-small .jbh-project-title { font-size: 15px; }
.jbh-title-medium .jbh-store-title, .jbh-title-medium .jbh-plans-title, .jbh-title-medium .jbh-portfolio-title { font-size: clamp(2rem, 4vw, 3rem); }
.jbh-title-large .jbh-store-title, .jbh-title-large .jbh-plans-title, .jbh-title-large .jbh-portfolio-title { font-size: clamp(2.5rem, 5vw, 4rem); }
.jbh-title-large .jbh-card-title, .jbh-title-large .jbh-product-title, .jbh-title-large .jbh-plan-name, .jbh-title-large .jbh-project-title { font-size: 24px; }

/* ================================================================
   8.  ANIMATION VARIANTS
   ================================================================ */
body:not(.editor-styles-wrapper):not(.block-editor-page) [data-jbh-animate="fadeIn"],
body:not(.editor-styles-wrapper):not(.block-editor-page) [data-jbh-animate="slideUp"],
body:not(.editor-styles-wrapper):not(.block-editor-page) [data-jbh-animate="scaleIn"] { opacity: 0; }
body:not(.editor-styles-wrapper):not(.block-editor-page) [data-jbh-animate="slideUp"] { transform: translateY(30px); }
body:not(.editor-styles-wrapper):not(.block-editor-page) [data-jbh-animate="scaleIn"] { transform: scale(0.95); }
body:not(.editor-styles-wrapper):not(.block-editor-page) [data-jbh-animate].jbh-animated,
[data-jbh-animate].jbh-animated { opacity: 1; transform: none; transition: opacity 0.6s ease, transform 0.6s ease; }
/* Stagger reveal — uses animation-fill-mode: backwards so the `from`
   keyframe state applies during animation-delay, and once the animation
   completes the element returns to its normal CSS state. Critical: do
   NOT use `forwards` here — that persists the keyframe `transform:
   translateY(0)` via the animation cascade origin and silently beats
   `.jbh-hover-lift ...:hover { transform: translateY(-4px) }` plus the
   `jbh-float` animation on `.jbh-plan-card.jbh-highlighted`. Highlighted
   plan card is excluded so its float declaration wins (the stagger rule
   has higher specificity than `.jbh-plan-card.jbh-highlighted` and would
   otherwise replace the float `animation` value). */
[data-jbh-animate].jbh-animated .jbh-service-card, [data-jbh-animate].jbh-animated .jbh-product-card, [data-jbh-animate].jbh-animated .jbh-plan-card:not(.jbh-highlighted), [data-jbh-animate].jbh-animated .jbh-project-card, [data-jbh-animate].jbh-animated .jbh-insight-card { animation: jbh-stagger-in 0.5s ease backwards; }
[data-jbh-animate].jbh-animated .jbh-service-card:nth-child(1), [data-jbh-animate].jbh-animated .jbh-product-card:nth-child(1), [data-jbh-animate].jbh-animated .jbh-plan-card:nth-child(1), [data-jbh-animate].jbh-animated .jbh-project-card:nth-child(1), [data-jbh-animate].jbh-animated .jbh-insight-card:nth-child(1) { animation-delay: 0.05s; }
[data-jbh-animate].jbh-animated .jbh-service-card:nth-child(2), [data-jbh-animate].jbh-animated .jbh-product-card:nth-child(2), [data-jbh-animate].jbh-animated .jbh-plan-card:nth-child(2), [data-jbh-animate].jbh-animated .jbh-project-card:nth-child(2), [data-jbh-animate].jbh-animated .jbh-insight-card:nth-child(2) { animation-delay: 0.10s; }
[data-jbh-animate].jbh-animated .jbh-service-card:nth-child(3), [data-jbh-animate].jbh-animated .jbh-product-card:nth-child(3), [data-jbh-animate].jbh-animated .jbh-plan-card:nth-child(3), [data-jbh-animate].jbh-animated .jbh-project-card:nth-child(3), [data-jbh-animate].jbh-animated .jbh-insight-card:nth-child(3) { animation-delay: 0.15s; }
[data-jbh-animate].jbh-animated .jbh-service-card:nth-child(n+4), [data-jbh-animate].jbh-animated .jbh-product-card:nth-child(n+4), [data-jbh-animate].jbh-animated .jbh-plan-card:nth-child(n+4), [data-jbh-animate].jbh-animated .jbh-project-card:nth-child(n+4), [data-jbh-animate].jbh-animated .jbh-insight-card:nth-child(n+4) { animation-delay: 0.20s; }
@keyframes jbh-stagger-in { from { opacity: 0; transform: translateY(16px); } to { opacity: 1; transform: translateY(0); } }
/* Unique keyframe name — prior iterations reused `jbhFadeIn` which
   collided with modal.css's simpler opacity-only fade. Because
   modal.css loads after frontend.css, the simpler rule silently
   overwrote the intended scale+translate entrance here. The rename
   isolates the portfolio-modal animation from the overlay backdrop
   / success-state / toast animations that want a plain opacity fade. */
@keyframes jbhPortfolioModalIn { from { opacity: 0; transform: scale(0.96) translateY(12px); } to { opacity: 1; transform: scale(1) translateY(0); } }

/* ================================================================
   9.  NUCLEAR SPECIFICITY SHIELD — Original 4 blocks
   ================================================================ */
body div.wp-block-jbh-studio-grid.jbh-studio-grid *, body div.wp-block-jbh-store-grid.jbh-store-grid *, body div.wp-block-jbh-pricing-plans.jbh-pricing-plans *, body div.wp-block-jbh-portfolio-grid.jbh-portfolio-grid * { box-sizing: border-box !important; }
body div.wp-block-jbh-studio-grid.jbh-studio-grid:not(.has-background), body div.wp-block-jbh-store-grid.jbh-store-grid:not(.has-background), body div.wp-block-jbh-pricing-plans.jbh-pricing-plans:not(.has-background), body div.wp-block-jbh-portfolio-grid.jbh-portfolio-grid:not(.has-background) { background-color: var(--jbh-custom-block-bg, var(--jbh-bg)) !important; }
body div.wp-block-jbh-studio-grid.jbh-studio-grid:not(.has-text-color), body div.wp-block-jbh-store-grid.jbh-store-grid:not(.has-text-color), body div.wp-block-jbh-pricing-plans.jbh-pricing-plans:not(.has-text-color), body div.wp-block-jbh-portfolio-grid.jbh-portfolio-grid:not(.has-text-color) { color: var(--jbh-text-color) !important; }
body div.wp-block-jbh-studio-grid.jbh-studio-grid, body div.wp-block-jbh-store-grid.jbh-store-grid, body div.wp-block-jbh-pricing-plans.jbh-pricing-plans, body div.wp-block-jbh-portfolio-grid.jbh-portfolio-grid { font-family: var(--jbh-font-sans) !important; line-height: 1.6 !important; -webkit-font-smoothing: antialiased !important; -moz-osx-font-smoothing: grayscale !important; box-sizing: border-box !important; word-wrap: break-word !important; }
body div.wp-block-jbh-store-grid .jbh-store-title, body div.wp-block-jbh-pricing-plans .jbh-plans-title, body div.wp-block-jbh-portfolio-grid .jbh-portfolio-title { color: var(--jbh-heading-color) !important; font-family: var(--jbh-font-serif) !important; font-weight: 700 !important; letter-spacing: normal !important; text-transform: none !important; line-height: 1.2 !important; margin-top: 0 !important; margin-bottom: 8px !important; padding: 0 !important; border: none !important; text-decoration: none !important; }
/* Nuclear shield — card titles across all four grid blocks. Now
   routes through --jbh-custom-header so the "Heading Color" picker
   each block already exposes in its inspector actually takes effect.
   Previously the shield forced var(--jbh-card-heading) which meant
   every title picker was silently dead on live pages. */
body div.wp-block-jbh-studio-grid .jbh-card-title, body div.wp-block-jbh-store-grid .jbh-product-title, body div.wp-block-jbh-pricing-plans .jbh-plan-name, body div.wp-block-jbh-portfolio-grid .jbh-project-title { color: var(--jbh-custom-header, var(--jbh-card-heading)) !important; font-family: var(--jbh-font-serif) !important; letter-spacing: normal !important; text-transform: none !important; margin-top: 0 !important; padding: 0 !important; border: none !important; }
/* Description / subtitle shield — routes through --jbh-custom-desc
   so the "Description Color" picker flows through to the live page. */
body div.wp-block-jbh-studio-grid .jbh-card-desc, body div.wp-block-jbh-store-grid .jbh-product-desc, body div.wp-block-jbh-store-grid .jbh-store-subtitle, body div.wp-block-jbh-pricing-plans .jbh-plans-subtitle, body div.wp-block-jbh-portfolio-grid .jbh-portfolio-subtitle, body div.wp-block-jbh-portfolio-grid .jbh-project-desc { color: var(--jbh-custom-desc, var(--jbh-text-color)) !important; font-family: var(--jbh-font-sans) !important; line-height: 1.7 !important; text-transform: none !important; letter-spacing: normal !important; }
body div.wp-block-jbh-pricing-plans .jbh-plan-perks { list-style: none !important; padding: 20px 0 !important; margin: 16px 0 !important; }
body div.wp-block-jbh-pricing-plans .jbh-plan-perks li { color: var(--jbh-custom-desc, var(--jbh-text-color)) !important; font-family: var(--jbh-font-sans) !important; font-size: 14px !important; list-style: none !important; list-style-type: none !important; line-height: 2.2 !important; padding-left: 20px !important; margin: 0 !important; background: none !important; background-image: none !important; position: relative !important; }
body div.wp-block-jbh-pricing-plans .jbh-plan-perks li::before { content: "\2713" !important; position: absolute !important; left: 0 !important; color: var(--jbh-custom-icon, var(--jbh-teal)) !important; font-weight: 700 !important; }
body div.wp-block-jbh-pricing-plans .jbh-plan-perks li::marker { content: none !important; font-size: 0 !important; }
body div.wp-block-jbh-pricing-plans .jbh-plan-card.jbh-highlighted .jbh-plan-perks li::before { color: var(--jbh-coral) !important; }
body div.wp-block-jbh-portfolio-grid .jbh-project-deliverables ul { list-style: none !important; padding: 0 !important; margin: 0 !important; }
body div.wp-block-jbh-portfolio-grid .jbh-project-deliverables li { color: var(--jbh-custom-desc, var(--jbh-text-color)) !important; font-size: 13px !important; list-style: none !important; list-style-type: none !important; line-height: 1.9 !important; padding-left: 18px !important; margin: 0 !important; background: none !important; background-image: none !important; position: relative !important; }
body div.wp-block-jbh-portfolio-grid .jbh-project-deliverables li::before { content: "\2713" !important; position: absolute !important; left: 0 !important; color: var(--jbh-custom-icon, var(--jbh-teal)) !important; font-weight: 700 !important; }
body div.wp-block-jbh-portfolio-grid .jbh-project-deliverables li::marker { content: none !important; font-size: 0 !important; }
body div.wp-block-jbh-portfolio-grid .jbh-project-deliverables h4 { color: var(--jbh-custom-header, var(--jbh-heading-color)) !important; font-size: 11px !important; letter-spacing: 2px !important; text-transform: uppercase !important; font-weight: 700 !important; margin: 0 0 14px !important; padding: 0 !important; }
body div.wp-block-jbh-studio-grid .jbh-card-price { color: var(--jbh-custom-price, var(--jbh-card-heading)) !important; font-family: var(--jbh-font-serif) !important; font-size: 36px !important; font-weight: 700 !important; text-decoration: none !important; }
body div.wp-block-jbh-studio-grid .jbh-card-includes { list-style: none !important; padding: 0 !important; margin: 0 0 24px !important; }
body div.wp-block-jbh-studio-grid .jbh-card-includes li { list-style: none !important; list-style-type: none !important; display: flex !important; align-items: flex-start !important; gap: var(--jbh-custom-includes-gap, 12px) !important; padding: 8px 0 !important; margin: 0 !important; background: none !important; background-image: none !important; color: var(--jbh-custom-includes-text, var(--jbh-heading-color)) !important; }
body div.wp-block-jbh-studio-grid .jbh-card-includes li::marker { content: none !important; font-size: 0 !important; }
body div.wp-block-jbh-studio-grid .jbh-check-icon { width: 16px !important; height: 16px !important; min-width: 16px !important; margin-top: 2px !important; color: var(--jbh-custom-includes-icon, var(--jbh-custom-icon, var(--jbh-teal))) !important; flex-shrink: 0 !important; }
body div.wp-block-jbh-studio-grid .jbh-card-includes-label { color: var(--jbh-custom-includes-label, var(--jbh-text-color)) !important; font-family: var(--jbh-font-mono) !important; text-transform: uppercase !important; letter-spacing: 0.12em !important; font-size: 10px !important; }
body div.wp-block-jbh-studio-grid .jbh-card-addons-label { color: var(--jbh-custom-addons-label, var(--jbh-text-color)) !important; font-family: var(--jbh-font-mono) !important; text-transform: uppercase !important; letter-spacing: 0.12em !important; font-size: 10px !important; }
body div.wp-block-jbh-studio-grid .jbh-addon-pill { color: var(--jbh-custom-addons-pill-tx, var(--jbh-text-color)) !important; border-color: var(--jbh-custom-addons-pill-bd, rgba(42,157,143,0.20)) !important; background: var(--jbh-custom-addons-pill-bg, var(--jbh-bg)) !important; }
body div.wp-block-jbh-studio-grid .jbh-addon-price { color: var(--jbh-custom-addons-price, var(--jbh-teal)) !important; }
body div.wp-block-jbh-studio-grid .jbh-card-price-label    { color: var(--jbh-custom-price-label, var(--jbh-custom-timeline-label, var(--jbh-text-color))) !important; font-family: var(--jbh-font-mono) !important; }
body div.wp-block-jbh-studio-grid .jbh-card-timeline-label { color: var(--jbh-custom-timeline-label, var(--jbh-text-color)) !important; font-family: var(--jbh-font-mono) !important; }
body div.wp-block-jbh-studio-grid .jbh-card-timeline       { color: var(--jbh-custom-timeline-value, var(--jbh-custom-icon, var(--jbh-teal))) !important; }
body div.wp-block-jbh-studio-grid .jbh-card-target-text    { color: var(--jbh-custom-target-text, var(--jbh-heading-color)) !important; }
body div.wp-block-jbh-studio-grid .jbh-card-icon-box { color: var(--jbh-custom-icon, var(--jbh-teal)) !important; }
/* Price / meta / tag / badge shield — each expression now defers to
   the relevant --jbh-custom-* picker slot, with a sensible fallback.
   These were the biggest sink for "I change the picker and nothing
   happens" reports in store-grid / pricing-plans / portfolio-grid. */
body div.wp-block-jbh-store-grid .jbh-product-price { color: var(--jbh-custom-price, var(--jbh-heading-color)) !important; font-size: 20px !important; font-weight: 700 !important; text-decoration: none !important; }
body div.wp-block-jbh-pricing-plans .jbh-plan-price { color: var(--jbh-custom-price, var(--jbh-card-heading)) !important; font-size: 40px !important; font-weight: 700 !important; text-decoration: none !important; }
body div.wp-block-jbh-pricing-plans .jbh-plan-price span { font-size: 14px !important; color: var(--jbh-custom-desc, var(--jbh-text-color)) !important; font-weight: 400 !important; }
body div.wp-block-jbh-store-grid .jbh-store-tag, body div.wp-block-jbh-pricing-plans .jbh-plans-tag, body div.wp-block-jbh-portfolio-grid .jbh-project-client { color: var(--jbh-custom-tag, var(--jbh-teal)) !important; font-weight: 700 !important; letter-spacing: 2px !important; text-transform: uppercase !important; }
body div.wp-block-jbh-store-grid .jbh-product-type, body div.wp-block-jbh-portfolio-grid .jbh-project-sector { color: var(--jbh-custom-desc, var(--jbh-text-color)) !important; letter-spacing: 2px !important; text-transform: uppercase !important; }
body div.wp-block-jbh-store-grid .jbh-product-badge { color: var(--jbh-custom-badge, var(--jbh-coral)) !important; }
body div.wp-block-jbh-pricing-plans .jbh-plan-badge { color: var(--jbh-custom-badge-text, #fff) !important; background-color: var(--jbh-custom-badge-bg, var(--jbh-coral)) !important; }
body div.wp-block-jbh-pricing-plans .jbh-plan-yearly-note { color: var(--jbh-custom-icon, var(--jbh-teal)) !important; }
body div.wp-block-jbh-pricing-plans .jbh-plan-yearly-total { color: var(--jbh-custom-desc, var(--jbh-text-color)) !important; opacity: 0.75 !important; font-weight: 600 !important; }
body div.wp-block-jbh-pricing-plans .jbh-plan-yearly-total[hidden] { display: none !important; }
/* Card layout resets — `background` is INTENTIONALLY omitted here and
   handled by the picker-aware rule at line ~1887
   (`background: var(--jbh-custom-card-bg, var(--jbh-card)) !important`).
   Previously this rule also wrote `background: var(--jbh-card) !important`
   which, being a duplicate with equal specificity, created confusion even
   though the later rule won the cascade. Removing the duplicate prevents
   future maintainers from chasing a ghost “card bg picker does nothing”
   bug when the real fix is to update the picker-aware rule below. */
body div.wp-block-jbh-studio-grid .jbh-service-card, body div.wp-block-jbh-store-grid .jbh-product-card, body div.wp-block-jbh-pricing-plans .jbh-plan-card, body div.wp-block-jbh-portfolio-grid .jbh-project-card { border-radius: var(--jbh-card-radius) !important; max-width: none !important; float: none !important; clear: none !important; }
body div.wp-block-jbh-studio-grid .jbh-get-started-btn, body div.wp-block-jbh-store-grid .jbh-product-btn, body div.wp-block-jbh-pricing-plans .jbh-plan-btn, body div.wp-block-jbh-portfolio-grid .jbh-project-cta { font-family: var(--jbh-font-sans) !important; text-decoration: none !important; box-shadow: none !important; cursor: pointer !important; }
body div.wp-block-jbh-pricing-plans .jbh-pricing-toggle { appearance: none !important; -webkit-appearance: none !important; background: var(--jbh-custom-toggle-track, var(--jbh-border)) !important; border: none !important; width: 48px !important; height: 26px !important; box-shadow: none !important; outline: none !important; }
body div.wp-block-jbh-pricing-plans .jbh-pricing-toggle:checked { background: var(--jbh-custom-toggle-track-active, var(--jbh-teal)) !important; }
body div.wp-block-jbh-pricing-plans .jbh-pricing-toggle::after { background: var(--jbh-custom-toggle-dot, #fff) !important; }
body div.wp-block-jbh-studio-grid .jbh-card-footer { background: var(--jbh-custom-card-footer-bg, color-mix(in srgb, var(--jbh-bg) 50%, transparent)) !important; border-color: var(--jbh-border) !important; }
body div.wp-block-jbh-pricing-plans .jbh-plan-perks, body div.wp-block-jbh-portfolio-grid .jbh-project-deliverables { border-color: var(--jbh-border) !important; }
body div.wp-block-jbh-studio-grid:not(.jbh-carousel-mode) .jbh-service-grid, body div.wp-block-jbh-store-grid .jbh-product-grid, body div.wp-block-jbh-pricing-plans .jbh-plans-grid, body div.wp-block-jbh-portfolio-grid .jbh-project-list { display: grid !important; list-style: none !important; }
body div.wp-block-jbh-studio-grid.jbh-carousel-mode .jbh-service-grid { display: flex !important; }

/* WP text/link color cascade */
body [class*="wp-block-jbh-"].has-text-color .jbh-card-desc, body [class*="wp-block-jbh-"].has-text-color .jbh-product-desc, body [class*="wp-block-jbh-"].has-text-color .jbh-project-desc, body [class*="wp-block-jbh-"].has-text-color .jbh-plan-perks li, body [class*="wp-block-jbh-"].has-text-color .jbh-store-subtitle, body [class*="wp-block-jbh-"].has-text-color .jbh-plans-subtitle, body [class*="wp-block-jbh-"].has-text-color .jbh-portfolio-subtitle, body [class*="wp-block-jbh-"].has-text-color .jbh-hero-subtitle, body [class*="wp-block-jbh-"].has-text-color .jbh-sh-subtitle, body [class*="wp-block-jbh-"].has-text-color .jbh-about-bio, body [class*="wp-block-jbh-"].has-text-color .jbh-insight-excerpt, body [class*="wp-block-jbh-"].has-text-color .jbh-cta-subtitle { color: inherit !important; }
body [class*="wp-block-jbh-"].has-link-color a:not(.jbh-plan-btn):not(.jbh-plan-btn-primary):not(.jbh-plan-btn-outline):not(.jbh-product-btn):not(.jbh-get-started-btn):not(.jbh-project-cta):not(.jbh-hero-btn):not(.jbh-cta-btn):not(.jbh-insight-read-more) { color: inherit; }

/* --- 9b. NUCLEAR SHIELD — Newer blocks (hero, section-header, about, insights-grid, cta-banner) --- */
body section.wp-block-jbh-hero-section.jbh-hero-section *, body header.wp-block-jbh-section-header.jbh-section-header *, body section.wp-block-jbh-about-section.jbh-about-section *, body section.wp-block-jbh-insights-grid.jbh-insights-grid *, body div.wp-block-jbh-cta-banner.jbh-cta-banner * { box-sizing: border-box !important; }
body section.wp-block-jbh-hero-section.jbh-hero-section:not(.has-background), body header.wp-block-jbh-section-header.jbh-section-header:not(.has-background), body section.wp-block-jbh-about-section.jbh-about-section:not(.has-background), body section.wp-block-jbh-insights-grid.jbh-insights-grid:not(.has-background), body div.wp-block-jbh-cta-banner.jbh-cta-banner:not(.has-background) { background-color: var(--jbh-custom-block-bg, var(--jbh-bg)) !important; }
body section.wp-block-jbh-hero-section.jbh-hero-section:not(.has-text-color), body header.wp-block-jbh-section-header.jbh-section-header:not(.has-text-color), body section.wp-block-jbh-about-section.jbh-about-section:not(.has-text-color), body section.wp-block-jbh-insights-grid.jbh-insights-grid:not(.has-text-color), body div.wp-block-jbh-cta-banner.jbh-cta-banner:not(.has-text-color) { color: var(--jbh-text-color) !important; }
body section.wp-block-jbh-hero-section.jbh-hero-section, body header.wp-block-jbh-section-header.jbh-section-header, body section.wp-block-jbh-about-section.jbh-about-section, body section.wp-block-jbh-insights-grid.jbh-insights-grid, body div.wp-block-jbh-cta-banner.jbh-cta-banner { font-family: var(--jbh-font-sans) !important; line-height: 1.6 !important; -webkit-font-smoothing: antialiased !important; -moz-osx-font-smoothing: grayscale !important; box-sizing: border-box !important; word-wrap: break-word !important; }
body section.wp-block-jbh-hero-section .jbh-hero-heading, body header.wp-block-jbh-section-header .jbh-sh-heading, body section.wp-block-jbh-about-section .jbh-about-heading, body section.wp-block-jbh-insights-grid .jbh-insight-title, body div.wp-block-jbh-cta-banner .jbh-cta-heading { font-family: var(--jbh-font-serif) !important; font-weight: 700 !important; letter-spacing: normal !important; text-transform: none !important; line-height: 1.2 !important; margin-top: 0 !important; padding: 0 !important; border: none !important; text-decoration: none !important; }
body section.wp-block-jbh-hero-section .jbh-hero-subtitle, body header.wp-block-jbh-section-header .jbh-sh-subtitle, body section.wp-block-jbh-about-section .jbh-about-bio, body section.wp-block-jbh-about-section .jbh-about-bio p, body section.wp-block-jbh-insights-grid .jbh-insight-excerpt, body div.wp-block-jbh-cta-banner .jbh-cta-subtitle { font-family: var(--jbh-font-sans) !important; line-height: 1.7 !important; text-transform: none !important; letter-spacing: normal !important; }
body section.wp-block-jbh-hero-section .jbh-hero-badge, body header.wp-block-jbh-section-header .jbh-sh-badge, body div.wp-block-jbh-cta-banner .jbh-cta-badge { text-decoration: none !important; }
body section.wp-block-jbh-hero-section .jbh-hero-btn, body div.wp-block-jbh-cta-banner .jbh-cta-btn { text-decoration: none !important; cursor: pointer !important; }
body section.wp-block-jbh-insights-grid .jbh-insight-card { background: var(--jbh-ig-card-bg, var(--jbh-card)) !important; border: 1px solid var(--jbh-ig-card-border, var(--jbh-border)) !important; border-radius: var(--jbh-card-radius) !important; }
body section.wp-block-jbh-insights-grid .jbh-insight-icon { color: var(--jbh-ig-icon-color, var(--jbh-teal)); }
body section.wp-block-jbh-insights-grid .jbh-insights-list { display: grid !important; list-style: none !important; }

/* ================================================================
   10. CUSTOM COLOR OVERRIDES
   ================================================================ */
body div.wp-block-jbh-store-grid .jbh-store-title, body div.wp-block-jbh-pricing-plans .jbh-plans-title, body div.wp-block-jbh-portfolio-grid .jbh-portfolio-title { color: var(--jbh-custom-header, var(--jbh-heading-color)) !important; }
body div.wp-block-jbh-studio-grid .jbh-card-title, body div.wp-block-jbh-store-grid .jbh-product-title, body div.wp-block-jbh-pricing-plans .jbh-plan-name, body div.wp-block-jbh-portfolio-grid .jbh-project-title { color: var(--jbh-custom-header, var(--jbh-card-heading)) !important; }
body div.wp-block-jbh-studio-grid .jbh-card-desc, body div.wp-block-jbh-store-grid .jbh-product-desc, body div.wp-block-jbh-store-grid .jbh-store-subtitle, body div.wp-block-jbh-pricing-plans .jbh-plans-subtitle, body div.wp-block-jbh-pricing-plans .jbh-plan-perks li, body div.wp-block-jbh-portfolio-grid .jbh-portfolio-subtitle, body div.wp-block-jbh-portfolio-grid .jbh-project-desc, body div.wp-block-jbh-portfolio-grid .jbh-project-deliverables li { color: var(--jbh-custom-desc, var(--jbh-text-color)) !important; }
body div.wp-block-jbh-studio-grid .jbh-card-price { color: var(--jbh-custom-price, var(--jbh-text-color)) !important; }
/* .jbh-product-price and .jbh-plan-price color overrides intentionally
   omitted here — the typography rules at the top of section 9.5 already
   set `color: var(--jbh-custom-price, ...)` on these selectors with the
   same fallback chain; declaring them again here would be a true
   duplicate. (See L3361 + L3362.) */
body div.wp-block-jbh-pricing-plans .jbh-plan-perks li::before, body div.wp-block-jbh-portfolio-grid .jbh-project-deliverables li::before { color: var(--jbh-custom-icon, var(--jbh-teal)) !important; }
body div.wp-block-jbh-store-grid .jbh-store-tag, body div.wp-block-jbh-pricing-plans .jbh-plans-tag, body div.wp-block-jbh-portfolio-grid .jbh-project-client { color: var(--jbh-custom-icon, var(--jbh-teal)) !important; }
body div.wp-block-jbh-pricing-plans .jbh-plan-btn-primary { background: var(--jbh-custom-btn, var(--jbh-coral)) !important; color: var(--jbh-custom-btn-text, #ffffff) !important; border-color: var(--jbh-custom-btn, var(--jbh-coral)) !important; transition: filter 0.2s ease, transform 0.2s ease; }
body div.wp-block-jbh-pricing-plans .jbh-plan-btn-primary:hover { background: var(--jbh-custom-btn-hover, var(--jbh-custom-btn, var(--jbh-coral))) !important; color: var(--jbh-custom-btn-hover-text, var(--jbh-custom-btn-text, #ffffff)) !important; border-color: var(--jbh-custom-btn-hover, var(--jbh-custom-btn, var(--jbh-coral))) !important; filter: brightness(1.08); transform: translateY(-1px); }
body div.wp-block-jbh-pricing-plans .jbh-plan-btn-outline { color: var(--jbh-custom-btn, var(--jbh-teal)) !important; border-color: var(--jbh-custom-btn, var(--jbh-teal)) !important; transition: background 0.2s ease, color 0.2s ease, transform 0.2s ease; }
body div.wp-block-jbh-pricing-plans .jbh-plan-btn-outline:hover { background: var(--jbh-custom-btn-hover, var(--jbh-custom-btn, var(--jbh-teal))) !important; color: var(--jbh-custom-btn-hover-text, var(--jbh-custom-btn-text, #ffffff)) !important; border-color: var(--jbh-custom-btn-hover, var(--jbh-custom-btn, var(--jbh-teal))) !important; transform: translateY(-1px); }
body div.wp-block-jbh-portfolio-grid .jbh-project-cta { color: var(--jbh-custom-btn, var(--jbh-teal)) !important; transition: color 0.2s ease; }
body div.wp-block-jbh-portfolio-grid .jbh-project-cta:hover { color: var(--jbh-custom-btn-hover, var(--jbh-custom-btn-text, var(--jbh-coral))) !important; }
body div.wp-block-jbh-studio-grid .jbh-service-card, body div.wp-block-jbh-store-grid .jbh-product-card, body div.wp-block-jbh-pricing-plans .jbh-plan-card, body div.wp-block-jbh-portfolio-grid .jbh-project-card { background: var(--jbh-custom-card-bg, var(--jbh-card)) !important; }
/* Border-colour picker — applies to every card-style preset that has a
   visible border (bordered, elevated, glass, neon, neumorphic, etc.).
   Previously scoped to `.jbh-cards-bordered` alone, which meant picking
   any other card style silently broke the "Card Border" dark / light
   pickers. The preset-agnostic selector below still respects a preset's
   `border: none` rule because border-color has no visual effect when
   border-width is 0, so the flat / minimal presets continue to render
   without an edge as designed. */
body div.wp-block-jbh-studio-grid .jbh-service-card, body div.wp-block-jbh-store-grid .jbh-product-card, body div.wp-block-jbh-pricing-plans .jbh-plan-card, body div.wp-block-jbh-portfolio-grid .jbh-project-card { border-color: var(--jbh-custom-card-border, var(--jbh-border)) !important; }
/* .jbh-plan-badge color/bg override intentionally omitted here —
   declared once at L3367 with identical values; a second copy was a
   verbatim duplicate. */
body div.wp-block-jbh-pricing-plans .jbh-highlighted { border-color: var(--jbh-custom-badge, var(--jbh-custom-badge-bg, var(--jbh-coral))) !important; }
body div.wp-block-jbh-portfolio-grid .jbh-project-tag { color: var(--jbh-custom-tag, var(--jbh-text-color)) !important; border-color: var(--jbh-custom-tag, var(--jbh-teal-dark)) !important; }

/* ── Override-Theme Class ─────────────────────────────────────── */
.jbh-override-theme.jbh-dark { --jbh-bg: #121212; --jbh-card: #1A1A1A; --jbh-heading-color: #F0EAD6; --jbh-text-color: #9CA3AF; --jbh-card-heading: #ffffff; --jbh-border: rgba(31, 95, 91, 0.20); }
.jbh-override-theme.jbh-light { --jbh-bg: #F9F8F6; --jbh-card: #FFFFFF; --jbh-heading-color: #121212; --jbh-text-color: #4B5563; --jbh-card-heading: #121212; --jbh-border: rgba(0, 0, 0, 0.08); }

/* ================================================================
   11. RESPONSIVE
   ================================================================ */
@media (max-width: 1024px) {
	.jbh-service-grid, .jbh-product-grid { grid-template-columns: repeat(2, 1fr) !important; }
	.jbh-plans-grid { grid-template-columns: repeat(2, 1fr) !important; }
}
@media (max-width: 768px) {
	.jbh-service-grid, .jbh-product-grid, .jbh-plans-grid, .jbh-project-list { grid-template-columns: 1fr !important; }
	.jbh-studio-grid, .jbh-store-grid, .jbh-pricing-plans, .jbh-portfolio-grid, .jbh-insights-grid { padding-left: 16px; padding-right: 16px; }
	.jbh-insights-list { grid-template-columns: 1fr !important; }
	.jbh-layout-list .jbh-service-card, .jbh-layout-list .jbh-product-card { flex-direction: column; gap: 0; }
	/* About-grid stack rule lives in its own 900px breakpoint now — see
	   the About-section responsive block further down. The old 768px
	   rule was leaving common portrait-tablet widths (iPad Air 820px,
	   iPad Pro 11" 834px) in the cramped 2-col layout; raising the
	   stack point to 900px covers every portrait tablet while still
	   giving landscape tablets (≥1024px) the full 2-col grid. */
}
@media (max-width: 600px) {
	.jbh-hero-section { padding: 48px 16px 40px; }
	.jbh-hero-heading { font-size: 32px; }
	.jbh-hero-btn { padding: 12px 20px; font-size: 14px; }
	.jbh-about-grid { gap: 24px; }
	/* `.jbh-about-contact-sidebar { position: static; }` moved to the
	   900px breakpoint in the About-section responsive block (the
	   stacking and sticky-drop now happen together at the same cut). */
	.jbh-insight-card { flex-direction: column; }
	.jbh-insights-horizontal .jbh-insight-icon { margin: 16px 0 0 16px; }
	.jbh-insights-horizontal .jbh-insight-image-wrap { width: 100%; min-width: 0; }
	.jbh-cta-banner { padding: 28px 16px; }
}

/* ================================================================
   12. ACCESSIBILITY
   ================================================================ */
.jbh-service-card:focus-within, .jbh-product-card:focus-within, .jbh-plan-card:focus-within, .jbh-project-card:focus-within, .jbh-insight-card:focus-within { outline: 2px solid var(--jbh-teal); outline-offset: 2px; }
.jbh-get-started-btn:focus-visible, .jbh-product-btn:focus-visible, .jbh-plan-btn:focus-visible, .jbh-project-cta:focus-visible, .jbh-hero-btn:focus-visible, .jbh-cta-btn:focus-visible { outline: 2px solid var(--jbh-teal); outline-offset: 2px; }
@media (prefers-reduced-motion: reduce) {
	[data-jbh-animate] { opacity: 1 !important; transform: none !important; transition: none !important; }
	[data-jbh-animate].jbh-animated .jbh-service-card, [data-jbh-animate].jbh-animated .jbh-product-card, [data-jbh-animate].jbh-animated .jbh-plan-card, [data-jbh-animate].jbh-animated .jbh-project-card, [data-jbh-animate].jbh-animated .jbh-insight-card { animation: none !important; opacity: 1; }
	.jbh-service-card, .jbh-product-card, .jbh-plan-card, .jbh-project-card, .jbh-insight-card { transition: none !important; }
	.jbh-pulse-dot { animation: none !important; }
	.jbh-plan-card.jbh-highlighted { transform: none !important; animation: none !important; }
	html.jbh-smooth-scroll { scroll-behavior: auto !important; }
	.jbh-plan-card.jbh-highlighted .jbh-plan-badge { animation: none; }
	.jbh-badge-dot .jbh-product-badge::before, .jbh-badge-dot .jbh-plan-badge::before, .jbh-badge-dot .jbh-hero-badge::before, .jbh-badge-dot .jbh-sh-badge::before, .jbh-badge-dot .jbh-cta-badge::before { animation: none; }
}
@media (prefers-contrast: high) {
	.jbh-service-card, .jbh-product-card, .jbh-plan-card, .jbh-project-card, .jbh-insight-card { border: 2px solid currentColor !important; }
}

/* ================================================================
   SKELETON / FAILSAFE
   ================================================================ */
@keyframes jbhShimmer { 0% { background-position: -400px 0; } 100% { background-position: 400px 0; } }
body:not(.editor-styles-wrapper):not(.block-editor-page) [data-jbh-animate]:not(.jbh-animated) .jbh-service-card, body:not(.editor-styles-wrapper):not(.block-editor-page) [data-jbh-animate]:not(.jbh-animated) .jbh-product-card, body:not(.editor-styles-wrapper):not(.block-editor-page) [data-jbh-animate]:not(.jbh-animated) .jbh-plan-card, body:not(.editor-styles-wrapper):not(.block-editor-page) [data-jbh-animate]:not(.jbh-animated) .jbh-project-card, body:not(.editor-styles-wrapper):not(.block-editor-page) [data-jbh-animate]:not(.jbh-animated) .jbh-insight-card { opacity: 0; }
@keyframes jbh-no-js-reveal { to { opacity: 1 !important; transform: none !important; } }
body:not(.editor-styles-wrapper):not(.block-editor-page) [data-jbh-animate]:not(.jbh-animated) { animation: jbh-no-js-reveal 0s 4s forwards; }
body:not(.editor-styles-wrapper):not(.block-editor-page) [data-jbh-animate]:not(.jbh-animated) .jbh-service-card, body:not(.editor-styles-wrapper):not(.block-editor-page) [data-jbh-animate]:not(.jbh-animated) .jbh-product-card, body:not(.editor-styles-wrapper):not(.block-editor-page) [data-jbh-animate]:not(.jbh-animated) .jbh-plan-card, body:not(.editor-styles-wrapper):not(.block-editor-page) [data-jbh-animate]:not(.jbh-animated) .jbh-project-card, body:not(.editor-styles-wrapper):not(.block-editor-page) [data-jbh-animate]:not(.jbh-animated) .jbh-insight-card { animation: jbh-no-js-reveal 0s 4s forwards; }
.jbh-skeleton { background: linear-gradient(90deg, var(--jbh-card) 25%, rgba(255,255,255,0.06) 50%, var(--jbh-card) 75%); background-size: 800px 100%; animation: jbhShimmer 1.6s ease-in-out infinite; border-radius: var(--jbh-card-radius); min-height: 180px; }
.jbh-light .jbh-skeleton,
html[data-theme="light"] .jbh-skeleton,
html.light .jbh-skeleton,
html[data-color-mode="light"] .jbh-skeleton { background: linear-gradient(90deg, #f0f0ee 25%, #ffffff 50%, #f0f0ee 75%); background-size: 800px 100%; }

/* ================================================================
   MAX-WIDTH / DEFAULT HOVER / SMOOTH SCROLL / TAP HIGHLIGHT
   ================================================================ */
.jbh-studio-grid:not(.alignwide):not(.alignfull):not(.jbh-overflow-container), .jbh-store-grid:not(.alignwide):not(.alignfull), .jbh-pricing-plans:not(.alignwide):not(.alignfull), .jbh-portfolio-grid:not(.alignwide):not(.alignfull), .jbh-insights-grid:not(.alignwide):not(.alignfull), .jbh-cta-banner:not(.alignwide):not(.alignfull) { max-width: 1280px; margin-left: auto; margin-right: auto; }
.jbh-product-card:hover, .jbh-project-card:hover, .jbh-insight-card:hover { transform: translateY(-2px); box-shadow: 0 8px 24px rgba(0,0,0,0.18); transition: transform 0.25s ease, box-shadow 0.25s ease; }
.jbh-light .jbh-product-card:hover, .jbh-light .jbh-project-card:hover, .jbh-light .jbh-insight-card:hover,
html[data-theme="light"] .jbh-product-card:hover, html[data-theme="light"] .jbh-project-card:hover, html[data-theme="light"] .jbh-insight-card:hover,
html.light .jbh-product-card:hover, html.light .jbh-project-card:hover, html.light .jbh-insight-card:hover { box-shadow: 0 8px 24px rgba(0,0,0,0.08); }
html.jbh-smooth-scroll { scroll-behavior: smooth; }
.jbh-studio-grid, .jbh-store-grid, .jbh-pricing-plans, .jbh-portfolio-grid, .jbh-hero-section, .jbh-section-header, .jbh-about-section, .jbh-insights-grid, .jbh-cta-banner { -webkit-tap-highlight-color: transparent; }

/* ================================================================
   PROTOTYPE EFFECTS
   ================================================================ */
.jbh-btn-filled .jbh-get-started-btn, .jbh-btn-filled .jbh-product-btn, .jbh-btn-filled .jbh-plan-btn, .jbh-btn-filled .jbh-project-cta { box-shadow: 0 4px 14px 0 rgba(214,79,66,0.39); }
.jbh-btn-filled .jbh-get-started-btn:hover, .jbh-btn-filled .jbh-product-btn:hover, .jbh-btn-filled .jbh-plan-btn:hover, .jbh-btn-filled .jbh-project-cta:hover { box-shadow: 0 6px 20px 0 rgba(214,79,66,0.50); }
.jbh-btn-outline .jbh-get-started-btn:hover, .jbh-btn-outline .jbh-product-btn:hover, .jbh-btn-outline .jbh-plan-btn:hover, .jbh-btn-outline .jbh-project-cta:hover { box-shadow: 0 4px 14px 0 rgba(42,157,143,0.30); }
.jbh-service-card:hover .jbh-card-title, .jbh-product-card:hover .jbh-product-title, .jbh-plan-card:hover .jbh-plan-name, .jbh-project-card:hover .jbh-project-title, .jbh-insight-card:hover .jbh-insight-title { color: var(--jbh-custom-icon, var(--jbh-teal)); transition: color 0.2s ease; }
@keyframes jbh-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.5; } }
.jbh-pulse-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--jbh-teal); display: inline-block; animation: jbh-pulse 3s cubic-bezier(0.4, 0, 0.6, 1) infinite; }
.jbh-light .jbh-service-card, .jbh-light .jbh-product-card, .jbh-light .jbh-plan-card, .jbh-light .jbh-project-card, .jbh-light .jbh-insight-card,
html[data-theme="light"] .jbh-service-card, html[data-theme="light"] .jbh-product-card, html[data-theme="light"] .jbh-plan-card, html[data-theme="light"] .jbh-project-card, html[data-theme="light"] .jbh-insight-card,
html.light .jbh-service-card, html.light .jbh-product-card, html.light .jbh-plan-card, html.light .jbh-project-card, html.light .jbh-insight-card { box-shadow: 0 4px 24px rgba(0,0,0,0.04); }
.jbh-light .jbh-service-card:hover, .jbh-light .jbh-product-card:hover, .jbh-light .jbh-plan-card:hover, .jbh-light .jbh-project-card:hover, .jbh-light .jbh-insight-card:hover,
html[data-theme="light"] .jbh-service-card:hover, html[data-theme="light"] .jbh-product-card:hover, html[data-theme="light"] .jbh-plan-card:hover, html[data-theme="light"] .jbh-project-card:hover, html[data-theme="light"] .jbh-insight-card:hover,
html.light .jbh-service-card:hover, html.light .jbh-product-card:hover, html.light .jbh-plan-card:hover, html.light .jbh-project-card:hover, html.light .jbh-insight-card:hover { box-shadow: 0 12px 40px rgba(0,0,0,0.08); }
.jbh-dark .jbh-service-card, .jbh-dark .jbh-product-card, .jbh-dark .jbh-plan-card, .jbh-dark .jbh-project-card, .jbh-dark .jbh-insight-card { box-shadow: 0 4px 24px rgba(0,0,0,0.20); }
.jbh-dark .jbh-service-card:hover, .jbh-dark .jbh-product-card:hover, .jbh-dark .jbh-plan-card:hover, .jbh-dark .jbh-project-card:hover, .jbh-dark .jbh-insight-card:hover { box-shadow: 0 12px 40px rgba(0,0,0,0.35); }
.jbh-get-started-btn svg, .jbh-product-btn svg, .jbh-plan-btn svg, .jbh-project-cta svg { transition: transform 0.2s ease; }
.jbh-get-started-btn:hover svg, .jbh-product-btn:hover svg, .jbh-plan-btn:hover svg, .jbh-project-cta:hover svg { transform: translateX(3px); }
@keyframes jbh-float { 0%, 100% { transform: scale(1.03) translateY(0); } 50% { transform: scale(1.03) translateY(-8px); } }
.jbh-plan-card.jbh-highlighted { transform: scale(1.03); z-index: 2; animation: jbh-float 3.5s ease-in-out infinite; }
.jbh-plan-card.jbh-highlighted:hover { animation-play-state: paused; transform: scale(1.05) translateY(-4px); }
/* Dead rules removed — `.jbh-pricing-toggle-track` was never emitted
   (the billing toggle uses a `::after` pseudo-element, not a sibling
   element). The actual toggle dot is styled at line 842 and now
   honours the --jbh-custom-toggle-dot picker. */

/* ================================================================
   PREMIUM POLISH
   ================================================================ */
.jbh-gradient-text { background: linear-gradient(135deg, var(--jbh-teal), var(--jbh-coral)); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; }
.jbh-service-card:focus-visible, .jbh-product-card:focus-visible, .jbh-plan-card:focus-visible, .jbh-project-card:focus-visible, .jbh-insight-card:focus-visible { outline: 2px solid var(--jbh-teal); outline-offset: 3px; border-radius: inherit; }
.jbh-studio-grid .jbh-get-started-btn:focus-visible, .jbh-store-grid .jbh-product-btn:focus-visible, .jbh-pricing-plans .jbh-plan-btn:focus-visible, .jbh-portfolio-grid .jbh-project-cta:focus-visible, .jbh-cta-banner .jbh-cta-btn:focus-visible { outline: 2px solid var(--jbh-teal); outline-offset: 2px; box-shadow: 0 0 0 4px rgba(42,157,143,0.18); }
.jbh-store-title, .jbh-plans-title, .jbh-portfolio-title { letter-spacing: -0.02em; line-height: 1.15; }
.jbh-store-subtitle, .jbh-plans-subtitle, .jbh-portfolio-subtitle { letter-spacing: 0.01em; line-height: 1.6; max-width: 640px; }
.jbh-card-footer, .jbh-product-btn, .jbh-plan-btn { margin-top: auto; }
@keyframes jbh-badge-shimmer { 0% { background-position: -200% center; } 100% { background-position: 200% center; } }
/* Shimmer gradient — active when the block does NOT carry .jbh-badge-no-gradient
   AND the badge style is not outline. Respects custom text colour. */
body .jbh-pricing-plans:not(.jbh-badge-no-gradient):not(.jbh-badge-outline) .jbh-plan-card.jbh-highlighted .jbh-plan-badge { background: linear-gradient(90deg, var(--jbh-teal) 0%, var(--jbh-coral) 50%, var(--jbh-teal) 100%) !important; background-size: 200% auto; animation: jbh-badge-shimmer 3s linear infinite; color: var(--jbh-custom-badge-text, #fff) !important; font-weight: 600; box-shadow: 0 4px 14px rgba(0,0,0,0.25); }
/* Gradient OFF + not outline — solid bg respecting custom colours */
body .jbh-pricing-plans.jbh-badge-no-gradient:not(.jbh-badge-outline) .jbh-plan-card.jbh-highlighted .jbh-plan-badge { background: var(--jbh-custom-badge-bg, var(--jbh-coral)) !important; color: var(--jbh-custom-badge-text, #fff) !important; animation: none; }
/* Outline — always wins, removes fill and shimmer regardless of gradient toggle */
body .jbh-pricing-plans.jbh-badge-outline .jbh-plan-card.jbh-highlighted .jbh-plan-badge { background: transparent !important; border: 2px solid var(--jbh-custom-badge-bg, var(--jbh-coral)); color: var(--jbh-custom-badge-text, var(--jbh-custom-badge-bg, var(--jbh-coral))) !important; animation: none; box-shadow: none; }
/* Solid — explicit solid fill, overrides shimmer when both are set */
body .jbh-pricing-plans.jbh-badge-solid .jbh-plan-card.jbh-highlighted .jbh-plan-badge { background: var(--jbh-custom-badge-bg, var(--jbh-coral)) !important; color: var(--jbh-custom-badge-text, #fff) !important; animation: none; }
.jbh-studio-grid .jbh-get-started-btn:active, .jbh-store-grid .jbh-product-btn:active, .jbh-pricing-plans .jbh-plan-btn:active, .jbh-portfolio-grid .jbh-project-cta:active { transform: scale(0.97); transition-duration: 0.08s; }
.jbh-cards-neon .jbh-service-card:focus-within, .jbh-cards-neon .jbh-product-card:focus-within, .jbh-cards-neon .jbh-plan-card:focus-within, .jbh-cards-neon .jbh-project-card:focus-within, .jbh-cards-neon .jbh-insight-card:focus-within { box-shadow: 0 0 20px rgba(42,157,143,0.35), 0 0 60px rgba(42,157,143,0.10); }
.jbh-cards-glass .jbh-service-card:hover, .jbh-cards-glass .jbh-product-card:hover, .jbh-cards-glass .jbh-plan-card:hover, .jbh-cards-glass .jbh-project-card:hover, .jbh-cards-glass .jbh-insight-card:hover { box-shadow: inset 0 0 30px rgba(42,157,143,0.05), 0 8px 32px rgba(0,0,0,0.15); }
.jbh-get-started-btn, .jbh-product-btn, .jbh-plan-btn, .jbh-project-cta, .jbh-hero-btn, .jbh-cta-btn { position: relative; overflow: hidden; }
.jbh-get-started-btn::after, .jbh-product-btn::after, .jbh-plan-btn::after, .jbh-project-cta::after, .jbh-hero-btn::after, .jbh-cta-btn::after { content: ''; position: absolute; top: 50%; left: 50%; width: 0; height: 0; border-radius: 50%; background: rgba(255,255,255,0.25); transform: translate(-50%, -50%); transition: width 0.5s ease, height 0.5s ease, opacity 0.5s ease; opacity: 0; pointer-events: none; }
.jbh-get-started-btn:active::after, .jbh-product-btn:active::after, .jbh-plan-btn:active::after, .jbh-project-cta:active::after, .jbh-hero-btn:active::after, .jbh-cta-btn:active::after { width: 300px; height: 300px; opacity: 1; transition: width 0s, height 0s, opacity 0s; }
@media (prefers-reduced-motion: reduce) {
	.jbh-get-started-btn::after, .jbh-product-btn::after, .jbh-plan-btn::after, .jbh-project-cta::after, .jbh-hero-btn::after, .jbh-cta-btn::after { display: none; }
	.jbh-studio-grid .jbh-get-started-btn:active, .jbh-store-grid .jbh-product-btn:active, .jbh-pricing-plans .jbh-plan-btn:active, .jbh-portfolio-grid .jbh-project-cta:active { transform: none; }
}

/* ================================================================
   13. HERO SECTION BLOCK
   ================================================================ */
.jbh-hero-section { padding: 80px 24px 60px; text-align: center; position: relative; overflow: hidden; background: var(--jbh-custom-block-bg, var(--jbh-bg)); }
.jbh-hero-section.jbh-hero-align-left { text-align: left; }
.jbh-hero-inner { max-width: var(--jbh-hero-max-w, 800px); margin: 0 auto; position: relative; z-index: 2; }
.jbh-hero-align-left .jbh-hero-inner { margin: 0; }
.jbh-hero-badge { display: inline-flex; align-items: center; gap: 8px; padding: 6px 16px; border-radius: 999px; font-size: 11px; font-family: var(--jbh-font-mono); text-transform: uppercase; letter-spacing: 0.1em; margin-bottom: 24px; border: 1px solid var(--jbh-border); background: var(--jbh-custom-badge-bg, var(--jbh-card)); color: var(--jbh-hero-badge-color, var(--jbh-creme)); }
.jbh-hero-heading { font-family: var(--jbh-font-serif); font-size: clamp(36px, 6vw, 64px); font-weight: 700; line-height: 1.08; margin: 0 0 20px; color: var(--jbh-hero-heading-color, var(--jbh-card-heading)); }
.jbh-hero-heading-small .jbh-hero-heading { font-size: clamp(24px, 4vw, 36px); }
.jbh-hero-heading-medium .jbh-hero-heading { font-size: clamp(30px, 5vw, 48px); }
.jbh-hero-heading-large .jbh-hero-heading { font-size: clamp(36px, 6vw, 64px); }
.jbh-hero-heading-xlarge .jbh-hero-heading { font-size: clamp(42px, 7vw, 80px); }
.jbh-hero-heading em { font-style: italic; font-weight: 500; }
/* Light-mode override for <em> inside the hero heading.
   ─────────────────────────────────────────────────────────────────
   Previously this rule fired on ANY site-wide light-mode signal
   regardless of the block's own colour mode, which meant a user
   who explicitly set the block to `.jbh-dark` (and even locked it
   with Override Theme) still had their heading em text forced to
   the LIGHT variant whenever the SITE was in light mode — the
   exact "Heading Line 2 uses the light-mode colour in dark mode"
   symptom reported by users running on Blocksy / theme-toggle
   setups.

   Fix: tighten the selectors so the rule only fires when the
   block itself is effectively in light mode:
     1. `.jbh-hero-section.jbh-light` → explicit light block mode,
        always applies.
     2. `[site-light-signal] .jbh-hero-section:not(.jbh-override-theme)`
        → the block follows site mode (no override) AND the site
        currently signals light mode. This matches the "STANDARD"
        pattern used by the base-palette rules at lines 1183-1188
        so the two cascades stay in lock-step.
     3. Media-query branch: same principle for OS-level prefers-
        color-scheme when no explicit site toggle is present.

   Explicit `.jbh-dark` or `.jbh-override-theme` blocks are now
   NEVER overridden by a site-wide light signal — the user's dark
   customisation (`--jbh-hero-heading2-dk` inline) wins every time.
   Also adds symmetric follow-site-signal selectors (`html.light`
   and `[data-color-mode="light"]`) that were missing from the
   original rule but documented elsewhere in this file. */
.jbh-hero-section.jbh-light .jbh-hero-heading em,
html[data-theme="light"] .jbh-hero-section:not(.jbh-override-theme) .jbh-hero-heading em,
html.light .jbh-hero-section:not(.jbh-override-theme) .jbh-hero-heading em,
html[data-color-mode="light"] .jbh-hero-section:not(.jbh-override-theme) .jbh-hero-heading em,
body[data-ct-color-mode="light"] .jbh-hero-section:not(.jbh-override-theme) .jbh-hero-heading em {
	color: var(--jbh-hero-heading2-lt, #000000) !important;
}
@media (prefers-color-scheme: light) {
	html:not([data-theme]):not(.dark):not(.light):not([data-color-mode]) .jbh-hero-section:not(.jbh-override-theme) .jbh-hero-heading em {
		color: var(--jbh-hero-heading2-lt, #000000) !important;
	}
}
.jbh-hero-heading-line2 { color: var(--jbh-hero-heading2-color, var(--jbh-hero-heading-color, var(--jbh-card-heading))); }
/* Heading Line 2 — explicit-mode lock against site-cascade override.
   ─────────────────────────────────────────────────────────────────
   The mega-cascade at L1183-1297 ("STANDARD: SITE LIGHT → blocks
   LIGHT") sets `--jbh-hero-heading2-color: var(--jbh-hero-heading2-lt)`
   on EVERY `.jbh-dark`, `.jbh-light`, `.jbh-auto` block (without
   `.jbh-override-theme`) when the SITE is in light mode — overriding
   the block's own colour-mode choice. That's correct for `.jbh-auto`
   blocks (which should follow site) but WRONG for blocks the user
   explicitly set to a fixed mode via the colorMode dropdown.

   Symptom: a Hero block set to `.jbh-dark` with a custom Dark-Mode
   "Heading Line 2 Color" rendered the LIGHT colour on the frontend
   when the site was light (editor showed correct colour because the
   editor doesn't render the site cascade). On page load users saw
   a brief flash of the dark colour (block-level rule applies first)
   before the higher-specificity site cascade replaced it.

   Fix: read the dk/lt variant DIRECTLY on the line2 element under
   the explicit `.jbh-dark` / `.jbh-light` block-mode classes. These
   rules have specificity 0,3,0 — higher than the L3656 default rule
   (0,1,0) — and bypass the `--jbh-hero-heading2-color` variable
   indirection that the site cascade hijacks. `.jbh-auto` blocks have
   no override here, so they continue to follow the site cascade as
   designed. */
.jbh-hero-section.jbh-dark .jbh-hero-heading-line2 {
	color: var(--jbh-hero-heading2-dk, var(--jbh-hero-heading-dk, var(--jbh-card-heading)));
}
.jbh-hero-section.jbh-light .jbh-hero-heading-line2 {
	color: var(--jbh-hero-heading2-lt, var(--jbh-hero-heading-lt, var(--jbh-card-heading)));
}
.jbh-hero-subtitle { font-family: var(--jbh-font-sans); font-size: 16px; line-height: 1.8; font-weight: 300; max-width: 640px; margin: 0 auto 36px; color: var(--jbh-hero-subtitle-color, var(--jbh-slate)); }
.jbh-hero-align-left .jbh-hero-subtitle { margin-left: 0; }
.jbh-hero-buttons { display: flex; gap: 16px; justify-content: center; flex-wrap: wrap; }
.jbh-hero-align-left .jbh-hero-buttons { justify-content: flex-start; }
.jbh-hero-btn { display: inline-flex; align-items: center; padding: 14px 28px; font-family: var(--jbh-font-serif); font-weight: 700; font-size: 15px; border-radius: var(--jbh-card-radius); text-decoration: none; transition: all var(--jbh-transition); cursor: pointer; }
.jbh-hero-btn-primary { background: var(--jbh-hero-btn-bg, var(--jbh-coral)); color: var(--jbh-hero-btn-text, #fff); box-shadow: 0 4px 14px rgba(214,79,66,0.39); }
.jbh-hero-btn-primary:hover { background: var(--jbh-hero-btn-hover-bg, var(--jbh-hero-btn-bg, var(--jbh-coral))); color: var(--jbh-hero-btn-hover-text, var(--jbh-hero-btn-text, #fff)); box-shadow: 0 6px 20px rgba(214,79,66,0.55); transform: translateY(-1px); }
.jbh-hero-btn-secondary { border: 1px solid var(--jbh-hero-sec-btn-bg, var(--jbh-border)); background: var(--jbh-hero-sec-btn-bg, var(--jbh-card)); color: var(--jbh-hero-sec-btn-text, var(--jbh-creme)); }
.jbh-hero-btn-secondary:hover { border-color: var(--jbh-hero-sec-btn-text, var(--jbh-teal)); color: var(--jbh-hero-sec-btn-text, var(--jbh-teal)); }
.jbh-hero-gradient-bridge { position: absolute; bottom: 0; left: 0; right: 0; height: 120px; background: linear-gradient(to bottom, transparent, var(--jbh-bg)); z-index: 1; pointer-events: none; }

/* ── Hero Feature Cards (optional row below the hero) ── */
.jbh-hero-features { max-width: 1120px; margin: 0 auto; padding: 80px 24px 40px; position: relative; z-index: 2; }
.jbh-hero-features-header { margin-bottom: 40px; text-align: center; }
.jbh-hero-features-eyebrow { display: inline-block; font-family: var(--jbh-font-mono); font-size: 12px; font-weight: 700; letter-spacing: 0.2em; text-transform: uppercase; color: var(--jbh-hero-feat-eyebrow, var(--jbh-coral)); margin-bottom: 12px; }
.jbh-hero-features-heading { font-family: var(--jbh-font-serif); font-size: clamp(1.75rem, 3.5vw, 2.5rem); font-weight: 700; color: var(--jbh-hero-feat-heading, var(--jbh-heading-color)); margin: 0; line-height: 1.2; }
.jbh-hero-features-grid { display: grid; gap: 32px; grid-template-columns: repeat(3, 1fr); }
.jbh-hero-feature-card { background: var(--jbh-hero-feat-card-bg, var(--jbh-card)); border-radius: var(--jbh-card-radius); padding: 40px; box-shadow: 0 4px 24px rgba(0,0,0,0.06); transition: box-shadow var(--jbh-transition), transform var(--jbh-transition); }
.jbh-hero-feature-card:hover { box-shadow: 0 12px 40px rgba(0,0,0,0.14); transform: translateY(-4px); }
.jbh-hero-feature-icon { width: 48px; height: 48px; display: flex; align-items: center; justify-content: center; background: var(--jbh-bg); border: 1px solid rgba(42,157,143,0.20); border-radius: var(--jbh-card-radius); color: var(--jbh-hero-feat-icon, var(--jbh-teal)); margin-bottom: 24px; transition: background-color var(--jbh-transition), color var(--jbh-transition); }
.jbh-hero-feature-icon svg { width: 24px; height: 24px; }
.jbh-hero-feature-card:hover .jbh-hero-feature-icon { background: var(--jbh-custom-icon, var(--jbh-teal)); color: var(--jbh-custom-btn-text, #fff); border-color: var(--jbh-custom-icon, var(--jbh-teal)); }
.jbh-hero-feature-title { font-family: var(--jbh-font-serif); font-size: 22px; font-weight: 700; color: var(--jbh-hero-feat-heading, var(--jbh-card-heading)); margin: 0 0 12px; line-height: 1.3; }
.jbh-hero-feature-desc { color: var(--jbh-hero-feat-desc, var(--jbh-text-color)); font-size: 14px; line-height: 1.7; font-weight: 300; margin: 0; }
@media (max-width: 900px) {
	.jbh-hero-features-grid { grid-template-columns: 1fr; }
	.jbh-hero-features { padding: 40px 20px 20px; }
}

/* ================================================================
   14. SECTION HEADER BLOCK
   ================================================================ */
.jbh-section-header { padding: 12px 0 28px; background: var(--jbh-custom-block-bg, transparent); }
.jbh-section-header.jbh-sh-align-center { text-align: center; }
.jbh-sh-badge { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; font-family: var(--jbh-font-mono); text-transform: uppercase; letter-spacing: 0.1em; font-weight: 700; padding-bottom: 6px; border-bottom: 2px solid currentColor; margin-bottom: 16px; color: var(--jbh-sh-badge-color, inherit); }
.jbh-sh-badge-coral { color: var(--jbh-sh-badge-color, var(--jbh-coral)); }
.jbh-sh-badge-teal { color: var(--jbh-sh-badge-color, var(--jbh-teal)); }
.jbh-sh-badge-muted { color: var(--jbh-sh-badge-color, var(--jbh-slate)); }
.jbh-sh-heading { font-family: var(--jbh-sh-heading-font, var(--jbh-font-serif)); font-weight: 700; margin: 0 0 10px; line-height: 1.15; color: var(--jbh-sh-heading-color, var(--jbh-card-heading)); }
.jbh-sh-large { font-size: clamp(36px, 5vw, 56px); }
.jbh-sh-medium { font-size: clamp(28px, 4vw, 42px); }
.jbh-sh-small { font-size: clamp(22px, 3vw, 32px); }
.jbh-sh-subtitle { font-family: var(--jbh-sh-subtitle-font, var(--jbh-font-sans)); font-size: 16px; line-height: 1.8; font-weight: 300; max-width: var(--jbh-sh-subtitle-max-w, 640px); margin: 0; color: var(--jbh-sh-subtitle-color, var(--jbh-slate)); }
.jbh-sh-align-center .jbh-sh-subtitle { margin: 0 auto; }

/* ================================================================
   14b. PAGE INTRO BLOCK
   ================================================================ */
.jbh-page-intro { padding: 12px 0 32px; max-width: 900px; background: var(--jbh-custom-block-bg, transparent); }
.jbh-page-intro.jbh-pi-align-center { text-align: center; }
.jbh-pi-label { display: inline-flex; align-items: center; gap: 6px; font-size: 13px; font-family: var(--jbh-font-mono); text-transform: uppercase; letter-spacing: 0.1em; font-weight: 700; padding-bottom: 6px; border-bottom: 2px solid currentColor; margin-bottom: 16px; color: var(--jbh-pi-label-color, inherit); }
.jbh-pi-label-coral { color: var(--jbh-pi-label-color, var(--jbh-coral)); }
.jbh-pi-label-teal  { color: var(--jbh-pi-label-color, var(--jbh-teal)); }
.jbh-pi-label-muted { color: var(--jbh-pi-label-color, var(--jbh-slate)); }
.jbh-pi-heading { font-family: var(--jbh-font-serif); font-weight: 700; margin: 0 0 16px; line-height: 1.1; color: var(--jbh-pi-heading-color, var(--jbh-card-heading)); }
.jbh-pi-xl     { font-size: clamp(40px, 6vw, 72px); }
.jbh-pi-large  { font-size: clamp(36px, 5vw, 56px); }
.jbh-pi-medium { font-size: clamp(28px, 4vw, 42px); }
.jbh-pi-subtitle { font-family: var(--jbh-font-sans); font-size: 16px; line-height: 1.8; font-weight: 300; max-width: 640px; margin: 0 0 24px; color: var(--jbh-pi-subtitle-color, var(--jbh-slate)); }
.jbh-pi-align-center .jbh-pi-subtitle { margin-left: auto; margin-right: auto; margin-bottom: 24px; }
.jbh-pi-callout { background: var(--jbh-card); border-left: 4px solid var(--jbh-pi-callout-border, var(--jbh-teal)); padding: 24px 28px; border-radius: 0 var(--jbh-card-radius) var(--jbh-card-radius) 0; box-shadow: 0 4px 12px rgba(0,0,0,0.08); margin-bottom: 8px; }
.jbh-pi-callout-text { font-size: 16px; line-height: 1.7; font-weight: 300; margin: 0 0 16px; color: var(--jbh-pi-callout-text-color, var(--jbh-creme)); }
.jbh-pi-callout-text:last-child { margin-bottom: 0; }
.jbh-pi-status { display: inline-flex; align-items: center; gap: 8px; font-size: 13px; font-family: var(--jbh-font-mono); color: var(--jbh-pi-status-text-color, var(--jbh-teal)); background: rgba(42,157,143,0.10); padding: 8px 14px; border-radius: 8px; margin-top: 4px; }
.jbh-pi-status-dot { width: 8px; height: 8px; border-radius: 50%; background: currentColor; flex-shrink: 0; animation: jbh-dot-pulse 2s ease-in-out infinite; }
@media (max-width: 640px) {
	.jbh-pi-callout { padding: 16px 20px; }
	.jbh-pi-status { font-size: 11px; padding: 6px 10px; }
}

/* ================================================================
   15. ABOUT SECTION BLOCK
   ================================================================ */
/* Outer section padding — previously `padding: 0` which made the
   block render flush to the viewport edges on mobile (text and
   cards touched the screen sides with no horizontal breathing
   room) and flush to preceding/following blocks vertically (no
   rhythm between About and its neighbour sections). The new
   defaults match the pattern every other section-level block in
   this plugin uses (hero: 80/24/60, studio-grid: 60/24, insights-
   grid: 60/24, cta-banner: 80/24, section-header: 60/24), so the
   About Section now participates in the same vertical rhythm. The
   responsive breakpoints below progressively tighten the padding
   on narrower viewports while preserving the minimum 16px
   horizontal gutter that keeps text off the screen edge on every
   phone down to 320px-wide devices. */
.jbh-about-section { padding: 60px 24px; color: var(--jbh-slate); background: var(--jbh-custom-block-bg, transparent); }
.jbh-about-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 48px; max-width: 1200px; margin: 0 auto; }
.jbh-about-label { color: var(--jbh-about-label-color, var(--jbh-teal)); font-family: var(--jbh-font-mono); font-size: 12px; text-transform: uppercase; letter-spacing: 0.1em; margin-bottom: 12px; }
.jbh-about-heading { font-family: var(--jbh-font-serif); font-size: clamp(32px, 4vw, 48px); font-weight: 700; line-height: 1.12; margin: 0 0 28px; color: var(--jbh-about-heading-color, var(--jbh-card-heading)); }
/* About heading <em> — the "highlight" half of the heading split
   rendered as `<?php echo $h_before; ?><br/><em><?php echo $h_hl; ?></em>`
   in render.php. Previously hardcoded to `var(--jbh-creme)` which
   meant (a) user-picked About heading colours did NOT cascade down
   to the em, producing split-coloured headings where the first
   half respected customisation and the emphasised half ignored it;
   and (b) on light-mode sites, `--jbh-creme` resolves to `#121212`
   (dark) which is correct, but the em didn't respect the user's
   explicit Light/Dark About Heading Color pickers either.
   Fix: inherit from the parent `.jbh-about-heading` via `color:
   inherit`. The parent already resolves to the mode-aware
   `--jbh-about-heading-color` which correctly flips between
   `-dk` and `-lt` variants via the same cascade used by every
   other customised text element in the plugin. No new variable
   needed, no regression for users who relied on the default
   creme-on-dark look (their default `--jbh-about-heading-color`
   falls back to `var(--jbh-card-heading)` which equals `#ffffff`
   on dark and `#121212` on light — identical to the old creme
   behaviour). */
.jbh-about-heading em { font-style: italic; font-weight: 500; color: inherit; }
.jbh-about-founder-card { padding: 28px; border-radius: var(--jbh-card-radius); margin-bottom: 28px; background: var(--jbh-about-card-bg, var(--jbh-card)); border: 1px solid var(--jbh-border); }
.jbh-about-founder-name { font-family: var(--jbh-font-serif); font-size: 20px; font-weight: 700; margin: 0 0 4px; color: var(--jbh-card-heading); }
.jbh-about-founder-title { color: var(--jbh-coral); font-family: var(--jbh-font-mono); font-size: 11px; text-transform: uppercase; letter-spacing: 0.1em; margin: 0 0 12px; }
.jbh-about-founder-skills p { font-size: 13px; line-height: 1.8; margin: 2px 0; }
.jbh-about-bio { font-size: 16px; line-height: 1.8; color: var(--jbh-about-bio-color, inherit); }
.jbh-about-bio p { margin: 0 0 16px; }
/* Bio <strong> — same rationale as `.jbh-about-heading em` above:
   previously hardcoded to `var(--jbh-creme)` which ignored the
   user's Bio Color pickers (dark + light variants) in the Inspector.
   Now inherits from the parent `.jbh-about-bio` which already
   resolves to the mode-aware `--jbh-about-bio-color`. User's
   customised bio colour cascades correctly to emphasised words,
   and the default still looks right because `--jbh-about-bio-color`
   falls back to `inherit` → `--jbh-slate` (mode-aware) which is
   the same visual weight as the old creme on dark or dark on light. */
.jbh-about-bio strong { color: inherit; font-weight: 700; }
.jbh-about-intro-eyebrow { font-family: var(--jbh-font-mono); font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.15em; color: var(--jbh-coral); margin: 0 0 18px; }
.jbh-about-tools { margin: 24px 0 0; font-family: var(--jbh-font-mono); font-size: 12px; line-height: 1.7; font-style: italic; color: var(--jbh-text-color); opacity: 0.75; padding-top: 16px; border-top: 1px dashed var(--jbh-border); }
.jbh-about-contact-sidebar { padding: 28px; border-radius: var(--jbh-card-radius); position: sticky; top: 80px; align-self: start; background: var(--jbh-card); border: 1px solid var(--jbh-border); scroll-margin-top: 80px; }
.jbh-about-contact-title { font-family: var(--jbh-font-serif); font-size: 20px; font-weight: 700; margin: 0 0 24px; padding-bottom: 12px; color: var(--jbh-creme); border-bottom: 1px solid var(--jbh-border); }
/* ── Contact card collapsible (mobile-only) ──────────────────────
   Native <details>/<summary> wraps the card body so the card can
   collapse on phones (where vertical real-estate is precious and
   the contact info is secondary to the bio narrative) while
   staying fully expanded and non-interactive on desktop.

   DESKTOP defaults below:
     · Strip the native UA disclosure marker.
     · Hide the chevron SVG (no toggle affordance shown).
     · `pointer-events:none` neutralises summary clicks so the
       card can never accidentally collapse on desktop.
     · The summary becomes the divider container (replaces the
       border-bottom that was on `.jbh-about-contact-title` so the
       line spans the full card width even though the title now
       sits in a flex row next to the chevron).
     · The nested `.jbh-about-contact-title` resets its own margin
       /padding/border so it integrates cleanly into the flex row.

   MOBILE overrides live in `@media (max-width: 768px)` further
   below — they re-enable the cursor, show the chevron, allow
   toggling, and reorder the sidebar above the main content. */
.jbh-about-contact-details { padding: 0; margin: 0; }
.jbh-about-contact-toggle {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 12px;
	margin: 0 0 24px;
	padding-bottom: 12px;
	border-bottom: 1px solid var(--jbh-border);
	list-style: none;
	cursor: default;
	-webkit-user-select: none;
	user-select: none;
	pointer-events: none;
}
.jbh-about-contact-toggle::-webkit-details-marker { display: none; }
.jbh-about-contact-toggle::marker { content: ''; }
.jbh-about-contact-toggle .jbh-about-contact-title {
	margin: 0;
	padding: 0;
	border-bottom: none;
	flex: 1 1 auto;
}
.jbh-about-contact-chevron {
	flex-shrink: 0;
	color: var(--jbh-text-color);
	transition: transform 0.25s ease;
	display: none;
}
.jbh-about-contact-list { display: block; }
/* Desktop safety net: if a user collapses the card on mobile and
   then resizes to desktop, the [open] attribute is gone but the
   chevron is hidden and the summary is non-interactive — they'd
   be stuck staring at a title with no contents. Force the list
   visible regardless of `[open]` state at ≥901px (matching the
   900px stack breakpoint — everything above that runs the full
   desktop 2-col layout). The selector specificity (0,3,0) beats
   the UA's `details:not([open]) > *` default (~0,1,1). On mobile
   this rule does not fire, so the native collapse behaviour is
   preserved. */
@media (min-width: 901px) {
	.jbh-about-contact-details:not([open]) > .jbh-about-contact-list { display: block; }
}
.jbh-about-contact-item { margin-bottom: 20px; display: flex; align-items: flex-start; gap: 12px; }
.jbh-about-contact-icon { width: 36px; height: 36px; min-width: 36px; background: rgba(42,157,143,0.10); color: var(--jbh-teal); border-radius: 8px; display: flex; align-items: center; justify-content: center; margin-top: 2px; }
.jbh-about-contact-label { display: block; font-size: 11px; font-family: var(--jbh-font-mono); text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 4px; }
.jbh-about-contact-value { font-style: normal; text-decoration: none; color: var(--jbh-card-heading); }
.jbh-about-contact-hours-value { line-height: 1.55; }
a.jbh-about-contact-value:hover { color: var(--jbh-teal); }
.jbh-about-founder-image { width: 64px; height: 64px; border-radius: 50%; object-fit: cover; margin-bottom: 12px; border: 2px solid var(--jbh-border); }
.jbh-about-social-list { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 4px; }
.jbh-about-social-link { display: inline-flex; align-items: center; justify-content: center; width: 32px; height: 32px; border-radius: 6px; background: var(--jbh-card); border: 1px solid var(--jbh-border); color: var(--jbh-slate); transition: color var(--jbh-transition), border-color var(--jbh-transition), background var(--jbh-transition); text-decoration: none; }
.jbh-about-social-link:hover { color: var(--jbh-teal); border-color: var(--jbh-teal); }

/* ── About Section responsive breakpoints ────────────────────────
   Three-layer cadence, tightening progressively as the viewport
   narrows:

     · 900px — STRUCTURAL break. The 2-col grid collapses to a
       single column (48px → 32px gap), `position: sticky` drops
       to `static`, and the native <details> toggle is enabled
       (so the contact card becomes a tap-to-expand accordion).
       900px was chosen over the more common 768px because every
       portrait tablet sits in the 768–834px band (iPad Mini 768,
       iPad Air 820, iPad Pro 11" 834) — a 768 breakpoint left
       those devices in a cramped 2-col layout where each column
       was only ~360px wide after gutters. Landscape tablets
       (≥1024px) still get the full 2-col grid as designed.

     · 768 / 600 / 480px — COSMETIC tightening. Section padding,
       inner-card padding, item gaps, and icon sizes shrink in
       three progressive steps so the "walls of padding" feel
       never happens on phones where every 28px of padding
       inside nested cards eats a significant percentage of
       the viewport width. These cuts align with the plugin's
       existing cadence used by studio-grid, store-grid,
       pricing-plans, portfolio-grid, and insights-grid.

   The contact card's MOBILE POSITION is controlled by the
   `.jbh-about-contact-pos-top` / `.jbh-about-contact-pos-bottom`
   class emitted by `render.php` from the `mobileContactPosition`
   attribute. Scoping `order` by that class (rather than blanket
   `order: -1`) lets authors choose whether contact info leads
   (high-intent "get in touch" pages) or trails (long-form bio
   narratives) on small viewports. */
@media (max-width: 900px) {
	/* Stack the grid and drop sticky positioning — the two go
	   together: a sticky sidebar in a single-column stacked layout
	   would just float over the content, creating a confusing
	   scroll experience. */
	.jbh-about-grid { grid-template-columns: 1fr; gap: 32px; }
	.jbh-about-contact-sidebar { position: static; top: auto; }
	/* Order override placed here so the class selector only
	   matters at mobile/tablet widths — desktop keeps the natural
	   DOM order (main first, sidebar second = right column). */
	.jbh-about-contact-pos-top    .jbh-about-contact-sidebar { order: -1; }
	.jbh-about-contact-pos-bottom .jbh-about-contact-sidebar { order: 0; }
	/* Re-enable the native <details> toggle at the same break so
	   the collapse/expand affordance is available wherever the
	   card is stacked — not just on the narrowest phones. */
	.jbh-about-contact-toggle {
		cursor: pointer;
		pointer-events: auto;
		min-height: 44px;
		-webkit-tap-highlight-color: transparent;
		transition: opacity 0.2s ease;
	}
	.jbh-about-contact-toggle:hover { opacity: 0.85; }
	.jbh-about-contact-toggle:focus-visible {
		outline: 2px solid var(--jbh-teal);
		outline-offset: 4px;
		border-radius: 6px;
	}
	.jbh-about-contact-chevron { display: block; }
	/* Default render is `<details open>`, so the chevron starts
	   rotated 180° (arrow up = "click to collapse"). When the
	   user closes it the [open] attr drops, the rotation resets
	   to 0° (arrow down = "click to expand"). */
	.jbh-about-contact-details[open] .jbh-about-contact-chevron { transform: rotate(180deg); }
	/* Collapsed state: drop the divider so the closed card looks
	   like a single tappable bar with no orphaned underline. */
	.jbh-about-contact-details:not([open]) .jbh-about-contact-toggle {
		margin-bottom: 0;
		padding-bottom: 0;
		border-bottom: none;
	}
}
/* Honour OS-level reduced-motion preference on the chevron rotation
   (the only animated piece introduced by the collapsible card). */
@media (prefers-reduced-motion: reduce) {
	.jbh-about-contact-chevron { transition: none; }
}
@media (max-width: 768px) {
	.jbh-about-section { padding: 48px 20px; }
	.jbh-about-founder-card { padding: 24px; }
	.jbh-about-contact-sidebar { padding: 24px; }
}
@media (max-width: 600px) {
	.jbh-about-section { padding: 40px 16px; }
	.jbh-about-heading { margin-bottom: 20px; }
	.jbh-about-founder-card { padding: 20px; margin-bottom: 20px; }
	.jbh-about-contact-sidebar { padding: 20px; }
	.jbh-about-contact-item { margin-bottom: 16px; gap: 10px; }
	.jbh-about-contact-icon { width: 32px; height: 32px; min-width: 32px; }
}
@media (max-width: 480px) {
	/* At 480px and below, break the email/phone/URL values from
	   the icon if the value is too long — prevents overflow that
	   would otherwise force horizontal scrolling on the whole
	   page. `word-break: break-word` keeps long unbroken strings
	   (emails like "christopher.montgomery@verylongdomain.com")
	   from pushing the sidebar wider than the viewport. */
	.jbh-about-section { padding: 32px 16px; }
	.jbh-about-contact-value { word-break: break-word; overflow-wrap: anywhere; }
	.jbh-about-contact-item address.jbh-about-contact-value { font-size: 14px; }
}

/* ================================================================
   CARD SHAPE UTILITIES
   ================================================================ */
.jbh-shape-sharp { --jbh-card-radius: 0 !important; }
.jbh-shape-rounded { --jbh-card-radius: 8px !important; }
.jbh-shape-soft { --jbh-card-radius: 16px !important; }
.jbh-shape-pill { --jbh-card-radius: 24px !important; }
.jbh-shape-circle { --jbh-card-radius: 50% !important; }
.jbh-hero-section[class*="jbh-shape-"], .jbh-page-intro[class*="jbh-shape-"], .jbh-about-section[class*="jbh-shape-"], .jbh-insights-grid[class*="jbh-shape-"], .jbh-cta-banner[class*="jbh-shape-"] { border-radius: var(--jbh-card-radius); }
[class*="jbh-shape-"] .jbh-service-card, [class*="jbh-shape-"] .jbh-product-card, [class*="jbh-shape-"] .jbh-plan-card, [class*="jbh-shape-"] .jbh-project-card, [class*="jbh-shape-"] .jbh-insight-card, [class*="jbh-shape-"] .jbh-about-founder-card, [class*="jbh-shape-"] .jbh-about-contact-sidebar { overflow: hidden; }
[class*="jbh-shape-"] .jbh-plan-card.jbh-highlighted, [class*="jbh-shape-"] .jbh-service-card.jbh-recommended { overflow: visible !important; }

/* ================================================================
   BADGE DESIGN SYSTEM
   ================================================================ */
.jbh-product-badge, .jbh-plan-badge, .jbh-hero-badge, .jbh-sh-badge, .jbh-cta-badge { transition: background 0.25s ease, color 0.25s ease, border-color 0.25s ease, box-shadow 0.25s ease; }
.jbh-badge-sharp .jbh-product-badge, .jbh-badge-sharp .jbh-plan-badge, .jbh-badge-sharp .jbh-hero-badge, .jbh-badge-sharp .jbh-sh-badge, .jbh-badge-sharp .jbh-cta-badge { border-radius: 0 !important; }
.jbh-badge-rounded .jbh-product-badge, .jbh-badge-rounded .jbh-plan-badge, .jbh-badge-rounded .jbh-hero-badge, .jbh-badge-rounded .jbh-sh-badge, .jbh-badge-rounded .jbh-cta-badge { border-radius: 8px !important; }
.jbh-badge-pill .jbh-product-badge, .jbh-badge-pill .jbh-plan-badge, .jbh-badge-pill .jbh-hero-badge, .jbh-badge-pill .jbh-sh-badge, .jbh-badge-pill .jbh-cta-badge { border-radius: 999px !important; }
.jbh-badge-sm .jbh-product-badge, .jbh-badge-sm .jbh-plan-badge, .jbh-badge-sm .jbh-hero-badge, .jbh-badge-sm .jbh-sh-badge, .jbh-badge-sm .jbh-cta-badge { font-size: 10px; padding: 3px 8px; }
.jbh-badge-md .jbh-product-badge, .jbh-badge-md .jbh-plan-badge, .jbh-badge-md .jbh-hero-badge, .jbh-badge-md .jbh-sh-badge, .jbh-badge-md .jbh-cta-badge { font-size: 12px; padding: 5px 12px; }
.jbh-badge-lg .jbh-product-badge, .jbh-badge-lg .jbh-plan-badge, .jbh-badge-lg .jbh-hero-badge, .jbh-badge-lg .jbh-sh-badge, .jbh-badge-lg .jbh-cta-badge { font-size: 14px; padding: 6px 16px; }
.jbh-badge-font-sans .jbh-product-badge, .jbh-badge-font-sans .jbh-plan-badge, .jbh-badge-font-sans .jbh-hero-badge, .jbh-badge-font-sans .jbh-sh-badge, .jbh-badge-font-sans .jbh-cta-badge { font-family: var(--jbh-font-sans); }
.jbh-badge-font-serif .jbh-product-badge, .jbh-badge-font-serif .jbh-plan-badge, .jbh-badge-font-serif .jbh-hero-badge, .jbh-badge-font-serif .jbh-sh-badge, .jbh-badge-font-serif .jbh-cta-badge { font-family: var(--jbh-font-serif); font-style: italic; }
.jbh-badge-font-mono .jbh-product-badge, .jbh-badge-font-mono .jbh-plan-badge, .jbh-badge-font-mono .jbh-hero-badge, .jbh-badge-font-mono .jbh-sh-badge, .jbh-badge-font-mono .jbh-cta-badge { font-family: var(--jbh-font-mono); letter-spacing: 0.5px; }
.jbh-badge-weight-normal .jbh-product-badge, .jbh-badge-weight-normal .jbh-plan-badge, .jbh-badge-weight-normal .jbh-hero-badge, .jbh-badge-weight-normal .jbh-sh-badge, .jbh-badge-weight-normal .jbh-cta-badge { font-weight: 400; }
.jbh-badge-weight-bold .jbh-product-badge, .jbh-badge-weight-bold .jbh-plan-badge, .jbh-badge-weight-bold .jbh-hero-badge, .jbh-badge-weight-bold .jbh-sh-badge, .jbh-badge-weight-bold .jbh-cta-badge { font-weight: 700; }
.jbh-badge-uppercase .jbh-product-badge, .jbh-badge-uppercase .jbh-plan-badge, .jbh-badge-uppercase .jbh-hero-badge, .jbh-badge-uppercase .jbh-sh-badge, .jbh-badge-uppercase .jbh-cta-badge { text-transform: uppercase; letter-spacing: 1px; }
.jbh-badge-solid .jbh-product-badge, .jbh-badge-solid .jbh-plan-badge, .jbh-badge-solid .jbh-hero-badge, .jbh-badge-solid .jbh-sh-badge, .jbh-badge-solid .jbh-cta-badge { background: var(--jbh-custom-badge-bg, var(--jbh-coral)) !important; color: var(--jbh-custom-badge-text, #fff) !important; }
.jbh-badge-outline .jbh-product-badge, .jbh-badge-outline .jbh-plan-badge, .jbh-badge-outline .jbh-hero-badge, .jbh-badge-outline .jbh-sh-badge, .jbh-badge-outline .jbh-cta-badge { background: transparent !important; border: 1px solid var(--jbh-custom-badge-bg, currentColor); color: var(--jbh-custom-badge-text, inherit) !important; padding: 3px 10px; }
.jbh-badge-dot .jbh-product-badge::before, .jbh-badge-dot .jbh-plan-badge::before, .jbh-badge-dot .jbh-hero-badge::before, .jbh-badge-dot .jbh-sh-badge::before, .jbh-badge-dot .jbh-cta-badge::before { content: ''; display: inline-block; width: 6px; height: 6px; border-radius: 50%; background: currentColor; margin-right: 6px; flex-shrink: 0; animation: jbh-dot-pulse 2s ease-in-out infinite; }
/* Flex-badge override: gap already handles spacing so neutralize the legacy margin-right on flex badges (hero / section-header / cta) to prevent double-gap */
.jbh-badge-dot .jbh-hero-badge::before, .jbh-badge-dot .jbh-sh-badge::before, .jbh-badge-dot .jbh-cta-badge::before { margin-right: 0; }
@keyframes jbh-dot-pulse { 0%, 100% { opacity: 1; transform: scale(1); } 50% { opacity: 0.5; transform: scale(0.8); } }
.jbh-badge-glow .jbh-plan-badge, .jbh-badge-glow .jbh-product-badge, .jbh-badge-glow .jbh-hero-badge, .jbh-badge-glow .jbh-sh-badge, .jbh-badge-glow .jbh-cta-badge { box-shadow: 0 0 16px var(--jbh-custom-badge-bg, rgba(214,79,66,0.35)); }
/* Removed `.jbh-product-badge { background: var(--jbh-teal); color: #fff; }`
   duplicate rule — it silently overrode the intended coral-light pill
   design at line 713 AND ignored the --jbh-custom-badge picker.
   The base coral pill + .jbh-badge-solid/outline classes + shield at
   line 1114 now own the full badge colour story. */
.jbh-badge-pill .jbh-plan-card.jbh-highlighted .jbh-plan-badge { border-radius: 999px; padding: 4px 14px; }

/* ================================================================
   PRINT STYLES
   ================================================================ */
@media print {
	.jbh-studio-grid, .jbh-store-grid, .jbh-pricing-plans, .jbh-portfolio-grid, .jbh-hero-section, .jbh-section-header, .jbh-page-intro, .jbh-about-section, .jbh-insights-grid, .jbh-cta-banner { color: #1e1e1e !important; background: #fff !important; }
	.jbh-service-card, .jbh-product-card, .jbh-plan-card, .jbh-project-card, .jbh-insight-card, .jbh-about-founder-card, .jbh-about-contact-sidebar, .jbh-hero-badge, .jbh-cta-badge { background: #fff !important; border: 1px solid #ccc !important; box-shadow: none !important; break-inside: avoid; page-break-inside: avoid; }
	.jbh-get-started-btn, .jbh-product-btn, .jbh-plan-btn, .jbh-hero-btn, .jbh-cta-btn, .jbh-pricing-toggle-wrap, .jbh-hero-gradient-bridge { display: none !important; }
	.jbh-card-title, .jbh-product-title, .jbh-plan-name, .jbh-project-title, .jbh-hero-heading, .jbh-sh-heading, .jbh-pi-heading, .jbh-about-heading, .jbh-insight-title, .jbh-cta-heading { color: #1e1e1e !important; }
	.jbh-card-desc, .jbh-product-desc, .jbh-project-desc, .jbh-plan-perks li, .jbh-hero-subtitle, .jbh-sh-subtitle, .jbh-pi-subtitle, .jbh-pi-callout-text, .jbh-about-bio, .jbh-insight-excerpt, .jbh-cta-subtitle { color: #333 !important; }
}

/* ================================================================
   16. INSIGHTS GRID BLOCK
   ================================================================ */
.jbh-insights-grid { padding: 40px 24px; background: var(--jbh-custom-block-bg, var(--jbh-bg)); }
.jbh-insights-list { display: grid; grid-template-columns: repeat(var(--jbh-cols, 3), 1fr); gap: var(--jbh-gap, 24px); list-style: none; padding: 0; margin: 0; }
.jbh-gap-tight .jbh-insights-list { --jbh-gap: 12px; }
.jbh-gap-normal .jbh-insights-list { --jbh-gap: 24px; }
.jbh-gap-relaxed .jbh-insights-list { --jbh-gap: 36px; }
.jbh-gap-loose .jbh-insights-list { --jbh-gap: 48px; }
.jbh-insight-card { display: flex; flex-direction: column; background: var(--jbh-ig-card-bg, var(--jbh-card)); border: 1px solid var(--jbh-ig-card-border, var(--jbh-border)); border-radius: var(--jbh-card-radius); overflow: hidden; transition: transform var(--jbh-transition), box-shadow var(--jbh-transition); }
.jbh-insight-content { padding: 20px; display: flex; flex-direction: column; flex: 1; }
.jbh-insight-icon { display: flex; align-items: center; justify-content: center; width: 56px; height: 56px; min-width: 56px; background: var(--jbh-ig-meta-bg, rgba(42,157,143,0.08)); border: 1px solid rgba(42,157,143,0.18); border-radius: 12px; color: var(--jbh-ig-icon-color, var(--jbh-teal)); margin: 20px 0 0 20px; transition: background var(--jbh-transition), color var(--jbh-transition), border-color var(--jbh-transition); flex-shrink: 0; }
.jbh-insight-card:hover .jbh-insight-icon { background: var(--jbh-ig-icon-color, var(--jbh-custom-icon, var(--jbh-teal))); color: #ffffff; border-color: var(--jbh-ig-icon-color, var(--jbh-custom-icon, var(--jbh-teal))); }
.jbh-insight-icon svg { width: 24px; height: 24px; }

/* ── Meta row ── */
.jbh-insight-meta { display: flex; align-items: center; flex-wrap: wrap; gap: 6px 10px; font-size: 12px; font-family: var(--jbh-font-mono); text-transform: uppercase; letter-spacing: 0.04em; margin-bottom: 12px; color: var(--jbh-ig-date-color, var(--jbh-slate)); background: var(--jbh-ig-meta-bg, transparent); padding: 0; border-radius: 6px; }
.jbh-insight-category { color: var(--jbh-ig-category-color, var(--jbh-teal)); font-weight: 700; }
.jbh-insight-date { opacity: 0.85; }
.jbh-insight-read-time { opacity: 0.85; }
.jbh-insight-meta > span + span::before { content: '\00B7'; margin-right: 6px; opacity: 0.5; }

/* ── Title ── */
.jbh-insight-title { font-family: var(--jbh-font-serif); font-size: 18px; font-weight: 700; line-height: 1.3; margin: 0 0 10px; color: var(--jbh-ig-heading-color, var(--jbh-card-heading)); }
.jbh-insight-title a { color: inherit; text-decoration: none; transition: color var(--jbh-transition); }
.jbh-insight-title a:hover { color: var(--jbh-ig-link-hover-color, var(--jbh-teal)); }

/* ── Excerpt ── */
.jbh-insight-excerpt { font-size: 14px; line-height: 1.7; margin: 0 0 16px; flex: 1; color: var(--jbh-ig-excerpt-color, var(--jbh-slate)); display: -webkit-box; -webkit-line-clamp: 3; line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }

/* ── Tags ── */
.jbh-insight-tags { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 16px; }
.jbh-insight-tag { font-size: 11px; font-family: var(--jbh-font-mono); font-weight: 600; text-transform: uppercase; letter-spacing: 0.04em; padding: 3px 10px; border-radius: 999px; background: var(--jbh-ig-meta-bg, rgba(42,157,143,0.08)); color: var(--jbh-ig-tag-color, var(--jbh-teal)); border: 1px solid rgba(42,157,143,0.15); transition: background var(--jbh-transition), color var(--jbh-transition); }

/* ── Footer (author + read more) ── */
.jbh-insight-footer { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-top: auto; padding-top: 16px; border-top: 1px solid var(--jbh-ig-card-border, var(--jbh-border)); }
.jbh-insight-author { display: flex; align-items: center; gap: 8px; min-width: 0; }
.jbh-insight-avatar { width: 28px; height: 28px; border-radius: 50%; object-fit: cover; flex-shrink: 0; border: 2px solid var(--jbh-ig-card-border, var(--jbh-border)); }
.jbh-insight-author-name { font-size: 12px; font-weight: 600; color: var(--jbh-ig-author-color, var(--jbh-slate)); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.jbh-insight-read-more { font-size: 13px; font-weight: 700; color: var(--jbh-ig-link-color, var(--jbh-teal)); text-decoration: none; display: inline-flex; align-items: center; gap: 4px; transition: color var(--jbh-transition); white-space: nowrap; flex-shrink: 0; }
.jbh-insight-read-more:hover { color: var(--jbh-ig-link-hover-color, var(--jbh-coral)); }

/* ── Images ── */
.jbh-insight-image-wrap { overflow: hidden; flex-shrink: 0; position: relative; display: block; text-decoration: none; }
.jbh-insight-image-wrap.jbh-img-ratio-16-9 { aspect-ratio: 16/9; }
.jbh-insight-image-wrap.jbh-img-ratio-4-3 { aspect-ratio: 4/3; }
.jbh-insight-image-wrap.jbh-img-ratio-1-1 { aspect-ratio: 1/1; }
.jbh-insight-image-wrap.jbh-img-ratio-3-2 { aspect-ratio: 3/2; }
.jbh-insight-image-wrap.jbh-img-ratio-auto { aspect-ratio: auto; }
.jbh-insight-image { width: 100%; height: 100%; object-fit: cover; display: block; transition: transform 0.4s ease; }
.jbh-insight-card:hover .jbh-insight-image:not(.jbh-insight-placeholder) { transform: scale(1.04); }
.jbh-insight-image-overlay { position: absolute; inset: 0; background: linear-gradient(to top, rgba(0,0,0,0.35) 0%, transparent 60%); pointer-events: none; transition: opacity 0.3s ease; opacity: 0.7; }
.jbh-insight-card:hover .jbh-insight-image-overlay { opacity: 1; }

/* ── Placeholder (no featured image) ── */
.jbh-insight-placeholder { display: flex; align-items: center; justify-content: center; background: var(--jbh-ig-meta-bg, rgba(42,157,143,0.06)); color: var(--jbh-ig-icon-color, var(--jbh-teal)); opacity: 0.5; }
.jbh-insight-placeholder svg { width: 48px; height: 48px; }

/* ── Empty state ── */
.jbh-insights-grid .jbh-insights-empty { text-align: center; font-style: italic; color: var(--jbh-slate); padding: 40px 0; }

/* ── Horizontal layout ── */
.jbh-insights-horizontal .jbh-insights-list { grid-template-columns: 1fr !important; }
.jbh-insights-horizontal .jbh-insight-card { flex-direction: row; align-items: stretch; }
.jbh-insights-horizontal .jbh-insight-icon { width: 56px; height: 56px; min-width: 56px; background: rgba(42,157,143,0.08); border-radius: 12px; padding: 0; margin: 24px 0 24px 24px; }
.jbh-insights-horizontal .jbh-insight-icon svg { width: 24px; height: 24px; }
.jbh-insights-horizontal .jbh-insight-content { padding: 24px; }
.jbh-insights-horizontal .jbh-insight-image-wrap { width: 240px; min-width: 240px; aspect-ratio: auto; height: auto; align-self: stretch; }

/* ── Responsive ── */
@media (max-width: 1024px) {
	.jbh-insights-list { grid-template-columns: repeat(2, 1fr) !important; }
}
@media (max-width: 600px) {
	.jbh-insights-list { grid-template-columns: 1fr !important; }
	.jbh-insights-horizontal .jbh-insight-card { flex-direction: column; }
	.jbh-insights-horizontal .jbh-insight-image-wrap { width: 100%; min-width: 0; }
	.jbh-insight-footer { flex-direction: column; align-items: flex-start; gap: 8px; }
}

/* ================================================================
   17. CTA BANNER BLOCK
   ================================================================ */
.jbh-cta-banner { padding: 48px 32px; border-radius: var(--jbh-card-radius); position: relative; background: var(--jbh-custom-block-bg, var(--jbh-card)); border: 1px solid var(--jbh-border); }
.jbh-cta-border-top { border-top: 3px solid var(--jbh-teal); }
.jbh-cta-inner { max-width: 640px; }
.jbh-cta-align-center { text-align: center; }
.jbh-cta-align-center .jbh-cta-inner { margin: 0 auto; }
.jbh-cta-align-left { text-align: left; }
.jbh-cta-align-right { text-align: right; }
.jbh-cta-align-right .jbh-cta-inner { margin-left: auto; }
.jbh-cta-badge { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; font-family: var(--jbh-font-mono); text-transform: uppercase; letter-spacing: 0.1em; font-weight: 700; margin-bottom: 16px; padding: 4px 12px; border-radius: 999px; border: 1px solid var(--jbh-border); background: var(--jbh-custom-badge-bg, rgba(42,157,143,0.10)); color: var(--jbh-cta-badge-color, var(--jbh-teal)); }
.jbh-cta-heading { font-family: var(--jbh-font-serif); font-size: clamp(24px, 4vw, 36px); font-weight: 700; line-height: 1.15; margin: 0 0 12px; color: var(--jbh-cta-heading-color, var(--jbh-card-heading)); }
.jbh-cta-subtitle { font-family: var(--jbh-font-sans); font-size: 16px; line-height: 1.7; font-weight: 300; margin: 0 0 24px; color: var(--jbh-cta-subtitle-color, var(--jbh-slate)); }
.jbh-cta-btn { display: inline-flex; align-items: center; padding: 12px 28px; font-family: var(--jbh-font-serif); font-weight: 700; font-size: 15px; border-radius: var(--jbh-card-radius); text-decoration: none; transition: all var(--jbh-transition); cursor: pointer; border: 2px solid transparent; }
.jbh-btn-filled .jbh-cta-btn { background: var(--jbh-cta-btn-bg, var(--jbh-coral)); color: var(--jbh-cta-btn-text, #fff); border-color: var(--jbh-cta-btn-bg, var(--jbh-coral)); box-shadow: 0 4px 14px rgba(214,79,66,0.39); }
.jbh-btn-filled .jbh-cta-btn:hover { background: var(--jbh-cta-btn-hover-bg, var(--jbh-cta-btn-bg, var(--jbh-coral))); color: var(--jbh-cta-btn-hover-text, var(--jbh-cta-btn-text, #fff)); filter: brightness(1.08); transform: translateY(-1px); box-shadow: 0 6px 20px rgba(214,79,66,0.55); }
.jbh-btn-outline .jbh-cta-btn { background: transparent; color: var(--jbh-teal); border-color: var(--jbh-teal); }
.jbh-btn-outline .jbh-cta-btn:hover { background: var(--jbh-teal); color: #fff; transform: translateY(-1px); }
.jbh-btn-ghost .jbh-cta-btn { background: transparent; color: var(--jbh-teal); border: none; text-decoration: underline; text-underline-offset: 4px; padding: 12px 0; }
.jbh-btn-ghost .jbh-cta-btn:hover { color: var(--jbh-coral); }
.jbh-cta-btn:active { transform: scale(0.97); transition-duration: 0.08s; }

/* ── Text clamp utilities ─────────────────────────────────────── */
.jbh-text-clamp-2 { display: -webkit-box; -webkit-line-clamp: 2; line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.jbh-text-clamp-3 { display: -webkit-box; -webkit-line-clamp: 3; line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }

/* ================================================================
   MOBILE RESPONSIVE FINE-TUNING — cross-cutting per-block layer
   ================================================================
   This consolidated section adds per-block mobile improvements not
   covered by the original global responsive rules at lines 3477-
   3498 (which only handled grid columns + horizontal block padding).

   Block-by-block audit findings driving these rules:

   1. Section Header — had ZERO @media rules. On standalone use,
      `padding: 12px 0` produced edge-flush text on phones.
   2. Page Intro — only had a 640px callout/status compression
      rule; missing horizontal gutter and heading-margin tightening
      for narrower viewports.
   3. Hero Section — the existing 600px rule set
      `font-size: 32px` (fixed) which DEFEATED the desktop clamp()
      formula and produced the same size on a 360px phone as on a
      599px tablet. Replaced with mode-specific clamp() ranges so
      headings keep scaling all the way down.
   4. CTA Banner — abrupt jump from 48/32 desktop padding to
      28/16 at 600px; now interpolates 36/24 at 768px and tightens
      heading + button on narrow widths.
   5. Studio Grid card internals — header/body/footer/target-band
      all used 32px horizontal padding. On a 320px phone with
      the card spanning ~288px, that left only ~224px for content
      (~22% lost to padding alone). Now compresses to 24/20/16px
      progressively.
   6. Pricing Plans card padding — 40px desktop default was even
      worse than studio-grid (40×2 = 80px lost on a 288px card).
      Now compresses through 28→24→20px and shrinks plan-price
      from fixed 40px to 32px → 28px.
   7. Pricing Toggle — 48×26px hit area was too short for WCAG
      2.5.5 Target Size minimum (44×44). Bumped to 56×32 on
      phones with proportionally-larger thumb dot.
   8. Insights Grid card padding — 24px content / 56px icon were
      generous on desktop but proportionally too much on phones.
      Compressed icon to 48px and content padding to 16px → 14px.
   9. Portfolio Grid project card content padding — 40px → 28/20.
   10. Touch targets via @media (pointer: coarse) — applies to
       touch screens and tablets without affecting mouse precision.
   11. Horizontal-scroll guard at 480px — `overflow-x: hidden` on
       block wrappers + `overflow-wrap: anywhere; word-break:
       break-word` on text content so long URLs / emails / words
       wrap inside cards rather than pushing the page wider than
       viewport (which would cause horizontal scroll bars).

   Each rule targets `.jbh-{block} .jbh-{component}` (block-scoped)
   so themes can override safely with their own block-scoped rules,
   and so the rules don't leak into non-JBH content. All paddings
   maintain the 4-step progressive cascade (desktop → 768 → 600 →
   480) for consistent breathing room across every viewport. */

/* ── Tablet (≤ 768px) ─────────────────────────────────────────── */
@media (max-width: 768px) {
	/* Standalone section-header / page-intro horizontal gutter.
	   The WP block wrapper class qualifier prevents the same rule
	   from leaking into the studio-grid internal `.jbh-section-header`
	   helper at L1552 (which is a different layout component
	   sharing the class name). */
	.wp-block-jbh-section-header.jbh-section-header { padding-left: 16px; padding-right: 16px; }
	.wp-block-jbh-page-intro.jbh-page-intro { padding-left: 16px; padding-right: 16px; }
	/* Hero — tablet padding step between desktop 80/24 and the
	   existing 600px rule's 48/16, smoothing the cascade. */
	.jbh-hero-section { padding: 64px 20px 50px; }
	/* CTA Banner — tablet step (existing 600px rule is 28/16). */
	.jbh-cta-banner { padding: 36px 24px; }
	/* Studio Grid card internals — compress 32px → 24px to give
	   content more horizontal room when grid is 1-column on tablet. */
	.jbh-studio-grid .jbh-card-header { padding-left: 24px; padding-right: 24px; }
	.jbh-studio-grid .jbh-card-target-band { padding: 14px 24px; }
	.jbh-studio-grid .jbh-card-body { padding: 28px 24px; }
	.jbh-studio-grid .jbh-card-footer { padding: 22px 24px; }
	/* Pricing Plans card — compress 40px → 28px. The highlighted
	   variant's extra top padding scales proportionally so the
	   "RECOMMENDED" ribbon still has room above the plan name. */
	.jbh-pricing-plans .jbh-plan-card { padding: 28px; }
	.jbh-pricing-plans .jbh-plan-card.jbh-highlighted { padding-top: 44px; }
	/* Insights Grid horizontal layout — content padding 24 → 20 */
	.jbh-insights-grid.jbh-insights-horizontal .jbh-insight-content { padding: 20px; }
	/* Portfolio project card content padding compression */
	.jbh-portfolio-grid .jbh-project-content-panel { padding: 32px 24px; }
	.jbh-portfolio-grid .jbh-project-stacked .jbh-project-content-panel { padding: 32px 24px; }
}

/* ── Phone (≤ 600px) ──────────────────────────────────────────── */
@media (max-width: 600px) {
	/* Section Header / Page Intro — vertical compression and
	   heading-margin tightening for tighter rhythm on phones. */
	.wp-block-jbh-section-header.jbh-section-header { padding-top: 8px; padding-bottom: 20px; }
	.wp-block-jbh-page-intro.jbh-page-intro { padding-top: 8px; padding-bottom: 24px; }
	.jbh-pi-heading { margin-bottom: 12px; }
	.jbh-pi-subtitle { margin-bottom: 18px; }
	/* Hero Section — restore progressive clamp() at narrow widths.
	   The original 600px rule set `font-size: 32px` (fixed) which
	   produced identical heading size at 599px and 360px. The new
	   clamp formulas keep scaling between size variants. */
	.jbh-hero-section .jbh-hero-heading { font-size: clamp(26px, 7vw, 32px); }
	.jbh-hero-section.jbh-hero-heading-small  .jbh-hero-heading { font-size: clamp(22px, 6vw, 28px); }
	.jbh-hero-section.jbh-hero-heading-medium .jbh-hero-heading { font-size: clamp(24px, 6.5vw, 30px); }
	.jbh-hero-section.jbh-hero-heading-xlarge .jbh-hero-heading { font-size: clamp(28px, 8vw, 38px); }
	.jbh-hero-section .jbh-hero-subtitle { font-size: 15px; margin-bottom: 28px; }
	.jbh-hero-section .jbh-hero-buttons { gap: 12px; }
	/* Hero buttons stack as full-width pills on narrow screens to
	   give thumbs an obvious tap target. Capped at 320px so on
	   tablets they don't stretch awkwardly. */
	.jbh-hero-section .jbh-hero-btn { width: 100%; justify-content: center; max-width: 320px; }
	.jbh-hero-section.jbh-hero-align-center .jbh-hero-btn { margin-left: auto; margin-right: auto; }
	/* Studio Grid — further card padding compression on phone */
	.jbh-studio-grid .jbh-card-header { padding: 24px 20px 18px; }
	.jbh-studio-grid .jbh-card-target-band { padding: 12px 20px; }
	.jbh-studio-grid .jbh-card-body { padding: 24px 20px; }
	.jbh-studio-grid .jbh-card-footer { padding: 20px; }
	/* Card pricing row — allow wrap when price + timeline don't fit
	   side-by-side, instead of squishing both columns. */
	.jbh-studio-grid .jbh-card-pricing { flex-wrap: wrap; gap: 8px; }
	.jbh-studio-grid .jbh-card-timeline-group { text-align: left; }
	/* Pricing Plans — phone padding + price scaling */
	.jbh-pricing-plans .jbh-plan-card { padding: 24px 20px; }
	.jbh-pricing-plans .jbh-plan-card.jbh-highlighted { padding-top: 40px; }
	.jbh-pricing-plans .jbh-plan-price { font-size: 32px; }
	/* Pricing Toggle — bump to 56×32 for WCAG 2.5.5 Target Size.
	   Default 48×26 was below the 44px minimum height for
	   touch-screen reliability. The dot scales with the track. */
	.jbh-pricing-toggle { width: 56px; height: 32px; }
	.jbh-pricing-toggle::after { width: 26px; height: 26px; top: 3px; left: 3px; }
	.jbh-pricing-toggle:checked::after { transform: translateX(24px); }
	/* Insights Grid card padding compression on phone */
	.jbh-insights-grid .jbh-insight-content { padding: 16px; }
	.jbh-insights-grid .jbh-insight-icon { width: 48px; height: 48px; min-width: 48px; margin: 16px 0 0 16px; }
	.jbh-insights-grid .jbh-insight-icon svg { width: 20px; height: 20px; }
	.jbh-insights-grid .jbh-insight-title { font-size: 17px; }
	/* CTA Banner buttons — same full-width-pill pattern as hero */
	.jbh-cta-banner .jbh-cta-btn { width: 100%; justify-content: center; max-width: 320px; }
	.jbh-cta-banner.jbh-cta-align-center .jbh-cta-btn { margin-left: auto; margin-right: auto; }
	/* About Section social link — bump from 32×32 to 36×36 for
	   touch ergonomics. Below WCAG 44 minimum but visually
	   appropriate for icon-only links; @media (pointer: coarse)
	   below extends to 40×40 for actual touch screens. */
	.jbh-about-section .jbh-about-social-link { width: 36px; height: 36px; }
	/* Portfolio Grid project card padding on phone */
	.jbh-portfolio-grid .jbh-project-content-panel { padding: 28px 20px; }
	.jbh-portfolio-grid .jbh-project-stacked .jbh-project-content-panel { padding: 28px 20px; }
	.jbh-portfolio-grid .jbh-project-stacked .jbh-project-icon-panel { padding: 32px 20px; }
}

/* ── Narrow phone (≤ 480px) ───────────────────────────────────── */
@media (max-width: 480px) {
	/* Hero Section — tightest padding for narrow phones */
	.jbh-hero-section { padding: 40px 16px 32px; }
	.jbh-hero-section .jbh-hero-badge { font-size: 10px; padding: 5px 12px; margin-bottom: 18px; }
	/* Buttons fully stack vertically (no side-by-side option at
	   this width — there's not enough horizontal room for two
	   pills + the gap between them). */
	.jbh-hero-section .jbh-hero-buttons { flex-direction: column; align-items: stretch; }
	/* CTA Banner — narrow phone compression */
	.jbh-cta-banner { padding: 24px 16px; }
	.jbh-cta-banner .jbh-cta-badge { font-size: 11px; padding: 3px 10px; }
	/* Studio Grid card — tightest internal paddings on tiny screens */
	.jbh-studio-grid .jbh-card-header { padding: 20px 16px 16px; }
	.jbh-studio-grid .jbh-card-target-band { padding: 10px 16px; }
	.jbh-studio-grid .jbh-card-body { padding: 20px 16px; }
	.jbh-studio-grid .jbh-card-footer { padding: 18px 16px; }
	.jbh-studio-grid .jbh-card-includes li { font-size: 13px; gap: 10px; }
	.jbh-studio-grid .jbh-addon-pill { padding: 6px 10px; font-size: 10px; gap: 8px; }
	/* Pricing Plans — minimal padding for tiny screens */
	.jbh-pricing-plans .jbh-plan-card { padding: 20px 16px; }
	.jbh-pricing-plans .jbh-plan-card.jbh-highlighted { padding-top: 36px; }
	.jbh-pricing-plans .jbh-plan-price { font-size: 28px; }
	.jbh-pricing-plans .jbh-plan-perks li { font-size: 13px; line-height: 2; }
	.jbh-pricing-plans .jbh-pricing-toggle-wrap { gap: 8px; margin: 18px 0 28px; }
	/* Section Header / Page Intro — final gutter compression */
	.wp-block-jbh-section-header.jbh-section-header { padding-left: 12px; padding-right: 12px; }
	.wp-block-jbh-page-intro.jbh-page-intro { padding-left: 12px; padding-right: 12px; }
	/* Insights — final compression */
	.jbh-insights-grid .jbh-insight-content { padding: 14px; }
	.jbh-insights-grid .jbh-insight-meta { font-size: 11px; gap: 4px 8px; }
	.jbh-insights-grid .jbh-insight-tag { font-size: 10px; padding: 2px 8px; }
	/* Portfolio — final compression */
	.jbh-portfolio-grid .jbh-project-content-panel { padding: 24px 16px; }
	.jbh-portfolio-grid .jbh-project-stacked .jbh-project-content-panel { padding: 24px 16px; }
	.jbh-portfolio-grid .jbh-project-title { font-size: clamp(18px, 5vw, 22px); }
	/* Horizontal-scroll guard rail — prevents the page from gaining
	   a horizontal scrollbar on narrow viewports because of any
	   single block overflowing. `overflow-x: hidden` on each block
	   wrapper isolates each block's overflow potential. */
	.jbh-studio-grid, .jbh-store-grid, .jbh-pricing-plans,
	.jbh-portfolio-grid, .jbh-hero-section, .jbh-section-header,
	.jbh-page-intro, .jbh-about-section, .jbh-insights-grid,
	.jbh-cta-banner { overflow-x: hidden; }
	/* Long URLs / emails / unbreakable words inside body text */
	.jbh-card-desc, .jbh-product-desc, .jbh-plan-perks li,
	.jbh-project-desc, .jbh-insight-excerpt, .jbh-cta-subtitle,
	.jbh-hero-subtitle, .jbh-pi-callout-text, .jbh-about-bio,
	.jbh-sh-subtitle, .jbh-pi-subtitle {
		overflow-wrap: anywhere;
		word-break: break-word;
	}
}

/* ── Touch-screen target sizing (WCAG 2.5.5 Target Size) ──────
   `pointer: coarse` matches devices with imprecise primary
   pointing — touch screens and TVs/remote-controlled UIs — but
   NOT mouse-driven small windows. So desktop users with small
   browser windows keep their pixel-precise click targets while
   phone/tablet users get larger hit areas. */
@media (pointer: coarse) {
	.jbh-pricing-toggle { min-height: 32px; }
	.jbh-about-social-link { min-width: 40px; min-height: 40px; }
	.jbh-store-search-clear { min-width: 32px; min-height: 32px; }
	.jbh-carousel-arrow { min-width: 44px; min-height: 44px; }
	/* Tag-style buttons get a 6px-wider tappable area via
	   transparent ::after halo — keeps the visual size compact
	   but prevents fat-fingering adjacent tags. */
	.jbh-insight-tag, .jbh-project-tag { position: relative; }
	.jbh-insight-tag::after, .jbh-project-tag::after {
		content: ''; position: absolute; inset: -6px;
	}
}

/* ================================================================
   PORTFOLIO MODAL — mobile compression + overflow safeguards
   ================================================================
   Portfolio modal sits in frontend.css (not modal.css, which is
   for the studio/store `get-started` flow). Without these rules,
   on narrow phones (<480px) three visual bugs appeared:

   1. Header `padding: 24px 32px` + 40px close button in a flex
      row left ~200px for the title, which then wrapped badly and
      crowded the meta badges.
   2. Body `padding: 24px 32px 32px` + description's `border-left:
      2px solid; padding-left: 24px` ate ~50px of horizontal space
      before any actual descriptive text could be read.
   3. Deliverables grid used `minmax(220px, 1fr)`. On a 320px-wide
      phone the modal's inner content area drops to ~216px (viewport
      320 − 32 overlay padding − 64 modal padding). 220px > 216px,
      so auto-fit couldn't shrink the column below its 220px floor
      and the grid forced horizontal scroll *inside* the modal body.

   Fix: progressive padding compression at 600/480 matching the
   plugin's existing cadence, and `minmax(min(220px, 100%), 1fr)`
   so the minimum track width gracefully collapses to the available
   width when the container is narrower than 220px — a well-known
   CSS Grid safeguard for auto-fit layouts in dialogs. */
@media (max-width: 600px) {
	.jbh-portfolio-modal-overlay { padding: 8px; }
	.jbh-portfolio-modal-header { padding: 18px 20px; gap: 10px; }
	.jbh-portfolio-modal-body { padding: 18px 20px 24px; }
	.jbh-portfolio-modal-desc { padding-left: 16px; margin-bottom: 28px; font-size: 15px; }
	.jbh-pm-deliverable-card { padding: 18px; }
	.jbh-portfolio-modal-deliverables-grid { grid-template-columns: repeat(auto-fit, minmax(min(220px, 100%), 1fr)); gap: 16px; }
	.jbh-portfolio-modal-actions { gap: 8px; margin-top: 24px; padding-top: 18px; flex-direction: column; }
	.jbh-pm-action-btn { padding: 11px 18px; font-size: 13px; width: 100%; justify-content: center; }
}
@media (max-width: 480px) {
	.jbh-portfolio-modal-overlay { padding: 4px; }
	.jbh-portfolio-modal-header { padding: 14px 16px; }
	.jbh-portfolio-modal-body { padding: 16px 16px 20px; }
	.jbh-portfolio-modal-desc { padding-left: 14px; margin-bottom: 24px; }
	.jbh-portfolio-modal-deliverables-heading { margin: 0 0 16px; }
	.jbh-pm-deliverable-card { padding: 14px; }
	/* Meta badges (client + sector) can wrap when the title and
	   badges all compete for the same header row at the narrowest
	   viewports. `flex-wrap` prevents visual overflow. */
	.jbh-portfolio-modal-meta { flex-wrap: wrap; gap: 8px; margin-bottom: 10px; }
}

/* ================================================================
   HERO FEATURE CARDS — mobile padding compression
   ================================================================
   The feature-cards row below the hero already stacks to 1-column
   at 900px (see L3718), but the card padding stayed at 40px which
   — on a 360px phone — consumes 80px of horizontal space (22% of
   viewport), leaving ~240px for the icon + title + description.
   Progressive compression at 600/480 matches the cadence used by
   the rest of the responsive fine-tuning layer. */
@media (max-width: 600px) {
	.jbh-hero-features { padding: 40px 16px 20px; }
	.jbh-hero-features-header { margin-bottom: 28px; }
	.jbh-hero-features-grid { gap: 20px; }
	.jbh-hero-feature-card { padding: 28px 22px; }
	.jbh-hero-feature-title { font-size: 20px; margin-bottom: 10px; }
	.jbh-hero-feature-icon { width: 44px; height: 44px; margin-bottom: 20px; }
}
@media (max-width: 480px) {
	.jbh-hero-features { padding: 32px 12px 16px; }
	.jbh-hero-feature-card { padding: 24px 18px; }
	.jbh-hero-feature-title { font-size: 18px; }
	.jbh-hero-feature-desc { font-size: 13.5px; }
}

/* ================================================================
   18. CONTACT SECTION BLOCK
   ================================================================ */
.jbh-contact-section { padding: 80px 24px; background: var(--jbh-custom-block-bg, var(--jbh-bg)); font-family: var(--jbh-font-sans); }
.jbh-contact-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 64px; max-width: 1200px; margin: 0 auto; align-items: start; }

.jbh-contact-info { display: flex; flex-direction: column; gap: 24px; }
.jbh-contact-heading { font-family: var(--jbh-font-serif); font-size: clamp(2.5rem, 4vw, 3.5rem); font-weight: 700; color: var(--jbh-custom-header, var(--jbh-card-heading)); margin: 0; line-height: 1.1; }
.jbh-contact-subtitle { color: var(--jbh-custom-desc, var(--jbh-text-color)); font-size: 16px; line-height: 1.7; margin: 0 0 16px; }

.jbh-contact-items-list { display: flex; flex-direction: column; gap: 28px; }
.jbh-contact-item { display: flex; align-items: flex-start; gap: 16px; }
.jbh-contact-icon { width: 56px; height: 56px; border-radius: 12px; background: rgba(42,157,143,0.10); color: var(--jbh-custom-icon, var(--jbh-teal)); display: flex; align-items: center; justify-content: center; flex-shrink: 0; border: 1px solid rgba(42,157,143,0.15); transition: background 0.3s, color 0.3s; }
.jbh-contact-icon svg { width: 24px; height: 24px; }
.jbh-contact-item:hover .jbh-contact-icon { background: var(--jbh-custom-icon, var(--jbh-teal)); color: #fff; }

.jbh-contact-item-content { display: flex; flex-direction: column; gap: 6px; padding-top: 6px; }
.jbh-contact-item-label { font-family: var(--jbh-font-mono); font-size: 11px; text-transform: uppercase; letter-spacing: 0.1em; color: var(--jbh-slate); }
.jbh-contact-item-value { font-size: 16px; color: var(--jbh-custom-desc, var(--jbh-card-heading)); text-decoration: none; transition: color 0.2s; word-break: break-word; overflow-wrap: anywhere; }
.jbh-contact-item-value:hover { color: var(--jbh-custom-icon, var(--jbh-teal)); }

.jbh-contact-item-hours .jbh-contact-item-content { gap: 8px; }
.jbh-contact-hours-main { font-weight: 700; line-height: 1.55; }
.jbh-contact-hours-world { display: block; color: var(--jbh-custom-desc, var(--jbh-text-color)); font-size: 14px; line-height: 1.55; opacity: 0.92; }
.jbh-contact-hours-note { display: block; color: var(--jbh-custom-desc, var(--jbh-text-color)); font-size: 13px; line-height: 1.55; opacity: 0.78; max-width: 34em; }
.jbh-working-hours-line { color: var(--jbh-text-color); font-size: 13px; line-height: 1.5; }
.jbh-working-hours-line-full { display: inline-block; max-width: 52em; }


.jbh-contact-form-wrap { background: var(--jbh-custom-card-bg, var(--jbh-card)); border: 1px solid var(--jbh-custom-card-border, var(--jbh-border)); padding: 48px; border-radius: var(--jbh-card-radius); box-shadow: 0 4px 24px rgba(0,0,0,0.06); transition: box-shadow var(--jbh-transition); }
.jbh-contact-form-wrap:hover { box-shadow: 0 8px 32px rgba(0,0,0,0.14); }

.jbh-contact-field { display: flex; flex-direction: column; gap: 8px; margin-bottom: 24px; }
.jbh-contact-field-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; margin-bottom: 24px; }
.jbh-contact-field-grid .jbh-contact-field { margin-bottom: 0; }
.jbh-contact-context-note { margin: 10px 0 0; padding: 12px 14px; border-left: 3px solid var(--jbh-custom-icon, var(--jbh-teal)); background: rgba(42,157,143,0.10); color: var(--jbh-custom-desc, var(--jbh-text-color)); font-size: 13px; line-height: 1.6; border-radius: 6px; }
.jbh-contact-context-note[hidden] { display: none !important; }

.jbh-contact-helper-text { margin: 8px 0 0; color: var(--jbh-custom-desc, var(--jbh-text-color)); font-size: 13px; line-height: 1.55; opacity: 0.86; }
.jbh-contact-optional-details { margin: 0 0 24px; border: 1px solid var(--jbh-custom-card-border, var(--jbh-border)); border-radius: 8px; background: rgba(42,157,143,0.04); overflow: hidden; }
.jbh-contact-details-summary { display: flex; align-items: center; justify-content: space-between; gap: 16px; padding: 14px 16px; color: var(--jbh-custom-header, var(--jbh-card-heading)); font-family: var(--jbh-font-mono); font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.1em; cursor: pointer; list-style: none; user-select: none; }
.jbh-contact-details-summary::-webkit-details-marker { display: none; }
.jbh-contact-details-summary::after { content: ""; width: 12px; height: 12px; flex: 0 0 12px; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 24 24' stroke='%23778899'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M19 9l-7 7-7-7'%3E%3C/path%3E%3C/svg%3E"); background-size: contain; background-repeat: no-repeat; transition: transform 0.2s ease; opacity: 0.8; }
.jbh-contact-optional-details[open] .jbh-contact-details-summary::after { transform: rotate(180deg); }
.jbh-contact-details-summary small { color: var(--jbh-custom-desc, var(--jbh-text-color)); font-size: 10px; letter-spacing: 0.08em; opacity: 0.72; margin-left: auto; }
.jbh-contact-details-body { padding: 0 16px 16px; }
.jbh-contact-detail-group[hidden], .jbh-contact-context-note[hidden] { display: none !important; }
.jbh-contact-detail-group .jbh-contact-field:last-child { margin-bottom: 0; }
.jbh-contact-field-label { font-family: var(--jbh-font-mono); font-size: 11px; font-weight: 700; color: var(--jbh-creme); text-transform: uppercase; letter-spacing: 0.1em; }
/* Enhanced Form Inputs & Placeholders */
.jbh-contact-input, .jbh-contact-textarea { width: 100%; padding: 14px 16px; background: var(--jbh-bg); border: 1px solid var(--jbh-border); border-radius: 6px; font-family: var(--jbh-font-sans); font-size: 15px; line-height: 1.5; min-height: 52px; color: var(--jbh-card-heading); transition: border-color 0.2s ease, box-shadow 0.2s ease; outline: none; -webkit-appearance: none; appearance: none; }
.jbh-contact-textarea { min-height: 120px; resize: vertical; }
.jbh-contact-input::placeholder, .jbh-contact-textarea::placeholder { color: var(--jbh-slate); opacity: 0.6; font-weight: 400; }
.jbh-contact-input:focus, .jbh-contact-textarea:focus { border-color: var(--jbh-custom-icon, var(--jbh-teal)); box-shadow: 0 0 0 3px rgba(42,157,143,0.15); }

/* Structured Routing Select Dropdown */
.jbh-select-wrapper { position: relative; width: 100%; }
.jbh-select-wrapper::after { content: ""; position: absolute; right: 16px; top: 50%; transform: translateY(-50%); width: 12px; height: 12px; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 24 24' stroke='%23778899'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M19 9l-7 7-7-7'%3E%3C/path%3E%3C/svg%3E"); background-size: contain; background-repeat: no-repeat; pointer-events: none; opacity: 0.7; transition: transform 0.2s ease; }
.jbh-contact-select { padding-right: 40px; cursor: pointer; }
.jbh-contact-select:focus + .jbh-select-wrapper::after { transform: translateY(-50%) rotate(180deg); }
.jbh-contact-select option { background: var(--jbh-card); color: var(--jbh-card-heading); }

/* Mobile Touch Target Optimizations */
@media (max-width: 768px) {
    .jbh-contact-input, .jbh-contact-textarea { font-size: 16px; /* Prevents iOS auto-zoom on focus */ padding: 16px; }
}

/* Force correct Text/Label mapping under Site-Light Conditions */
:is(.jbh-light, html[data-theme="light"], html.light, body[data-ct-color-mode="light"]) .jbh-contact-field-label { color: var(--jbh-text-color); }
:is(.jbh-light, html[data-theme="light"], html.light, body[data-ct-color-mode="light"]) .jbh-contact-input,
:is(.jbh-light, html[data-theme="light"], html.light, body[data-ct-color-mode="light"]) .jbh-contact-textarea { color: var(--jbh-card-heading); }

/* Mobile Responsive Cascade */
@media(max-width: 900px) {
	.jbh-contact-grid { grid-template-columns: 1fr; gap: 48px; }
}
@media(max-width: 768px) {
	.jbh-contact-section { padding: 60px 20px; }
	.jbh-contact-form-wrap { padding: 32px; }
}
@media(max-width: 600px) {
	.jbh-contact-section { padding: 40px 16px; }
	.jbh-contact-form-wrap { padding: 24px; }
	.jbh-contact-heading { font-size: 32px; }
	.jbh-contact-icon { width: 48px; height: 48px; }
}

@media (max-width: 640px) {
	.jbh-contact-field-grid { grid-template-columns: 1fr; gap: 0; margin-bottom: 0; }
	.jbh-contact-field-grid .jbh-contact-field { margin-bottom: 24px; }
}

/* ================================================================
   19. CONTACT SUCCESS STATE
   ================================================================ */
.jbh-contact-success-state { display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; padding: 48px 24px; animation: jbhFadeIn 0.5s ease; height: 100%; min-height: 400px; }
.jbh-success-icon { width: 64px; height: 64px; border-radius: 50%; background: rgba(42,157,143,0.15); color: var(--jbh-custom-icon, var(--jbh-teal)); display: flex; align-items: center; justify-content: center; margin-bottom: 24px; }
.jbh-success-icon svg { width: 32px; height: 32px; }
.jbh-success-title { font-family: var(--jbh-font-serif); font-size: 28px; color: var(--jbh-custom-header, var(--jbh-card-heading)); margin: 0 0 12px; }
.jbh-success-desc { color: var(--jbh-custom-desc, var(--jbh-text-color)); font-size: 16px; line-height: 1.6; max-width: 400px; margin: 0 auto; }

@keyframes jbhFadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }

/* ================================================================
   20. CONTACT SECTION BUTTON COLORS
   ================================================================ */
/* Idle state (without hover) defaults to var(--jbh-teal) and #ffffff.
   Hover state defaults to whatever the idle state is set to, 
   ensuring it never flashes transparent if the user forgets to set a hover color.
*/
.jbh-contact-section .jbh-get-started-btn {
    background: var(--jbh-custom-btn, var(--jbh-teal)) !important;
    color: var(--jbh-custom-btn-text, #ffffff) !important;
    border-color: var(--jbh-custom-btn, var(--jbh-teal)) !important;
}

.jbh-contact-section .jbh-get-started-btn:hover,
.jbh-contact-section .jbh-get-started-btn:focus-visible {
    background: var(--jbh-custom-btn-hover, var(--jbh-custom-btn, var(--jbh-teal-dark))) !important;
    color: var(--jbh-custom-btn-hover-text, var(--jbh-custom-btn-text, #ffffff)) !important;
    border-color: var(--jbh-custom-btn-hover, var(--jbh-custom-btn, var(--jbh-teal-dark))) !important;
}

/* ================================================================
   21. JBH TESTIMONIALS — premium carousel with dark/light mode
   ================================================================
   Token strategy (v1.2.4 — invert-aware to match every other JBH
   block and the modal cascade):
   - DARK palette is the CANONICAL default. Declared on
     `.jbh-testimonials.jbh-dark, .jbh-testimonials.jbh-auto` plus the
     explicit dark-signal selectors. This matches `:root` (which is
     dark) and the four nuclear-shield cases at L946-1413 — a no-
     signal site renders the block dark, exactly like every other JBH
     block.
   - LIGHT palette REBINDS on lock OR on any auto+light signal.
   - Every site-signal selector is qualified with `:not([data-jbh-invert])`
     for STANDARD mode, AND a mirror set with `[data-jbh-invert]` and
     OPPOSITE signal is added for INVERTED mode. The plugin's admin
     "Invert color mode" toggle (Settings → JBH Starter Blocks →
     General → Frontend Enhancements) writes `data-jbh-invert="1"`
     onto `<html>`, which flips the palette: site dark → block light
     and site light → block dark. Mirrors the modal.css cascade at
     L78-128 and the nuclear shield at L946-1413 so testimonials
     follows the invert toggle in lock-step with studio-grid /
     hero-section / cta-banner etc.
   - `.jbh-override-theme` short-circuits the signal rebinding: a
     locked block ignores site-level theme switches AND the invert
     toggle. Use it for hero testimonials that must always read on
     a specific palette regardless of site mode.
   - `@media (prefers-color-scheme: ...)` provides a last-resort
     rebinding for auto blocks on themes that broadcast NO signal at
     all. The media query also branches on invert state so OS-level
     auto-detection stays consistent with the toggle.
   - The carousel JS reads behaviour flags from `data-jbh-*` attributes
     on the root <section>, so no per-block JSON localisation is needed.
   ================================================================ */

.jbh-testimonials {
    /* Behaviour / sizing custom properties (set inline from render.php) */
    --jbh-tst-card-radius: 20px;
    --jbh-tst-card-padding: 24px;
    --jbh-tst-avatar-size: 48px;
    --jbh-tst-gap: 24px;
    --jbh-tst-gap-mobile: 16px;
    --jbh-tst-pad-x: 50px;
    --jbh-tst-pad-x-mobile: 14px;
    --jbh-tst-max-width: 1240px;
    --jbh-tst-slides: 3;
    --jbh-tst-slides-tablet: 2;
    --jbh-tst-slides-mobile: 1;
    --jbh-tst-nav-size: 44px;

    /* Layout — mode-agnostic. Palette resolvers below only touch
       colour tokens, never sizing or layout properties. Block bg
       marked `!important` so inspector-picked Block Background survives
       host-theme overrides (mirrors tools-resources fix). */
    position: relative;
    margin: 50px auto;
    max-width: var(--jbh-tst-max-width);
    padding: 0 var(--jbh-tst-pad-x);
    box-sizing: border-box;
    background: var(--tst-block-bg) !important;
    font-family: var(--jbh-font-sans, inherit);
}

/* Dark palette resolver — canonical default + lock + invert-aware.
   Selector list expands to:
     1) Locked dark / auto block (canonical no-signal default)
     2) STANDARD: site DARK → block DARK (html-level signals)
     3) STANDARD: site DARK → block DARK (body-level signals)
     4) INVERTED: site LIGHT → block DARK (html-level signals)
     5) INVERTED: site LIGHT → block DARK (body-level signals)
     6) `.is-jbh-dark-mode` JS lock (future-proofed)
   `:is()` grouping keeps the rule readable; per-alternative
   specificity is constant so `:is()` doesn't introduce surprises. */
.jbh-testimonials.jbh-dark,
.jbh-testimonials.jbh-auto,
.jbh-testimonials.is-jbh-dark-mode,
:is(
    html:not([data-jbh-invert])[data-theme="dark"],
    html:not([data-jbh-invert]).dark,
    html:not([data-jbh-invert])[data-color-mode="dark"],
    html[data-jbh-invert][data-theme="light"],
    html[data-jbh-invert].light,
    html[data-jbh-invert][data-color-mode="light"]
) .jbh-testimonials.jbh-auto:not(.jbh-override-theme),
html:not([data-jbh-invert]) :is(
    body[data-theme="dark"],
    body[data-color-mode="dark"],
    body[data-ct-color-mode="dark"],
    body.ct-dark-mode,
    body.dark-mode
) .jbh-testimonials.jbh-auto:not(.jbh-override-theme),
html[data-jbh-invert] :is(
    body[data-theme="light"],
    body[data-color-mode="light"],
    body[data-ct-color-mode="light"],
    body.ct-light-mode,
    body.light-mode
) .jbh-testimonials.jbh-auto:not(.jbh-override-theme) {
    --tst-card-bg:       var(--jbh-tst-card-bg-dk, #1a1a1a);
    --tst-card-border:   var(--jbh-tst-card-border-dk, rgba(148, 163, 184, 0.18));
    --tst-card-shadow:   0 10px 28px rgba(0, 0, 0, 0.32);
    --tst-card-shadow-h: 0 18px 40px rgba(0, 191, 179, 0.16);
    --tst-name:          var(--jbh-tst-name-dk, #f8fafc);
    --tst-role:          var(--jbh-tst-role-dk, #ff8b86);
    --tst-quote:         var(--jbh-tst-quote-dk, #cbd5e1);
    --tst-bar-border:    var(--jbh-tst-bar-border-dk, rgba(148, 163, 184, 0.22));
    --tst-nav-bg:        var(--jbh-tst-nav-bg-dk, #1a1a1a);
    --tst-nav-color:     var(--jbh-tst-nav-color-dk, #f8fafc);
    --tst-nav-hover-bg:  var(--jbh-tst-nav-hover-bg-dk, var(--jbh-teal, #00bfb3));
    --tst-nav-hover-cl:  var(--jbh-tst-nav-hover-color-dk, #ffffff);
    --tst-avatar-border: rgba(255, 255, 255, 0.10);
    --tst-glow:          rgba(0, 191, 179, 0.18);
    --tst-block-bg:      var(--jbh-tst-block-bg-dk, transparent);
    --tst-heading:       var(--jbh-tst-heading-dk, #f8fafc);
    --tst-subtitle:      var(--jbh-tst-subtitle-dk, #cbd5e1);
}

/* Light palette rebinding — lock + invert-aware (mirror of the
   dark resolver above with opposite signals). */
.jbh-testimonials.jbh-light,
.jbh-testimonials.is-jbh-light-mode,
:is(
    html:not([data-jbh-invert])[data-theme="light"],
    html:not([data-jbh-invert]).light,
    html:not([data-jbh-invert])[data-color-mode="light"],
    html[data-jbh-invert][data-theme="dark"],
    html[data-jbh-invert].dark,
    html[data-jbh-invert][data-color-mode="dark"]
) .jbh-testimonials.jbh-auto:not(.jbh-override-theme),
html:not([data-jbh-invert]) :is(
    body[data-theme="light"],
    body[data-color-mode="light"],
    body[data-ct-color-mode="light"],
    body.ct-light-mode,
    body.light-mode
) .jbh-testimonials.jbh-auto:not(.jbh-override-theme),
html[data-jbh-invert] :is(
    body[data-theme="dark"],
    body[data-color-mode="dark"],
    body[data-ct-color-mode="dark"],
    body.ct-dark-mode,
    body.dark-mode
) .jbh-testimonials.jbh-auto:not(.jbh-override-theme) {
    --tst-card-bg:       var(--jbh-tst-card-bg-lt, #ffffff);
    --tst-card-border:   var(--jbh-tst-card-border-lt, #edf1f5);
    --tst-card-shadow:   0 6px 18px rgba(15, 23, 42, 0.04);
    --tst-card-shadow-h: 0 16px 32px rgba(0, 191, 179, 0.10);
    --tst-name:          var(--jbh-tst-name-lt, #0f172a);
    --tst-role:          var(--jbh-tst-role-lt, #ff8b86);
    --tst-quote:         var(--jbh-tst-quote-lt, #475569);
    --tst-bar-border:    var(--jbh-tst-bar-border-lt, #e8eef5);
    --tst-nav-bg:        var(--jbh-tst-nav-bg-lt, #ffffff);
    --tst-nav-color:     var(--jbh-tst-nav-color-lt, #172033);
    --tst-nav-hover-bg:  var(--jbh-tst-nav-hover-bg-lt, var(--jbh-teal, #00bfb3));
    --tst-nav-hover-cl:  var(--jbh-tst-nav-hover-color-lt, #ffffff);
    --tst-avatar-border: #ffffff;
    --tst-glow:          rgba(0, 191, 179, 0.12);
    --tst-block-bg:      var(--jbh-tst-block-bg-lt, transparent);
    --tst-heading:       var(--jbh-tst-heading-lt, #0f172a);
    --tst-subtitle:      var(--jbh-tst-subtitle-lt, #475569);
}

/* prefers-color-scheme last-resort for auto-mode blocks on themes
   that broadcast NO signal at all. Branches on invert state so OS-
   level auto-detection stays consistent with the admin toggle:
   - STANDARD (invert OFF): OS light → block light
   - INVERTED (invert ON):  OS dark  → block light (because OS dark
                            + invert means the block flips opposite
                            to the OS) */
@media (prefers-color-scheme: light) {
    html:not([data-jbh-invert]):not([data-theme]):not(.dark):not(.light):not([data-color-mode]) body:not([data-theme]):not([data-color-mode]):not([data-ct-color-mode]):not(.ct-light-mode):not(.ct-dark-mode):not(.light-mode):not(.dark-mode) .jbh-testimonials.jbh-auto:not(.jbh-override-theme) {
        --tst-card-bg:       var(--jbh-tst-card-bg-lt, #ffffff);
        --tst-card-border:   var(--jbh-tst-card-border-lt, #edf1f5);
        --tst-card-shadow:   0 6px 18px rgba(15, 23, 42, 0.04);
        --tst-card-shadow-h: 0 16px 32px rgba(0, 191, 179, 0.10);
        --tst-name:          var(--jbh-tst-name-lt, #0f172a);
        --tst-role:          var(--jbh-tst-role-lt, #ff8b86);
        --tst-quote:         var(--jbh-tst-quote-lt, #475569);
        --tst-bar-border:    var(--jbh-tst-bar-border-lt, #e8eef5);
        --tst-nav-bg:        var(--jbh-tst-nav-bg-lt, #ffffff);
        --tst-nav-color:     var(--jbh-tst-nav-color-lt, #172033);
        --tst-nav-hover-bg:  var(--jbh-tst-nav-hover-bg-lt, var(--jbh-teal, #00bfb3));
        --tst-nav-hover-cl:  var(--jbh-tst-nav-hover-color-lt, #ffffff);
        --tst-avatar-border: #ffffff;
        --tst-glow:          rgba(0, 191, 179, 0.12);
        --tst-block-bg:      var(--jbh-tst-block-bg-lt, transparent);
        --tst-heading:       var(--jbh-tst-heading-lt, #0f172a);
        --tst-subtitle:      var(--jbh-tst-subtitle-lt, #475569);
    }
}
@media (prefers-color-scheme: dark) {
    html[data-jbh-invert]:not([data-theme]):not(.dark):not(.light):not([data-color-mode]) body:not([data-theme]):not([data-color-mode]):not([data-ct-color-mode]):not(.ct-light-mode):not(.ct-dark-mode):not(.light-mode):not(.dark-mode) .jbh-testimonials.jbh-auto:not(.jbh-override-theme) {
        --tst-card-bg:       var(--jbh-tst-card-bg-lt, #ffffff);
        --tst-card-border:   var(--jbh-tst-card-border-lt, #edf1f5);
        --tst-card-shadow:   0 6px 18px rgba(15, 23, 42, 0.04);
        --tst-card-shadow-h: 0 16px 32px rgba(0, 191, 179, 0.10);
        --tst-name:          var(--jbh-tst-name-lt, #0f172a);
        --tst-role:          var(--jbh-tst-role-lt, #ff8b86);
        --tst-quote:         var(--jbh-tst-quote-lt, #475569);
        --tst-bar-border:    var(--jbh-tst-bar-border-lt, #e8eef5);
        --tst-nav-bg:        var(--jbh-tst-nav-bg-lt, #ffffff);
        --tst-nav-color:     var(--jbh-tst-nav-color-lt, #172033);
        --tst-nav-hover-bg:  var(--jbh-tst-nav-hover-bg-lt, var(--jbh-teal, #00bfb3));
        --tst-nav-hover-cl:  var(--jbh-tst-nav-hover-color-lt, #ffffff);
        --tst-avatar-border: #ffffff;
        --tst-glow:          rgba(0, 191, 179, 0.12);
        --tst-block-bg:      var(--jbh-tst-block-bg-lt, transparent);
        --tst-heading:       var(--jbh-tst-heading-lt, #0f172a);
        --tst-subtitle:      var(--jbh-tst-subtitle-lt, #475569);
    }
}

/* Optional section heading row.
   Heading/subtitle colours are nested under `.jbh-testimonials` AND
   marked `!important` so they ALWAYS win against host-theme rules
   like `.entry-content h2.wp-block-heading` (specificity 0,0,2,1) or
   `body.dark .entry-content h2` (0,0,2,1) that would otherwise eat
   the inspector-picked colour on the live page. Mirrors the v1.2.4
   tools-resources fix at frontend.css:5236. */
.jbh-testimonials .jbh-tst-heading {
    text-align: center;
    margin: 0 auto 32px;
    max-width: 720px;
}
.jbh-testimonials .jbh-tst-heading-title {
    font-family: var(--jbh-font-serif, var(--jbh-font-sans, inherit));
    font-size: clamp(24px, 3vw, 36px);
    line-height: 1.2;
    margin: 0 0 12px;
    color: var(--tst-heading) !important;
}
.jbh-testimonials .jbh-tst-heading-subtitle {
    font-size: 15px;
    line-height: 1.55;
    margin: 0;
    color: var(--tst-subtitle) !important;
}

/* Carousel viewport + track */
.jbh-tst-viewport {
    overflow: hidden;
    width: 100%;
    position: relative;
    touch-action: pan-y;
    cursor: grab;
    user-select: none;
    box-sizing: border-box;
    opacity: 0;
    transition: opacity 0.3s ease-in;
}
.jbh-tst-viewport.is-jbh-ready { opacity: 1; }
.jbh-tst-viewport:active { cursor: grabbing; }
/* Keyboard focus ring — render.php sets tabindex="0" so keyboard
   users can focus the carousel viewport and steer with arrows. The
   default UA outline gets clipped by `overflow: hidden` above, so we
   draw a bright accent ring with a 2px offset that lives just outside
   the clipped area. */
.jbh-tst-viewport:focus { outline: none; }
.jbh-tst-viewport:focus-visible {
    outline: 2px solid var(--jbh-teal, #00bfb3);
    outline-offset: 4px;
    border-radius: 4px;
}

.jbh-tst-track {
    display: flex;
    flex-wrap: nowrap;
    gap: var(--jbh-tst-gap);
    width: 100%;
    margin: 0;
    padding: 16px 0;
    align-items: stretch;
    will-change: transform;
    transform: translate3d(0, 0, 0);
    backface-visibility: hidden;
    box-sizing: border-box;
}
.jbh-tst-track.jbh-tst-transition {
    transition: transform 0.5s cubic-bezier(0.25, 1, 0.5, 1);
}

/* Slide cells — width derived from the per-breakpoint slides-per-view CSS var.
   `.jbh-tst-clone` (added by the carousel JS to leading + trailing
   duplicate slides) is intentionally a marker-only class: clones must
   look identical to real slides for the infinite-loop illusion to hold,
   so they inherit every rule below by also carrying `.jbh-tst-slide`.
   No dedicated `.jbh-tst-clone` rule is needed. */
.jbh-tst-slide {
    flex: 0 0 calc((100% - (var(--jbh-tst-slides) - 1) * var(--jbh-tst-gap)) / var(--jbh-tst-slides));
    width: calc((100% - (var(--jbh-tst-slides) - 1) * var(--jbh-tst-gap)) / var(--jbh-tst-slides));
    max-width: calc((100% - (var(--jbh-tst-slides) - 1) * var(--jbh-tst-gap)) / var(--jbh-tst-slides));
    min-width: 0;
    box-sizing: border-box;
    display: flex;
    pointer-events: auto;
}

/* Card layout — bg/border marked `!important` so the inspector-
   picked Card Background / Card Border always win against host-theme
   block rules like `.wp-block .has-background` (0,0,2,0) or Blocksy's
   prefix-themed rules at 0,0,2,1+. */
.jbh-testimonials .jbh-tst-card {
    background: var(--tst-card-bg) !important;
    border: 1px solid var(--tst-card-border) !important;
    border-radius: var(--jbh-tst-card-radius);
    padding: var(--jbh-tst-card-padding);
    width: 100%;
    min-height: 100%;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    position: relative;
    box-shadow: var(--tst-card-shadow);
    transition: transform 0.35s ease, box-shadow 0.35s ease, border-color 0.35s ease, background 0.35s ease;
    overflow: hidden;
    box-sizing: border-box;
}

/* Card-style variants */
.jbh-testimonials.jbh-tst-card-flat .jbh-tst-card { box-shadow: none; }
.jbh-testimonials.jbh-tst-card-bordered .jbh-tst-card { box-shadow: none; border-width: 1.5px; }
.jbh-testimonials.jbh-tst-card-glass .jbh-tst-card {
    background: color-mix(in srgb, var(--tst-card-bg) 70%, transparent) !important;
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
}

/* Card-shape preset variants — only apply when no explicit radius was set */
.jbh-testimonials.jbh-tst-shape-sharp   .jbh-tst-card { border-radius: 0; }
.jbh-testimonials.jbh-tst-shape-rounded .jbh-tst-card { border-radius: 8px; }
.jbh-testimonials.jbh-tst-shape-pill    .jbh-tst-card { border-radius: 28px; }
/* `soft` uses the inline --jbh-tst-card-radius (default 20px) */

/* Glow halo behind card */
.jbh-testimonials.jbh-tst-has-glow .jbh-tst-card::before {
    content: "";
    position: absolute;
    inset: 0;
    background: radial-gradient(circle at top right, var(--tst-glow), transparent 38%);
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.35s ease;
}
.jbh-testimonials.jbh-tst-has-glow .jbh-tst-card:hover::before { opacity: 1; }

/* Hover effects — `border-color` declarations need `!important` so
   they can override the base card rule which is now `!important` to
   defend against host themes. */
.jbh-testimonials.jbh-tst-hover-lift  .jbh-tst-card:hover {
    transform: translateY(-5px);
    border-color: var(--jbh-teal, #00bfb3) !important;
    box-shadow: var(--tst-card-shadow-h);
}
.jbh-testimonials.jbh-tst-hover-scale .jbh-tst-card:hover {
    transform: scale(1.02);
    border-color: var(--jbh-teal, #00bfb3) !important;
    box-shadow: var(--tst-card-shadow-h);
}
.jbh-testimonials.jbh-tst-hover-glow  .jbh-tst-card:hover {
    border-color: var(--jbh-teal, #00bfb3) !important;
    box-shadow: 0 0 0 1px var(--jbh-teal, #00bfb3), var(--tst-card-shadow-h);
}
/* .jbh-tst-hover-none — no transform */

.jbh-tst-card-inner { display: flex; flex-direction: column; flex: 1 1 auto; }

/* Profile row */
.jbh-tst-profile {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-bottom: 16px;
    position: relative;
    z-index: 1;
    min-width: 0;
}
.jbh-tst-avatar {
    width: var(--jbh-tst-avatar-size);
    height: var(--jbh-tst-avatar-size);
    flex: 0 0 var(--jbh-tst-avatar-size);
    border-radius: 50%;
    overflow: hidden;
    background: rgba(148, 163, 184, 0.08);
    display: flex;
    align-items: center;
    justify-content: center;
}
.jbh-testimonials.jbh-tst-avatar-rounded .jbh-tst-avatar { border-radius: 12px; }
.jbh-testimonials.jbh-tst-avatar-square  .jbh-tst-avatar { border-radius: 0; }

.jbh-tst-avatar img {
    width: 100%;
    height: 100%;
    border-radius: inherit;
    object-fit: cover;
    border: 2px solid var(--tst-avatar-border);
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.20);
    transition: border-color 0.35s ease;
    display: block;
    box-sizing: border-box;
}
.jbh-tst-card:hover .jbh-tst-avatar img { border-color: var(--jbh-teal, #00bfb3); }

.jbh-testimonials .jbh-tst-avatar-placeholder { color: var(--tst-quote) !important; padding: 8px; }
.jbh-testimonials .jbh-tst-avatar-placeholder svg { width: 60%; height: 60%; opacity: 0.5; }

.jbh-testimonials .jbh-tst-identity { display: flex; flex-direction: column; min-width: 0; }
.jbh-testimonials .jbh-tst-name {
    margin: 0;
    font-size: 16px;
    font-weight: 700;
    color: var(--tst-name) !important;
    line-height: 1.2;
    overflow-wrap: anywhere;
    font-family: inherit;
}
.jbh-testimonials .jbh-tst-role {
    margin: 2px 0 0 0;
    font-size: 11px;
    color: var(--tst-role) !important;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.02em;
    line-height: 1.3;
    overflow-wrap: anywhere;
}

.jbh-testimonials .jbh-tst-quote {
    font-size: 14px;
    line-height: 1.65;
    color: var(--tst-quote) !important;
    margin: 0 0 16px;
    flex-grow: 1;
    position: relative;
    z-index: 1;
}

/* Action bar — border-top marked `!important` so inspector-picked
   Action Bar Border colour survives theme overrides. */
.jbh-testimonials .jbh-tst-actions {
    display: flex;
    justify-content: flex-end;
    align-items: center;
    margin-top: auto;
    padding-top: 12px;
    border-top: 1px dashed var(--tst-bar-border) !important;
    position: relative;
    z-index: 1;
    min-height: 32px;
}

/* Per-link-type pill colors. LinkedIn and Twitter retain their brand
   colors; Website + Email use the block accent so they harmonise with
   the rest of the design system. */
.jbh-tst-action {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    min-width: 32px;
    min-height: 32px;
    border-radius: 999px;
    text-decoration: none;
    transition: transform 0.25s ease, background-color 0.25s ease, box-shadow 0.25s ease;
    overflow: hidden;
    color: #ffffff;
}
.jbh-tst-action svg { width: 16px; height: 16px; display: block; fill: currentColor; flex: 0 0 16px; }

.jbh-tst-link-linkedin { background-color: #0a66c2; box-shadow: 0 4px 12px rgba(10, 102, 194, 0.22); }
.jbh-tst-link-linkedin:hover { background-color: #084f98; transform: scale(1.08) rotate(4deg); box-shadow: 0 6px 16px rgba(10, 102, 194, 0.32); }

.jbh-tst-link-twitter  { background-color: #0f172a; box-shadow: 0 4px 12px rgba(15, 23, 42, 0.25); }
.jbh-tst-link-twitter:hover { background-color: #000000; transform: scale(1.08) rotate(4deg); box-shadow: 0 6px 16px rgba(0, 0, 0, 0.35); }

.jbh-tst-link-website,
.jbh-tst-link-email {
    background-color: var(--jbh-teal, #00bfb3);
    box-shadow: 0 4px 12px color-mix(in srgb, var(--jbh-teal, #00bfb3) 28%, transparent);
}
.jbh-tst-link-website:hover,
.jbh-tst-link-email:hover {
    background-color: var(--jbh-teal-dark, #008d83);
    transform: scale(1.08) rotate(4deg);
    box-shadow: 0 6px 16px color-mix(in srgb, var(--jbh-teal, #00bfb3) 40%, transparent);
}

/* Navigation buttons — colours marked `!important` so inspector-
   picked Nav Background / Nav Color / Nav Hover colours survive
   theme overrides on the live page. */
.jbh-testimonials .jbh-tst-nav {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    width: var(--jbh-tst-nav-size);
    height: var(--jbh-tst-nav-size);
    background-color: var(--tst-nav-bg) !important;
    border: 1px solid var(--tst-card-border) !important;
    border-radius: 50%;
    color: var(--tst-nav-color) !important;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    z-index: 25;
    box-shadow: 0 8px 20px rgba(0, 0, 0, 0.25);
    transition: transform 0.3s ease, background-color 0.3s ease, color 0.3s ease, border-color 0.3s ease;
    padding: 0;
}
.jbh-testimonials .jbh-tst-nav svg { width: 22px; height: 22px; fill: currentColor; }
.jbh-testimonials .jbh-tst-nav:hover {
    background-color: var(--tst-nav-hover-bg) !important;
    color: var(--tst-nav-hover-cl) !important;
    border-color: var(--tst-nav-hover-bg) !important;
    transform: translateY(-50%) scale(1.1);
}
.jbh-tst-nav-prev { left: 0; }
.jbh-tst-nav-next { right: 0; }

.jbh-testimonials.jbh-tst-nav-rounded .jbh-tst-nav { border-radius: 12px; }
.jbh-testimonials.jbh-tst-nav-square  .jbh-tst-nav { border-radius: 0; }

/* Empty state — colours marked `!important` for theme-override
   resistance, matching the rest of testimonials. */
.jbh-testimonials .jbh-tst-empty {
    flex: 1;
    text-align: center;
    padding: 48px 24px;
    color: var(--tst-quote) !important;
    font-size: 14px;
    border: 1px dashed var(--tst-bar-border) !important;
    border-radius: var(--jbh-tst-card-radius);
}

/* Tablet — switch to tablet slides-per-view */
@media screen and (max-width: 1024px) {
    .jbh-testimonials { padding: 0 45px; }
    .jbh-tst-slide {
        flex: 0 0 calc((100% - (var(--jbh-tst-slides-tablet) - 1) * var(--jbh-tst-gap)) / var(--jbh-tst-slides-tablet));
        width:   calc((100% - (var(--jbh-tst-slides-tablet) - 1) * var(--jbh-tst-gap)) / var(--jbh-tst-slides-tablet));
        max-width: calc((100% - (var(--jbh-tst-slides-tablet) - 1) * var(--jbh-tst-gap)) / var(--jbh-tst-slides-tablet));
    }
}

/* Mobile — switch to mobile slides-per-view + move nav BELOW carousel.
   Every nav-related selector here is qualified with `.jbh-testimonials`
   so it matches the base rule's specificity (0,0,2,0 for plain, 0,0,3,0
   for `:hover`). Without that qualification the base rules at
   frontend.css:5076-5103 win the cascade tie-break and the nav buttons
   stay vertically centred ON the card area instead of dropping below
   — the v1.2.4 bug where editors reported "buttons inside the cards on
   mobile".
   Cards also get a tighter padding/typography pass so a single-column
   mobile testimonial reads as a compact card, not a full-bleed wall of
   text. */
@media screen and (max-width: 767px) {
    .jbh-testimonials {
        margin-top: 28px;
        margin-bottom: 80px;
        padding: 0 var(--jbh-tst-pad-x-mobile);
        max-width: 100%;
    }
    .jbh-tst-track {
        gap: var(--jbh-tst-gap-mobile);
        padding: 8px 0;
    }
    .jbh-tst-slide {
        flex: 0 0 calc((100% - (var(--jbh-tst-slides-mobile) - 1) * var(--jbh-tst-gap-mobile)) / var(--jbh-tst-slides-mobile));
        width:   calc((100% - (var(--jbh-tst-slides-mobile) - 1) * var(--jbh-tst-gap-mobile)) / var(--jbh-tst-slides-mobile));
        max-width: calc((100% - (var(--jbh-tst-slides-mobile) - 1) * var(--jbh-tst-gap-mobile)) / var(--jbh-tst-slides-mobile));
    }
    .jbh-testimonials .jbh-tst-card { padding: 18px 16px; border-radius: 16px; }
    .jbh-testimonials .jbh-tst-card-inner { gap: 0; }
    .jbh-testimonials .jbh-tst-profile { gap: 10px; margin-bottom: 12px; }
    .jbh-testimonials .jbh-tst-avatar { width: 40px; height: 40px; flex-basis: 40px; }
    .jbh-testimonials .jbh-tst-name { font-size: 14.5px; }
    .jbh-testimonials .jbh-tst-role { font-size: 10px; letter-spacing: 0.02em; }
    .jbh-testimonials .jbh-tst-quote { font-size: 13.5px; line-height: 1.6; margin-bottom: 12px; }
    .jbh-testimonials .jbh-tst-actions { padding-top: 10px; min-height: 28px; }
    .jbh-testimonials .jbh-tst-action { width: 30px; height: 30px; min-width: 30px; min-height: 30px; }
    .jbh-testimonials .jbh-tst-action svg { width: 14px; height: 14px; flex-basis: 14px; }
    .jbh-testimonials .jbh-tst-nav {
        top: auto;
        bottom: -56px;
        transform: none;
        width: 40px;
        height: 40px;
    }
    .jbh-testimonials .jbh-tst-nav svg { width: 18px; height: 18px; }
    .jbh-testimonials .jbh-tst-nav:hover { transform: scale(1.08); }
    .jbh-testimonials .jbh-tst-nav-prev { left: calc(50% - 50px); right: auto; }
    .jbh-testimonials .jbh-tst-nav-next { right: calc(50% - 50px); left: auto; }
}

@media screen and (max-width: 390px) {
    .jbh-testimonials { padding: 0 10px; margin-bottom: 76px; }
    .jbh-testimonials .jbh-tst-card { padding: 16px 14px; border-radius: 14px; }
    .jbh-testimonials .jbh-tst-profile { gap: 9px; margin-bottom: 10px; }
    .jbh-testimonials .jbh-tst-avatar { width: 38px; height: 38px; flex-basis: 38px; }
    .jbh-testimonials .jbh-tst-name { font-size: 14px; }
    .jbh-testimonials .jbh-tst-quote { font-size: 13px; line-height: 1.58; margin-bottom: 10px; }
    .jbh-testimonials .jbh-tst-actions { padding-top: 8px; }
}

/* Editor preview — show carousel as a static row so editors can see all cards */
.jbh-editor-testimonials .jbh-tst-viewport { opacity: 1; overflow: visible; cursor: default; }
.jbh-editor-testimonials .jbh-tst-track { transform: none !important; flex-wrap: wrap; }
.jbh-editor-testimonials .jbh-tst-slide { flex-basis: calc((100% - 32px) / 3); width: calc((100% - 32px) / 3); max-width: calc((100% - 32px) / 3); }
@media screen and (max-width: 1024px) {
    .jbh-editor-testimonials .jbh-tst-slide { flex-basis: calc((100% - 16px) / 2); width: calc((100% - 16px) / 2); max-width: calc((100% - 16px) / 2); }
}
@media screen and (max-width: 767px) {
    .jbh-editor-testimonials .jbh-tst-slide { flex-basis: 100%; width: 100%; max-width: 100%; }
}

/* ================================================================
   22. JBH TOOLS & RESOURCES — logo strip with dark/light swap
   ================================================================
   Each logo cell renders two <img> elements when colorMode=auto. The
   visible variant is chosen by the same theme-signal cascade used by
   the testimonials block above. When colorMode is locked to dark or
   light, only one variant is emitted to the DOM by render.php — the
   CSS swap rules here are still valid but never have a partner to
   hide.
   ================================================================ */

.jbh-tools-resources {
    /* Layout custom properties (set inline from render.php) */
    --jbh-tr-cols-d: 4;
    --jbh-tr-cols-t: 4;
    --jbh-tr-cols-m: 2;
    --jbh-tr-gap: 35px;
    --jbh-tr-gap-m: 14px;
    --jbh-tr-max-h: 60px;
    --jbh-tr-max-w: 200px;
    --jbh-tr-cell-h: 74px;
    --jbh-tr-pad-y: 50px;
    --jbh-tr-pad-x: 0px;

    /* Layout — spacings/positionings live here ONLY. They are mode-
       agnostic so a light-mode block renders identically to a dark-
       mode block at any breakpoint. The palette resolvers below only
       touch colour tokens, never sizing or layout properties. */
    position: relative;
    margin: 0 auto;
    padding: var(--jbh-tr-pad-y) var(--jbh-tr-pad-x);
    box-sizing: border-box;
    background: var(--tr-block-bg) !important;
    font-family: var(--jbh-font-sans, inherit);
    max-width: 100%;
}
.jbh-tools-resources *,
.jbh-tools-resources *::before,
.jbh-tools-resources *::after { box-sizing: border-box; }

/* Dark palette resolver — canonical default + lock + invert-aware.
   Selector list expands to:
     1) Locked dark / auto block (canonical no-signal default)
     2) STANDARD: site DARK → block DARK (html + body signals)
     3) INVERTED: site LIGHT → block DARK (html + body signals)
     4) `.is-jbh-dark-mode` JS lock (future-proofed)
   Matches the testimonials resolver at frontend.css:4608 and the
   modal cascade at modal.css:78-128 — the plugin's admin
   "Invert color mode" toggle (Settings → JBH Starter Blocks →
   General → Frontend Enhancements) writes `data-jbh-invert="1"`
   onto `<html>`, which this resolver honours so tools-resources
   flips palette in lock-step with studio-grid / hero-section etc. */
.jbh-tools-resources.jbh-dark,
.jbh-tools-resources.jbh-auto,
.jbh-tools-resources.is-jbh-dark-mode,
:is(
    html:not([data-jbh-invert])[data-theme="dark"],
    html:not([data-jbh-invert]).dark,
    html:not([data-jbh-invert])[data-color-mode="dark"],
    html[data-jbh-invert][data-theme="light"],
    html[data-jbh-invert].light,
    html[data-jbh-invert][data-color-mode="light"]
) .jbh-tools-resources.jbh-auto:not(.jbh-override-theme),
html:not([data-jbh-invert]) :is(
    body[data-theme="dark"],
    body[data-color-mode="dark"],
    body[data-ct-color-mode="dark"],
    body.ct-dark-mode,
    body.dark-mode
) .jbh-tools-resources.jbh-auto:not(.jbh-override-theme),
html[data-jbh-invert] :is(
    body[data-theme="light"],
    body[data-color-mode="light"],
    body[data-ct-color-mode="light"],
    body.ct-light-mode,
    body.light-mode
) .jbh-tools-resources.jbh-auto:not(.jbh-override-theme) {
    --tr-block-bg:    var(--jbh-tr-block-bg-dk, transparent);
    --tr-heading:     var(--jbh-tr-heading-dk, #f8fafc);
    --tr-count:       var(--jbh-tr-count-dk, var(--jbh-teal, #00bfb3));
    --tr-count-label: var(--jbh-tr-count-label-dk, #cbd5e1);
    --tr-subtitle:    var(--jbh-tr-subtitle-dk, #94a3b8);
    --tr-cell-bg:     var(--jbh-tr-cell-bg-dk, transparent);
    --tr-cell-border: var(--jbh-tr-cell-border-dk, transparent);
}

/* Light palette rebinding — lock + invert-aware (mirror of the
   dark resolver above with opposite signals). */
.jbh-tools-resources.jbh-light,
.jbh-tools-resources.is-jbh-light-mode,
:is(
    html:not([data-jbh-invert])[data-theme="light"],
    html:not([data-jbh-invert]).light,
    html:not([data-jbh-invert])[data-color-mode="light"],
    html[data-jbh-invert][data-theme="dark"],
    html[data-jbh-invert].dark,
    html[data-jbh-invert][data-color-mode="dark"]
) .jbh-tools-resources.jbh-auto:not(.jbh-override-theme),
html:not([data-jbh-invert]) :is(
    body[data-theme="light"],
    body[data-color-mode="light"],
    body[data-ct-color-mode="light"],
    body.ct-light-mode,
    body.light-mode
) .jbh-tools-resources.jbh-auto:not(.jbh-override-theme),
html[data-jbh-invert] :is(
    body[data-theme="dark"],
    body[data-color-mode="dark"],
    body[data-ct-color-mode="dark"],
    body.ct-dark-mode,
    body.dark-mode
) .jbh-tools-resources.jbh-auto:not(.jbh-override-theme) {
    --tr-block-bg:    var(--jbh-tr-block-bg-lt, transparent);
    --tr-heading:     var(--jbh-tr-heading-lt, #0f172a);
    --tr-count:       var(--jbh-tr-count-lt, var(--jbh-teal, #00bfb3));
    --tr-count-label: var(--jbh-tr-count-label-lt, #475569);
    --tr-subtitle:    var(--jbh-tr-subtitle-lt, #64748b);
    --tr-cell-bg:     var(--jbh-tr-cell-bg-lt, transparent);
    --tr-cell-border: var(--jbh-tr-cell-border-lt, transparent);
}

/* Header layouts */
.jbh-tr-header {
    margin-bottom: 32px;
}
.jbh-tools-resources.jbh-tr-header-centered .jbh-tr-header {
    text-align: center;
    max-width: 720px;
    margin-left: auto;
    margin-right: auto;
}
.jbh-tools-resources.jbh-tr-header-split .jbh-tr-header {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    align-items: center;
    gap: 24px;
}
.jbh-tools-resources.jbh-tr-header-split .jbh-tr-heading     { flex: 1 1 50%; margin: 0; text-align: left; }
.jbh-tools-resources.jbh-tr-header-split .jbh-tr-countup-wrap{ flex: 0 0 auto; text-align: right; }
.jbh-tools-resources.jbh-tr-header-split .jbh-tr-subtitle    { flex: 0 0 100%; text-align: left; }
.jbh-tools-resources.jbh-tr-header-inline .jbh-tr-header {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    align-items: baseline;
    gap: 14px;
}
.jbh-tools-resources.jbh-tr-header-inline .jbh-tr-heading {
    margin: 0;
}
.jbh-tools-resources.jbh-tr-header-inline .jbh-tr-countup {
    font-size: 1.4em;
    line-height: 1;
}
.jbh-tools-resources.jbh-tr-header-inline .jbh-tr-countup-label {
    flex: 1 1 100%;
    text-align: center;
    margin-top: 4px;
}

/* Aside layout — header section (heading + count-up + subtitle) sits
   to the LEFT of the logo grid on desktop and tablet, stacking on top
   of the logos on mobile. Matches the modern "social-proof beside
   logos" pattern requested in v1.2.3. Header text is left-aligned on
   desktop, recentred on mobile so the stacked layout still reads as a
   centered hero block. */
.jbh-tools-resources.jbh-tr-header-aside {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: clamp(32px, 5vw, 80px);
}
.jbh-tools-resources.jbh-tr-header-aside .jbh-tr-header {
    flex: 0 0 38%;
    max-width: 480px;
    margin-bottom: 0;
    text-align: left;
}
.jbh-tools-resources.jbh-tr-header-aside .jbh-tr-heading,
.jbh-tools-resources.jbh-tr-header-aside .jbh-tr-countup-label,
.jbh-tools-resources.jbh-tr-header-aside .jbh-tr-subtitle {
    text-align: left;
    margin-left: 0;
    margin-right: 0;
    max-width: none;
}
.jbh-tools-resources.jbh-tr-header-aside .jbh-tr-grid {
    flex: 1 1 0;
    min-width: 0;
}

/* Heading / count-up / subtitle text colours.
   Nested under `.jbh-tools-resources` so the selector specificity is
   0,0,2,0 — beats most host-theme rules that style typographic
   elements with a class+tag selector such as `.entry-content h2`
   (0,0,1,1). For aggressive themes that ship higher-specificity rules
   (Blocksy, Kadence, Astra prefix selectors at 0,0,2,1+), the colour
   declarations are marked `!important` so the inspector-picked
   Heading / Count / Subtitle colour ALWAYS wins on the live page.
   This is the same protection contact-section uses (frontend.css:4530)
   and was the v1.2.3 live-preview color-not-applying bug. */
.jbh-tools-resources .jbh-tr-heading {
    font-family: var(--jbh-font-serif, var(--jbh-font-sans, inherit));
    font-size: clamp(22px, 2.6vw, 32px);
    line-height: 1.2;
    margin: 0 0 16px;
    color: var(--tr-heading) !important;
    font-weight: 700;
}

.jbh-tools-resources .jbh-tr-countup-wrap { margin-bottom: 12px; }

/* `.jbh-tr-countup-animate` is a marker-only class added when
   `countUpAnimate` is true; the frontend count-up IIFE
   (assets/js/frontend.js) queries for it to know which numbers to
   animate on scroll. No dedicated CSS is required — visual styling
   lives on the parent `.jbh-tr-countup` class below. */
.jbh-tools-resources .jbh-tr-countup {
    font-family: var(--jbh-font-serif, var(--jbh-font-sans, inherit));
    font-size: clamp(36px, 6vw, 56px);
    line-height: 1;
    font-weight: 800;
    color: var(--tr-count) !important;
    margin: 0 0 6px;
    letter-spacing: -0.02em;
}
.jbh-tools-resources .jbh-tr-countup-label {
    margin: 0;
    font-size: 14px;
    line-height: 1.5;
    color: var(--tr-count-label) !important;
    max-width: 480px;
    margin-left: auto;
    margin-right: auto;
}
.jbh-tools-resources.jbh-tr-header-split .jbh-tr-countup-label { margin-left: auto; margin-right: 0; }

.jbh-tools-resources .jbh-tr-subtitle {
    margin: 0;
    font-size: 14px;
    line-height: 1.55;
    color: var(--tr-subtitle) !important;
    max-width: 540px;
    margin-left: auto;
    margin-right: auto;
}

/* Logo grid — base layout (Row).
   The default is a single horizontal flexbox row that matches the
   source HTML sample exactly: full container width, no card chrome,
   logos centred with per-tool sizing applied via inline style from
   render.php.
   `.jbh-tr-layout-grid` and `.jbh-tr-layout-compact` opt out of the
   default and apply their own display rules below. */
.jbh-tr-grid {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    align-items: center;
    column-gap: var(--jbh-tr-gap);
    row-gap: var(--jbh-tr-gap);
    width: 100%;
    max-width: 100%;
}

.jbh-tr-cell {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: 1 1 0;
    min-width: 0;
    min-height: var(--jbh-tr-cell-h);
    padding: 0;
    background: transparent;
    border: 0 solid transparent;
    border-radius: 0;
    transition: transform 0.3s ease, background-color 0.3s ease, border-color 0.3s ease, filter 0.3s ease;
    text-decoration: none;
    color: inherit;
}
a.jbh-tr-cell { cursor: pointer; }

/* Grid layout — bordered cards on a CSS grid. Restores the card chrome
   that the row layout strips out, and switches to grid display so
   columns stay even regardless of logo aspect ratio. */
.jbh-tools-resources.jbh-tr-layout-grid .jbh-tr-grid {
    display: grid;
    grid-template-columns: repeat(var(--jbh-tr-cols-d), 1fr);
    justify-items: center;
}
.jbh-tools-resources.jbh-tr-layout-grid .jbh-tr-cell {
    flex: 0 0 auto;
    width: 100%;
    background: var(--tr-cell-bg) !important;
    border: 1px solid var(--tr-cell-border) !important;
    border-radius: 8px;
    padding: 8px;
}

/* Compact layout — tight inline strip with reduced gaps and a smaller
   cell height. Useful for footer credit rows or inline tool callouts. */
.jbh-tools-resources.jbh-tr-layout-compact .jbh-tr-grid {
    column-gap: calc(var(--jbh-tr-gap) * 0.55);
    row-gap: calc(var(--jbh-tr-gap) * 0.55);
}
.jbh-tools-resources.jbh-tr-layout-compact .jbh-tr-cell {
    min-height: calc(var(--jbh-tr-cell-h) * 0.78);
    flex: 0 1 auto;
}
.jbh-tools-resources.jbh-tr-layout-compact .jbh-tr-logo {
    max-height: calc(var(--jbh-tr-max-h) * 0.78);
}

.jbh-tr-figure {
    margin: 0;
    padding: 0;
    width: 100%;
    height: 100%;
    display: flex;
    justify-content: center;
    align-items: center;
    overflow: visible;
    position: relative;
}

.jbh-tr-logo {
    display: block;
    width: auto;
    height: auto;
    max-width: var(--jbh-tr-max-w);
    max-height: var(--jbh-tr-max-h);
    object-fit: contain;
    transform-origin: center center;
    transition: filter 0.3s ease, transform 0.3s ease, opacity 0.3s ease;
}

/* Typographic fallback for cells without an uploaded logo. Rendered
   by render.php whenever both `darkLogo` and `lightLogo` are empty
   strings (e.g. a fresh install on a build that doesn't bundle the
   /images/ directory, or a brand the editor just added but hasn't
   uploaded artwork for yet). Uses the block heading colour token so
   it picks up the user's inspector colours and still flips with the
   palette resolver. Sized in CH units rather than px so the label
   reads at parity with the visible logos in the same row regardless
   of locale. */
.jbh-tools-resources .jbh-tr-logo-fallback {
    display: inline-block;
    padding: 8px 14px;
    color: var(--tr-heading) !important;
    font-family: var(--jbh-font-mono, monospace);
    font-size: 13px;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    border: 1px dashed var(--tr-cell-border, color-mix(in srgb, var(--tr-heading, #94a3b8) 35%, transparent)) !important;
    border-radius: 6px;
    opacity: 0.78;
    transition: opacity 0.3s ease, border-color 0.3s ease;
}
.jbh-tools-resources a.jbh-tr-cell:hover .jbh-tr-logo-fallback,
.jbh-tools-resources .jbh-tr-cell:hover .jbh-tr-logo-fallback {
    opacity: 1;
}

/* Theme-based logo swap. When both variants are in the DOM
   (colorMode=auto), the dark-mode logo is visible by default and
   hidden once the block resolves to light. The selector list mirrors
   the palette resolvers above so the logo swap stays in lock-step
   with the colour swap — both honour the "Invert color mode" admin
   toggle. When only one variant exists (colorMode locked), these
   rules become no-ops. */
.jbh-tr-logo-dark  { display: block; }
.jbh-tr-logo-light { display: none; }

/* Hide the DARK logo whenever the block resolves to LIGHT. */
.jbh-tools-resources.jbh-light .jbh-tr-logo-dark,
.jbh-tools-resources.is-jbh-light-mode .jbh-tr-logo-dark,
:is(
    html:not([data-jbh-invert])[data-theme="light"],
    html:not([data-jbh-invert]).light,
    html:not([data-jbh-invert])[data-color-mode="light"],
    html[data-jbh-invert][data-theme="dark"],
    html[data-jbh-invert].dark,
    html[data-jbh-invert][data-color-mode="dark"]
) .jbh-tools-resources.jbh-auto:not(.jbh-override-theme) .jbh-tr-logo-dark,
html:not([data-jbh-invert]) :is(
    body[data-theme="light"],
    body[data-color-mode="light"],
    body[data-ct-color-mode="light"],
    body.ct-light-mode,
    body.light-mode
) .jbh-tools-resources.jbh-auto:not(.jbh-override-theme) .jbh-tr-logo-dark,
html[data-jbh-invert] :is(
    body[data-theme="dark"],
    body[data-color-mode="dark"],
    body[data-ct-color-mode="dark"],
    body.ct-dark-mode,
    body.dark-mode
) .jbh-tools-resources.jbh-auto:not(.jbh-override-theme) .jbh-tr-logo-dark { display: none; }

/* Show the LIGHT logo whenever the block resolves to LIGHT. */
.jbh-tools-resources.jbh-light .jbh-tr-logo-light,
.jbh-tools-resources.is-jbh-light-mode .jbh-tr-logo-light,
:is(
    html:not([data-jbh-invert])[data-theme="light"],
    html:not([data-jbh-invert]).light,
    html:not([data-jbh-invert])[data-color-mode="light"],
    html[data-jbh-invert][data-theme="dark"],
    html[data-jbh-invert].dark,
    html[data-jbh-invert][data-color-mode="dark"]
) .jbh-tools-resources.jbh-auto:not(.jbh-override-theme) .jbh-tr-logo-light,
html:not([data-jbh-invert]) :is(
    body[data-theme="light"],
    body[data-color-mode="light"],
    body[data-ct-color-mode="light"],
    body.ct-light-mode,
    body.light-mode
) .jbh-tools-resources.jbh-auto:not(.jbh-override-theme) .jbh-tr-logo-light,
html[data-jbh-invert] :is(
    body[data-theme="dark"],
    body[data-color-mode="dark"],
    body[data-ct-color-mode="dark"],
    body.ct-dark-mode,
    body.dark-mode
) .jbh-tools-resources.jbh-auto:not(.jbh-override-theme) .jbh-tr-logo-light { display: block; }

/* prefers-color-scheme last-resort for auto mode with no theme
   attributes. Branches on invert state:
     STANDARD (invert OFF) + OS light → block light (swap to light logo)
     INVERTED (invert ON)  + OS dark  → block light (swap to light logo)
   The palette tokens are rebound to the light variant in BOTH
   branches so the cascade stays consistent with the swap. */
@media (prefers-color-scheme: light) {
    html:not([data-jbh-invert]):not([data-theme]):not(.dark):not(.light):not([data-color-mode]) body:not([data-theme]):not([data-color-mode]):not([data-ct-color-mode]):not(.ct-light-mode):not(.ct-dark-mode):not(.light-mode):not(.dark-mode) .jbh-tools-resources.jbh-auto:not(.jbh-override-theme) .jbh-tr-logo-dark  { display: none; }
    html:not([data-jbh-invert]):not([data-theme]):not(.dark):not(.light):not([data-color-mode]) body:not([data-theme]):not([data-color-mode]):not([data-ct-color-mode]):not(.ct-light-mode):not(.ct-dark-mode):not(.light-mode):not(.dark-mode) .jbh-tools-resources.jbh-auto:not(.jbh-override-theme) .jbh-tr-logo-light { display: block; }
    html:not([data-jbh-invert]):not([data-theme]):not(.dark):not(.light):not([data-color-mode]) body:not([data-theme]):not([data-color-mode]):not([data-ct-color-mode]):not(.ct-light-mode):not(.ct-dark-mode):not(.light-mode):not(.dark-mode) .jbh-tools-resources.jbh-auto:not(.jbh-override-theme) {
        --tr-block-bg:    var(--jbh-tr-block-bg-lt, transparent);
        --tr-heading:     var(--jbh-tr-heading-lt, #0f172a);
        --tr-count:       var(--jbh-tr-count-lt, var(--jbh-teal, #00bfb3));
        --tr-count-label: var(--jbh-tr-count-label-lt, #475569);
        --tr-subtitle:    var(--jbh-tr-subtitle-lt, #64748b);
        --tr-cell-bg:     var(--jbh-tr-cell-bg-lt, transparent);
        --tr-cell-border: var(--jbh-tr-cell-border-lt, transparent);
    }
}
@media (prefers-color-scheme: dark) {
    html[data-jbh-invert]:not([data-theme]):not(.dark):not(.light):not([data-color-mode]) body:not([data-theme]):not([data-color-mode]):not([data-ct-color-mode]):not(.ct-light-mode):not(.ct-dark-mode):not(.light-mode):not(.dark-mode) .jbh-tools-resources.jbh-auto:not(.jbh-override-theme) .jbh-tr-logo-dark  { display: none; }
    html[data-jbh-invert]:not([data-theme]):not(.dark):not(.light):not([data-color-mode]) body:not([data-theme]):not([data-color-mode]):not([data-ct-color-mode]):not(.ct-light-mode):not(.ct-dark-mode):not(.light-mode):not(.dark-mode) .jbh-tools-resources.jbh-auto:not(.jbh-override-theme) .jbh-tr-logo-light { display: block; }
    html[data-jbh-invert]:not([data-theme]):not(.dark):not(.light):not([data-color-mode]) body:not([data-theme]):not([data-color-mode]):not([data-ct-color-mode]):not(.ct-light-mode):not(.ct-dark-mode):not(.light-mode):not(.dark-mode) .jbh-tools-resources.jbh-auto:not(.jbh-override-theme) {
        --tr-block-bg:    var(--jbh-tr-block-bg-lt, transparent);
        --tr-heading:     var(--jbh-tr-heading-lt, #0f172a);
        --tr-count:       var(--jbh-tr-count-lt, var(--jbh-teal, #00bfb3));
        --tr-count-label: var(--jbh-tr-count-label-lt, #475569);
        --tr-subtitle:    var(--jbh-tr-subtitle-lt, #64748b);
        --tr-cell-bg:     var(--jbh-tr-cell-bg-lt, transparent);
        --tr-cell-border: var(--jbh-tr-cell-border-lt, transparent);
    }
}

/* Hover effects (cell-level so per-logo scale is preserved) */
.jbh-tools-resources.jbh-tr-hover-lift  .jbh-tr-cell:hover { transform: translateY(-3px); }
.jbh-tools-resources.jbh-tr-hover-scale .jbh-tr-cell:hover { transform: scale(1.05); }
.jbh-tools-resources.jbh-tr-hover-glow  .jbh-tr-cell:hover {
    box-shadow: 0 0 0 1px var(--jbh-teal, #00bfb3), 0 8px 22px color-mix(in srgb, var(--jbh-teal, #00bfb3) 22%, transparent);
    border-color: var(--jbh-teal, #00bfb3);
}
.jbh-tools-resources.jbh-tr-hover-desaturate .jbh-tr-logo { filter: grayscale(0%); }
.jbh-tools-resources.jbh-tr-hover-desaturate .jbh-tr-cell:hover .jbh-tr-logo { filter: grayscale(100%); }

/* Global filter modes */
.jbh-tools-resources.jbh-tr-grayscale       .jbh-tr-logo { filter: grayscale(100%); }
.jbh-tools-resources.jbh-tr-grayscale-hover .jbh-tr-logo { filter: grayscale(100%); }
.jbh-tools-resources.jbh-tr-grayscale-hover .jbh-tr-cell:hover .jbh-tr-logo { filter: grayscale(0%); }

/* Empty state — colours marked `!important` for theme-override
   resistance, matching the rest of tools-resources. */
.jbh-tools-resources .jbh-tr-empty {
    flex: 1 1 100%;
    text-align: center;
    padding: 48px 24px;
    color: var(--tr-subtitle) !important;
    font-size: 14px;
    border: 1px dashed var(--tr-cell-border, rgba(148,163,184,0.3)) !important;
    border-radius: 8px;
}
.jbh-tools-resources.jbh-tr-layout-grid .jbh-tr-empty { grid-column: 1 / -1; }

/* ─────────────────────────────────────────────────────────────
   Tablet — flex layouts use 4-per-row reflow; grid layout swaps
   to its tablet column count. Section padding compresses for
   medium-width devices to mirror the HTML sample. */
@media screen and (max-width: 1024px) {
    .jbh-tools-resources {
        padding-top: calc(var(--jbh-tr-pad-y) * 0.85);
        padding-bottom: calc(var(--jbh-tr-pad-y) * 0.85);
        padding-left: 22px;
        padding-right: 22px;
    }
    .jbh-tools-resources.jbh-tr-layout-grid .jbh-tr-grid {
        grid-template-columns: repeat(var(--jbh-tr-cols-t), 1fr);
        column-gap: calc(var(--jbh-tr-gap) * 0.7);
        row-gap: calc(var(--jbh-tr-gap) * 0.7);
    }
    .jbh-tools-resources.jbh-tr-layout-row .jbh-tr-grid,
    .jbh-tools-resources.jbh-tr-layout-compact .jbh-tr-grid {
        column-gap: 24px;
        row-gap: 26px;
    }
    .jbh-tools-resources.jbh-tr-layout-row .jbh-tr-cell {
        flex: 0 0 calc(25% - 18px);
        max-width: calc(25% - 18px);
    }
    .jbh-tools-resources.jbh-tr-layout-row .jbh-tr-figure {
        min-height: 70px;
    }
    .jbh-tools-resources.jbh-tr-header-aside {
        gap: 32px;
    }
    .jbh-tools-resources.jbh-tr-header-aside .jbh-tr-header {
        flex: 0 0 42%;
    }
}

/* ─────────────────────────────────────────────────────────────
   Mobile — Row layout: compact logos (Krita, Godot) sit two per
   row; wide wordmarks (Inkscape, Tracktion) get full-width rows
   for readability. Grid layout swaps to its mobile column count.
   This mirrors the HTML sample's behaviour exactly. */
@media screen and (max-width: 767px) {
    .jbh-tools-resources {
        padding-top: calc(var(--jbh-tr-pad-y) * 0.7);
        padding-bottom: calc(var(--jbh-tr-pad-y) * 0.7);
        padding-left: 14px;
        padding-right: 14px;
    }
    .jbh-tools-resources.jbh-tr-header-split .jbh-tr-header {
        flex-direction: column;
        text-align: center;
        align-items: center;
    }
    .jbh-tools-resources.jbh-tr-header-split .jbh-tr-heading,
    .jbh-tools-resources.jbh-tr-header-split .jbh-tr-countup-wrap,
    .jbh-tools-resources.jbh-tr-header-split .jbh-tr-subtitle { text-align: center; flex: 1 1 100%; }
    .jbh-tools-resources.jbh-tr-header-split .jbh-tr-countup-label { margin-left: auto; margin-right: auto; }

    /* Aside layout stacks on mobile so the heading group sits above
       the logo grid the same way the centred layout does. Re-centre
       text so the stacked block stays balanced on narrow viewports. */
    .jbh-tools-resources.jbh-tr-header-aside {
        flex-direction: column;
        gap: 24px;
    }
    .jbh-tools-resources.jbh-tr-header-aside .jbh-tr-header {
        flex: 1 1 100%;
        max-width: 100%;
        text-align: center;
        margin-bottom: 0;
    }
    .jbh-tools-resources.jbh-tr-header-aside .jbh-tr-heading,
    .jbh-tools-resources.jbh-tr-header-aside .jbh-tr-countup-label,
    .jbh-tools-resources.jbh-tr-header-aside .jbh-tr-subtitle {
        text-align: center;
        margin-left: auto;
        margin-right: auto;
        max-width: 540px;
    }

    .jbh-tools-resources.jbh-tr-layout-grid .jbh-tr-grid {
        grid-template-columns: repeat(var(--jbh-tr-cols-m), 1fr);
        column-gap: var(--jbh-tr-gap-m);
        row-gap: calc(var(--jbh-tr-gap-m) * 1.4);
    }
    .jbh-tools-resources.jbh-tr-layout-grid .jbh-tr-cell { min-height: 66px; padding: 6px; }

    .jbh-tools-resources.jbh-tr-layout-row .jbh-tr-grid,
    .jbh-tools-resources.jbh-tr-layout-compact .jbh-tr-grid {
        column-gap: var(--jbh-tr-gap-m);
        row-gap: calc(var(--jbh-tr-gap-m) * 1.4);
    }
    .jbh-tools-resources.jbh-tr-layout-row .jbh-tr-cell {
        flex: 0 0 calc(50% - (var(--jbh-tr-gap-m) / 2));
        max-width: calc(50% - (var(--jbh-tr-gap-m) / 2));
    }
    .jbh-tools-resources.jbh-tr-layout-row .jbh-tr-figure {
        min-height: 66px;
    }

    .jbh-tr-logo {
        /* Default scale-down for grid layout — row layout uses per-tool
           slug rules below to avoid squishing wide wordmarks. */
        max-width: calc(var(--jbh-tr-max-w) * 0.85);
        max-height: calc(var(--jbh-tr-max-h) * 0.92);
    }
}

@media screen and (max-width: 420px) {
    .jbh-tools-resources.jbh-tr-layout-grid .jbh-tr-grid { column-gap: 12px; row-gap: 18px; }
    .jbh-tools-resources.jbh-tr-layout-grid .jbh-tr-cell { min-height: 60px; }
    .jbh-tools-resources.jbh-tr-layout-row .jbh-tr-grid,
    .jbh-tools-resources.jbh-tr-layout-compact .jbh-tr-grid {
        column-gap: 12px;
        row-gap: 18px;
    }
}

/* ─────────────────────────────────────────────────────────────
   Per-tool-slug responsive sizing — Row layout only.
   Mirrors the HTML sample's per-cell media-query overrides.
   data-tool-slug is emitted by render.php from sanitize_title( name ),
   so the rules fire for any tool whose name slugifies to one of these
   well-known slots. Editors who insert custom tools simply rely on the
   inline maxWidth/maxHeight/scale they pick in the Inspector. */

/* Wide wordmarks (Inkscape + Tracktion) — span full row on mobile
   because squeezing them into 50%-wide columns truncates the text. */
@media screen and (max-width: 767px) {
    .jbh-tools-resources.jbh-tr-layout-row .jbh-tr-cell[data-tool-slug="inkscape"],
    .jbh-tools-resources.jbh-tr-layout-row .jbh-tr-cell[data-tool-slug="tracktion"] {
        flex: 0 0 100%;
        max-width: 100%;
    }
    /* Inkscape needs extra figure height because the scale(1.63)
       transform overflows the usual 66px figure. */
    .jbh-tools-resources.jbh-tr-layout-row .jbh-tr-cell[data-tool-slug="inkscape"] .jbh-tr-figure {
        min-height: 97px;
    }
    .jbh-tools-resources.jbh-tr-layout-row .jbh-tr-cell[data-tool-slug="tracktion"] .jbh-tr-figure {
        min-height: 64px;
    }
}

/* Extra narrow devices — stack compact logos one per row to prevent
   over-squeeze. */
@media screen and (max-width: 360px) {
    .jbh-tools-resources.jbh-tr-layout-row .jbh-tr-cell[data-tool-slug="krita"],
    .jbh-tools-resources.jbh-tr-layout-row .jbh-tr-cell[data-tool-slug="godot"] {
        flex: 0 0 100%;
        max-width: 100%;
    }
}

/* Reduced motion */
@media (prefers-reduced-motion: reduce) {
    .jbh-tr-cell,
    .jbh-tr-logo,
    .jbh-tst-card,
    .jbh-tst-nav,
    .jbh-tst-action,
    .jbh-tst-track { transition: none !important; }
}

/* Editor preview — show the variant matching the editor wrapper's
   mode class so a switch to colorMode=light in the Inspector is
   reflected immediately in the canvas. The wrapper always carries
   one of `jbh-auto` / `jbh-light` / `jbh-dark`; auto and dark both
   show the dark variant since the WP admin iframe doesn't carry a
   theme signal that would otherwise resolve. */
.jbh-editor-tools-resources.jbh-light .jbh-tr-logo-dark   { display: none; }
.jbh-editor-tools-resources.jbh-light .jbh-tr-logo-light  { display: block; }
.jbh-editor-tools-resources.jbh-auto .jbh-tr-logo-dark,
.jbh-editor-tools-resources.jbh-dark .jbh-tr-logo-dark    { display: block; }
.jbh-editor-tools-resources.jbh-auto .jbh-tr-logo-light,
.jbh-editor-tools-resources.jbh-dark .jbh-tr-logo-light   { display: none; }

/* ── v1.2.6 Studio priority preset: custom scope card + plan notes ── */
.jbh-custom-scope-card {
	margin: clamp(28px, 4vw, 48px) auto 0;
	max-width: min(940px, 100%);
	background: color-mix(in srgb, var(--jbh-custom-card-bg, var(--jbh-card)) 92%, var(--jbh-teal) 8%);
	border: 1px solid color-mix(in srgb, var(--jbh-custom-card-border, var(--jbh-border)) 72%, var(--jbh-teal) 28%);
	border-radius: var(--jbh-card-radius);
	box-shadow: 0 14px 44px rgba(0,0,0,0.16);
	overflow: hidden;
}
.jbh-custom-scope-inner {
	display: grid;
	grid-template-columns: auto minmax(0, 1fr) auto;
	gap: clamp(16px, 3vw, 28px);
	align-items: center;
	padding: clamp(24px, 4vw, 36px);
}
.jbh-custom-scope-icon {
	width: 54px;
	height: 54px;
	border-radius: 18px;
	display: grid;
	place-items: center;
	background: rgba(42,157,143,0.12);
	color: var(--jbh-custom-icon, var(--jbh-teal));
}
.jbh-custom-scope-icon svg { width: 26px; height: 26px; }
.jbh-custom-scope-title {
	margin: 0 0 8px;
	font-size: clamp(1.25rem, 2vw, 1.65rem);
	line-height: 1.2;
	color: var(--jbh-custom-header, var(--jbh-heading));
}
.jbh-custom-scope-desc {
	margin: 0;
	color: var(--jbh-custom-desc, var(--jbh-text-color));
	line-height: 1.7;
}
.jbh-custom-scope-note {
	margin: 10px 0 0;
	font-size: 0.86rem;
	line-height: 1.55;
	color: color-mix(in srgb, var(--jbh-custom-desc, var(--jbh-text-color)) 78%, transparent);
}
.jbh-custom-scope-btn {
	white-space: nowrap;
	text-decoration: none;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	padding: 12px 18px;
	border-radius: 999px;
	font-weight: 700;
	background: var(--jbh-custom-btn, var(--jbh-teal));
	color: var(--jbh-custom-btn-text, #fff);
	transition: transform var(--jbh-transition), background var(--jbh-transition), color var(--jbh-transition), box-shadow var(--jbh-transition);
	box-shadow: 0 8px 18px rgba(42,157,143,0.18);
}
.jbh-custom-scope-btn:hover,
.jbh-custom-scope-btn:focus-visible {
	transform: translateY(-2px);
	background: var(--jbh-custom-btn-hover, var(--jbh-teal-dark));
	color: var(--jbh-custom-btn-hover-text, #fff);
}
.jbh-plan-note {
	margin: -4px 0 22px;
	padding: 12px 14px;
	border: 1px solid color-mix(in srgb, var(--jbh-border) 72%, var(--jbh-teal) 28%);
	border-radius: 12px;
	font-size: 0.82rem;
	line-height: 1.55;
	color: var(--jbh-custom-desc, var(--jbh-text-color));
	background: color-mix(in srgb, var(--jbh-card) 86%, transparent);
}
@media (max-width: 900px) {
	.jbh-custom-scope-inner { grid-template-columns: 1fr; text-align: center; }
	.jbh-custom-scope-icon { margin: 0 auto; }
	.jbh-custom-scope-btn { justify-self: center; width: min(100%, 280px); }
}
