/**
 * CDSWerx Sticky Nav Styler — Base Stylesheet (v5.0)
 *
 * Stuck-state visual skin + sticky-triggered entrance/exit animations.
 * All rules key off the internal state contract:
 *   [data-cds-sticky-nav][data-state="default" | "stuck" | "unsticking"]
 * "unsticking" is a transient state held by the companion JS for the exit
 * animation's duration — every stuck-look rule therefore matches
 * :is([data-state="stuck"], [data-state="unsticking"]) so the element
 * keeps its stuck appearance while animating out.
 *
 * Provider classes (Elementor Pro / JetSticky) are never referenced here —
 * the state-machine JS handles that translation. Pinning behavior (sticky
 * offset, devices, stop-at-parent, anchor offset) is intentionally NOT in
 * this stylesheet: provider territory + CDSWerx Plugin → Frontend Fixes.
 *
 * @package CDSWerx_Widget_Library
 * @since   4.0.0
 * @since   5.0.0
 * @since   6.0.0 (#121) Stuck-size model: the bar is padding + the visible logo;
 *          no measured layout, no forced height. See spec §13.
 */

/* === Stacking guard =========================================================
   A styled header must out-rank ordinary page content in BOTH states —
   otherwise it slides behind the page when the provider releases it.
   The CDSWerx Plugin tier system (cdswerx-globalstyles.css) only covers
   elements matching `header.sticky-header` (z-index 10000 !important);
   this is the baseline for containers that don't follow that convention.
   - :where() drops the position guard to zero specificity, so Elementor's
     own position settings (absolute/fixed) always win.
   - z-index is overridable via Elementor's Advanced → Z-Index control
     (higher specificity) or the --cds-nav-z variable. */
:where([data-cds-sticky-nav]) {
	position: relative;
}
[data-cds-sticky-nav] {
	z-index: var(--cds-nav-z, 100);
}

/* === Shared timing token =================================================== */
[data-cds-sticky-nav] {
	--cds-transition: var(--cds-transition-duration, .45s) var(--cds-transition-easing, cubic-bezier(.4, 0, .2, 1));
	transition:
		background-color  var(--cds-transition),
		backdrop-filter   var(--cds-transition),
		-webkit-backdrop-filter var(--cds-transition),
		box-shadow        var(--cds-transition),
		border-color      var(--cds-transition);
}

/* #64 — release sync. The provider (JetSticky / Elementor Pro) snaps the
   element from fixed back into flow INSTANTLY on release; our skin must not
   keep fading for another 0.45s over page content (reads as a color smear/
   flash). data-state="default" lands in the same task as the provider's
   class removal, so zeroing the duration here drops the stuck skin in the
   same frame position snaps. Stick-IN keeps the configured duration (this
   rule stops applying the moment state flips to "stuck"), and a configured
   Return Effect still gets its hold via the transient "unsticking" state,
   which this selector deliberately does not match. */
[data-cds-sticky-nav][data-state="default"] {
	transition-duration: 0s;
}

/* === Stuck state — backdrop filter =========================================
   Background color/gradient/image come from the "Sticky Section Style"
   Background group control (Elementor-generated CSS at high specificity);
   only the backdrop filter lives here, driven by the blur/saturation vars. */
[data-cds-sticky-nav]:is([data-state="stuck"], [data-state="unsticking"]) {
	-webkit-backdrop-filter: saturate(var(--cds-nav-saturate, 100%)) blur(var(--cds-nav-blur, 0px));
	        backdrop-filter: saturate(var(--cds-nav-saturate, 100%)) blur(var(--cds-nav-blur, 0px));
}

/* === Sticky-triggered entrance / exit animations (v5.0) =====================
   --cds-entrance-anim / --cds-exit-anim carry keyframe names set by the
   Effect selects ("none" when unset). "both" fill keeps the final frame
   while stuck and the exit start-frame during the unsticking hold. */
[data-cds-sticky-nav][data-state="stuck"] {
	animation:
		var(--cds-entrance-anim, none)
		var(--cds-entrance-duration, .4s)
		var(--cds-transition-easing, cubic-bezier(.4, 0, .2, 1))
		var(--cds-entrance-delay, 0ms)
		both;
}
[data-cds-sticky-nav][data-state="unsticking"] {
	animation:
		var(--cds-exit-anim, none)
		var(--cds-entrance-duration, .4s)
		var(--cds-transition-easing, cubic-bezier(.4, 0, .2, 1))
		0ms
		both;
}

