/**
 * The Wicked — Case Hero Video (tw-case-hero-video).
 * A hosted film in a frame that changes aspect ratio when playback starts.
 * From design-reference/work.html L605-614 — the case-study modal's hero.
 *
 * ── SIX THINGS HERE THAT ARE NOT STYLE CHOICES ────────────────────────────────
 *
 * 1. THE RATIO IS `padding-top: calc(100% / (W / H))`, NOT `aspect-ratio`.
 *    Percentage padding resolves against the containing block's WIDTH, so the
 *    frame's height is width-derived, and it interpolates LINEARLY. Measured in
 *    headless Chrome at 840px wide: calc form 360.00px exactly (a literal
 *    42.8571% gives 359.98px), 388.13px at 25% of a linear 600ms run — the
 *    arithmetic mean to 2dp. `aspect-ratio` also animates in this Chrome but
 *    interpolates the RATIO, so the height ramp is not the curve anyone chose;
 *    and its animatability is recent, where this technique works in every engine
 *    that has ever shipped. Hares reviews on an iPhone.
 *
 * 2. ⛔ THE `padding-top` VALUES IN THIS FILE CANNOT WIN AND ARE NOT MEANT TO.
 *    `ratio_start` and `ratio_played` are controls; a control compiles at
 *    (0,4,0) and every rule here is (0,1,0)-(0,3,0) (PROJECT-NOTES §6a). Both
 *    values below are FALLBACKS for the case where no control CSS has been
 *    generated yet. The state change itself is a ladder BETWEEN THE TWO
 *    CONTROLS — `ratio_played` writes `.tw-chv.is-playing .tw-chv__frame` at
 *    (0,6,0). ⚠️ Do not "fix" the state change by adding an `.is-playing` rule
 *    here: it would be dead CSS that looks alive, which is the exact bug this
 *    plugin has shipped four times.
 *
 * 3. NO `transition:` SHORTHAND, ANYWHERE, ON ANY OF THE FOUR ANIMATED
 *    ELEMENTS — frame, scrim, tick, play button. §6b: a shorthand in a later
 *    block re-sets duration and silently cancels the reduced-motion rule at the
 *    bottom of this file. This file owns `transition-property`; the `duration`
 *    and `easing` controls own `transition-duration` and
 *    `transition-timing-function`. Three longhands, three separate owners, no
 *    overlap — and all four elements share the one pair of controls, so the
 *    ratio, the scrim and the tick read as a single event rather than three.
 *    ⚠️ ADDING A FIFTH MEANS ADDING IT IN FOUR PLACES: its own rule, both
 *    control `selectors` arrays in the PHP, the `is-snap` block and the
 *    reduced-motion block. Miss the last and it keeps moving for a reader who
 *    asked it not to.
 *
 * 4. ⛔ `align-self: stretch` ON THE WIDGET WRAPPER, AND `width: 100%` IS NOT A
 *    SUBSTITUTE FOR IT. MEASURED, not reasoned: dropped into a column container
 *    with `align-items: flex-start` — which every section shell in this project
 *    sets — this widget rendered at **0.00 x 0.00px and vanished**, silently,
 *    with no overflow and no error. The flex item is `.elementor-element`, it is
 *    shrink-to-fit, and every child of the frame is absolutely positioned, so its
 *    max-content width is genuinely zero; `width:100%` of a zero-width parent is
 *    zero. §6b's cure — `flex_align_items: stretch` on the CONTAINER — is
 *    correct and is still the right thing to set when placing this, but it is a
 *    setting a person has to remember, and forgetting it makes the widget
 *    disappear rather than merely look wrong. So the widget defends itself.
 *    ⚠️ It is deliberately (0,1,0), the weakest thing that works: an explicit
 *    Align Self chosen in the editor compiles far above it and still wins.
 *    `width:100%` stays — it is what makes the percentage padding resolve
 *    against the full container once the stretch has happened (§6b, the 0.3.6
 *    collapse: a width-derived height inside a max-content item resolves against
 *    the wrong number).
 *
 * 5. `object-fit: cover` ON A RESIZING PANEL, WHICH §6b WARNS ABOUT, AND IT IS
 *    RIGHT HERE FOR THE REASON THAT WARNING GIVES. The rule is "size by the
 *    constant axis" — and the constant axis IS the width: the frame's width never
 *    changes, only its height. With a source at the played ratio the film is
 *    width-driven throughout, so it does not rescale during the change; the crop
 *    opens up instead. A source TALLER than the played ratio makes cover
 *    height-driven and it does rescale — that is what the `media_fit` control's
 *    description warns about, and `contain` is the way out.
 *
 * 6. THE PLAY BUTTON RESTATES ITS FILL FOR `:hover`, `:focus` AND `:active`.
 *    shared.css blanks every `<button>` background in those states at (0,2,1) to
 *    neutralise Hello Elementor's pink, and says in as many words that a widget
 *    needing a FILLED button must out-rank it. `.tw-chv .tw-chv__play:hover` is
 *    (0,3,0) and does. Without this the circle empties the moment a pointer
 *    touches it — and only in this build, only on hover, which is exactly the
 *    kind of thing a static screenshot never catches.
 */

