/* JBH Color Mode Reversed */
/* ============================================================
   JBH Starter Blocks v1.0.9 — modal.css
   Slide-over modal panel UI for the Studio Grid service order flow.
   
   Brand palette:  teal #2A9D8F | teal-dark #1F5F5B | coral #D64F42
                   bg-dark #121212 | card-dark #1A1A1A | creme #F0EAD6
                   slate #9CA3AF
   ============================================================ */

/* ── Reset / tokens ───────────────────────────────────────
   All modal tokens are scoped to #jbh-modal-overlay so the
   modal owns its own theme surface instead of leaking hard
   dark-mode values onto :root (which used to bleed into any
   other context that consumed these variable names).

   Each token has two layers:
     1. --jbh-modal-*  -> driven by the block's Inspector
                          color settings (per-page override)
     2. fallback chain -> frontend.css -> Blocksy palette ->
                          hard-coded safe default

   The two-layer fallback is what fixes the "white text on
   white background" bug in light mode: when the block does
   NOT supply a modal color, we now resolve through the
   frontend palette (which itself reacts to html.light/dark)
   instead of a hard-coded cream value.
   ────────────────────────────────────────────────────────── */
#jbh-modal-overlay {
	/*
	 * Bridge the block-level --jbh-modal-* overrides into the
	 * design tokens the rest of modal.css consumes. The fallback
	 * MUST be `inherit`, not `var(--jbh-bg, ...)` — a self-reference
	 * in a custom property's declaration is treated as a cycle and
	 * computes to "invalid" per CSS Variables L1, which would break
	 * the entire modal cascade (children would see --jbh-bg as
	 * unset and fall back to the browser default).
	 *
	 * `inherit` explicitly forwards the cascaded value from the
	 * parent (body/html), which in turn is driven by frontend.css
	 * (html.dark/html.light), Blocksy palette bridge, and the
	 * prefers-color-scheme safety net below.
	 */
	--jbh-teal:         var(--jbh-modal-accent,   inherit);
	--jbh-teal-dark:    var(--jbh-modal-accent-2, inherit);
	--jbh-bg:           var(--jbh-modal-bg-outer, inherit);
	--jbh-card:         var(--jbh-modal-bg,       inherit);
	--jbh-creme:        var(--jbh-modal-text,     inherit);
	--jbh-slate:        var(--jbh-modal-label,    inherit);
	--jbh-card-heading: var(--jbh-modal-heading,  inherit);
	--jbh-border:       var(--jbh-modal-border,   inherit);

	--jbh-radius:       var(--jbh-card-radius, 4px);
	--jbh-panel-w:      480px;
	--jbh-font-sans:    Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
	--jbh-font-serif:   "Playfair Display", Georgia, serif;
	--jbh-font-mono:    "Fira Code", "Fira Mono", Consolas, monospace;
	--jbh-ease-out:     cubic-bezier(0.16, 1, 0.3, 1);
	--jbh-anim-dur:     0.38s;

	/* Default to dark for form controls (scrollbars, selection, caret,
	   native text-fill-color). The light-mode override below flips this
	   to `light` so inputs repaint correctly when the site is in light
	   mode. Leaving it as `light dark` lets the UA pick based on the
	   user's OS preference, which fights our explicit color tokens and
	   causes the symptom where input text paints white during focus and
	   reverts to the correct colour only on blur. */
	color-scheme: dark;
}

/* ── Safety net: theme-specific surface resolution ──────────
   If the host theme's Colour Mode Switch doesn't propagate to
   the modal via frontend.css's html.light/dark selectors (e.g.
   Blocksy re-defines palette vars on :root only), these rules
   guarantee legibility by re-reading the palette at the modal
   root itself. Block-level --jbh-modal-* overrides still win.
   ────────────────────────────────────────────────────────── */