@keyframes cds-fade-in {
	from { opacity: 0; }
	to   { opacity: 1; }
}
@keyframes cds-fade-in-down {
	from { opacity: 0; transform: translateY(-24px); }
	to   { opacity: 1; transform: translateY(0); }
}
@keyframes cds-slide-in-down {
	from { transform: translateY(-100%); }
	to   { transform: translateY(0); }
}
@keyframes cds-fade-out {
	from { opacity: 1; }
	to   { opacity: 0; }
}
@keyframes cds-fade-out-up {
	from { opacity: 1; transform: translateY(0); }
	to   { opacity: 0; transform: translateY(-24px); }
}
@keyframes cds-slide-out-up {
	from { transform: translateY(0); }
	to   { transform: translateY(-100%); }
}

/* Accessibility: states still flip (styling applies), motion is removed. */
@media (prefers-reduced-motion: reduce) {
	[data-cds-sticky-nav][data-state="stuck"],
	[data-cds-sticky-nav][data-state="unsticking"] {
		animation: none !important;
	}
}

/* === Stuck state — nav link colors ==========================================
   INTENTIONALLY NOT HERE (#66/#70). Vendor menu selectors live in ONE place —
   the NAV_ADAPTERS registry in class-cdswerx-sticky-nav-styler.php — and the
   color bindings are generated PER ELEMENT in before_render(), emitted only
   for colors the user actually set (#70 contract: unset color = no rule at
   all, so the menu widget's own styling is untouched by definition). The old
   hardcoded block bound `.jet-nav .sub-menu`, which JetBlocks' walker never
   renders (dead Sub-menu controls), and `.jet-nav .menu-item-link`, which
   leaked the top-level color into sub links. Do not re-add vendor selectors
   to this file. */

/* === Smooth color transitions on link elements ============================= */
[data-cds-sticky-nav] .elementor-nav-menu .menu-item a,
[data-cds-sticky-nav] .jet-nav .menu-item a,
[data-cds-sticky-nav] .jet-nav .menu-item-link {
	transition: color var(--cds-transition);
}

/* === Logo Swap (v4.2 — static convention classes) ==========================
   Two mechanisms, both opacity/visibility-only (no reflow), both driven
   entirely by the rules below — no PHP-generated selectors.

   SIMPLE mode (panel media picker):
     The companion JS tags the detected logo widget `.cds-logo-host` and
     appends the sticky image as `<img class="cds-logo--sticky cds-logo--injected">`
     inside it. The injected image is absolutely centered over the host.

   ADVANCED mode (two widgets, user-applied classes):
     `.cds-logo`         → default logo widget (visible until stuck)
     `.cds-logo--sticky` → sticky logo widget  (visible only when stuck)
     `.cds-logo-stack`   → parent wrapper for true overlap — auto-detected in
                           CSS (see the overlap rules below) and stamped by
                           the JS; hand-applied only for mixed containers.
   ========================================================================== */

/* Logo-swap timing — its OWN duration/easing (Logo Swap → Duration / Easing),
   decoupled from the header transition so header height and logo don't fight. */
[data-cds-sticky-nav] {
	--cds-logo-transition: var(--cds-logo-duration, .4s) var(--cds-logo-easing, cubic-bezier(.4, 0, .2, 1));
}
/* Swap Style → slide offsets. Fade/None leave the offsets at 0. */
[data-cds-sticky-nav][data-cds-logo-anim="slide-up"]   { --cds-logo-slide-in: 12px;  --cds-logo-slide-out: -12px; }
[data-cds-sticky-nav][data-cds-logo-anim="slide-down"] { --cds-logo-slide-in: -12px; --cds-logo-slide-out: 12px;  }
[data-cds-sticky-nav][data-cds-logo-anim="none"]       { --cds-logo-duration: 0s; }

/* Swap Timing → entrance delay. Sequential holds the incoming logo back until
   the outgoing has (mostly) faded, so the two are never both visible ("2×
   logos" ghosting). Crossfade leaves the delay at 0 (simultaneous). */
