/**
 * SmartHeader — the states.
 *
 * Nothing here styles a header. It only describes how one moves between
 * states, so whatever you built keeps its own colours, spacing and
 * typography until a state says otherwise.
 *
 * Every value the script sets is a custom property, so a settings
 * change is one style write rather than a stylesheet rebuild.
 */

.smartheader {
	/*
	 * Every transitioned property is named.
	 *
	 * `transition: all` would also animate anything added later -- by
	 * this plugin, by Elementor, or by a theme update -- and is the
	 * usual reason a shrink reads as a lurch rather than a movement.
	 */
	transition:
		background-color var(--sh-duration, 350ms) var(--sh-ease, ease),
		height var(--sh-duration, 350ms) var(--sh-ease, ease),
		box-shadow var(--sh-duration, 350ms) var(--sh-ease, ease),
		transform var(--sh-duration, 350ms) var(--sh-ease, ease),
		backdrop-filter var(--sh-duration, 350ms) var(--sh-ease, ease),
		-webkit-backdrop-filter var(--sh-duration, 350ms) var(--sh-ease, ease);

	/*
	 * The bar the progress line is positioned against -- and the header's
	 * place in the stack.
	 *
	 * A header that is not sticky had no z-index at all, and a page whose
	 * first section is pulled up under the header with a negative margin
	 * -- the ordinary way to put a hero behind a transparent header --
	 * then painted straight over it, because that section comes later in
	 * the document. The header was still there, full size, with its menu:
	 * simply buried. Sticky headers never showed this, since sticking
	 * gives them a z-index of its own.
	 *
	 * The same 100 as .is-sticky: above ordinary page content, below
	 * WordPress's admin bar and most modal overlays.
	 */
	position: relative;
	z-index: 100;
}

/* ── Sticky ──────────────────────────────────────────────────────── */

/*
 * Only applied when SmartHeader was asked to, and only when nothing
 * else is already positioning the element. position:sticky rather than
 * fixed, because sticky keeps the header in the flow: the space it
 * occupies stays reserved, so nothing below it jumps upward the moment
 * it sticks.
 */
/*
 * is-sticky is not always on the same element as .smartheader. A sticky
 * element only travels inside its own parent, and a header's immediate
 * wrapper often hugs it exactly -- so the class goes on whichever
 * ancestor has room, while the states stay on the header itself.
 */
.is-sticky,
.smartheader.is-sticky {
	position: sticky;
	top: var(--sh-offset, 0px);
	/* Above ordinary page content, below WordPress's admin bar at
	   99999 and below most modal overlays. */
	z-index: 100;
}

/*
 * Anything in the header written to inherit its colour follows the
 * header's state, and transitions with it rather than snapping.
 */
.smartheader [class*="-item"],
.smartheader [class*="__link"] {
	transition: color var(--sh-duration, 350ms) var(--sh-ease, ease);
}

/* ── Solid ───────────────────────────────────────────────────────── */

.smartheader.is-solid {
	background-color: var(--sh-solid-bg, rgba(255, 255, 255, .95));
	box-shadow: 0 2px 16px rgba(0, 0, 0, .08);
}

/* ── Shrink ──────────────────────────────────────────────────────── */

/*
 * Height, not padding.
 *
 * A transparent header is usually pulled over the section below it by
 * that section's negative margin, which is set from the header's
 * height. Changing padding would move the box while the space reserved
 * for it stayed put, and the hero would jump as the header shrank.
 */
.smartheader.is-shrunk {
	height: var(--sh-stuck-h, 58px);
	min-height: var(--sh-stuck-h, 58px);
}

/* ── Blur ────────────────────────────────────────────────────────── */

/*
 * Declared at zero at rest so there is something to transition from.
 * Left undeclared, the blur would snap in at the threshold while the
 * colour and height eased, which reads as a stutter rather than a
 * transition.
 */
.smartheader {
	backdrop-filter: blur(0);
	-webkit-backdrop-filter: blur(0);
}

.smartheader.is-blurred {
	backdrop-filter: blur(var(--sh-blur, 10px));
	-webkit-backdrop-filter: blur(var(--sh-blur, 10px));
}

/* ── Hide on scroll ──────────────────────────────────────────────── */

.smartheader.is-hidden {
	transform: translateY(-100%);
}

/* ── Reading progress ────────────────────────────────────────────── */

.smartheader-progress {
	position: absolute;
	left: 0;
	bottom: 0;
	height: var(--sh-progress-h, 2px);
	width: 0;
	background: var(--sh-progress-bg, currentColor);
	/*
	 * Opacity on the element rather than baked into the colour, so the
	 * two can be changed independently -- a translucent colour would
	 * mean every shade change quietly altered the strength too.
	 */
	opacity: var(--sh-progress-o, 1);
	/* Linear rather than eased: it tracks a position rather than
	   animating between two states, and easing makes it lag the page. */
	transition: width .1s linear;
	pointer-events: none;
}

/* ── Logo cross-fade ─────────────────────────────────────────────── */

.smartheader-logo {
	position: relative;
	display: inline-block;
	line-height: 0;
}

