/**
 * BRN Updates - "Heading With Line" widget.
 *
 * Structural CSS only. Colors, sizes, spacing, offsets and timings all come
 * from the widget's style sections, whose selectors carry the element wrapper
 * and therefore outrank everything here.
 */

.brn-heading {
	display: flex;
	align-items: center;
	column-gap: var(--brn-gap, 20px);
	width: 100%;
}

.brn-heading__title {
	flex: 0 1 auto;
	margin: 0;
	padding: 0;
}

.brn-heading__title a {
	color: inherit;
}

.brn-heading__decoration {
	display: flex;
	align-items: center;
	column-gap: 12px;
	flex: 0 0 auto;
	min-width: 0;
}

/* Which physical side each decoration lives on decides two things: where the
 * line grows from, and which way "in from the edge" points. Both are set here
 * once, so the animation rules below stay direction-agnostic. */
.brn-heading__decoration--start {
	--brn-line-origin: 100%;
	--brn-slide-dir: -1;
}

.brn-heading__decoration--end {
	--brn-line-origin: 0%;
	--brn-slide-dir: 1;
}

[dir="rtl"] .brn-heading__decoration--start {
	--brn-line-origin: 0%;
	--brn-slide-dir: 1;
}

[dir="rtl"] .brn-heading__decoration--end {
	--brn-line-origin: 100%;
	--brn-slide-dir: -1;
}

/* The shape is always first in the DOM. Flipping the flex direction is what
 * puts it beside the title on the start side, and out at the far end on the
 * end side — so one markup order serves all four combinations. */
.brn-heading__decoration--start.brn-heading__decoration--shape-inner,
.brn-heading__decoration--end.brn-heading__decoration--shape-outer {
	flex-direction: row-reverse;
}

/* "Stretch To Edge": the rule eats whatever width the title leaves over. */
.brn-heading--line-fill .brn-heading__decoration {
	flex: 1 1 0%;
}

.brn-heading--line-fill .brn-heading__line {
	flex: 1 1 0%;
	width: auto;
}

/* Break out of the container — the line and shape only, never the title.
 *
 * The decoration is sized to the overhang and then pulled out by exactly that
 * much, so its margin box contributes `-gap` to the row and the column-gap
 * adds `+gap` back: net zero. The title is laid out as if it were alone in the
 * row, hard against the container edge, while the decoration hangs past it.
 *
 * The default overhang, `50vw - 50%`, is the distance from a centered
 * container's edge to the screen edge — the percentage resolves against the
 * widget's own width, so no page width is hard-coded. Flooring it at 0 keeps a
 * full-width container from pulling the decoration the wrong way. The
 * "Break Out Distance" control overrides it through --brn-bleed. */
.brn-heading--bleed {
	--brn-bleed-distance: var(--brn-bleed, max(0px, calc(50vw - 50%)));
}

.brn-heading--bleed .brn-heading__decoration {
	flex: 0 0 auto;
	width: max(0px, calc(var(--brn-bleed-distance) - var(--brn-gap, 20px)));
}

.brn-heading--bleed .brn-heading__decoration--start {
	margin-inline-start: calc(-1 * var(--brn-bleed-distance));
}

.brn-heading--bleed .brn-heading__decoration--end {
	margin-inline-end: calc(-1 * var(--brn-bleed-distance));
}

.brn-heading__line {
	display: block;
	flex: 0 0 auto;
	width: 120px;
	height: 0;
	border-top: 1px solid currentColor;
	transform-origin: var(--brn-line-origin, 0%) 50%;
	transform: translateY(var(--brn-line-offset, 0px)) scaleX(1);
}

.brn-heading__shape {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	flex: 0 0 auto;
	width: 14px;
	height: 14px;
	line-height: 1;
	background-color: currentColor;
	/* Offset, rotation and animation scale all ride one transform, so the
	 * controls that feed them cannot overwrite each other. */
	transform: translateY(var(--brn-shape-offset, 0px)) rotate(var(--brn-shape-rotate, 0deg)) scale(1);
}

.brn-heading__shape--circle {
	border-radius: 50%;
}

.brn-heading__shape--diamond {
	clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%);
}

.brn-heading__shape--hexagon {
	clip-path: polygon(25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%, 0% 50%);
}

.brn-heading__shape--hexagon-vertical {
	clip-path: polygon(50% 0%, 100% 25%, 100% 75%, 50% 100%, 0% 75%, 0% 25%);
}

.brn-heading__shape--triangle {
	clip-path: polygon(50% 0%, 100% 100%, 0% 100%);
}

/* An icon is painted text, not a block: it sizes itself from font-size. */
.brn-heading__shape--icon {
	width: auto;
	height: auto;
	background-color: transparent;
	color: currentColor;
}

.brn-heading__shape--icon svg {
	width: 1em;
	height: 1em;
	fill: currentColor;
}

/* ---------------------------------------------------------------------------
 * Entrance animation
 *
 * The "before" state hangs off :not(.brn-heading--in-view); the script adds
 * that class when the heading scrolls into view and the element simply
 * transitions back to its resting style above.
 * ------------------------------------------------------------------------ */