[data-cds-sticky-nav][data-cds-logo-timing="sequential"] {
	--cds-logo-in-delay: calc(var(--cds-logo-duration, .4s) * .55);
}

/* Transition the INDIVIDUAL transform properties (translate/scale) + opacity,
   applied to the widgets AND their inner img/svg. The v4.2 rule declared the
   transition only on the wrappers, so the scale — applied to the descendant
   img/svg — SNAPPED with no easing (the jerkiness). Using individual props
   also lets the injected image keep its centering in `transform` untouched. */
[data-cds-sticky-nav] .cds-logo,
[data-cds-sticky-nav] .cds-logo--sticky,
[data-cds-sticky-nav] .cds-logo-host > *,
[data-cds-sticky-nav] .cds-logo img,
[data-cds-sticky-nav] .cds-logo svg,
[data-cds-sticky-nav] .cds-logo--sticky img,
[data-cds-sticky-nav] .cds-logo--sticky svg {
	transition:
		opacity    var(--cds-logo-transition),
		visibility var(--cds-logo-transition),
		translate  var(--cds-logo-transition),
		scale      var(--cds-logo-transition);
}

/* Default state: sticky variants hidden, pre-offset by the slide-in distance */
[data-cds-sticky-nav] .cds-logo--sticky {
	opacity: 0;
	visibility: hidden;
	pointer-events: none;
	translate: 0 var(--cds-logo-slide-in, 0);
}

/* Stuck state — ADVANCED two-widget swap.
   :not(.cds-logo-host) keeps a `.cds-logo`-tagged Simple-mode host from
   hiding itself (which would also hide the injected sticky image inside).
   [data-cds-logo-anim] gates the swap on a swap MODE being selected — the
   attribute is emitted for simple/advanced only — so a `.cds-logo` tag
   left on a widget no longer swaps anything when Logo Swap is Off or
   "Keep same logo" (where the tag legitimately means "this is the logo
   to scale", not "hide me when stuck"). */
[data-cds-sticky-nav][data-cds-logo-anim]:is([data-state="stuck"], [data-state="unsticking"]) .cds-logo:not(.cds-logo-host) {
	opacity: 0;
	visibility: hidden;
	pointer-events: none;
	translate: 0 var(--cds-logo-slide-out, 0);
}
[data-cds-sticky-nav][data-cds-logo-anim]:is([data-state="stuck"], [data-state="unsticking"]) .cds-logo--sticky {
	opacity: 1;
	visibility: visible;
	pointer-events: auto;
	translate: 0 0;
}

/* Stuck state — SIMPLE injected swap: hide the host widget's original
   content (Image widget markup or CDSWerx SVG markup), not the host. */
[data-cds-sticky-nav]:is([data-state="stuck"], [data-state="unsticking"]) .cds-logo-host > :not(.cds-logo--injected) {
	opacity: 0;
	visibility: hidden;
	pointer-events: none;
	translate: 0 var(--cds-logo-slide-out, 0);
}

/* Injected sticky image: centered over the host (centering lives in `transform`
   so the animated `translate`/`scale` properties stay free). */
[data-cds-sticky-nav] .cds-logo-host {
	position: relative;
}
[data-cds-sticky-nav] .cds-logo--injected {
	/* Full-box overlay, NO transform centering: the composed matrix
	   scales any centering translate along with the element (a -50%
	   pull becomes -40% at scale .8), which makes edge-anchored
	   transform-origins drift by half the shrink. inset:0 + 100% box
	   needs no translate, so scale pivots exactly on the chosen origin;
	   the drawn image is anchored inside the box by object-position
	   (same --cds-logo-origin var). Matches the anchor path (#61). */
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: contain;
}
/* #61: the injected element may be a cloned <a> wrapping the image (link
   parity). The anchor must NOT shrink-to-fit: an absolutely-positioned
   auto-width anchor whose child img uses max-width:100% is a cyclic
   constraint browsers resolve to a 0×0 box (verified live on beta.28 —
   logo present, linked, loaded, and zero pixels). Fill the host box
   explicitly and contain the image inside it — identical geometry to the
   bare-img fallback. */
