/**
 * DFS Motion — Hover Grow for Elementor Columns.
 *
 * @decision D410 — the columns sit in line at their own height; hovering one
 * grows it vertically PAST that band, and the page does not move.
 *
 * Chris, via Brad: "the columns are all normal in line but when one is hovered
 * it grows vertically ... also has a slight dropshadow around the hovered
 * column". Brad, on the version that shrank them instead: "when i turn on hover
 * grow it still just makes section short and grows it back to 100 it never
 * extends".
 *
 * ---------------------------------------------------------------------------
 * HOW IT WORKS
 *
 *   on hover, the card takes NEGATIVE block margins
 *
 * A stretched flex item is sized to the line MINUS its margins, so negative
 * margins make it taller by exactly that much — while its contribution back to
 * the column's height (height + margins) is unchanged. The card grows and
 * overflows its column; nothing in the layout moves.
 *
 * The column keeps its own height at rest. Nothing is shrunk, and no height is
 * ever typed.
 *
 * THE RESERVE GOES ON THE CONTAINER, NOT THE COLUMN. That padding is written by
 * the Grow By control (see the PHP), because the room has to exist INSIDE the
 * clipping box — see the next section. It is a one-time cost paid at load.
 *
 * ---------------------------------------------------------------------------
 * WHY THE RESERVE CANNOT GO ON THE COLUMN — MEASURED ON THE REAL PAGE
 *
 * The first working version put `padding-block` on the column itself. On a test
 * row where EVERY column had the feature, that raised the row and behaved. On
 * Brad's actual row, where ONE column has it, it did the opposite:
 *
 *   column padding 30/30 applied, column 552, card 492, row 552
 *
 * The column is a STRETCH flex item, so its height is the line's height, not
 * its content's. Padding on one stretched item does not push the line up — it
 * just eats that item's own content box. So the card shrank by 60 and "grew
 * back to 100" on hover, which is exactly what Brad saw.
 *
 * MEASURED with the reserve moved to the container instead:
 *
 *                        row   column   card   clipped   page
 *   as shipped (column)   552    552     492     no      4646
 *   container, at rest    586    526     526     no      4680
 *   container, hovered    586    526     586     NO      4680
 *
 * Card at full height at rest, grows by exactly 60, row and page stable.
 *
 * ---------------------------------------------------------------------------
 * THE CLIPPING TRAP — WHY A RESERVE IS NEEDED AT ALL
 *
 * Negative margins alone are enough to grow the card, and on an ordinary row
 * that is the whole job. MEASURED on Brad's row, though:
 *
 *   .elementor-container   overflow: auto hidden   overflow-y: hidden
 *
 * That row is a `dfs-hscroll` horizontal scroller, and overflow clips at the
 * PADDING box. Without the reserve the card grows 30px above and below and is
 * cut off on both edges — the effect runs perfectly and is invisible. With the
 * reserve, the grown card lands exactly on the padding box (measured: card top
 * 780 == clip top 780, card bottom 1366 == clip bottom 1366) and survives.
 *
 * ---------------------------------------------------------------------------
 * THE DISCARD PILE — every model was driven on the live page, not reasoned about
 *
 *   A. animate the card's height
 *      row 122 -> 140, page 2048 -> 2066.  REJECTED: the page shifts.
 *
 *   B. min-height reserve + clip-path window
 *      Worked, shipped in 4.39.0. REJECTED: min-height cannot be "the column's
 *      natural height", so it forced a typed Card Height field.
 *
 *   C. padding reserve on the column + margins animated on hover
 *      Shipped in 4.40.0 and WRONG on a real row — see above. The proof that
 *      passed had the class on all five columns, which is not how it is used.
 *
 *   D. padding + PERMANENT negative margins + clip-path
 *      MEASURED: reserve 0, card visible 42px instead of 122. Padding and
 *      margin cancel exactly, so nothing is reserved and the card shrinks.
 *
 *   E. container reserve + margins animated on hover   <- THIS
 *
 * E animates margin, a layout property, which the gsap-core skill rightly warns
 * about. Both composite-only candidates were measured and neither can reserve
 * space: clip-path only ever reveals what is already inside an element's box, so
 * it cannot grow anything past its own footprint. The layout triggered here is
 * confined to one column's subtree, and row and page were measured unchanged.
 *
 * ---------------------------------------------------------------------------
 * EVERY VALUE HAS A FLOOR (@decision D407). If Elementor's post CSS is cleared,
 * the container reserve goes with it and the growth still runs off this file —
 * it degrades to "may be clipped inside a scroller", never to "broken".
 */