/* Rule 4, first half. The flex item is Elementor's own widget wrapper, so this
   is the one rule in the file that reaches outside `.tw-chv` — and it has to.
   Deliberately a single class (0,1,0): an Align Self set in the editor outranks
   it, and so does anything else with an opinion. */
.elementor-widget-tw-case-hero-video {
	align-self: stretch;
}

/* Rule 4, second half. No margin of any kind: a widget must not own the space
   outside itself (§6b) — the container owns that. */
.tw-chv {
	width: 100%;
}

.tw-chv__frame {
	position: relative;
	width: 100%;
	height: 0;
	padding-top: calc(100% / (21 / 9));    /* ⛔ FALLBACK ONLY — ratio_start owns this. Rule 2. */
	overflow: hidden;
	background-color: #0c0c0e;             /* frame_bg overrides */
	/* Rule 3: this file owns the property; the controls own duration and curve. */
	transition-property: padding-top;
	transition-duration: 450ms;            /* duration overrides */
	transition-timing-function: ease;      /* easing overrides */
}

/* ⚠️ `.tw-chv` prefix, not a bare `.tw-chv__media`: Elementor ships
   `.elementor img{height:auto;max-width:100%}` at (0,1,1), which would otherwise
   beat a single-class rule and un-size the poster fallback. */
.tw-chv .tw-chv__media {
	position: absolute;
	inset: 0;
	display: block;
	width: 100%;
	height: 100%;
	max-width: none;
	margin: 0;
	border: 0;
	background: transparent;
	object-fit: cover;                     /* media_fit overrides — rule 5 */
	object-position: center;
}

/* An absolutely positioned child resolves `inset:0` against the containing
   block's PADDING box, so the scrim covers the whole frame even though the
   frame's content box is zero-height. */
.tw-chv__scrim {
	position: absolute;
	inset: 0;
	pointer-events: none;
	background-image: linear-gradient(0deg, rgba(16, 16, 19, .9) 0%, transparent 55%);
	opacity: 1;
	transition-property: opacity;
	transition-duration: 450ms;            /* duration overrides */
	transition-timing-function: ease;      /* easing overrides */
}

.tw-chv.is-playing .tw-chv__scrim {
	opacity: 0;
}

/* Longhands, never the `border` shorthand: a shorthand built from a value that
   fails to resolve computes to `none` and vanishes silently (§6b). */