[data-cds-sticky-nav] a.cds-logo--injected {
	width: 100%;
	height: 100%;
}
[data-cds-sticky-nav] a.cds-logo--injected img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: contain;
}

/* Logo Scale When Stuck (--cds-logo-scale) — a REAL size, via `zoom` (v6, #121).
   `zoom` scales the widget's declared lengths in LAYOUT — the artwork's
   max-width / height, the widget's own px sizes — so the box shrinks with the
   picture and the bar follows. A transform (`scale`) is paint-only by spec
   and left a full-size box around a smaller picture in every mode: the trap.
   Placement: the logo WIDGET element itself — not .elementor-widget-container
   (absent under Elementor's optimized markup, default in 4.x) and not the
   img/svg (a percentage width resolves against the unzoomed parent and would
   not shrink). Known limit: a logo sized ONLY as a percentage of its column is
   sized by the column and nothing but the column can shrink it — the panel
   says so. Gated on an active logo mode so a stray tag on a swap-off header
   keeps its size (the old paint rule was not gated). Verified by rendered
   geometry in Chrome 152 and Firefox 155; `zoom` is standard (CSS Viewport L1).
   The transition list REPEATS the swap properties: a later same-specificity
   shorthand would otherwise wipe the crossfade. In the default state only the
   zoom duration is zeroed (#64: the size snaps back in the frame the provider
   un-pins, the fade still plays). */
[data-cds-sticky-nav]:is([data-cds-logo-anim], [data-cds-logo-scale-only]) :is(.cds-logo, .cds-logo--sticky, .cds-logo-host, .cds-logo-scale) {
	transition:
		opacity    var(--cds-logo-transition),
		visibility var(--cds-logo-transition),
		translate  var(--cds-logo-transition),
		zoom       var(--cds-logo-transition);
}
[data-cds-sticky-nav]:is([data-cds-logo-anim], [data-cds-logo-scale-only]):is([data-state="stuck"], [data-state="unsticking"]) :is(.cds-logo, .cds-logo--sticky, .cds-logo-host, .cds-logo-scale) {
	zoom: var(--cds-logo-scale, .8);
}
[data-cds-sticky-nav]:is([data-cds-logo-anim], [data-cds-logo-scale-only])[data-state="default"] :is(.cds-logo, .cds-logo--sticky, .cds-logo-host, .cds-logo-scale) {
	transition-duration: var(--cds-logo-duration, .4s), var(--cds-logo-duration, .4s), var(--cds-logo-duration, .4s), 0s;
}

/* Scale From (--cds-logo-origin / --cds-logo-anchor). With `zoom` the box
   shrinks in layout from its own top-left; the pair's shared edge is owned by
   `justify-self` on the two logo roles (overlap cell) and the injected image
   by object-position below. transform-origin is kept for the injected overlay
   only; it is inert on zoomed widgets. */
[data-cds-sticky-nav] .cds-logo img,
[data-cds-sticky-nav] .cds-logo svg,
[data-cds-sticky-nav] .cds-logo--sticky img,
[data-cds-sticky-nav] .cds-logo--sticky svg,
[data-cds-sticky-nav] .cds-logo--injected {
	transform-origin: var(--cds-logo-origin, center center);
}
/* Injected path: the contained image must anchor to the same edge inside its
   box, or object-fit's centering visually cancels an edge origin. (Ignored
   on the non-replaced <a>; applies to the bare-img fallback and inner img.) */
[data-cds-sticky-nav] .cds-logo--injected,
[data-cds-sticky-nav] a.cds-logo--injected img {
	object-position: var(--cds-logo-origin, center center);
}

/* Sequential handoff — delay ONLY the entering logo. The delay lives in the
   state where each logo APPEARS (sticky logo in the stuck state; default logo
   in the default state), so entrance waits but exit stays immediate — a
   direction-correct handoff that never leaves both logos visible at once. */
[data-cds-sticky-nav]:is([data-state="stuck"], [data-state="unsticking"]) .cds-logo--sticky {
	transition-delay: var(--cds-logo-in-delay, 0s);
}
[data-cds-sticky-nav]:not([data-state="stuck"]):not([data-state="unsticking"]) .cds-logo:not(.cds-logo-host),
[data-cds-sticky-nav]:not([data-state="stuck"]):not([data-state="unsticking"]) .cds-logo-host > :not(.cds-logo--injected) {
	transition-delay: var(--cds-logo-in-delay, 0s);
}