.smartheader-logo img {
	transition:
		opacity var(--sh-duration, 350ms) var(--sh-ease, ease),
		height var(--sh-duration, 350ms) var(--sh-ease, ease),
		width var(--sh-duration, 350ms) var(--sh-ease, ease);
	display: block;

	/*
	 * Width follows the height.
	 *
	 * Setting a height alone leaves the width wherever the theme or
	 * page builder put it, so the logo squashes instead of scaling --
	 * and, less obviously, the space it occupies never changes. A
	 * header laid out with space-between then has nothing to
	 * redistribute as the logo shrinks, and appears not to respond at
	 * all. Measured on a real header: 97px to 75px tall, 150px wide
	 * throughout.
	 *
	 * !important because Elementor writes an explicit width onto logo
	 * images, which is exactly the value that has to give way.
	 */
	width: auto !important;
	max-width: 100%;

	/*
	 * A last resort, for the case where no height was ever established
	 * -- a logo that failed to measure, or a script that did not run to
	 * completion. With the width released, `height: auto` on an SVG
	 * collapses it entirely, and a missing logo is far worse than one
	 * at an approximate size.
	 */
	min-height: 1px;
}

/*
 * Both images take the same height at any given moment.
 *
 * They are stacked exactly on top of each other, so they have to: two
 * logos at different heights in the same box would show one poking out
 * from behind the other during the fade.
 *
 * Which height that is depends on the state, not on which image it is.
 */
/*
 * !important on the height, for the same reason as the width.
 *
 * Measured on a real page, three rules set a height on this image:
 *
 *   img                   { height: auto }  (a theme reset)
 *   .elementor img        { height: auto }  (Elementor's frontend css)
 *   .smartheader-logo img { height: ... }   (this)
 *
 * Elementor's is one class and an element, and so is this one -- they
 * are equally specific, and it loads later, so it won on source order.
 * This rule has therefore never applied.
 *
 * The logo looked correct anyway, because Elementor's per-page
 * stylesheet sets an explicit width three classes deep, and `height:
 * auto` derived the right height from it.
 *
 * Releasing the width in 0.7.2 removed that, leaving auto on both axes
 * and an SVG with no intrinsic pixel size, which collapses to nothing.
 * The height was never in charge; it only looked like it was.
 */
.smartheader-logo img {
	height: var(--sh-logo-h, auto) !important;
}

/* The second image sits exactly over the first rather than beside it,
   so the pair occupies one logo's worth of space. */
.smartheader-logo img[data-sh-logo="stuck"] {
	position: absolute;
	inset: 0;
	opacity: 0;
}

.smartheader.is-solid .smartheader-logo img[data-sh-logo="rest"] { opacity: 0; }
.smartheader.is-solid .smartheader-logo img[data-sh-logo="stuck"] { opacity: 1; }

/*
 * The smaller height belongs to the stuck state, not to the header
 * shrinking.
 *
 * It used to hang off .is-shrunk, which meant a smaller logo only
 * appeared if the header's own shrink effect happened to be switched on
 * -- two unrelated settings, one silently requiring the other. Wanting
 * a smaller logo on a solid header is an ordinary thing to want on its
 * own.
 */
.smartheader.is-solid .smartheader-logo img {
	height: var(--sh-logo-stuck-h, var(--sh-logo-h, auto)) !important;
}

/* ── Reduced motion ──────────────────────────────────────────────── */

/*
 * The states still apply -- a reader who has asked for less movement
 * still needs a readable header once scrolled -- but they arrive
 * instantly rather than animating, and the header never slides away.
 */
@media (prefers-reduced-motion: reduce) {
	.smartheader,
	.smartheader-logo img,
	.smartheader-progress {
		transition-duration: 0s;
	}

	.smartheader.is-hidden {
		transform: none;
	}
}

/* ── Anchor targets ──────────────────────────────────────────────── */

/*
 * Stops a sticky header covering the top of whatever an anchor points
 * at.
 *
 * scroll-margin-top exists for exactly this: it changes where a scroll
 * comes to rest and nothing else. No layout is affected, no spacer
 * elements are needed, and no click handler has to intercept anything
 * -- which matters, because it also works for someone arriving at
 * /#experiences from another page, where there is no click to
 * intercept.
 *
 * The property is set on the document by the script, from the header's
 * measured height, and removed entirely when the header is not sticky.
 * With it absent this rule resolves to 0 and does nothing at all.
 */
[id] {
	scroll-margin-top: var(--sh-anchor-offset, 0px);
}

/*
 * And the same for every other reason a browser scrolls something into
 * view -- above all, moving focus.
 *
 * scroll-margin only helps an element that has one, which an anchor's
 * target does and a form field generally does not. Tabbing down a long
 * form therefore kept putting the field being typed into underneath the
 * header. scroll-padding is set on the scrolling element instead and
 * applies to whatever is being scrolled to, so the field, the anchor and
 * anything a script scrolls to all come to rest below the header.
 */
html {
	scroll-padding-top: var(--sh-anchor-offset, 0px);
}