/*
 * THE CLASS IS REPEATED THREE TIMES ON PURPOSE. Do not "tidy" it.
 *
 * Elementor's column Border/Background hover-transition control writes a
 * `transition` SHORTHAND to the very same element, from post CSS:
 *
 *   .elementor-4800 .elementor-element.elementor-element-34317310 > .elementor-element-populated
 *       { transition: background 0.3s, border 0.3s, border-radius 0.3s, box-shadow 0.3s }
 *
 * That is (0,4,0) and it beat this rule at (0,2,0). Because it is a SHORTHAND it
 * also resets transition-property to its own four entries — none of which is
 * margin — so the growth applied instantly. MEASURED on the live page:
 *
 *   computed transition-property = "background, border, border-radius, box-shadow"
 *
 * which is exactly the snap Brad reported: "it just like snaps to grow".
 *
 * Repeating the opt-in class takes this to (0,4,0) plus the element selector and
 * wins without !important, which would be the wrong tool — it would silently
 * kill an author's own transitions on that column.
 *
 * Elementor's four properties are RESTATED here so raising specificity does not
 * cost them. 0.3s is Elementor's own default; an author who changed it loses
 * that customisation on hover-grow columns only, which is the smallest price
 * available and is why it is written down rather than hidden. MEASURED after the
 * fix: transition-property = "margin-top, margin-bottom, background, border,
 * border-radius, box-shadow", durations "0.5s, 0.5s, 0.3s, 0.3s, 0.3s, 0.3s".
 */
/*
 * AN INNER SECTION MUST FILL THE COLUMN.
 *
 * Brad, with a video-background inner section in column 3: "theoretically would
 * take up 100% of column height but i think the column specific padding youre
 * adding limits the inner section".
 *
 * MEASURED — the padding is innocent. The column has padding 0, and removing the
 * container reserve entirely changed the column height by 0px at both 30px and
 * 110px of reserve; the container absorbs it by growing.
 *
 * The real cause is Elementor's own wrap:
 *
 *   .elementor-widget-wrap   display:flex   flex-wrap:wrap   align-content:flex-start
 *
 * With flex-wrap:wrap, align-items stretches an item within its LINE, but
 * align-content:flex-start packs the single line to the top and sizes it to the
 * item's own height. So the inner section sat at its intrinsic 437 inside a 537
 * column and never stretched. MEASURED with align-content:stretch: 437 -> 537,
 * exactly filling the column, with the other four columns, the row and the page
 * all unchanged.
 */
.elementor-column.dfs-hg--yes > .elementor-widget-wrap {
	align-content: stretch;
}

/*
 * AND THE BACKGROUND VIDEO INSIDE IT MUST RE-FIT.
 *
 * Elementor's background-video script sizes the <video> with INLINE insets and a
 * translate, computed once at load. MEASURED on the live page:
 *
 *   video.elementor-background-video-hosted
 *     position: absolute
 *     inset:  218.391px  -126.5px  -218.375px  126.5px
 *     transform: matrix(1, 0, 0, 1, -126.5, -218.383)
 *
 * Those are baked numbers. When the inner section grew to 537 the video stayed
 * at 437, and it would be equally stale while the column grows on hover.
 *
 * Anchoring it to its container and letting object-fit:cover do the work is both
 * simpler and correct at any size. !important is required because the values it
 * overrides are INLINE styles, which no stylesheet beats otherwise; the whole
 * rule is scoped to dfs-hg--yes so nothing outside an opted-in column is touched.
 *
 * MEASURED after: video 437 -> 537, flush at top and bottom (offset 0 both
 * edges), object-fit still cover.
 */