/* Accessibility: collapse the logo motion for reduced-motion users. */
@media (prefers-reduced-motion: reduce) {
	[data-cds-sticky-nav] .cds-logo,
	[data-cds-sticky-nav] .cds-logo--sticky,
	[data-cds-sticky-nav] .cds-logo-host > *,
	[data-cds-sticky-nav] .cds-logo img,
	[data-cds-sticky-nav] .cds-logo svg,
	[data-cds-sticky-nav] .cds-logo--sticky img,
	[data-cds-sticky-nav] .cds-logo--sticky svg,
	[data-cds-sticky-nav] .cds-logo-scale img,
	[data-cds-sticky-nav] .cds-logo-scale svg {
		transition-duration: 0.01ms;
	}
}

/* VENDOR-SEAM:BEGIN — Elementor widget/container DOM (register: VENDOR_DOM in the styler PHP) */
/* Overlap cell for ADVANCED mode: the parent holding default + sticky logo
   widgets becomes a grid and both children occupy the same cell so the swap
   happens in place.

   The parent is matched TWO ways, in one selector list so the declarations
   can never drift:
     1. `.cds-logo-stack` — the class the JS stamps (ensureLogoStack, safe
        case) or the user hand-applies (mixed containers). Also the marker
        the measurement pass keys off, so the JS keeps stamping it.
     2. `:has()` auto-detection of the SAME safe case the JS applies — both
        logos are direct children and no OTHER .elementor-element shares the
        parent (mixed containers are never collapsed: #63). Simple mode is
        excluded like the JS (`:not([data-cds-logo-src] *)`).
   Why both: the JS is footer-loaded and runs after first paint, so with
   the class alone the un-stacked header painted first — logos stacked
   VERTICALLY, the header grew past its negative overlay margin, and a blank
   band flashed above the hero until the class landed (live-hit on TMG:
   269px vs 142px header, 77px band). CSS applies at first paint; the JS
   stamp that follows is a no-op visually. Wrapped in :is()/:where():
   forgiving list — a browser without :has() drops that branch and keeps
   the class branch (today's behavior, no regression); :where() zeroes the
   :has() chain so specificity stays exactly the class rule's (0,2,0) /
   (0,3,0) — no new cascade weight over Elementor's container rules.
   The :where() compound MUST stay on one line: whitespace between its
   pseudo-classes is a descendant combinator and silently turns it into a
   selector that never matches (caught by the no-JS fixture on TMG).
   KEEP IN SYNC with ensureLogoStack() in cdswerx-sticky-nav.js.

   justify-content maps from --align-items ON PURPOSE: the stack usually
   lands on a flex-COLUMN Elementor container, where the user's horizontal
   alignment lives in Align Items (--align-items) and Justify Content is
   the VERTICAL axis. Bare `display: grid` re-reads the user's
   --justify-content as horizontal — a silent axis remap that centered
   logo pairs no control could move (live-hit on TMG staging), and made
   editor (flex semantics) and frontend (grid semantics) disagree. Mapping
   the grid's inline axis to --align-items keeps "Align Items: left/
   center/right" meaning horizontal in both render models. flex-start/
   flex-end are valid grid alignment values (CSS Box Alignment maps them);
   unset falls back to start. */
[data-cds-sticky-nav] :is(
	.cds-logo-stack,
	:where(:not([data-cds-logo-src] *):has(> .cds-logo):has(> .cds-logo--sticky):not(:has(> .elementor-element:not(.cds-logo, .cds-logo--sticky))))
) {
	display: grid;
	justify-content: var(--align-items, start);
}
/* #63: cell assignment is scoped to the two logo roles — `> *` collapsed
   EVERY child (nav, buttons, spacers) into one cell when the stack class
   landed on a mixed container. Non-logo children now flow normally.

   justify-self maps from Scale From (--cds-logo-anchor) ON PURPOSE: the two
   logos usually differ in size, and a shared grid cell left-aligns them by
   default — their pivot edges (transform-origin, same control) then never
   coincide, so "Scale From: right" pivots each logo around a DIFFERENT x and
   the swap still reads as collapsing left (live-hit on TMG staging). One
   value must own the pair's shared edge: Scale From anchors both boxes to
   that edge AND pivots the shrink there — the box-level analog of what
   Simple mode already does with object-position from the same var. Division
   of labor: container Align Items places the pair; Scale From aligns the two
   logos to each other. justify-self is per-item (never justify-items — a
   container-wide default would re-align non-logo children in manual mixed
   stacks, the exact blast radius #63 scoped away). left/right stay physical
   to match transform-origin's physical keywords in RTL. */