/* INVERTED: site light → modal dark */
html[data-jbh-invert][data-jbh-site-mode="light"] #jbh-modal-overlay,
html[data-jbh-invert][data-theme="light"] #jbh-modal-overlay,
html[data-jbh-invert].light #jbh-modal-overlay,
html[data-jbh-invert][data-color-mode="light"] #jbh-modal-overlay,
html[data-jbh-invert] body[data-ct-color-mode="light"] #jbh-modal-overlay {
	--jbh-bg:           var(--jbh-modal-bg-outer, var(--theme-palette-color-7, #121212));
	--jbh-card:         var(--jbh-modal-bg,       var(--theme-palette-color-6, #1A1A1A));
	--jbh-creme:        var(--jbh-modal-text,     var(--theme-palette-color-4, #F0EAD6));
	--jbh-slate:        var(--jbh-modal-label,    var(--theme-palette-color-3, #9CA3AF));
	--jbh-card-heading: var(--jbh-modal-heading,  var(--theme-palette-color-4, #FFFFFF));
	--jbh-border:       var(--jbh-modal-border,   rgba(31, 95, 91, 0.20));
}
/* INVERTED: site dark → modal light */
html[data-jbh-invert][data-jbh-site-mode="dark"] #jbh-modal-overlay,
html[data-jbh-invert][data-theme="dark"] #jbh-modal-overlay,
html[data-jbh-invert].dark #jbh-modal-overlay,
html[data-jbh-invert][data-color-mode="dark"] #jbh-modal-overlay,
html[data-jbh-invert] body[data-ct-color-mode="dark"] #jbh-modal-overlay {
	--jbh-bg:           var(--jbh-modal-bg-outer, var(--theme-palette-color-7, #F9F8F6));
	--jbh-card:         var(--jbh-modal-bg,       var(--theme-palette-color-6, #FFFFFF));
	--jbh-creme:        var(--jbh-modal-text,     var(--theme-palette-color-4, #121212));
	--jbh-slate:        var(--jbh-modal-label,    var(--theme-palette-color-3, #4B5563));
	--jbh-card-heading: var(--jbh-modal-heading,  var(--theme-palette-color-4, #121212));
	--jbh-border:       var(--jbh-modal-border,   rgba(0, 0, 0, 0.12));
	color-scheme: light;
}

/* STANDARD: site light → modal light */
html:not([data-jbh-invert])[data-jbh-site-mode="light"] #jbh-modal-overlay,
html:not([data-jbh-invert])[data-theme="light"] #jbh-modal-overlay,
html:not([data-jbh-invert]).light #jbh-modal-overlay,
html:not([data-jbh-invert])[data-color-mode="light"] #jbh-modal-overlay,
html:not([data-jbh-invert]) body[data-ct-color-mode="light"] #jbh-modal-overlay {
	--jbh-bg:           var(--jbh-modal-bg-outer, var(--theme-palette-color-7, #F9F8F6));
	--jbh-card:         var(--jbh-modal-bg,       var(--theme-palette-color-6, #FFFFFF));
	--jbh-creme:        var(--jbh-modal-text,     var(--theme-palette-color-4, #121212));
	--jbh-slate:        var(--jbh-modal-label,    var(--theme-palette-color-3, #4B5563));
	--jbh-card-heading: var(--jbh-modal-heading,  var(--theme-palette-color-4, #121212));
	--jbh-border:       var(--jbh-modal-border,   rgba(0, 0, 0, 0.12));
	color-scheme: light;
}
/* STANDARD: site dark → modal dark */
html:not([data-jbh-invert])[data-jbh-site-mode="dark"] #jbh-modal-overlay,
html:not([data-jbh-invert])[data-theme="dark"] #jbh-modal-overlay,
html:not([data-jbh-invert]).dark #jbh-modal-overlay,
html:not([data-jbh-invert])[data-color-mode="dark"] #jbh-modal-overlay,
html:not([data-jbh-invert]) body[data-ct-color-mode="dark"] #jbh-modal-overlay {
	--jbh-bg:           var(--jbh-modal-bg-outer, var(--theme-palette-color-7, #121212));
	--jbh-card:         var(--jbh-modal-bg,       var(--theme-palette-color-6, #1A1A1A));
	--jbh-creme:        var(--jbh-modal-text,     var(--theme-palette-color-4, #F0EAD6));
	--jbh-slate:        var(--jbh-modal-label,    var(--theme-palette-color-3, #9CA3AF));
	--jbh-card-heading: var(--jbh-modal-heading,  var(--theme-palette-color-4, #FFFFFF));
	--jbh-border:       var(--jbh-modal-border,   rgba(31, 95, 91, 0.20));
}

/* INVERTED: OS dark → modal light */
@media (prefers-color-scheme: dark) {
	html[data-jbh-invert]:not([data-jbh-site-mode]):not([data-theme]):not(.dark):not(.light):not([data-color-mode]) body:not([data-ct-color-mode]) #jbh-modal-overlay {
		--jbh-bg:           var(--jbh-modal-bg-outer, #F9F8F6);
		--jbh-card:         var(--jbh-modal-bg,       #FFFFFF);
		--jbh-creme:        var(--jbh-modal-text,     #121212);
		--jbh-slate:        var(--jbh-modal-label,    #4B5563);
		--jbh-card-heading: var(--jbh-modal-heading,  #121212);
		--jbh-border:       var(--jbh-modal-border,   rgba(0, 0, 0, 0.12));
		color-scheme: light;
	}
}
/* STANDARD: OS light → modal light */
@media (prefers-color-scheme: light) {
	html:not([data-jbh-invert]):not([data-jbh-site-mode]):not([data-theme]):not(.dark):not(.light):not([data-color-mode]) body:not([data-ct-color-mode]) #jbh-modal-overlay {
		--jbh-bg:           var(--jbh-modal-bg-outer, #F9F8F6);
		--jbh-card:         var(--jbh-modal-bg,       #FFFFFF);
		--jbh-creme:        var(--jbh-modal-text,     #121212);
		--jbh-slate:        var(--jbh-modal-label,    #4B5563);
		--jbh-card-heading: var(--jbh-modal-heading,  #121212);
		--jbh-border:       var(--jbh-modal-border,   rgba(0, 0, 0, 0.12));
		color-scheme: light;
	}
}

/* ── OVERLAY ─────────────────────────────────────────────── */
/* The overlay is a native <dialog>. When opened via showModal(),
   the element enters the browser's Top Layer — a viewport-rooted
   render context above the normal document flow, immune to
   ancestor containing-block traps (transform / filter /
   backdrop-filter / contain / perspective / will-change). That's
   how we guarantee `position: fixed; inset: 0` actually covers
   the viewport even when the theme wraps wp_footer in a
   transformed or contained container (Blocksy smooth-scroll,
   Lenis/Locomotive, Astra full-screen layouts, etc.). */
.jbh-overlay {
	position: fixed;
	inset: 0;
	z-index: 99999;
	display: flex;
	align-items: flex-start;
	justify-content: flex-end;
}

/* <dialog>-specific UA defaults we need to neutralise so the
   overlay renders the same way regardless of which open/close
   API is used (showModal() in the Top Layer vs legacy hidden
   attribute). Without these resets, the UA stylesheet applies
   `max-width`, `max-height`, `margin: auto`, `padding: 1em`,
   `border: solid`, and a white `background` — all of which
   would visibly break the slide-over panel. */
dialog.jbh-overlay {
	max-width: none;
	max-height: none;
	width: 100%;
	height: 100%;
	margin: 0;
	padding: 0;
	border: 0;
	background: transparent;
	color: inherit;
	overflow: visible;
}

/* Defense-in-depth against content-width bridges.
   The Blocksy-compat palette bridge historically applied
   `max-width: var(--theme-content-width, 1280px); margin: auto`
   to `#jbh-modal-overlay:not(.alignwide):not(.alignfull)` with
   specificity (1,2,0). That single ID + two negated classes
   beat `dialog.jbh-overlay` (0,1,1), collapsing the dialog into
   a 1280 px centered box so the blurred backdrop only spanned
   the theme's content column. The root-cause fix lives in
   `class-jbh-starter-blocksy-compat.php::emit_content_width_css()`
   which now excludes modal selectors — but we still keep this
   belt-and-suspenders rule here so third-party themes/plugins
   that attempt the same trick cannot break the overlay.

   Selector matches the exact (1,2,0) specificity of the trap and
   loads AFTER the inline Blocksy bridge (modal.css is a separate
   stylesheet handle that comes later in the cascade), so ties
   resolve in our favour. `inset: 0` guarantees the dialog pins
   to every viewport edge regardless of ancestor transforms — the
   Top Layer escape via showModal() does the heavy lifting, this
   CSS just prevents layout-level collapse. */
#jbh-modal-overlay:not(.alignwide):not(.alignfull),
#jbh-modal-overlay.jbh-overlay {
	max-width: none;
	max-height: none;
	width: 100%;
	height: 100%;
	margin: 0;
	inset: 0;
}

/* The dialog's ::backdrop pseudo is the Top Layer's default dim
   layer. We use our own .jbh-overlay-backdrop child element so
   backdrop-filter and the mode-reactive --jbh-modal-backdrop
   token still work, so ::backdrop stays transparent to avoid
   double-dimming the page. */
dialog.jbh-overlay::backdrop {
	background: transparent;
}

.jbh-overlay[hidden] {
	display: none;
}

/* Native <dialog> UA rule: `dialog:not([open]) { display: none; }`
   handles the closed state automatically. The [hidden] selector
   above is kept as a legacy-browser fallback. */

.jbh-overlay-backdrop {
	position: absolute;
	inset: 0;
	/* Mode-reactive backdrop. `--jbh-modal-backdrop` is defined at :root
	   with a heavy black default; light-mode overrides in frontend.css
	   swap it for a softer slate-900 tint so the overlay feels like an
	   intentional dim rather than a dark curtain thrown over a white page. */
	background: var(--jbh-modal-backdrop, rgba(0, 0, 0, 0.65));
	backdrop-filter: blur(8px) saturate(1.2);
	-webkit-backdrop-filter: blur(8px) saturate(1.2);
	animation: jbhModalFadeIn 0.3s ease forwards;
}

/* ── PANEL (slide-over) ────────────────────────────────────── */
.jbh-panel {
	position: relative;
	z-index: 1;
	width: 100%;
	max-width: var(--jbh-panel-w);
	height: 100dvh;
	height: 100vh;
	background: var(--jbh-card);
	/* Panel's own outer edge — flows through the Inspector's Borders / Dividers
	   picker (`modalBorder` / `modalBorderLight`) via --jbh-modal-border. Falls
	   back to --jbh-teal-dark so installs that never set the picker keep the
	   original teal-dark visual. Dual-palette resolution (dark vs light) is
	   handled upstream by render.php which emits --jbh-modal-border separately
	   at #jbh-modal-overlay and at html[data-theme="light"] #jbh-modal-overlay. */
	border-left: 1px solid var(--jbh-modal-border, var(--jbh-teal-dark));
	overflow-y: auto;
	overflow-x: hidden;
	overscroll-behavior: contain;
	/* Mode-reactive shadow. Light mode flips the deep dark-mode shadow
	   to a softer slate-900 tint via --jbh-modal-panel-shadow. */
	box-shadow: var(--jbh-modal-panel-shadow, -8px 0 48px rgba(0, 0, 0, 0.5), -2px 0 8px rgba(0, 0, 0, 0.2));
	animation: jbhSlideIn var(--jbh-anim-dur) var(--jbh-ease-out) forwards;
	scrollbar-width: thin;
	/* Scrollbar colouring flows through the Inspector's "Scrollbar Track"
	   / "Scrollbar Thumb" pickers via `--jbh-modal-scroll-track` /
	   `--jbh-modal-scroll-thumb`. Firefox reads them as the shorthand
	   `scrollbar-color: <thumb> <track>` below; WebKit reads them via
	   `::-webkit-scrollbar-track` / `::-webkit-scrollbar-thumb`. Both
	   tokens fall back to the previous teal-dark-on-bg look so sites
	   that never open the new picker are unaffected. */
	scrollbar-color: var(--jbh-modal-scroll-thumb, var(--jbh-teal-dark)) var(--jbh-modal-scroll-track, var(--jbh-bg));
}

.jbh-panel::-webkit-scrollbar        { width: 6px; }
.jbh-panel::-webkit-scrollbar-track  { background: var(--jbh-modal-scroll-track, var(--jbh-bg)); }
.jbh-panel::-webkit-scrollbar-thumb  { background: var(--jbh-modal-scroll-thumb, var(--jbh-teal-dark)); border-radius: 3px; }

/* closing state */
.jbh-overlay.is-closing .jbh-panel   { animation: jbhSlideOut var(--jbh-anim-dur) var(--jbh-ease-out) forwards; }
.jbh-overlay.is-closing .jbh-overlay-backdrop { animation: jbhModalFadeOut 0.25s ease forwards; }

/* ── Panel subtitle / base-recap / step-sub / privacy note ──
   These class names replaced inline styles that previously lived
   inside the wp_footer modal HTML. The values are identical to
   the originals except that colours flow through the modal token
   chain instead of hardcoded fallbacks, so the text stays legible
   regardless of theme mode. */
.jbh-panel-sub {
	font-family: var(--jbh-font-sans);
	font-size: 0.85rem;
	color: var(--jbh-slate);
	margin: 6px 0 0;
	font-weight: 300;
}
.jbh-panel-sub strong { color: var(--jbh-modal-heading, var(--jbh-creme)); }

.jbh-base-recap {
	background: var(--jbh-modal-bg-outer, var(--jbh-bg));
	border: 1px solid var(--jbh-border);
	border-radius: var(--jbh-radius);
	padding: 20px 18px;
}
.jbh-base-recap-row {
	display: flex;
	justify-content: space-between;
	align-items: flex-end;
	margin-bottom: 14px;
}
.jbh-base-recap-label {
	font-family: var(--jbh-font-mono);
	font-size: 0.65rem;
	text-transform: uppercase;
	letter-spacing: 0.14em;
	color: var(--jbh-slate);
}
.jbh-base-price {
	font-family: var(--jbh-font-serif);
	font-size: 1.5rem;
	font-weight: 700;
	color: var(--jbh-modal-heading, var(--jbh-card-heading, currentColor));
}
.jbh-step-sub {
	font-family: var(--jbh-font-sans);
	font-size: 0.75rem;
	color: var(--jbh-slate);
	margin: 0 0 16px;
	font-weight: 300;
	line-height: 1.6;
}
.jbh-drop-sub {
	font-family: var(--jbh-font-sans);
	font-size: 0.75rem;
	color: var(--jbh-slate);
	font-weight: 300;
	text-align: center;
}
.jbh-privacy-note {
	font-size: 0.65rem;
	color: var(--jbh-slate);
	margin-top: 8px;
	line-height: 1.5;
	font-family: var(--jbh-font-mono);
}

@keyframes jbhSlideIn       { from { transform: translateX(100%); } to { transform: translateX(0); } }
@keyframes jbhSlideOut      { from { transform: translateX(0);    } to { transform: translateX(100%); } }
/* Modal-scoped fade. Intentionally NOT named `jbhFadeIn`/`jbhFadeOut`
   to avoid colliding with the same-named keyframes already declared
   in frontend.css for the contact-section success state — `@keyframes`
   resolves cascade-style on declaration order, so a generic-named
   modal keyframe loaded AFTER frontend.css would silently override
   the contact-section's slide-up `jbhFadeIn`, breaking that block's
   success-state animation on every page that renders both a contact
   form AND a studio-grid (which is the typical layout). */
@keyframes jbhModalFadeIn   { from { opacity: 0; } to { opacity: 1; } }
@keyframes jbhModalFadeOut  { from { opacity: 1; } to { opacity: 0; } }

/* ── Panel header ─────────────────────────────────────────── */
.jbh-panel-header {
	position: sticky;
	top: 0;
	z-index: 10;
	display: flex;
	align-items: flex-start;
	justify-content: space-between;
	gap: 16px;
	padding: 24px 28px;
	background: var(--jbh-card);
	border-bottom: 1px solid var(--jbh-border);
	backdrop-filter: blur(12px);
	-webkit-backdrop-filter: blur(12px);
}

.jbh-panel-header-text {
	flex: 1;
	min-width: 0;
}

.jbh-panel-category {
	display: block;
	font-family: var(--jbh-font-mono);
	font-size: 0.625rem;
	font-weight: 700;
	letter-spacing: 0.18em;
	text-transform: uppercase;
	color: var(--jbh-teal);
	margin-bottom: 6px;
}

.jbh-panel-title {
	font-family: var(--jbh-font-serif);
	font-size: 1.5rem;
	font-weight: 700;
	color: var(--jbh-modal-heading, var(--jbh-card-heading, currentColor));
	margin: 0;
	line-height: 1.2;
}

.jbh-close-btn {
	flex-shrink: 0;
	background: transparent;
	border: none;
	cursor: pointer;
	color: var(--jbh-slate);
	padding: 6px;
	border-radius: var(--jbh-radius);
	transition: color 0.2s, background 0.2s, transform 0.15s ease;
	line-height: 0;
}

.jbh-close-btn:hover { color: var(--jbh-modal-heading, var(--jbh-card-heading, currentColor)); background: rgba(128,128,128,0.12); transform: scale(1.05); }
.jbh-close-btn:active { transform: scale(0.95); }
.jbh-close-btn:focus-visible { outline: 2px solid var(--jbh-teal); outline-offset: 2px; box-shadow: 0 0 0 4px rgba(42, 157, 143, 0.15); }

/* ── Success state ────────────────────────────────────────── */
.jbh-success {
	padding: 60px 32px;
	text-align: center;
	display: flex;
	flex-direction: column;
	align-items: center;
	animation: jbhModalFadeIn 0.4s ease forwards;
}

.jbh-success-icon {
	width: 72px;
	height: 72px;
	background: rgba(42, 157, 143, 0.15);
	border-radius: 50%;
	display: flex;
	align-items: center;
	justify-content: center;
	color: var(--jbh-teal);
	margin-bottom: 28px;
}

.jbh-success-icon svg { width: 36px; height: 36px; }

.jbh-success-heading {
	font-family: var(--jbh-font-serif);
	font-size: 1.6rem;
	font-weight: 700;
	color: var(--jbh-modal-heading, var(--jbh-card-heading, currentColor));
	margin: 0 0 12px 0;
}

.jbh-success-sub {
	font-family: var(--jbh-font-sans);
	font-size: 0.925rem;
	color: var(--jbh-slate);
	margin: 0 0 8px 0;
}

.jbh-success-sub strong { color: var(--jbh-creme); }

.jbh-success-meta {
	font-family: var(--jbh-font-mono);
	font-size: 0.75rem;
	color: var(--jbh-teal);
	margin: 0 0 24px 0;
}

.jbh-success-note {
	font-family: var(--jbh-font-sans);
	font-size: 0.8rem;
	font-weight: 300;
	color: var(--jbh-slate);
	margin: 0 0 40px 0;
}

/* ── Enforce hidden attribute on flex-display elements ───── */
.jbh-form-wrap[hidden],
.jbh-success[hidden] {
	display: none !important;
}

/* ── Form wrap ───────────────────────────────────────────── */
.jbh-form-wrap {
	padding: 32px 28px;
	display: flex;
	flex-direction: column;
	gap: 40px;
}

/* ── Steps ───────────────────────────────────────────────── */
.jbh-step-label {
	font-family: var(--jbh-font-mono);
	font-size: 0.7rem;
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.16em;
	color: var(--jbh-slate);
	margin: 0 0 18px 0;
	display: flex;
	align-items: center;
	gap: 10px;
}

.jbh-step-num {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 22px;
	/* Upgrade badge ring — flows through the Inspector's Borders / Dividers
	   picker so the little circular badge around the expedited-request note
	   matches the rest of the modal's divider treatment. Falls back to
	   --jbh-teal-dark to preserve the original ring colour when the picker
	   is unset. */
	height: 22px;
	border: 1px solid var(--jbh-modal-border, var(--jbh-teal-dark));
	border-radius: 50%;
	font-size: 0.65rem;
	color: var(--jbh-teal);
}

/* (Tier buttons and includes-box removed — flat package architecture) */

.jbh-includes-list {
	list-style: none;
	margin: 0;
	padding: 14px 0 0 0;
	border-top: 1px solid var(--jbh-border);
	display: flex;
	flex-direction: column;
	gap: 8px;
}

.jbh-includes-list li {
	display: flex;
	align-items: flex-start;
	gap: 10px;
	font-family: var(--jbh-font-sans);
	font-size: 0.85rem;
	color: var(--jbh-creme);
	line-height: 1.4;
}

/* Check icons are added inline by modal.js — no ::before needed */

/* ── Upgrades ─────────────────────────────────────────────── */
.jbh-upgrades-list {
	display: flex;
	flex-direction: column;
	gap: 10px;
}

.jbh-upgrade-item {
	display: flex;
	align-items: flex-start;
	gap: 12px;
	padding: 14px 16px;
	border-radius: var(--jbh-radius);
	border: 1px solid var(--jbh-border);
	background: var(--jbh-bg);
	cursor: pointer;
	transition: border-color 0.2s, background 0.2s;
}

.jbh-upgrade-item:has(.jbh-upgrade-check:checked) {
	border-color: var(--jbh-teal);
	background: rgba(42, 157, 143, 0.06);
}

.jbh-upgrade-check {
	flex-shrink: 0;
	margin-top: 2px;
	accent-color: var(--jbh-teal);
	width: 15px;
	height: 15px;
	cursor: pointer;
}

.jbh-upgrade-info {
	flex: 1;
	min-width: 0;
}

.jbh-upgrade-name {
	display: block;
	font-family: var(--jbh-font-sans);
	font-size: 0.875rem;
	font-weight: 600;
	color: var(--jbh-creme);
	margin-bottom: 2px;
}

.jbh-upgrade-sub {
	display: block;
	font-family: var(--jbh-font-sans);
	font-size: 0.75rem;
	color: var(--jbh-slate);
}

.jbh-upgrade-cost {
	flex-shrink: 0;
	font-family: var(--jbh-font-mono);
	font-size: 0.7rem;
	/* Inspector-bound pricing accent. Falls back to the modal accent
	   picker (shared with check-icons/links) before the brand teal so
	   a single accent change propagates here for free. */
	color: var(--jbh-modal-upgrade-cost, var(--jbh-modal-accent, var(--jbh-teal)));
	white-space: nowrap;
	margin-top: 2px;
}

/* ── Dynamic Add-ons ─────────────────────────────────────── */
.jbh-addons-container { margin-bottom: 16px; }
.jbh-addons-heading {
	font-family: var(--jbh-font-mono);
	font-size: 0.65rem;
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.14em;
	color: var(--jbh-creme);
	margin: 0 0 12px;
}
.jbh-addon-row {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 16px;
	padding: 14px 16px;
	background: rgba(255,255,255,0.03);
	/* Add-on row surround — persistent divider between each add-on entry.
	   Now flows through the Inspector's Borders / Dividers picker
	   (`--jbh-modal-border`) so toggling the colour retints every add-on
	   row at once. Fallback preserves the prior teal-tinted appearance. */
	border: 1px solid var(--jbh-modal-border, rgba(42,157,143,0.12));
	border-radius: 8px;
	margin-bottom: 8px;
	transition: border-color 0.2s, background 0.2s;
}
.jbh-addon-row:hover {
	/* Hover state intentionally stays brand-teal (accent signal), not
	   driven by the Borders / Dividers picker. Use the Accent picker for
	   that path via --jbh-modal-accent if needed in the future. */
	border-color: rgba(42,157,143,0.30);
}
.jbh-addon-info {
	flex: 1;
	min-width: 0;
	display: flex;
	flex-direction: column;
	gap: 2px;
}
.jbh-addon-name {
	font-family: var(--jbh-font-sans);
	font-size: 0.85rem;
	font-weight: 600;
	color: var(--jbh-creme);
}
.jbh-addon-desc {
	font-family: var(--jbh-font-sans);
	font-size: 0.72rem;
	color: var(--jbh-slate);
	line-height: 1.4;
}
.jbh-addon-lead-time {
	font-family: var(--jbh-font-sans);
	font-size: 0.7rem;
	line-height: 1.4;
	color: var(--jbh-slate);
	margin-top: 2px;
}

.jbh-addon-unit-price {
	font-family: var(--jbh-font-mono);
	font-size: 0.68rem;
	/* Inspector-bound per-addon pricing accent. Same fallback chain as
	   .jbh-upgrade-cost so a single --jbh-modal-accent change retints
	   every price badge in the modal consistently. */
	color: var(--jbh-modal-addon-price, var(--jbh-modal-accent, var(--jbh-teal)));
	font-weight: 700;
	margin-top: 2px;
}

/* Toggle switch for boolean add-ons.
   Every colour surface is now Inspector-bound:
     --jbh-modal-toggle-track         Off-state track background
     --jbh-modal-toggle-track-active  On-state (checked) track background
     --jbh-modal-toggle-dot           Round handle/dot colour
   Fallbacks preserve the original hard-coded rgba whites + brand teal
   on sites that never open the Inspector, so existing pages don't
   visually regress after this upgrade. */
.jbh-addon-toggle {
	position: relative;
	display: inline-flex;
	align-items: center;
	cursor: pointer;
	flex-shrink: 0;
}
.jbh-addon-check {
	position: absolute;
	opacity: 0;
	width: 0;
	height: 0;
}
.jbh-addon-slider {
	width: 40px;
	height: 22px;
	/* Off-state track: Inspector-bound, with a mode-reactive fallback.
	   `--jbh-border` already flips light/dark via modal.css:77-103, so
	   when no explicit picker is set the track stays subtly visible on
	   both palettes — instead of collapsing to invisible-white on a
	   light panel (the old hardcoded rgba(255,255,255,0.08) did). */
	background:   var(--jbh-modal-toggle-track,        var(--jbh-border, rgba(255,255,255,0.08)));
	border: 1px solid var(--jbh-modal-toggle-track,    var(--jbh-border, rgba(255,255,255,0.12)));
	border-radius: 999px;
	position: relative;
	transition: background 0.2s, border-color 0.2s;
}
.jbh-addon-slider::after {
	content: '';
	position: absolute;
	top: 2px;
	left: 2px;
	width: 16px;
	height: 16px;
	background: var(--jbh-modal-toggle-dot, #fff);
	border-radius: 50%;
	transition: transform 0.2s;
	box-shadow: 0 1px 3px rgba(0,0,0,0.3);
}
.jbh-addon-check:checked + .jbh-addon-slider {
	background:       var(--jbh-modal-toggle-track-active, var(--jbh-modal-accent, var(--jbh-teal)));
	border-color:     var(--jbh-modal-toggle-track-active, var(--jbh-modal-accent, var(--jbh-teal)));
}
.jbh-addon-check:checked + .jbh-addon-slider::after {
	transform: translateX(18px);
}
.jbh-addon-check:focus-visible + .jbh-addon-slider {
	outline: 2px solid var(--jbh-modal-accent, var(--jbh-teal));
	outline-offset: 2px;
}

/* Quantity controls for quantity add-ons */
.jbh-addon-qty-controls {
	display: flex;
	align-items: center;
	gap: 0;
	flex-shrink: 0;
	/* Quantity control outer box — routes through the Borders / Dividers
	   picker so the qty +/- control matches the surrounding add-on row.
	   Original teal-tinted rgba is retained as the fallback. */
	border: 1px solid var(--jbh-modal-border, rgba(42,157,143,0.20));
	border-radius: 8px;
	overflow: hidden;
}
.jbh-qty-btn {
	width: 32px;
	height: 32px;
	display: flex;
	align-items: center;
	justify-content: center;
	background: transparent;
	border: none;
	color: var(--jbh-creme);
	font-size: 1rem;
	cursor: pointer;
	transition: background 0.15s, color 0.15s;
	font-family: var(--jbh-font-sans);
}
.jbh-qty-btn:hover {
	background: rgba(42,157,143,0.15);
	color: var(--jbh-teal);
}
.jbh-qty-btn:focus-visible {
	outline: 2px solid var(--jbh-teal);
	outline-offset: -2px;
}
.jbh-qty-display {
	min-width: 28px;
	text-align: center;
	font-family: var(--jbh-font-mono);
	font-size: 0.85rem;
	font-weight: 700;
	color: var(--jbh-creme);
	padding: 0 4px;
	/* Inner dividers separating the +/- buttons from the quantity digits
	   — same picker-driven colour as the outer .jbh-qty-group frame so
	   the whole control reads as one visual unit. */
	border-left: 1px solid var(--jbh-modal-border, rgba(42,157,143,0.12));
	border-right: 1px solid var(--jbh-modal-border, rgba(42,157,143,0.12));
	height: 32px;
	line-height: 32px;
}

/* ── Fields ───────────────────────────────────────────────── */
.jbh-fields {
	display: flex;
	flex-direction: column;
	gap: 20px;
}

.jbh-field {
	display: flex;
	flex-direction: column;
	gap: 8px;
}

.jbh-label {
	font-family: var(--jbh-font-mono);
	font-size: 0.65rem;
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.14em;
	color: var(--jbh-creme);
}

.jbh-required { color: var(--jbh-coral); }

.jbh-textarea,
.jbh-input {
	width: 100%;
	box-sizing: border-box;
	background: var(--jbh-bg);
	border: 1px solid var(--jbh-border);
	border-radius: var(--jbh-radius);
	padding: 12px 14px;
	font-family: var(--jbh-font-sans);
	font-size: 0.875rem;
	color: var(--jbh-creme);
	transition: border-color 0.2s;
	outline: none;
}

.jbh-textarea::placeholder,
.jbh-input::placeholder {
	color: rgba(156, 163, 175, 0.45);
	/* Explicit -webkit- counterpart so Safari doesn't fall back to its
	   own placeholder colour (which ignores `color` on iOS < 16). */
	-webkit-text-fill-color: rgba(156, 163, 175, 0.45);
}
/* Light-mode placeholder override.
   Previously gated on `.jbh-light .jbh-input::placeholder` — but the
   modal lives at `#jbh-modal-overlay` rendered once in wp_footer,
   OUTSIDE any `.jbh-dark` / `.jbh-light` block wrapper. So that
   selector NEVER matched in practice, and the modal's input
   placeholder text rendered with the dark-mode slate-on-near-white
   colour `rgba(156,163,175,0.45)` in light mode — barely visible
   against the white modal panel.
   Mirrors the four-toggle + OS-light pattern used by the input text
   belt-and-braces override at modal.css L838-863 so every light-mode
   signal path resolves the placeholder to the correct contrast. */
/* INVERTED: site dark → modal light → darker placeholder for contrast */
html[data-jbh-invert][data-jbh-site-mode="dark"] #jbh-modal-overlay .jbh-textarea::placeholder,
html[data-jbh-invert][data-jbh-site-mode="dark"] #jbh-modal-overlay .jbh-input::placeholder,
html[data-jbh-invert][data-theme="dark"] #jbh-modal-overlay .jbh-textarea::placeholder,
html[data-jbh-invert][data-theme="dark"] #jbh-modal-overlay .jbh-input::placeholder,
html[data-jbh-invert].dark #jbh-modal-overlay .jbh-textarea::placeholder,
html[data-jbh-invert].dark #jbh-modal-overlay .jbh-input::placeholder,
html[data-jbh-invert][data-color-mode="dark"] #jbh-modal-overlay .jbh-textarea::placeholder,
html[data-jbh-invert][data-color-mode="dark"] #jbh-modal-overlay .jbh-input::placeholder,
html[data-jbh-invert] body[data-ct-color-mode="dark"] #jbh-modal-overlay .jbh-textarea::placeholder,
html[data-jbh-invert] body[data-ct-color-mode="dark"] #jbh-modal-overlay .jbh-input::placeholder {
	color: rgba(75, 85, 99, 0.55);
	-webkit-text-fill-color: rgba(75, 85, 99, 0.55);
}
/* STANDARD: site light → modal light → same darker placeholder */
html:not([data-jbh-invert])[data-jbh-site-mode="light"] #jbh-modal-overlay .jbh-textarea::placeholder,
html:not([data-jbh-invert])[data-jbh-site-mode="light"] #jbh-modal-overlay .jbh-input::placeholder,
html:not([data-jbh-invert])[data-theme="light"] #jbh-modal-overlay .jbh-textarea::placeholder,
html:not([data-jbh-invert])[data-theme="light"] #jbh-modal-overlay .jbh-input::placeholder,
html:not([data-jbh-invert]).light #jbh-modal-overlay .jbh-textarea::placeholder,
html:not([data-jbh-invert]).light #jbh-modal-overlay .jbh-input::placeholder,
html:not([data-jbh-invert])[data-color-mode="light"] #jbh-modal-overlay .jbh-textarea::placeholder,
html:not([data-jbh-invert])[data-color-mode="light"] #jbh-modal-overlay .jbh-input::placeholder,
html:not([data-jbh-invert]) body[data-ct-color-mode="light"] #jbh-modal-overlay .jbh-textarea::placeholder,
html:not([data-jbh-invert]) body[data-ct-color-mode="light"] #jbh-modal-overlay .jbh-input::placeholder {
	color: rgba(75, 85, 99, 0.55);
	-webkit-text-fill-color: rgba(75, 85, 99, 0.55);
}
/* INVERTED: OS dark → modal light placeholder */
@media (prefers-color-scheme: dark) {
	html[data-jbh-invert]:not([data-jbh-site-mode]):not([data-theme]):not(.dark):not(.light):not([data-color-mode]) body:not([data-ct-color-mode]) #jbh-modal-overlay .jbh-textarea::placeholder,
	html[data-jbh-invert]:not([data-jbh-site-mode]):not([data-theme]):not(.dark):not(.light):not([data-color-mode]) body:not([data-ct-color-mode]) #jbh-modal-overlay .jbh-input::placeholder {
		color: rgba(75, 85, 99, 0.55);
		-webkit-text-fill-color: rgba(75, 85, 99, 0.55);
	}
}
/* STANDARD: OS light → modal light placeholder */
@media (prefers-color-scheme: light) {
	html:not([data-jbh-invert]):not([data-jbh-site-mode]):not([data-theme]):not(.dark):not(.light):not([data-color-mode]) body:not([data-ct-color-mode]) #jbh-modal-overlay .jbh-textarea::placeholder,
	html:not([data-jbh-invert]):not([data-jbh-site-mode]):not([data-theme]):not(.dark):not(.light):not([data-color-mode]) body:not([data-ct-color-mode]) #jbh-modal-overlay .jbh-input::placeholder {
		color: rgba(75, 85, 99, 0.55);
		-webkit-text-fill-color: rgba(75, 85, 99, 0.55);
	}
}

.jbh-textarea:focus,
.jbh-input:focus {
	border-color: var(--jbh-teal);
}

/* Explicit text-fill-color on every input state. Without this, Safari
   and Chrome inherit the UA's form-control text colour (which reacts
   to `color-scheme` rather than our `color` token) and paint typed
   characters in the wrong shade during focus. */
.jbh-textarea,
.jbh-input {
	-webkit-text-fill-color: var(--jbh-creme);
	caret-color: var(--jbh-teal);
}

/* Autofill defense. Chrome repaints autofilled fields with a yellow
   background and white text that ignores `color`. We repaint with our
   own bg (1000px inset shadow trick) and force text-fill-color back
   to the palette value. The 9999s transition prevents the brief
   yellow-flash visible on page load. */
.jbh-input:-webkit-autofill,
.jbh-input:-webkit-autofill:hover,
.jbh-input:-webkit-autofill:focus,
.jbh-textarea:-webkit-autofill,
.jbh-textarea:-webkit-autofill:hover,
.jbh-textarea:-webkit-autofill:focus {
	-webkit-text-fill-color: var(--jbh-creme) !important;
	-webkit-box-shadow: 0 0 0 1000px var(--jbh-bg) inset !important;
	caret-color: var(--jbh-teal);
	transition: background-color 9999s ease-in-out 0s;
}

/* Final belt-and-braces per-mode override. Redundant with the cascade
   when everything is wired correctly, but it ensures that even if a
   host theme re-defines --jbh-creme at a lower-specificity scope than
   our modal resolver, the input text colour still flips on mode. */
/* INVERTED: site dark → modal light → force dark input text */
html[data-jbh-invert][data-jbh-site-mode="dark"] #jbh-modal-overlay .jbh-input,
html[data-jbh-invert][data-jbh-site-mode="dark"] #jbh-modal-overlay .jbh-textarea,
html[data-jbh-invert][data-theme="dark"] #jbh-modal-overlay .jbh-input,
html[data-jbh-invert][data-theme="dark"] #jbh-modal-overlay .jbh-textarea,
html[data-jbh-invert].dark #jbh-modal-overlay .jbh-input,
html[data-jbh-invert].dark #jbh-modal-overlay .jbh-textarea,
html[data-jbh-invert][data-color-mode="dark"] #jbh-modal-overlay .jbh-input,
html[data-jbh-invert][data-color-mode="dark"] #jbh-modal-overlay .jbh-textarea,
html[data-jbh-invert] body[data-ct-color-mode="dark"] #jbh-modal-overlay .jbh-input,
html[data-jbh-invert] body[data-ct-color-mode="dark"] #jbh-modal-overlay .jbh-textarea {
	color: var(--jbh-modal-text, #121212);
	-webkit-text-fill-color: var(--jbh-modal-text, #121212);
}
/* STANDARD: site light → modal light → force dark input text */
html:not([data-jbh-invert])[data-jbh-site-mode="light"] #jbh-modal-overlay .jbh-input,
html:not([data-jbh-invert])[data-jbh-site-mode="light"] #jbh-modal-overlay .jbh-textarea,
html:not([data-jbh-invert])[data-theme="light"] #jbh-modal-overlay .jbh-input,
html:not([data-jbh-invert])[data-theme="light"] #jbh-modal-overlay .jbh-textarea,
html:not([data-jbh-invert]).light #jbh-modal-overlay .jbh-input,
html:not([data-jbh-invert]).light #jbh-modal-overlay .jbh-textarea,
html:not([data-jbh-invert])[data-color-mode="light"] #jbh-modal-overlay .jbh-input,
html:not([data-jbh-invert])[data-color-mode="light"] #jbh-modal-overlay .jbh-textarea,
html:not([data-jbh-invert]) body[data-ct-color-mode="light"] #jbh-modal-overlay .jbh-input,
html:not([data-jbh-invert]) body[data-ct-color-mode="light"] #jbh-modal-overlay .jbh-textarea {
	color: var(--jbh-modal-text, #121212);
	-webkit-text-fill-color: var(--jbh-modal-text, #121212);
}
/* INVERTED: OS dark → modal light input text */
@media (prefers-color-scheme: dark) {
	html[data-jbh-invert]:not([data-jbh-site-mode]):not([data-theme]):not(.dark):not(.light):not([data-color-mode]) body:not([data-ct-color-mode]) #jbh-modal-overlay .jbh-input,
	html[data-jbh-invert]:not([data-jbh-site-mode]):not([data-theme]):not(.dark):not(.light):not([data-color-mode]) body:not([data-ct-color-mode]) #jbh-modal-overlay .jbh-textarea {
		color: var(--jbh-modal-text, #121212);
		-webkit-text-fill-color: var(--jbh-modal-text, #121212);
	}
}
/* STANDARD: OS light → modal light input text */
@media (prefers-color-scheme: light) {
	html:not([data-jbh-invert]):not([data-jbh-site-mode]):not([data-theme]):not(.dark):not(.light):not([data-color-mode]) body:not([data-ct-color-mode]) #jbh-modal-overlay .jbh-input,
	html:not([data-jbh-invert]):not([data-jbh-site-mode]):not([data-theme]):not(.dark):not(.light):not([data-color-mode]) body:not([data-ct-color-mode]) #jbh-modal-overlay .jbh-textarea {
		color: var(--jbh-modal-text, #121212);
		-webkit-text-fill-color: var(--jbh-modal-text, #121212);
	}
}

.jbh-textarea {
	resize: vertical;
	min-height: 100px;
}

/* ── Tone buttons ─────────────────────────────────────────── */
.jbh-tone-grid {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
}

.jbh-tone-btn {
	padding: 7px 14px;
	border-radius: var(--jbh-radius);
	border: 1px solid var(--jbh-border);
	background: var(--jbh-bg);
	font-family: var(--jbh-font-mono);
	font-size: 0.7rem;
	color: var(--jbh-slate);
	cursor: pointer;
	transition: all 0.18s ease;
}

.jbh-tone-btn:hover { border-color: rgba(42,157,143,0.4); color: var(--jbh-creme); }

.jbh-tone-btn[aria-pressed="true"],
.jbh-tone-btn.is-selected {
	background: var(--jbh-teal);
	border-color: var(--jbh-teal);
	color: #fff;
	font-weight: 700;
	box-shadow: 0 0 0 2px rgba(42, 157, 143, 0.25);
	transform: scale(1.04);
}

.jbh-tone-btn:focus-visible { outline: 2px solid var(--jbh-teal); outline-offset: 2px; }

/* ── Dropzone ─────────────────────────────────────────────── */
.jbh-dropzone {
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 8px;
	padding: 32px 20px;
	border: 2px dashed var(--jbh-border);
	border-radius: var(--jbh-radius);
	background: var(--jbh-bg);
	cursor: pointer;
	transition: border-color 0.2s, background 0.2s;
}

.jbh-dropzone:hover,
.jbh-dropzone.is-dragover {
	border-color: rgba(42, 157, 143, 0.5);
	background: rgba(42, 157, 143, 0.04);
}

.jbh-upload-icon {
	width: 36px;
	height: 36px;
	color: rgba(42, 157, 143, 0.45);
}

.jbh-drop-text {
	font-family: var(--jbh-font-sans);
	font-size: 0.85rem;
	color: var(--jbh-slate);
	text-align: center;
}

.jbh-drop-types {
	font-family: var(--jbh-font-mono);
	font-size: 0.6rem;
	text-transform: uppercase;
	letter-spacing: 0.1em;
	color: rgba(42, 157, 143, 0.5);
}

.jbh-file-hidden {
	display: none;
}

.jbh-file-list {
	list-style: none;
	margin: 10px 0 0 0;
	padding: 0;
	display: flex;
	flex-direction: column;
	gap: 6px;
}

.jbh-file-list li {
	display: flex;
	align-items: center;
	gap: 8px;
	font-family: var(--jbh-font-mono);
	font-size: 0.7rem;
	color: var(--jbh-teal);
}

.jbh-file-list li::before {
	content: "";
	flex-shrink: 0;
	width: 12px;
	height: 12px;
	background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='%232A9D8F' viewBox='0 0 24 24'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' stroke-width='2.5' d='M5 13l4 4L19 7'/%3E%3C/svg%3E") center/contain no-repeat;
}

/* ── Disclaimer ───────────────────────────────────────────── */
.jbh-disclaimer-row {
	padding-top: 8px;
	border-top: 1px solid var(--jbh-border);
}

.jbh-disclaimer-label {
	display: flex;
	align-items: flex-start;
	gap: 12px;
	cursor: pointer;
}

.jbh-disclaimer-check {
	flex-shrink: 0;
	margin-top: 2px;
	accent-color: var(--jbh-teal);
	width: 15px;
	height: 15px;
	cursor: pointer;
}

.jbh-disclaimer-text {
	font-family: var(--jbh-font-sans);
	font-size: 0.78rem;
	color: var(--jbh-slate);
	line-height: 1.6;
}

/* ── Order summary & submit ──────────────────────────────── */
.jbh-order-summary {
	background: var(--jbh-bg);
	border: 1px solid var(--jbh-border);
	border-radius: var(--jbh-radius);
	padding: 24px 22px;
	display: flex;
	flex-direction: column;
	gap: 16px;
}

.jbh-order-total-row {
	display: flex;
	align-items: flex-end;
	justify-content: space-between;
	gap: 16px;
}

.jbh-total-label {
	display: block;
	font-family: var(--jbh-font-mono);
	font-size: 0.6rem;
	text-transform: uppercase;
	letter-spacing: 0.14em;
	color: var(--jbh-slate);
	margin-bottom: 4px;
}

.jbh-total-amount {
	font-family: var(--jbh-font-serif);
	font-size: 2.4rem;
	font-weight: 700;
	color: var(--jbh-modal-heading, var(--jbh-card-heading, currentColor));
	line-height: 1;
}

.jbh-total-delivery {
	font-family: var(--jbh-font-mono);
	font-size: 0.7rem;
	color: var(--jbh-slate);
	text-align: right;
}

.jbh-total-delivery span:last-child {
	color: var(--jbh-teal);
	font-weight: 700;
}

/* Primary buttons (success close, submit) */
.jbh-btn-primary,
.jbh-submit-btn {
	width: 100%;
	padding: 14px 24px;
	border-radius: var(--jbh-radius);
	font-family: var(--jbh-font-serif);
	font-size: 1rem;
	font-weight: 700;
	letter-spacing: 0.04em;
	cursor: pointer;
	transition: background 0.2s, box-shadow 0.2s, opacity 0.2s, transform 0.15s ease;
	border: none;
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 10px;
	position: relative;
	overflow: hidden;
}

.jbh-btn-primary {
	background: var(--jbh-teal-dark);
	color: #fff;
	margin-top: 8px;
}

.jbh-btn-primary:hover { background: var(--jbh-teal); transform: translateY(-1px); }
.jbh-btn-primary:active { transform: scale(0.98); }

.jbh-submit-btn {
	background: var(--jbh-modal-submit-bg, var(--jbh-coral));
	color: var(--jbh-modal-submit-text, #fff);
	box-shadow: 0 4px 14px rgba(214, 79, 66, 0.38);
}

/* Hover state now uses DEDICATED hover vars so the Inspector's
   "Submit Button Hover Bg / Text" pickers actually change the
   colour on hover instead of re-using the normal-state pickers.
   Fallback chain: explicit hover var → coral-hover literal. */
.jbh-submit-btn:not([disabled]):hover {
	background: var(--jbh-modal-submit-bg-hover, var(--jbh-modal-submit-bg, var(--jbh-coral-hover)));
	color: var(--jbh-modal-submit-text-hover, var(--jbh-modal-submit-text, #fff));
	box-shadow: 0 6px 20px rgba(214, 79, 66, 0.48);
	transform: translateY(-1px);
	filter: brightness(1.08);
}
.jbh-submit-btn:not([disabled]):active {
	transform: scale(0.98);
	transition-duration: 0.08s;
}

.jbh-submit-btn[disabled] {
	background: var(--jbh-card);
	color: var(--jbh-slate);
	border: 1px solid var(--jbh-border);
	box-shadow: none;
	cursor: not-allowed;
}

.jbh-btn-primary:focus-visible,
.jbh-submit-btn:focus-visible {
	outline: 2px solid var(--jbh-teal);
	outline-offset: 3px;
	box-shadow: 0 0 0 4px rgba(42, 157, 143, 0.20);
}

/* Ripple effect for modal primary/submit buttons */
.jbh-btn-primary::after,
.jbh-submit-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-btn-primary:active::after,
.jbh-submit-btn:active::after {
	width: 300px; height: 300px;
	opacity: 1;
	transition: width 0s, height 0s, opacity 0s;
}

/* Spinner */
.jbh-submit-spinner {
	width: 16px;
	height: 16px;
	border: 2px solid rgba(255,255,255,0.3);
	border-top-color: #fff;
	border-radius: 50%;
	animation: jbhSpin 0.6s linear infinite;
}

@keyframes jbhSpin { to { transform: rotate(360deg); } }

.jbh-submit-hint {
	font-family: var(--jbh-font-mono);
	font-size: 0.65rem;
	text-align: center;
	color: var(--jbh-slate);
	opacity: 0.6;
	margin: 0;
	transition: opacity 0.2s;
}

.jbh-submit-hint.is-hidden { opacity: 0; }

/* ── Responsive ───────────────────────────────────────────── */
@media (max-width: 520px) {
	.jbh-panel {
		max-width: 100%;
		border-left: none;
		/* Mobile: slide-over pivots to a top-anchored sheet, so the customisable
		   border moves from the left edge to the top edge. Same picker flow. */
		border-top: 1px solid var(--jbh-modal-border, var(--jbh-teal-dark));
	}
}

/* ================================================================
   MODAL STYLE VARIANTS
   ================================================================
   Activated via data-modal-style attribute on .jbh-overlay.
   Default (no attribute) = side-panel (existing slide-over).
   ================================================================ */

/* ── POPUP (centered dialog) ─────────────────────────────── */
.jbh-overlay[data-modal-style="popup"] {
	align-items: center;
	justify-content: center;
	padding: 24px;
}

.jbh-overlay[data-modal-style="popup"] .jbh-panel {
	height: auto;
	max-height: 90dvh;
	max-height: 90vh;
	max-width: 560px;
	border-left: none;
	/* Popup modal style: centred card with all-sides border. Honours the
	   Inspector picker via --jbh-modal-border. */
	border: 1px solid var(--jbh-modal-border, var(--jbh-teal-dark));
	border-radius: 12px;
	/* Mode-reactive popup shadow — see `.jbh-panel` above. */
	box-shadow: var(--jbh-modal-popup-shadow, 0 24px 80px rgba(0, 0, 0, 0.5));
	animation: jbhPopupIn var(--jbh-anim-dur) var(--jbh-ease-out) forwards;
}

.jbh-overlay[data-modal-style="popup"].is-closing .jbh-panel {
	animation: jbhPopupOut var(--jbh-anim-dur) var(--jbh-ease-out) forwards;
}

@keyframes jbhPopupIn  {
	from { opacity: 0; transform: scale(0.92) translateY(16px); }
	to   { opacity: 1; transform: scale(1) translateY(0); }
}
@keyframes jbhPopupOut {
	from { opacity: 1; transform: scale(1) translateY(0); }
	to   { opacity: 0; transform: scale(0.92) translateY(16px); }
}

/* ── FULLSCREEN ──────────────────────────────────────────── */
.jbh-overlay[data-modal-style="fullscreen"] {
	align-items: stretch;
	justify-content: stretch;
}

.jbh-overlay[data-modal-style="fullscreen"] .jbh-panel {
	max-width: 100%;
	width: 100%;
	height: 100dvh;
	height: 100vh;
	border-left: none;
	border-radius: 0;
	box-shadow: none;
	animation: jbhModalFadeIn var(--jbh-anim-dur) ease forwards;
}

.jbh-overlay[data-modal-style="fullscreen"].is-closing .jbh-panel {
	animation: jbhModalFadeOut var(--jbh-anim-dur) ease forwards;
}

.jbh-overlay[data-modal-style="fullscreen"] .jbh-panel-header {
	max-width: 680px;
	margin-left: auto;
	margin-right: auto;
	width: 100%;
}

.jbh-overlay[data-modal-style="fullscreen"] .jbh-form-wrap {
	max-width: 680px;
	margin-left: auto;
	margin-right: auto;
}

.jbh-overlay[data-modal-style="fullscreen"] .jbh-success {
	max-width: 680px;
	margin-left: auto;
	margin-right: auto;
}

/* ── BOTTOM SHEET ────────────────────────────────────────── */
.jbh-overlay[data-modal-style="bottom-sheet"] {
	align-items: flex-end;
	justify-content: center;
}

.jbh-overlay[data-modal-style="bottom-sheet"] .jbh-panel {
	width: 100%;
	max-width: 640px;
	height: auto;
	max-height: 85dvh;
	max-height: 85vh;
	border-left: none;
	/* Bottom-sheet modal style: full-width sheet rising from the bottom.
	   Only the top edge is visible, so that is what the picker controls. */
	border-top: 1px solid var(--jbh-modal-border, var(--jbh-teal-dark));
	border-radius: 16px 16px 0 0;
	box-shadow: 0 -12px 60px rgba(0, 0, 0, 0.4);
	animation: jbhSheetIn var(--jbh-anim-dur) var(--jbh-ease-out) forwards;
}

.jbh-overlay[data-modal-style="bottom-sheet"].is-closing .jbh-panel {
	animation: jbhSheetOut var(--jbh-anim-dur) var(--jbh-ease-out) forwards;
}

.jbh-overlay[data-modal-style="bottom-sheet"] .jbh-panel-header::before {
	content: '';
	display: block;
	width: 36px;
	height: 4px;
	background: var(--jbh-slate);
	border-radius: 2px;
	margin: 0 auto 12px;
	opacity: 0.5;
}

@keyframes jbhSheetIn  {
	from { transform: translateY(100%); }
	to   { transform: translateY(0); }
}
@keyframes jbhSheetOut {
	from { transform: translateY(0); }
	to   { transform: translateY(100%); }
}

/* ── Responsive overrides for modal variants ─────────────── */
@media (max-width: 520px) {
	.jbh-overlay[data-modal-style="popup"] {
		padding: 0;
	}
	.jbh-overlay[data-modal-style="popup"] .jbh-panel {
		max-width: 100%;
		max-height: 100dvh;
		max-height: 100vh;
		border-radius: 0;
		height: 100dvh;
		height: 100vh;
	}
	.jbh-overlay[data-modal-style="bottom-sheet"] .jbh-panel {
		max-width: 100%;
		max-height: 95dvh;
		max-height: 95vh;
	}
}

/* ── Reduced motion ───────────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
	.jbh-panel,
	.jbh-overlay-backdrop,
	.jbh-overlay.is-closing .jbh-panel,
	.jbh-overlay.is-closing .jbh-overlay-backdrop {
		animation: none;
	}

	.jbh-submit-spinner {
		animation: none;
		border-top-color: rgba(255,255,255,0.6);
	}

	.jbh-btn-primary::after,
	.jbh-submit-btn::after {
		display: none;
	}

	.jbh-close-btn:hover,
	.jbh-close-btn:active,
	.jbh-btn-primary:hover,
	.jbh-btn-primary:active,
	.jbh-submit-btn:hover,
	.jbh-submit-btn:active {
		transform: none;
	}
}

/* Anti-spam honeypot: remains in the DOM for simple bots but cannot affect layout. */
.jbh-order-honeypot {
	position: absolute !important;
	inline-size: 1px !important;
	block-size: 1px !important;
	overflow: hidden !important;
	clip: rect(0 0 0 0) !important;
	clip-path: inset(50%) !important;
	white-space: nowrap !important;
}


/* Phase 2 canonical fallbacks inside the Studio configurator. */
.jbh-panel-full-link { display: inline-flex; margin-top: 6px; color: var(--jbh-modal-accent, var(--jbh-teal)); font-size: .82rem; font-weight: 700; text-underline-offset: .18em; }
.jbh-panel-full-link[hidden] { display: none !important; }
a.jbh-addon-name { text-decoration: none; }
a.jbh-addon-name:hover,
a.jbh-addon-name:focus-visible { color: var(--jbh-modal-accent, var(--jbh-teal)); text-decoration: underline; text-underline-offset: .18em; }

/* v1.14.2 — quantity controls expose their real boundary state. */
.jbh-qty-btn:disabled,
.jbh-qty-btn[aria-disabled="true"] {
	opacity: 0.42;
	cursor: not-allowed;
	background: transparent;
	color: var(--jbh-slate);
}
.jbh-qty-btn:disabled:hover,
.jbh-qty-btn[aria-disabled="true"]:hover {
	background: transparent;
	color: var(--jbh-slate);
}

/* ================================================================
   v1.15.21 — Modal control isolation from theme button rules
   ================================================================ */
#jbh-modal-overlay button.jbh-close-btn,
#jbh-modal-overlay button.jbh-close-btn:focus,
#jbh-modal-overlay button.jbh-close-btn:active {
	-webkit-appearance: none !important;
	appearance: none !important;
	border: 0 !important;
	background-color: transparent !important;
	background-image: none !important;
	box-shadow: none !important;
	color: var(--jbh-slate) !important;
	text-shadow: none !important;
	filter: none !important;
}
#jbh-modal-overlay button.jbh-close-btn:hover {
	background-color: rgba(128,128,128,0.12) !important;
	color: var(--jbh-modal-heading, var(--jbh-card-heading, currentColor)) !important;
}
#jbh-modal-overlay button.jbh-close-btn:focus-visible {
	outline: 2px solid var(--jbh-teal) !important;
	outline-offset: 2px !important;
	box-shadow: 0 0 0 4px rgba(42, 157, 143, 0.15) !important;
}
#jbh-modal-overlay button.jbh-tone-btn {
	-webkit-appearance: none !important;
	appearance: none !important;
	border-color: var(--jbh-border) !important;
	background-color: var(--jbh-bg) !important;
	background-image: none !important;
	box-shadow: none !important;
	color: var(--jbh-slate) !important;
	font-family: var(--jbh-font-mono) !important;
	text-transform: none !important;
	text-shadow: none !important;
}
#jbh-modal-overlay button.jbh-tone-btn:hover {
	border-color: rgba(42,157,143,0.4) !important;
	background-color: var(--jbh-bg) !important;
	color: var(--jbh-creme) !important;
}
#jbh-modal-overlay button.jbh-tone-btn:is([aria-pressed="true"], .is-selected),
#jbh-modal-overlay button.jbh-tone-btn:is([aria-pressed="true"], .is-selected):hover,
#jbh-modal-overlay button.jbh-tone-btn:is([aria-pressed="true"], .is-selected):focus-visible {
	border-color: var(--jbh-teal) !important;
	background-color: var(--jbh-teal) !important;
	color: #fff !important;
	box-shadow: 0 0 0 2px rgba(42, 157, 143, 0.25) !important;
}
#jbh-modal-overlay :is(button.jbh-btn-primary, button.jbh-submit-btn) {
	-webkit-appearance: none !important;
	appearance: none !important;
	background-image: none !important;
	text-shadow: none !important;
}
#jbh-modal-overlay button.jbh-btn-primary {
	border: 0 !important;
	background-color: var(--jbh-teal-dark) !important;
	color: #fff !important;
}
#jbh-modal-overlay button.jbh-btn-primary:hover {
	background-color: var(--jbh-teal) !important;
	color: #fff !important;
}
#jbh-modal-overlay button.jbh-submit-btn:not([disabled]) {
	border: 0 !important;
	background-color: var(--jbh-modal-submit-bg, var(--jbh-coral)) !important;
	color: var(--jbh-modal-submit-text, #fff) !important;
}
#jbh-modal-overlay button.jbh-submit-btn:not([disabled]):hover {
	background-color: var(--jbh-modal-submit-bg-hover, var(--jbh-modal-submit-bg, var(--jbh-coral-hover))) !important;
	color: var(--jbh-modal-submit-text-hover, var(--jbh-modal-submit-text, #fff)) !important;
}
#jbh-modal-overlay button.jbh-submit-btn[disabled] {
	border: 1px solid var(--jbh-border) !important;
	background-color: var(--jbh-card) !important;
	color: var(--jbh-slate) !important;
	box-shadow: none !important;
}

/* v1.15.21 — Complete configurator field and micro-control ownership. */
#jbh-modal-overlay :is(input.jbh-input, textarea.jbh-textarea) {
	box-sizing: border-box !important;
	width: 100% !important;
	max-width: 100% !important;
	margin: 0 !important;
	padding: 12px 14px !important;
	border: 1px solid var(--jbh-border) !important;
	border-radius: var(--jbh-radius) !important;
	background-color: var(--jbh-bg) !important;
	background-image: none !important;
	box-shadow: none !important;
	color: var(--jbh-creme) !important;
	font-family: var(--jbh-font-sans) !important;
	font-size: .875rem !important;
	font-weight: 400 !important;
	line-height: 1.5 !important;
	letter-spacing: normal !important;
	text-transform: none !important;
	text-shadow: none !important;
	filter: none !important;
}
#jbh-modal-overlay :is(input.jbh-input, textarea.jbh-textarea):focus {
	border-color: var(--jbh-teal) !important;
	background-color: var(--jbh-bg) !important;
	box-shadow: 0 0 0 3px color-mix(in srgb, var(--jbh-teal) 20%, transparent) !important;
	outline: 0 !important;
}
#jbh-modal-overlay :is(input.jbh-input, textarea.jbh-textarea)::placeholder {
	color: var(--jbh-slate) !important;
	-webkit-text-fill-color: var(--jbh-slate) !important;
	opacity: .58 !important;
}
#jbh-modal-overlay :is(input.jbh-upgrade-check, input.jbh-disclaimer-check) {
	-webkit-appearance: auto !important;
	appearance: auto !important;
	width: 16px !important;
	height: 16px !important;
	min-width: 16px !important;
	min-height: 16px !important;
	margin: 2px 0 0 !important;
	padding: 0 !important;
	border: initial !important;
	border-radius: initial !important;
	background: initial !important;
	box-shadow: none !important;
	accent-color: var(--jbh-teal) !important;
	filter: none !important;
}
#jbh-modal-overlay button.jbh-qty-btn,
#jbh-modal-overlay button.jbh-qty-btn:focus,
#jbh-modal-overlay button.jbh-qty-btn:active,
#jbh-modal-overlay button.jbh-file-remove,
#jbh-modal-overlay button.jbh-file-remove:focus,
#jbh-modal-overlay button.jbh-file-remove:active {
	-webkit-appearance: none !important;
	appearance: none !important;
	margin: 0 !important;
	border: 0 !important;
	border-radius: 0 !important;
	background-color: transparent !important;
	background-image: none !important;
	box-shadow: none !important;
	font-family: var(--jbh-font-sans) !important;
	text-transform: none !important;
	text-shadow: none !important;
	filter: none !important;
}
#jbh-modal-overlay button.jbh-qty-btn {
	width: 32px !important;
	height: 32px !important;
	min-width: 32px !important;
	min-height: 32px !important;
	padding: 0 !important;
	color: var(--jbh-creme) !important;
	font-size: 1rem !important;
	line-height: 1 !important;
}
#jbh-modal-overlay button.jbh-qty-btn:hover {
	background-color: color-mix(in srgb, var(--jbh-teal) 15%, transparent) !important;
	color: var(--jbh-teal) !important;
}
#jbh-modal-overlay button.jbh-qty-btn:focus-visible {
	outline: 2px solid var(--jbh-teal) !important;
	outline-offset: -2px !important;
}
#jbh-modal-overlay button.jbh-qty-btn:is(:disabled, [aria-disabled="true"]),
#jbh-modal-overlay button.jbh-qty-btn:is(:disabled, [aria-disabled="true"]):hover {
	background-color: transparent !important;
	color: var(--jbh-slate) !important;
	box-shadow: none !important;
	opacity: .42 !important;
	transform: none !important;
}
#jbh-modal-overlay button.jbh-file-remove {
	min-width: 28px !important;
	min-height: 28px !important;
	padding: 0 4px !important;
	color: var(--jbh-coral, #d64f42) !important;
	font-size: .9rem !important;
	line-height: 1 !important;
}
#jbh-modal-overlay button.jbh-file-remove:hover {
	background-color: color-mix(in srgb, var(--jbh-coral, #d64f42) 12%, transparent) !important;
	color: var(--jbh-coral-hover, #e76f51) !important;
}
#jbh-modal-overlay button.jbh-file-remove:focus-visible {
	outline: 2px solid var(--jbh-coral, #d64f42) !important;
	outline-offset: 2px !important;
}

/* v1.16.9 — resilient lazy-loading feedback and narrow-viewport ownership. */
[data-jbh-service-modal-trigger].jbh-modal-trigger-loading {
	cursor: progress !important;
	opacity: .78;
}
.jbh-modal-load-notice {
	box-sizing: border-box;
	width: 100%;
	margin-top: 10px;
	padding: 10px 12px;
	border: 1px solid color-mix(in srgb, var(--jbh-coral, #d64f42) 55%, transparent);
	border-radius: 8px;
	background: color-mix(in srgb, var(--jbh-coral, #d64f42) 10%, var(--jbh-card, #fff));
	color: var(--jbh-card-heading, currentColor);
	font-size: .875rem;
	line-height: 1.45;
}
#jbh-modal-overlay {
	box-sizing: border-box;
	max-width: 100vw;
	max-height: 100dvh;
}
#jbh-modal-overlay .jbh-panel {
	box-sizing: border-box;
	max-width: min(100%, 680px);
	max-height: 100dvh;
}
#jbh-modal-overlay :is(input.jbh-input, textarea.jbh-textarea) {
	height: auto !important;
	min-height: 48px !important;
	max-height: none !important;
}
#jbh-modal-overlay textarea.jbh-textarea {
	min-height: 112px !important;
}
#jbh-modal-overlay :is(button, a, input[type="checkbox"], input[type="radio"]) {
	touch-action: manipulation;
}

@media (max-width: 520px) {
	#jbh-modal-overlay {
		padding: 0 !important;
	}
	#jbh-modal-overlay .jbh-panel {
		width: 100% !important;
		height: 100dvh;
		max-width: 100% !important;
		max-height: 100dvh !important;
		padding-bottom: env(safe-area-inset-bottom, 0px);
	}
	#jbh-modal-overlay :is(input.jbh-input, textarea.jbh-textarea, button.jbh-submit-btn) {
		font-size: 16px !important;
	}
	#jbh-modal-overlay :is(button.jbh-close-btn, button.jbh-submit-btn, button.jbh-btn-primary) {
		min-height: 48px !important;
	}
	#jbh-modal-overlay button.jbh-close-btn {
		min-width: 48px !important;
	}
}