.elementor-column.dfs-hg--yes .elementor-background-video-hosted {
	position: absolute !important;
	top: 0 !important;
	left: 0 !important;
	right: 0 !important;
	bottom: 0 !important;
	width: 100% !important;
	height: 100% !important;
	transform: none !important;
	object-fit: cover !important;
}

.elementor-column.dfs-hg--yes.dfs-hg--yes.dfs-hg--yes > .elementor-widget-wrap {
	transition:
		margin-top    var( --dfs-hg-dur, 0.5s ) var( --dfs-hg-ease, cubic-bezier( 0.226, 0.861, 0.408, 1.033 ) ),
		margin-bottom var( --dfs-hg-dur, 0.5s ) var( --dfs-hg-ease, cubic-bezier( 0.226, 0.861, 0.408, 1.033 ) ),
		background     var( --dfs-hg-el-dur, 0.3s ),
		border         var( --dfs-hg-el-dur, 0.3s ),
		border-radius  var( --dfs-hg-el-dur, 0.3s ),
		box-shadow     var( --dfs-hg-el-dur, 0.3s );
}

/* ----------------------------------------------------------------- grow ---- */
.elementor-column.dfs-hg--yes:hover > .elementor-widget-wrap,
.elementor-column.dfs-hg--yes:focus-within > .elementor-widget-wrap {
	margin-top: calc( -1 * var( --dfs-hg-extra, 60px ) / 2 );
	margin-bottom: calc( -1 * var( --dfs-hg-extra, 60px ) / 2 );
}

/* --------------------------------------------------------- shadow layer ---- */
/*
 * At rest the card fills its column exactly, so the shadow sits flush at inset
 * 0. On hover it follows the card out past the column edges.
 *
 * It is a pseudo-element rather than a shadow on the card itself because the
 * card is the element whose margins move: a box-shadow on it would be dragged
 * along by the transition instead of settling on the final edge.
 *
 * MEASURED in elementor/assets/css/frontend.css:
 *   .elementor-column            position:relative; min-height:1px; display:flex
 *   .elementor-widget-wrap       position:relative; width:100%
 *   .elementor-column::before/after   NO RULES — both pseudo-elements are free
 *
 * ::before rather than ::after: the wrap and the pseudo are both positioned with
 * z-index:auto in one stacking context, so they paint in DOM order. ::after
 * would paint ON TOP of the card. Absolutely-positioned children of a flex
 * container are not flex items, so the pseudo does not join the column's layout.
 */
.elementor-column.dfs-hg--yes::before {
	content: "";
	position: absolute;
	left: 0;
	right: 0;
	top: 0;
	bottom: 0;
	pointer-events: none;
	border-radius: var( --dfs-hg-radius, 0px );
	opacity: 0;
	transition:
		top     var( --dfs-hg-dur, 0.5s ) var( --dfs-hg-ease, cubic-bezier( 0.226, 0.861, 0.408, 1.033 ) ),
		bottom  var( --dfs-hg-dur, 0.5s ) var( --dfs-hg-ease, cubic-bezier( 0.226, 0.861, 0.408, 1.033 ) ),
		opacity var( --dfs-hg-dur, 0.5s ) linear;
}

.elementor-column.dfs-hg--yes:hover::before,
.elementor-column.dfs-hg--yes:focus-within::before {
	top: calc( -1 * var( --dfs-hg-extra, 60px ) / 2 );
	bottom: calc( -1 * var( --dfs-hg-extra, 60px ) / 2 );
	opacity: 1;
}

/*
 * THE SHADOW IS OFF UNTIL ASKED FOR, AND GOOD THE MOMENT IT IS.
 *
 * Brad: "make it so the boxshadow isnt compeytley not set by default but
 * disabled but if turned on gives it a nice subtle boxshadow then can configure
 * fully. dont want a pain to add and manual config."
 *
 * So the layer above carries NO box-shadow at all — the pseudo-element still
 * exists and still animates, it simply paints nothing. Flipping Drop Shadow on
 * adds this class and a shadow appears immediately, with the same values
 * pre-filled into the Box Shadow control so the first click is a working
 * shadow rather than an empty form.
 *
 * The value below is the FLOOR. Elementor's group control writes its own
 * box-shadow at higher specificity the moment the author touches it, so this
 * only shows through if post CSS is cleared (@decision D407).
 *
 * 0 14px 34px rgba(0,0,0,0.22) reaches 48px below and 20px above, which the
 * default Shadow Room of 60px clears on a row that clips.
 */