/* align-self: start — pins BOTH logo boxes to the top of the shared cell
   (identical paint to grid's default stretch for the artwork, which already
   sat at the top). In v6 it also positions the out-of-flow inactive logo:
   an absolutely-positioned grid child with explicit lines uses the cell as
   its containing block and honours justify-self / align-self, so the
   outgoing logo keeps the same anchor as the incoming one during the swap. */
[data-cds-sticky-nav] :is(
	.cds-logo-stack,
	:where(:not([data-cds-logo-src] *):has(> .cds-logo):has(> .cds-logo--sticky):not(:has(> .elementor-element:not(.cds-logo, .cds-logo--sticky))))
) > :is(.cds-logo, .cds-logo--sticky) {
	grid-column: 1 / 1;
	grid-row:    1 / 1;
	justify-self: var(--cds-logo-anchor, center);
	align-self: start;
}


/* === Stuck-size model (v6, #121) ============================================
   THE BAR IS NEVER GIVEN A HEIGHT. It is stuck padding (Elementor's own
   padding vars, written by the Padding control) + the VISIBLE logo + whatever
   else is in flow. Flow layout is the clamp; nothing is measured. The v5.1
   fit machinery and the v5.2 true-dimensions stamps are gone with their
   five runtime variables — every August regression was a wrong measurement.

   P3 — only the ACTIVE logo takes up space. The overlap cell keeps both
   logos for the crossfade, but the INACTIVE one is lifted out of flow, so
   the cell (and the bar) is sized by the logo you can see: the main logo at
   rest, the sticky logo when stuck. Its containing block is still grid cell
   1/1 (absolutely-positioned grid children with explicit lines use the cell),
   so justify-self / align-self keep it anchored to the same edge while it
   fades; insets stay auto so it keeps its own size. Matches the parent the
   same TWO ways as the overlap rules above (class + :has() first-paint
   detection) — KEEP THE THREE LISTS IN SYNC. */
[data-cds-sticky-nav] :is(
	.cds-logo-stack,
	:where(:not([data-cds-logo-src] *):has(> .cds-logo):has(> .cds-logo--sticky):not(:has(> .elementor-element:not(.cds-logo, .cds-logo--sticky))))
) {
	position: relative;
}
/* A HIDDEN logo never takes up space, in any mode: the sticky-tagged widget is
   out of flow at rest, and stays out of flow in non-swap modes (Keep-same-logo
   with a leftover tagged widget — live config on TMG desktop), where it is
   never shown. In swap modes the roles trade places while stuck. */
[data-cds-sticky-nav] :is(
	.cds-logo-stack,
	:where(:not([data-cds-logo-src] *):has(> .cds-logo):has(> .cds-logo--sticky):not(:has(> .elementor-element:not(.cds-logo, .cds-logo--sticky))))
) > .cds-logo--sticky,
[data-cds-sticky-nav][data-cds-logo-anim]:is([data-state="stuck"], [data-state="unsticking"]) :is(
	.cds-logo-stack,
	:where(:not([data-cds-logo-src] *):has(> .cds-logo):has(> .cds-logo--sticky):not(:has(> .elementor-element:not(.cds-logo, .cds-logo--sticky))))
) > .cds-logo:not(.cds-logo-host) {
	position: absolute;
}
[data-cds-sticky-nav][data-cds-logo-anim]:is([data-state="stuck"], [data-state="unsticking"]) :is(
	.cds-logo-stack,
	:where(:not([data-cds-logo-src] *):has(> .cds-logo):has(> .cds-logo--sticky):not(:has(> .elementor-element:not(.cds-logo, .cds-logo--sticky))))
) > .cds-logo--sticky {
	position: relative;
}