.brn-heading--animated .brn-heading__decoration,
.brn-heading--animated .brn-heading__line,
.brn-heading--animated .brn-heading__shape {
	transition-property: transform, opacity;
	transition-duration: var(--brn-anim-duration, 900ms);
	transition-delay: var(--brn-anim-delay, 0ms);
	transition-timing-function: cubic-bezier(0.22, 0.61, 0.36, 1);
}

/* Draw: the rule grows out of the title, then the shape lands on it. */
.brn-heading--anim-draw:not(.brn-heading--in-view) .brn-heading__line {
	transform: translateY(var(--brn-line-offset, 0px)) scaleX(0);
}

.brn-heading--anim-draw:not(.brn-heading--in-view) .brn-heading__shape {
	opacity: 0;
	transform: translateY(var(--brn-shape-offset, 0px)) rotate(var(--brn-shape-rotate, 0deg)) scale(0);
}

.brn-heading--anim-draw .brn-heading__shape {
	transition-delay: calc(var(--brn-anim-delay, 0ms) + var(--brn-anim-duration, 900ms) * 0.55);
	transition-timing-function: cubic-bezier(0.34, 1.56, 0.64, 1);
}

/* Fade. */
.brn-heading--anim-fade:not(.brn-heading--in-view) .brn-heading__decoration {
	opacity: 0;
}

/* Slide: the whole decoration arrives from the outer edge. */
.brn-heading--anim-slide:not(.brn-heading--in-view) .brn-heading__decoration {
	opacity: 0;
	transform: translateX(calc(var(--brn-slide-dir, 1) * var(--brn-slide-distance, 60px)));
}

/* ---------------------------------------------------------------------------
 * Shape loop
 *
 * Held back until the entrance has finished — an animation outranks a
 * transition on the same property, so starting early would swallow it. During
 * the delay the default fill mode leaves the transition in charge.
 * ------------------------------------------------------------------------ */

.brn-heading--in-view[class*="brn-heading--loop-"] .brn-heading__shape {
	animation-duration: var(--brn-loop-duration, 2.5s);
	animation-iteration-count: infinite;
	animation-timing-function: ease-in-out;
	animation-delay: calc(var(--brn-anim-delay, 0ms) + var(--brn-anim-duration, 0ms));
}

.brn-heading--in-view.brn-heading--loop-pulse .brn-heading__shape {
	animation-name: brn-heading-pulse;
}

.brn-heading--in-view.brn-heading--loop-spin .brn-heading__shape {
	animation-name: brn-heading-spin;
	animation-timing-function: linear;
}

.brn-heading--in-view.brn-heading--loop-float .brn-heading__shape {
	animation-name: brn-heading-float;
}

.brn-heading--in-view.brn-heading--loop-glow .brn-heading__shape {
	animation-name: brn-heading-glow;
}

/* Every keyframe restates the offset and rotation, so a looping shape keeps
 * whatever position the style controls gave it. */
@keyframes brn-heading-pulse {
	0%,
	100% {
		transform: translateY(var(--brn-shape-offset, 0px)) rotate(var(--brn-shape-rotate, 0deg)) scale(1);
	}

	50% {
		transform: translateY(var(--brn-shape-offset, 0px)) rotate(var(--brn-shape-rotate, 0deg)) scale(1.35);
	}
}

@keyframes brn-heading-spin {
	from {
		transform: translateY(var(--brn-shape-offset, 0px)) rotate(var(--brn-shape-rotate, 0deg)) scale(1);
	}

	to {
		transform: translateY(var(--brn-shape-offset, 0px)) rotate(calc(var(--brn-shape-rotate, 0deg) + 360deg)) scale(1);
	}
}

@keyframes brn-heading-float {
	0%,
	100% {
		transform: translateY(var(--brn-shape-offset, 0px)) rotate(var(--brn-shape-rotate, 0deg)) scale(1);
	}

	50% {
		transform: translateY(calc(var(--brn-shape-offset, 0px) - 8px)) rotate(var(--brn-shape-rotate, 0deg)) scale(1);
	}
}

@keyframes brn-heading-glow {
	0%,
	100% {
		opacity: 1;
		filter: drop-shadow(0 0 0 currentColor);
	}

	50% {
		opacity: 0.75;
		filter: drop-shadow(0 0 8px currentColor);
	}
}

/* ---------------------------------------------------------------------------
 * Motion preferences
 *
 * Reduced motion gets the finished layout with nothing moving. The script
 * makes the same call, so the reveal never depends on this alone.
 * ------------------------------------------------------------------------ */

@media (prefers-reduced-motion: reduce) {
	.brn-heading__decoration,
	.brn-heading__line,
	.brn-heading__shape {
		transition: none !important;
		animation: none !important;
	}

	.brn-heading--animated:not(.brn-heading--in-view) .brn-heading__decoration {
		opacity: 1;
		transform: none;
	}

	.brn-heading--animated:not(.brn-heading--in-view) .brn-heading__line {
		transform: translateY(var(--brn-line-offset, 0px)) scaleX(1);
	}

	.brn-heading--animated:not(.brn-heading--in-view) .brn-heading__shape {
		opacity: 1;
		transform: translateY(var(--brn-shape-offset, 0px)) rotate(var(--brn-shape-rotate, 0deg)) scale(1);
	}
}