.tw-chv__tick {
	position: absolute;
	top: 24px;                             /* tick_offset overrides */
	left: 24px;                            /* tick_offset overrides */
	width: 20px;                           /* tick_size overrides */
	height: 20px;                          /* tick_size overrides */
	border-top-width: 1px;
	border-top-style: solid;
	border-top-color: var(--tw-tan, #B18051);
	border-left-width: 1px;
	border-left-style: solid;
	border-left-color: var(--tw-tan, #B18051);
	pointer-events: none;
	opacity: 1;
	transition-property: opacity;
	transition-duration: 450ms;            /* duration overrides */
	transition-timing-function: ease;      /* easing overrides */
}

/* Hares, 2026-08-09: "the orange corner on the top left should disappear once
   the movie actually starts playing". It is the SAME `is-playing` state as the
   ratio and the scrim, so it is driven by the same real `play` event and cannot
   be triggered by a click that fails to start playback — and it comes back with
   the reset, because it belongs to the resting state.
   ⚠️ OPACITY, NOT `display:none` OR A REMOVAL. The tick is absolutely positioned
   and `pointer-events:none`, so fading it leaves no layout hole and takes nothing
   out of flow; it is `aria-hidden` already, so there is nothing to hide from
   assistive tech either. It reuses `duration` and `easing` rather than owning a
   second pair: a tick that snapped away while the frame eased would read as two
   events instead of one. */
.tw-chv.is-playing .tw-chv__tick {
	opacity: 0;
}

.tw-chv__play {
	position: absolute;
	top: 50%;
	left: 50%;
	/* Centred by transform rather than by a flex parent so the frame keeps only
	   absolutely-positioned children and the button can be scaled on hover
	   without a second wrapper. */
	transform: translate(-50%, -50%) scale(1);
	display: flex;
	align-items: center;
	justify-content: center;
	width: 72px;                           /* play_size overrides */
	height: 72px;                          /* play_size overrides */
	/* The touch-target floor, and no control can lower it — play_size's range
	   starts at 44 for the same reason. */
	min-width: 44px;
	min-height: 44px;
	margin: 0;
	padding: 0;
	appearance: none;
	border: 0;
	border-radius: 50%;
	background-color: var(--tw-tan, #B18051);   /* play_bg overrides */
	color: #08080A;                             /* play_icon_color overrides; the SVG is currentColor */
	line-height: 0;
	cursor: pointer;
	opacity: 1;
	visibility: visible;
	transition-property: opacity, visibility, background-color, transform;
	transition-duration: 450ms;            /* duration overrides */
	transition-timing-function: ease;      /* easing overrides */
}

/* Rule 6 — restate the fill for the three states shared.css blanks. Ordered so
   :hover comes last and wins over :focus at equal specificity. */
.tw-chv .tw-chv__play:focus,
.tw-chv .tw-chv__play:focus-visible,
.tw-chv .tw-chv__play:active {
	background-color: var(--tw-tan, #B18051);
}

.tw-chv .tw-chv__play:hover {
	background-color: var(--tw-tan-hi, #c9a074);   /* play_bg_hover overrides */
	transform: translate(-50%, -50%) scale(1.06);
}

/* ⚠️ AN INK-COLOURED RING, NOT THE HOUSE TAN. The button IS tan, so a tan ring
   on it is invisible — the one place the house focus colour is the wrong
   answer. `outline-offset` keeps it clear of the circle's edge. */
.tw-chv .tw-chv__play:focus-visible {
	outline: 2px solid var(--tw-ink, #f6f4f0);
	outline-offset: 3px;
}

.tw-chv__tri {
	flex: none;
	display: block;
	width: 16px;                           /* play_icon_size overrides */
	height: 22px;                          /* play_icon_size overrides */
	margin-left: 4px;                      /* play_icon_size overrides — optical centring, work.html L611 */
}

/* `visibility:hidden` and not `display:none`: it leaves the tab order and the
   accessibility tree either way, but only this one can be transitioned, and
   `display:none` would also make the button's disappearance a layout event. */
.tw-chv.is-playing .tw-chv__play {
	opacity: 0;
	visibility: hidden;
	pointer-events: none;
}

/* Rule 4's second half. Cheap, and the 0.3.6 collapse is what it costs to leave
   out — a width-derived height resolving against max-content, on a phone,
   reported by nothing. */
@media (max-width: 767px) {
	.tw-chv {
		width: 100%;
	}
}

/* One frame with motion suppressed, while the JS resets a closed popup back to
   its starting ratio. Without it the collapse animates behind the popup's own
   fade-out. `!important` is not decoration: `duration` writes
   `transition-duration` at (0,4,0) and this rule is (0,2,0). Declared ABOVE the
   reduced-motion block, which must stay last. */
.tw-chv.is-snap .tw-chv__frame,
.tw-chv.is-snap .tw-chv__scrim,
.tw-chv.is-snap .tw-chv__tick,
.tw-chv.is-snap .tw-chv__play {
	transition-duration: 0s !important;
}

/* --- LAST IN THE FILE, root-prefixed, !important --------------------------
   ⚠️ Prove this with Elementor's frontend.css out of the cascade — it ships
   `html *{transition-duration:0s!important}`, which can mask a failure here and
   can vanish in any release. Nothing is lost when it applies: the change of
   SHAPE is the information, and it still happens — instantly. */
@media (prefers-reduced-motion: reduce) {
	.tw-chv .tw-chv__frame,
	.tw-chv .tw-chv__scrim,
	.tw-chv .tw-chv__tick,
	.tw-chv .tw-chv__play { transition-duration: 0s !important; }
}