/* Box == artwork for EVERY logo surface (Widget-mode pair, Image-file host,
   Keep-same-logo host). The CDSWerx SVG widget is a flex container since #123;
   the Elementor Image widget still puts an inline-block anchor/img on a line
   box (vertical-align: middle leaves the strut's descent below it). Zero the
   line box so the bar is the artwork, not the artwork plus the theme's
   line-height. Captioned images keep their text. */
[data-cds-sticky-nav] :is(.cds-logo, .cds-logo--sticky, .cds-logo-host, .cds-logo-scale) :is(img, svg) {
	vertical-align: top;
}
[data-cds-sticky-nav] :is(.cds-logo, .cds-logo--sticky, .cds-logo-host, .cds-logo-scale) > .elementor-widget-container:not(:has(figcaption)) {
	line-height: 0;
}
/* VENDOR-SEAM:END */

/* === Logo Height (stuck) — Image-file / Keep-same-logo cap (#121 v6) =======
   Those modes have ONE logo widget (the injected overlay is inset:0 in its
   host and follows it), so the only way to slim the bar is to cap the host's
   in-flow img/svg. max-height ONLY — an inline SVG has no intrinsic width and
   collapses to 0×0 under any width rule (live-hit on TMG, 2.57.0-beta.3).
   Gated on data-cds-stuck-logo-h (emitted when the control is authored on
   any breakpoint, or migrated from the retired Height (stuck)): an element
   without it emits nothing. interpolate-size lets none→length animate where
   supported (Chromium); elsewhere the cap snaps — layout never depends on it. */
[data-cds-sticky-nav][data-cds-stuck-logo-h] :is(.cds-logo-host, .cds-logo-scale) {
	min-height: 0;
	min-width: 0;
}
[data-cds-sticky-nav][data-cds-stuck-logo-h] :is(.cds-logo-host, .cds-logo-scale) :is(img:not(.cds-logo--injected), svg) {
	interpolate-size: allow-keywords;
	transition:
		opacity    var(--cds-logo-transition),
		visibility var(--cds-logo-transition),
		translate  var(--cds-logo-transition),
		scale      var(--cds-logo-transition),
		max-height var(--cds-transition);
}
[data-cds-sticky-nav][data-cds-stuck-logo-h]:is([data-state="stuck"], [data-state="unsticking"]) :is(.cds-logo-host, .cds-logo-scale) :is(img:not(.cds-logo--injected), svg) {
	max-height: var(--cds-stuck-logo-h);
}
/* #64 release sync: the cap lifts in the frame the provider un-pins. */
[data-cds-sticky-nav][data-cds-stuck-logo-h][data-state="default"] :is(.cds-logo-host, .cds-logo-scale) :is(img, svg) {
	transition-duration: 0s;
}
@media (prefers-reduced-motion: reduce) {
	[data-cds-sticky-nav][data-cds-stuck-logo-h] :is(.cds-logo-host, .cds-logo-scale) :is(img, svg) {
		transition-duration: 0.01ms;
	}
}

/* VENDOR-SEAM:BEGIN — provider spacers (register: VENDOR_DOM spacer_jet / spacer_pro) */
/* === Page space while stuck (v5.2.1) ========================================
   Overlay mode ("None"): collapse the provider's reserved space entirely —
   for headers that float over the page content by design. Scoped to OUR
   styled header's own spacer via adjacency (both providers insert it as the
   bar's next sibling — verified in vendor source: jSticky o.after(a),
   Elementor Pro $element.after($spacer)); other sticky sections on the page
   keep their reserve. !important beats the vendors' inline height (jSticky
   .height(t); Pro's clone sizes itself by content — min-height covers any
   authored floor the clone carries, overflow clips its hidden contents).
   "Follow" mode has no CSS here on purpose: the companion JS mirrors the
   spacer to the bar's live height per frame — a static rule would need a
   predicted target and a second bookkeeping system. */
[data-cds-sticky-nav][data-cds-spacer="none"] + .sticky-placeholder,
[data-cds-sticky-nav][data-cds-spacer="none"] + .elementor-sticky__spacer {
	height: 0 !important;
	min-height: 0 !important;
	overflow: hidden;
}
/* VENDOR-SEAM:END */