.elementor-column.dfs-hg--yes.dfs-hg-sh--yes::before {
	box-shadow: var( --dfs-hg-shadow, 0 16px 48px rgba( 0, 0, 0, 0.4 ) );
}

/*
 * Lift the hovered column above its neighbours, so the grown card is not
 * underlapped by the next column and the shadow is not clipped by it.
 *
 * NOT a control, deliberately. As a switcher it would need prefix_class with a
 * default of "yes", which stamps a class onto every column already saved on
 * every site — the exact shape of silent change to saved instances that
 * @decision D403 exists to prevent. z-index applies on hover only.
 */
.elementor-column.dfs-hg--yes:hover,
.elementor-column.dfs-hg--yes:focus-within {
	z-index: 60;
}

/* ---------------------------------------------------------- content anchor ---- */
/*
 * @decision D411 — hold the inner section's content against one edge so it
 * tracks the grow instead of drifting. The inner section already fills the
 * column (align-content: stretch, above) and grows with it, so making it a
 * flex column and justifying it pins the content to that moving edge.
 *
 * Gated on BOTH classes: nothing here matches a column that is not an opted-in
 * Hover Grow column with an anchor chosen. Targets a DIRECT-CHILD inner
 * section only.
 */
/*
 * v3 (Brad, live test): DO NOT touch the inner section's display — making it a
 * flex column collapsed .elementor-container's width to ~105px (content) and
 * Elementor's margin:0 auto centred it, so the inner column read as a skinny
 * centred strip. Instead the container is filled with height:100%. A stretched
 * flex item's height is definite, so 100% resolves and grows with the section.
 * min-height (the author's Min Height) stays a floor. The edge is chosen on the
 * deep widget-wrap with align-content, at (0,8,0) so it wins over — and agrees
 * with — Elementor's own Vertical Align.
 */
.elementor-column.dfs-hg--yes.dfs-hg-anchor--top > .elementor-widget-wrap > .elementor-section > .elementor-container,
.elementor-column.dfs-hg--yes.dfs-hg-anchor--middle > .elementor-widget-wrap > .elementor-section > .elementor-container,
.elementor-column.dfs-hg--yes.dfs-hg-anchor--bottom > .elementor-widget-wrap > .elementor-section > .elementor-container {
	height: 100%;
}

.elementor-column.dfs-hg--yes.dfs-hg-anchor--top > .elementor-widget-wrap > .elementor-section > .elementor-container > .elementor-column > .elementor-widget-wrap {
	align-content: flex-start;
}

.elementor-column.dfs-hg--yes.dfs-hg-anchor--middle > .elementor-widget-wrap > .elementor-section > .elementor-container > .elementor-column > .elementor-widget-wrap {
	align-content: center;
}

.elementor-column.dfs-hg--yes.dfs-hg-anchor--bottom > .elementor-widget-wrap > .elementor-section > .elementor-container > .elementor-column > .elementor-widget-wrap {
	align-content: flex-end;
}

/* ------------------------------------------------------------------ touch --- */
/*
 * The degradation rule: smaller, softer, later — never broken. :hover on a touch
 * device is either never delivered or delivered sticky, so the growth and the
 * shadow are switched off entirely and the row renders exactly as it would
 * without the feature.
 */
@media ( hover: none ) {
	.elementor-column.dfs-hg--yes > .elementor-widget-wrap {
		margin-top: 0;
		margin-bottom: 0;
		transition: none;
	}

	.elementor-column.dfs-hg--yes::before {
		display: none;
	}
}

/* WCAG 2.3.3 — keep the end states, drop the animation between them. */
@media ( prefers-reduced-motion: reduce ) {
	.elementor-column.dfs-hg--yes > .elementor-widget-wrap,
	.elementor-column.dfs-hg--yes::before {
		transition: none;
	}
}
