/**
 * Finewerk Hero Banner
 *
 * Two-column hero: a gradient text column (title, description, CTA with the
 * review block beside it) next to a full-bleed image slider, with a static
 * white corner panel — carrying the bilingual badge — notched into the
 * bottom-right corner of the banner.
 *
 * Reference: refferences/hero-banner.png (captured at ~1920px wide).
 *
 * SIZING MODEL — why almost nothing here is a fixed pixel value
 * ---------------------------------------------------------------------------
 * Every reference measurement was taken from a 1920px-wide capture, so a hard
 * px value would only be correct on that one viewport. Instead each dimension
 * is a `clamp(min, <the reference value expressed in vw>, max)`: the layout
 * reproduces the reference exactly at 1920px and degrades smoothly at every
 * other width, with no breakpoint stack to maintain. The matching Elementor
 * controls deliberately ship WITHOUT defaults so they stay empty until an
 * editor sets one — an unset control emits no CSS, so these fluid defaults
 * survive, and a set control simply overrides them.
 *
 * NO LAYOUT JUMPS
 * ---------------------------------------------------------------------------
 * The slides are absolutely positioned inside a viewport that is sized by the
 * banner itself, never by the current image, so switching slides (or loading a
 * portrait image after a landscape one) can never resize anything. The stats
 * panel is absolutely positioned too, so its own content — a number that grows
 * from "10" to "1000" — never pushes the slider around either.
 *
 * REUSED FINEWERK COMPONENTS
 * ---------------------------------------------------------------------------
 *   .fw-bg-gradient  child theme — the shared Finewerk background utility
 *                    (gradient + grain). The banner keeps its OWN, Elementor-
 *                    configurable gradient by outranking the utility with a
 *                    doubled class (see the root rule below), so in practice
 *                    it takes only the grain — the utility's default gradient
 *                    is byte-identical to this banner's own defaults anyway.
 *
 * NATIVE CTA COMPONENT — `.fw-hb-cta` (bottom of this file)
 * ---------------------------------------------------------------------------
 * The dual-state pill → liquid-glass card is the banner's OWN component: a
 * faithful port of the child theme's `.fw-hero-cta` design (structure,
 * dimensions, material, click-to-open morph), carried entirely by this file
 * and hero-banner.js under scoped class names, so a theme's copy of the
 * original — current or stale — can never restyle it or drive its state.
 *
 * All custom properties are namespaced `--fw-hb-`/`--fw-hcta-`/`--fw-glass-`
 * and every one this file consumes is declared inside the component itself.
 */

/* ------------------------------------------------------------------
 * Typography defaults (see assets/css/fonts.css)
 *
 * Hubot Sans for headings/titles/stat numbers, Archivo for everything
 * else. Declared at single-class specificity — the tag group through a
 * zero-specificity :where() — so an explicit Elementor Typography
 * control (which Elementor writes at element-id specificity) always
 * overrides it. No !important anywhere.
 * ---------------------------------------------------------------- */

.finewerk-hero-banner {
	font-family: var(--fw-font-body);
}

.finewerk-hero-banner :where(h1, h2, h3, h4, h5, h6) {
	font-family: var(--fw-font-title);
}

/* Form controls do not inherit the document font: the UA sheet gives
   button/input/select/textarea their own `font: 400 13.33px Arial`.
   Opt them back into the component's face. */
.finewerk-hero-banner :where(button, input, select, textarea, optgroup) {
	font-family: inherit;
}

.finewerk-hero-banner {
	/* ---- Layout tunables ---- */
	--fw-hb-media-width: 53.5%;
	/* The reference-fitted height minus a flat 115px at every width. */
	--fw-hb-min-height: calc(clamp(520px, 55.5vw, 1065px) - 115px);
	--fw-hb-radius: clamp(16px, 1.85vw, 36px);
	--fw-hb-content-justify: center;

	/* ---- Background (exactly the gradient the brief specifies) ---- */
	--fw-hb-bg-color: #0F3D3A;
	--fw-hb-bg-angle: 150deg;
	--fw-hb-bg-from: rgba(15, 61, 58, 1);
	--fw-hb-bg-from-stop: 43%;
	--fw-hb-bg-to: rgba(65, 99, 46, 1);
	--fw-hb-bg-to-stop: 100%;

	/* ---- Corner panel curvature ----
	   One value drives the rounded corner and BOTH inverted cut-outs, so the
	   shape stays coherent at any size. Pinned to the global Finewerk 20px
	   corner standard now that the panel runs at 0.6x its original size. */
	--fw-hb-panel-radius: 20px;
	--fw-hb-panel-notch: var(--fw-hb-panel-radius);

	/* ---- Colors ---- */
	--fw-hb-title-color: #FFFFFF;
	--fw-hb-description-color: rgba(255, 255, 255, 0.82);
	--fw-hb-marker-color: rgba(255, 255, 255, 0.55);
	--fw-hb-review-color: #FFFFFF;
	--fw-hb-star-color: #F04E33;
	/* The badge sits on the white corner panel, so it reads dark. The
	   `badge_color` control ships the same default. */
	--fw-hb-badge-color: #4A4A4A;

	/* ---- Title entrance animation ---- */
	--fw-hb-anim-duration: 900ms;
	--fw-hb-anim-stagger: 26ms;
	--fw-hb-anim-delay: 120ms;
	--fw-hb-anim-distance: 100%;
	--fw-hb-anim-ease: cubic-bezier(0.22, 1, 0.36, 1);
	/* Line box the per-word mask clips against. Roomier than the title's own
	   line-height so ascenders and descenders are never cut off, then pulled
	   back out of the flow by the negative margins below so the visible line
	   spacing stays exactly --fw-hb-title-lh. */
	--fw-hb-mask-lh: 1.42;
	/* Re-fitted against the reference glyphs: cap-top of line 1 to cap-top of
	   line 2 is 74px at a 1307px capture (108.7px at 1920) with a 100px font.
	   The `title_line_height` control ships the same 1.09 default. */
	--fw-hb-title-lh: 1.09;

	position: relative;
	display: block;
	width: 100%;
	box-sizing: border-box;
	overflow: hidden;
	border-radius: var(--fw-hb-radius);
	background-color: var(--fw-hb-bg-color);
	background-image: linear-gradient(
		var(--fw-hb-bg-angle),
		var(--fw-hb-bg-from) var(--fw-hb-bg-from-stop),
		var(--fw-hb-bg-to) var(--fw-hb-bg-to-stop)
	);
}

/* The banner root also carries the shared `.fw-bg-gradient` utility, which is
   what gives it the grain — and that utility paints a gradient of its own at
   (0,1,0), tying with the rule above. Repeating the background here at (0,2,0)
   pins the banner's OWN, Elementor-configurable gradient as the winner by
   SPECIFICITY rather than by load order, so it holds however the child theme
   and the widget stylesheets happen to be ordered. The values are the same
   custom properties, and the utility's default gradient is byte-identical to
   this banner's defaults, so nothing changes visually until an editor
   actually retunes the Background controls. */
.finewerk-hero-banner.finewerk-hero-banner {
	background-color: var(--fw-hb-bg-color);
	background-image: linear-gradient(
		var(--fw-hb-bg-angle),
		var(--fw-hb-bg-from) var(--fw-hb-bg-from-stop),
		var(--fw-hb-bg-to) var(--fw-hb-bg-to-stop)
	);
}

.finewerk-hero-banner *,
.finewerk-hero-banner *::before,
.finewerk-hero-banner *::after {
	box-sizing: border-box;
}

/* ==========================================================================
   Shell
   ========================================================================== */

/* Grid rather than flex so the two tracks are sized by the container alone:
   an over-wide image or a very long title can never widen its own column. */
.finewerk-hero-banner__inner {
	display: grid;
	grid-template-columns: minmax(0, 1fr) minmax(0, var(--fw-hb-media-width));
	align-items: stretch;
	min-height: var(--fw-hb-min-height);
	width: 100%;
}

/* Media-left variant: swap the track order, keep the same DOM order so the
   text is still read first by assistive tech and by search engines. */
.finewerk-hero-banner--media-left .finewerk-hero-banner__inner {
	grid-template-columns: minmax(0, var(--fw-hb-media-width)) minmax(0, 1fr);
}

.finewerk-hero-banner--media-left .finewerk-hero-banner__content {
	grid-column: 2;
	grid-row: 1;
}

.finewerk-hero-banner--media-left .finewerk-hero-banner__media {
	grid-column: 1;
	grid-row: 1;
}

/* ==========================================================================
   Content column
   ========================================================================== */

.finewerk-hero-banner__content {
	display: flex;
	flex-direction: column;
	justify-content: var(--fw-hb-content-justify);
	align-items: flex-start;
	min-width: 0;
	/* Measured off the reference: the text's shared left edge (title cap,
	   marker, pill) sits 213px from the banner's left edge at 1920px, and the
	   whole stack is biased above the optical centre — the extra bottom
	   padding produces that bias while `justify-content: center` does the
	   rest. At exactly 1920px the CTA pill + social-proof row fit this inset
	   with only a few px to spare (the `.fw-hb-cta` pill is wider than the
	   one drawn in the mockup); below ~1900px the proof row wraps
	   under the pill, which the flex-wrap on the actions row handles. */
	padding:
		clamp(40px, 4.6vw, 88px)
		8px
		clamp(56px, 11.2vw, 215px)
		clamp(24px, 10.9vw, 209px);
	/* Above the media column so the CTA's glass card may overlap the image. */
	position: relative;
	z-index: 2;
	/* One overall vertical offset for the whole text column, set per device
	   by the "Content vertical offset" Elementor control. */
	transform: translateY(var(--fw-hb-content-offset-y, 0px));
}

/* ---------- Title ---------- */

.finewerk-hero-banner__title {
	margin: 0;
	max-width: 100%;
	color: var(--fw-hb-title-color);
	/* Deliberate exception to the Hubot Sans title default: this title is a
	   reference-matched reproduction of Archivo's fully condensed cut, and
	   Hubot Sans' width axis does not reach 62%. Archivo is the site body
	   face, so no extra font is loaded for it. */
	font-family: var(--fw-font-body);
	font-size: clamp(38px, 5.21vw, 100px);
	/* Archivo carries a width axis; the reference face is the fully condensed
	   62% cut at hairline weight with a whisper of positive tracking — that
	   combination is what reproduces both the glyph shapes and the line
	   width of the capture. Browsers without variable-font support simply
	   ignore the width axis. */
	font-stretch: var(--fw-hb-title-stretch, 62%);
	font-weight: 100;
	line-height: var(--fw-hb-title-lh);
	letter-spacing: 0.015em;
	text-wrap: balance;
	overflow-wrap: break-word;
}

.finewerk-hero-banner__title a {
	color: inherit;
}

/* ---------- Description + its measure marker ---------- */

.finewerk-hero-banner__desc-row {
	display: flex;
	align-items: stretch;
	gap: clamp(12px, 1.46vw, 28px);
	margin-top: var(--fw-hb-description-gap, clamp(0px, 0.3vw, 6px));
	max-width: clamp(280px, 29vw, 557px);
}

/* Thin rule with a small round dot at each end, matching the reference's
   measurement-line motif. Drawn from one span plus its two pseudo-elements so
   it needs no extra markup. */
.finewerk-hero-banner__desc-marker {
	position: relative;
	flex: 0 0 auto;
	width: 1px;
	/* From the paragraph's first line centre down to its last line, as in the
	   reference. */
	height: var(--fw-hb-marker-height, 2.6em);
	margin-top: var(--fw-hb-marker-offset, 1.1em);
	background: var(--fw-hb-marker-color);
	/* Matches the paragraph so the marker's `em`-based height tracks the
	   description's line box at every viewport width. */
	font-size: clamp(14px, 1.07vw, 20.5px);
}

.finewerk-hero-banner__desc-marker::before,
.finewerk-hero-banner__desc-marker::after {
	content: "";
	position: absolute;
	left: 50%;
	width: 0.36em;
	height: 0.36em;
	border-radius: 50%;
	background: var(--fw-hb-marker-color);
	transform: translate(-50%, -50%);
}

.finewerk-hero-banner__desc-marker::before {
	top: 0;
}

.finewerk-hero-banner__desc-marker::after {
	top: 100%;
}

.finewerk-hero-banner__description {
	margin: 0;
	min-width: 0;
	color: var(--fw-hb-description-color);
	font-family: var(--fw-font-body);
	font-size: clamp(14px, 1.07vw, 20.5px);
	font-weight: 400;
	line-height: var(--fw-hb-description-lh, 1.68);
	letter-spacing: 0;
}

/* ---------- Actions row: CTA + social proof ---------- */

.finewerk-hero-banner__actions {
	display: flex;
	/* CTA pill on the left, the review block directly to its right on a
	   shared vertical centre; when the row runs out of room the review
	   wraps onto the next line naturally. */
	align-items: center;
	flex-wrap: wrap;
	gap: var(--fw-hb-actions-gap, 8px);
	margin-top: var(--fw-hb-actions-gap-top, clamp(24px, 3.44vw, 66px));
	max-width: 100%;
}

/* The pill keeps its own intrinsic size — this only stops it from being
   stretched or squashed by the row. The component itself is the widget's own
   `.fw-hb-cta`, styled at the bottom of this file. */
.finewerk-hero-banner__cta {
	flex: 0 0 auto;
}

/* The banner runs its CTA at 0.75x of the design's Home-3 size. `zoom`
   scales the whole component together — pill, padding, text, dot, glass
   card and its layout box. */
.finewerk-hero-banner__cta .fw-hb-cta {
	zoom: 0.75;
}

/* ---------- Social proof (the review block) ---------- */

.finewerk-hero-banner__proof {
	display: flex;
	align-items: stretch;
	flex: 0 1 auto;
	min-width: 0;
	gap: clamp(8px, 0.68vw, 13px);
}

.finewerk-hero-banner__proof-cell {
	flex: 0 0 auto;
	display: flex;
	flex-direction: column;
	justify-content: center;
	gap: clamp(2px, 0.3vw, 6px);
	min-width: 0;
}

.finewerk-hero-banner__review {
	display: flex;
	flex-direction: column;
	gap: clamp(2px, 0.3vw, 6px);
	color: var(--fw-hb-review-color);
	text-decoration: none;
}

.finewerk-hero-banner__review-line {
	display: flex;
	align-items: center;
	gap: clamp(6px, 0.62vw, 12px);
}

.finewerk-hero-banner__review-text,
.finewerk-hero-banner__review-count {
	color: inherit;
	font-family: var(--fw-font-body);
	font-size: clamp(13px, 0.96vw, 18px);
	font-weight: 600;
	line-height: 1.2;
	letter-spacing: -0.01em;
	white-space: nowrap;
}

.finewerk-hero-banner__stars {
	display: inline-flex;
	align-items: center;
	gap: 0.12em;
	color: var(--fw-hb-star-color);
	font-size: clamp(12px, 1vw, 19px);
	line-height: 1;
}

.finewerk-hero-banner__star {
	display: block;
	width: 1em;
	height: 1em;
	fill: currentColor;
}

.finewerk-hero-banner__review-logo {
	display: block;
	width: auto;
	height: clamp(16px, 1.15vw, 22px);
	object-fit: contain;
}

/* ---------- Bilingual badge (rendered inside the corner panel) ---------- */

.finewerk-hero-banner__badge {
	display: flex;
	align-items: center;
	gap: clamp(8px, 0.63vw, 12px);
	min-width: 0;
}

.finewerk-hero-banner__badge-flags {
	display: inline-flex;
	align-items: center;
	flex: 0 0 auto;
	/* The overlap below is expressed in `em`, so the flag size drives it. */
	font-size: var(--fw-hb-flag-size, clamp(31px, 2.51vw, 48px));
}

.finewerk-hero-banner__badge-flag {
	display: block;
	flex: 0 0 auto;
	width: var(--fw-hb-flag-size, clamp(31px, 2.51vw, 48px));
	height: var(--fw-hb-flag-size, clamp(31px, 2.51vw, 48px));
	border-radius: 50%;
	object-fit: cover;
}

.finewerk-hero-banner__badge-flag + .finewerk-hero-banner__badge-flag {
	margin-left: var(--fw-hb-flag-overlap, -0.5em);
}

.finewerk-hero-banner__badge-text {
	margin: 0;
	min-width: 0;
	color: var(--fw-hb-badge-color);
	/* Condensed Archivo, matching the title above. */
	font-family: var(--fw-font-body);
	font-stretch: var(--fw-hb-title-stretch, 62%);
	font-size: clamp(13px, 1vw, 19px);
	font-weight: 300;
	line-height: 1.36;
	letter-spacing: 0;
}

/* ==========================================================================
   Media column — slider
   ========================================================================== */

.finewerk-hero-banner__media {
	position: relative;
	min-width: 0;
	/* The grid row is stretched, so this is always exactly as tall as the
	   banner. Slides read their size from here and never from their image. */
	align-self: stretch;
}

.finewerk-hero-banner__slider {
	position: absolute;
	inset: 0;
	overflow: hidden;
	border-radius: var(--fw-hb-media-radius, 0);
}

.finewerk-hero-banner__slides {
	position: absolute;
	inset: 0;
	margin: 0;
	padding: 0;
	list-style: none;
}

/* Every slide occupies the full viewport box from the first frame, so the
   transition only ever animates opacity/transform — never geometry. */
.finewerk-hero-banner__slide {
	position: absolute;
	inset: 0;
	opacity: 0;
	visibility: hidden;
	transition:
		opacity var(--fw-hb-slide-speed, 800ms) ease,
		transform var(--fw-hb-slide-speed, 800ms) cubic-bezier(0.4, 0, 0.2, 1),
		visibility 0s linear var(--fw-hb-slide-speed, 800ms);
	will-change: opacity, transform;
}

.finewerk-hero-banner__slide.is-active {
	opacity: 1;
	visibility: visible;
	transform: none;
	z-index: 2;
	transition:
		opacity var(--fw-hb-slide-speed, 800ms) ease,
		transform var(--fw-hb-slide-speed, 800ms) cubic-bezier(0.4, 0, 0.2, 1),
		visibility 0s;
}

/* The outgoing slide stays fully painted underneath the incoming one for the
   length of the transition, so a crossfade never dips through the background
   and a horizontal slide always has something to push out of frame. */
.finewerk-hero-banner__slide.is-leaving {
	opacity: 1;
	visibility: visible;
	z-index: 1;
}

.finewerk-hero-banner__slide-img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: var(--fw-hb-image-fit, cover);
	object-position: var(--fw-hb-image-position, center center);
	transform: scale(var(--fw-hb-image-zoom, 1));
}

/* ---- Slide effect: horizontal slide ---- */

.finewerk-hero-banner--effect-slide .finewerk-hero-banner__slide {
	opacity: 1;
	transform: translate3d(100%, 0, 0);
}

.finewerk-hero-banner--effect-slide .finewerk-hero-banner__slide.is-active {
	transform: translate3d(0, 0, 0);
}

.finewerk-hero-banner--effect-slide .finewerk-hero-banner__slide.is-leaving {
	transform: translate3d(-100%, 0, 0);
}

/* Reverse direction (prev / backwards autoplay) mirrors both offsets. */
.finewerk-hero-banner--effect-slide.is-reversing .finewerk-hero-banner__slide {
	transform: translate3d(-100%, 0, 0);
}

.finewerk-hero-banner--effect-slide.is-reversing .finewerk-hero-banner__slide.is-leaving {
	transform: translate3d(100%, 0, 0);
}

/* A slide that is jumped into place (initial paint, or a resize) must not
   animate in from the side. */
.finewerk-hero-banner__slide.is-instant {
	transition: none !important;
}

/* ---------- Navigation ---------- */

.finewerk-hero-banner__nav {
	position: absolute;
	z-index: 5;
	display: flex;
	align-items: center;
	gap: var(--fw-hb-nav-gap, clamp(10px, 0.99vw, 19px));
	left: var(--fw-hb-nav-x, clamp(10px, 0.7vw, 13px));
	bottom: var(--fw-hb-nav-y, clamp(6px, 0.63vw, 12px));
	pointer-events: none;
}

.finewerk-hero-banner--nav-center .finewerk-hero-banner__nav {
	left: 50%;
	transform: translateX(-50%);
}

.finewerk-hero-banner--nav-right .finewerk-hero-banner__nav {
	left: auto;
	right: var(--fw-hb-nav-x, clamp(12px, 1.05vw, 20px));
}

.finewerk-hero-banner__arrows {
	display: inline-flex;
	align-items: center;
	gap: var(--fw-hb-arrow-gap, 8px);
	pointer-events: auto;
}

.finewerk-hero-banner__arrow {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	flex: 0 0 auto;
	width: var(--fw-hb-arrow-size, clamp(32px, 2.4vw, 46px));
	height: var(--fw-hb-arrow-size, clamp(32px, 2.4vw, 46px));
	padding: 0;
	border: 1px solid var(--fw-hb-arrow-border, rgba(255, 255, 255, 0.55));
	border-radius: var(--fw-hb-arrow-radius, 999px);
	background: var(--fw-hb-arrow-bg, rgba(255, 255, 255, 0.16));
	color: var(--fw-hb-arrow-color, #FFFFFF);
	-webkit-backdrop-filter: blur(10px);
	backdrop-filter: blur(10px);
	cursor: pointer;
	transition: background-color 0.25s ease, color 0.25s ease, border-color 0.25s ease, transform 0.25s ease;
}

.finewerk-hero-banner__arrow:hover,
.finewerk-hero-banner__arrow:focus-visible {
	background: var(--fw-hb-arrow-bg-hover, rgba(255, 255, 255, 0.92));
	color: var(--fw-hb-arrow-color-hover, #0F3D3A);
	border-color: var(--fw-hb-arrow-bg-hover, rgba(255, 255, 255, 0.92));
}

.finewerk-hero-banner__arrow:focus-visible {
	outline: 2px solid rgba(255, 255, 255, 0.9);
	outline-offset: 2px;
}

.finewerk-hero-banner__arrow[disabled] {
	opacity: 0.4;
	cursor: default;
}

.finewerk-hero-banner__arrow svg {
	width: 42%;
	height: 42%;
	fill: none;
	stroke: currentColor;
	stroke-width: 1.8;
	stroke-linecap: round;
	stroke-linejoin: round;
}

.finewerk-hero-banner__dots {
	display: inline-flex;
	align-items: center;
	gap: var(--fw-hb-dot-gap, clamp(16px, 1.87vw, 36px));
	pointer-events: auto;
}

.finewerk-hero-banner__dot {
	display: block;
	flex: 0 0 auto;
	width: var(--fw-hb-dot-size, clamp(7px, 0.52vw, 10px));
	height: var(--fw-hb-dot-size, clamp(7px, 0.52vw, 10px));
	padding: 0;
	border: 0;
	border-radius: 999px;
	background: var(--fw-hb-dot-color, rgba(255, 255, 255, 0.72));
	cursor: pointer;
	transition: background-color 0.3s ease, width 0.3s ease, transform 0.3s ease;
}

.finewerk-hero-banner__dot:hover {
	transform: scale(1.15);
}

.finewerk-hero-banner__dot.is-active {
	background: var(--fw-hb-dot-active-color, #0F3D3A);
	width: var(--fw-hb-dot-active-size, clamp(9px, 0.73vw, 14px));
	height: var(--fw-hb-dot-active-size, clamp(9px, 0.73vw, 14px));
}

.finewerk-hero-banner__dot:focus-visible {
	outline: 2px solid #FFFFFF;
	outline-offset: 3px;
}

/* ==========================================================================
   Corner panel — the static white shape in the bottom-right corner,
   carrying the bilingual badge
   ==========================================================================
   Part of the banner's own layout, never part of a slide image, so the slider
   can run underneath it without ever moving it. Anchored to the banner's
   bottom-right corner, so the banner's own border-radius (via `overflow:
   hidden` on the root) trims it to the same curve as the frame.

   THE SHAPE — three curves, not one
   ---------------------------------------------------------------------------
   The reference does not draw a plain rounded rectangle. The panel reads as a
   tab carved out of the banner's corner, and it meets the frame with a curve
   on BOTH sides:

       ╭───────────────────────  ← ① convex corner, top-left
       │                       ╮ ← ② inverted corner: the fill climbs the
       │  ◉◉ bilingual studio, │    banner's RIGHT edge above the panel
    ╮  │     native quality    │
    ╰──╯ ↑                     │
         ③ inverted corner: the fill spreads along the banner's BOTTOM edge
           to the LEFT of the panel

   ① is a normal `border-top-left-radius`. ② and ③ are square boxes parked
   just outside the panel, each painted with a corner-anchored radial gradient
   — the panel colour everywhere except a quarter-disc, which is exactly the
   negative space a rounded cut-out leaves behind. Both use the identical
   `circle farthest-side at 0 0` gradient; only their anchoring differs, which
   is what mirrors the curve onto the other side.
   ========================================================================== */

.finewerk-hero-banner__panel {
	position: absolute;
	right: 0;
	bottom: 0;
	z-index: 6;
	display: flex;
	align-items: center;
	gap: var(--fw-hb-panel-gap, clamp(5px, 0.36vw, 7px));
	/* 0.6x of the original reference-fitted size in every dimension. */
	min-width: var(--fw-hb-panel-min-width, clamp(168px, 16.98vw, 325px));
	padding:
		clamp(5px, 0.28vw, 6px)
		clamp(10px, 1.74vw, 34px)
		clamp(5px, 0.28vw, 6px)
		clamp(11px, 2.28vw, 43px);
	min-height: var(--fw-hb-panel-min-height, clamp(38px, 3.36vw, 65px));
	background: var(--fw-hb-panel-bg, #FFFFFF);
	border-top-left-radius: var(--fw-hb-panel-radius);
}

/* ② and ③ — the two inverted corners.

   `aspect-ratio: 1` with an auto width keeps each box exactly square however
   its height ends up resolving, and `farthest-side` ties the gradient's radius
   to the box itself rather than to a length. Together that means the arc can
   never be squashed into an ellipse: cap the size, and the whole quarter-disc
   scales with it. `max-height: 100%` is that cap — a cut-out deeper than the
   panel would otherwise spill white past the panel's own edges. */
.finewerk-hero-banner__panel-notch {
	position: absolute;
	height: var(--fw-hb-panel-notch);
	width: auto;
	aspect-ratio: 1;
	max-height: 100%;
	pointer-events: none;
	background: radial-gradient(
		circle farthest-side at 0 0,
		transparent 99.4%,
		var(--fw-hb-panel-bg, #FFFFFF) 100%
	);
}

/* Both boxes overlap the panel by 1px. Their edge and the panel's edge would
   otherwise meet at the same fractional coordinate, where browsers leave a
   hairline of the image showing through; the overlap lands inside the panel's
   own fill, so it closes that seam without changing the silhouette. */

/* ② Above the panel, flush to the banner's right edge: the fill climbs the
   edge and curves back down onto the panel's top edge. */
.finewerk-hero-banner__panel-notch--top {
	right: 0;
	bottom: 100%;
	margin-bottom: -1px;
}

/* ③ Beside the panel, flush to the banner's bottom edge: the same curve
   mirrored, so the fill spreads left along the bottom and curves back up onto
   the panel's left edge. */
.finewerk-hero-banner__panel-notch--start {
	right: 100%;
	bottom: 0;
	margin-right: -1px;
}

/* The badge inside the panel is the same `.finewerk-hero-banner__badge`
   component the content column used to carry; at the panel's 0.6x size its
   generic text sizing already fits, so nothing is overridden here. */

/* ==========================================================================
   Title entrance animation — per-character slide up
   ==========================================================================
   The title is split server-side into words and characters, so the split is
   already in the first HTML response: nothing reflows after hydration and the
   text is fully present for assistive tech (the visible copy is mirrored by an
   `aria-label`, and every generated span is `aria-hidden` free but inert).

   Each word is its own mask. `overflow: hidden` on the word clips the letters
   while they sit below the line, and the roomier `--fw-hb-mask-lh` line box
   (pulled back out of the flow by the negative block margins) guarantees the
   mask never crops an ascender or descender at rest.
   ========================================================================== */

.finewerk-hero-banner__word {
	display: inline-flex;
	overflow: hidden;
	vertical-align: baseline;
	line-height: var(--fw-hb-mask-lh);
	margin-block: calc((var(--fw-hb-title-lh) - var(--fw-hb-mask-lh)) * 0.5em);
}

.finewerk-hero-banner__char {
	display: inline-block;
	line-height: inherit;
	white-space: pre;
	will-change: transform, opacity;
}

/* Resting (pre-animation) state. Only applied while the widget is opted into
   the animation AND has not played yet, so a browser without JS — or a visitor
   who prefers reduced motion — always sees the finished title. */
.finewerk-hero-banner.is-animated:not(.is-inview) .finewerk-hero-banner__char {
	opacity: 0;
	transform: translate3d(0, var(--fw-hb-anim-distance), 0);
}

.finewerk-hero-banner.is-animated .finewerk-hero-banner__char {
	transition:
		opacity calc(var(--fw-hb-anim-duration) * 0.7) var(--fw-hb-anim-ease),
		transform var(--fw-hb-anim-duration) var(--fw-hb-anim-ease);
	transition-delay: calc(var(--fw-hb-anim-delay) + var(--fw-hb-char-i, 0) * var(--fw-hb-anim-stagger));
}

.finewerk-hero-banner.is-animated.is-inview .finewerk-hero-banner__char {
	opacity: 1;
	transform: translate3d(0, 0, 0);
}

/* ==========================================================================
   Responsive
   ==========================================================================
   Single stacking breakpoint: below it the media becomes a fixed-ratio band
   under the text, which keeps the "no layout jump" guarantee (the band, not
   the image, decides the height) on phones and tablets too.
   ========================================================================== */

@media (max-width: 1024px) {
	.finewerk-hero-banner {
		--fw-hb-min-height: 0px;
	}

	.finewerk-hero-banner__inner,
	.finewerk-hero-banner--media-left .finewerk-hero-banner__inner {
		grid-template-columns: minmax(0, 1fr);
	}

	.finewerk-hero-banner__content,
	.finewerk-hero-banner--media-left .finewerk-hero-banner__content {
		grid-column: 1;
		grid-row: 1;
		padding: clamp(32px, 6vw, 64px) clamp(20px, 5vw, 56px) clamp(32px, 6vw, 64px);
	}

	.finewerk-hero-banner__media,
	.finewerk-hero-banner--media-left .finewerk-hero-banner__media {
		grid-column: 1;
		grid-row: 2;
		aspect-ratio: var(--fw-hb-media-ratio-stacked, 4 / 3);
	}

	.finewerk-hero-banner__title {
		max-width: none;
	}

	.finewerk-hero-banner__desc-row {
		max-width: 56ch;
	}
}

@media (max-width: 640px) {
	.finewerk-hero-banner {
		--fw-hb-panel-min-width: 0px;
		--fw-hb-panel-mobile-height: 56px;
	}

	/* The actions row keeps its flex-wrap behaviour on phones too: the
	   review block simply wraps under the pill when it runs out of room. */

	/* Full width along the bottom edge on phones. */
	.finewerk-hero-banner__panel {
		left: 0;
		right: 0;
		gap: 10px;
		padding: 8px 16px;
		min-height: var(--fw-hb-panel-mobile-height);
	}

	/* …which is where the dots would otherwise sit, so lift them clear of it.
	   Only when a panel is actually rendered — without one the dots stay on
	   the bottom edge of the image, as everywhere else. */
	.finewerk-hero-banner--has-panel .finewerk-hero-banner__nav {
		bottom: calc(var(--fw-hb-panel-mobile-height) + 12px);
	}

	/* Full-width on phones: the panel already reaches both side edges, so
	   neither cut-out has a corner left to carve. */
	.finewerk-hero-banner__panel-notch {
		display: none;
	}

	.finewerk-hero-banner__media {
		aspect-ratio: var(--fw-hb-media-ratio-mobile, 3 / 4);
	}
}

/* ==========================================================================
   Reduced motion — the slider still advances, nothing slides or staggers.
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {
	.finewerk-hero-banner.is-animated .finewerk-hero-banner__char,
	.finewerk-hero-banner.is-animated:not(.is-inview) .finewerk-hero-banner__char {
		opacity: 1;
		transform: none;
		transition: none;
	}

	.finewerk-hero-banner__slide,
	.finewerk-hero-banner__slide.is-active,
	.finewerk-hero-banner__slide.is-leaving {
		transition: opacity 0.01s linear, visibility 0.01s linear;
		transform: none;
	}
}

/* ==========================================================================
   Native CTA component — .fw-hb-cta
   ==========================================================================
   The banner's own dual-state hero CTA: a faithful port of the child theme's
   `.fw-hero-cta` (same structure, dimensions, material and morph), rendered
   by the widget (get_cta_html()) and driven by hero-banner.js. The class
   names are scoped on purpose: a theme's copy of the original component —
   current or stale — can never restyle this one or attach behaviour to it.

       .fw-hb-cta                     state root (pill-sized in layout)
         a.fw-hb-cta__default        DEFAULT: white pill
         div.fw-hb-cta__card         OPENED:  liquid-glass card (the glass
                                     material is baked into the card below —
                                     no `finewerk-liquid-glass` dependency)

   TRANSITION MODEL — why this never causes layout jumps
   ---------------------------------------------------------------------------
   The root keeps the DEFAULT pill's size in the layout at all times. The card
   is absolutely positioned over the pill's top-left corner and animates
   opacity + scale from a pill-sized origin, so it reads as the pill growing
   into the card. Nothing in the flow ever resizes.

   CLICK TO OPEN — the card does not react to hover
   ---------------------------------------------------------------------------
   There is exactly ONE open state, `.is-open`, and only hero-banner.js adds
   it. No `:hover`, `:active` or `:focus-within` appears in the open-state
   selectors below, and that is deliberate: any of them would re-introduce a
   pointer-over reveal.

   Tunables (all overridable via the widget's Style → CTA Button controls):
       --fw-hcta-duration       morph duration
       --fw-hcta-title          default title color
       --fw-hcta-muted          availability text color
       --fw-hcta-dot            green dot color
       --fw-hcta-default-bg     default pill background
       --fw-hcta-card-radius    card corner radius
       --fw-hcta-card-max-w     card max width
   ========================================================================== */

.fw-hb-cta {
	/* Tunables */
	--fw-hcta-duration: 450ms;
	--fw-hcta-ease: cubic-bezier(0.22, 1, 0.36, 1);
	--fw-hcta-title: #0b0b0f;
	--fw-hcta-muted: #8a8a92;
	--fw-hcta-dot: #3ecf6e;
	--fw-hcta-default-bg: #ffffff;
	--fw-hcta-default-border: #ececec;
	--fw-hcta-card-radius: 36px;
	--fw-hcta-card-max-w: 480px;

	position: relative;
	display: inline-block;
	/* Above the static hero content so the expanded card overlays instead of
	   pushing anything around. */
	z-index: 20;
}

/* --------------------------------------------------------------------------
   DEFAULT face — white pill: bold title + "● Available now"
   -------------------------------------------------------------------------- */
.fw-hb-cta__default {
	display: inline-flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 3px;
	padding: 15px 30px 14px;
	background: var(--fw-hcta-default-bg);
	border: 1px solid var(--fw-hcta-default-border);
	border-radius: 999px;
	box-shadow:
		0 6px 16px rgba(17, 17, 26, 0.08),
		0 1px 3px rgba(17, 17, 26, 0.06);
	text-decoration: none;
	-webkit-tap-highlight-color: transparent;
	transition:
		opacity calc(var(--fw-hcta-duration) * 0.45) ease,
		transform calc(var(--fw-hcta-duration) * 0.45) ease,
		box-shadow 0.3s ease;
}

.fw-hb-cta__default-text {
	color: var(--fw-hcta-title);
	font-family: var(--fw-font-body);
	font-size: 18px;
	font-weight: 700;
	line-height: 1.25;
	letter-spacing: -0.01em;
	white-space: nowrap;
}

.fw-hb-cta__availability {
	display: inline-flex;
	align-items: center;
	gap: 7px;
	color: var(--fw-hcta-muted);
	font-family: var(--fw-font-body);
	font-size: 14px;
	font-weight: 500;
	line-height: 1.2;
}

.fw-hb-cta__dot {
	flex: 0 0 auto;
	width: 10px;
	height: 10px;
	border-radius: 50%;
	background: var(--fw-hcta-dot);
}

/* --------------------------------------------------------------------------
   OPENED face — liquid-glass card (portrait + name/role + inner CTA + email).
   The glass material (the same "dark smoke plate" the design uses) is baked
   into the card's own ::before / ::after below.
   -------------------------------------------------------------------------- */
.fw-hb-cta .fw-hb-cta__card {
	position: absolute;
	top: -16px;
	left: -16px;
	width: min(var(--fw-hcta-card-max-w), 86vw);
	padding: 30px;
	display: flex;
	flex-direction: column;
	gap: 46px;
	border-radius: var(--fw-hcta-card-radius);
	z-index: 2;

	/* Glass material tuning — the effective values of the design's
	   `finewerk-liquid-glass --dark` material with the card's own overrides,
	   flattened. Every variable the material rules below consume is declared
	   here, so nothing can leak in from an ancestor stylesheet. */
	--fw-glass-tint: 52, 54, 58;
	--fw-glass-opacity: 0.62;
	--fw-glass-blur: 22px;
	--fw-glass-saturation: 1.5;
	--fw-glass-border-opacity: 0.22;
	--fw-glass-highlight-x: 28%;
	--fw-glass-highlight-y: 18%;
	--fw-glass-highlight-opacity: 0.35;
	--fw-glass-highlight-size: 110px;
	--fw-glass-shadow-rgb: 15, 21, 38;
	--fw-glass-inner-shadow-opacity: 0.35;
	--fw-glass-lens-glow: inset 0 0 0 0 rgba(255, 255, 255, 0);

	/* Closed state: invisible, non-interactive, pill-sized (scaled down
	   around a point inside the pill so the morph starts "from" the pill). */
	opacity: 0;
	visibility: hidden;
	pointer-events: none;
	transform: scale(0.3);
	transform-origin: 90px 48px;
	transition:
		transform var(--fw-hcta-duration) var(--fw-hcta-ease),
		opacity calc(var(--fw-hcta-duration) * 0.6) ease,
		visibility 0s linear var(--fw-hcta-duration);
	/* NO will-change here: `will-change: opacity` turns the card into a
	   backdrop root, which silently disables the glass backdrop-filter (the
	   plate would stop blurring the hero behind it). The transition only
	   runs while opening or closing, so the compositing hint isn't needed
	   anyway. */
}

/* ---- Open state (click-driven; see hero-banner.js) ------------------------ */
.fw-hb-cta.is-open .fw-hb-cta__card {
	opacity: 1;
	visibility: visible;
	pointer-events: auto;
	transform: scale(1);
	transition:
		transform var(--fw-hcta-duration) var(--fw-hcta-ease),
		opacity calc(var(--fw-hcta-duration) * 0.5) ease,
		visibility 0s;
}

/* Once the card is up it owns the pointer: the pill underneath it fades out
   and stops taking clicks, so the card's own inner link is what a second
   click hits. */
.fw-hb-cta.is-open .fw-hb-cta__default {
	opacity: 0;
	transform: scale(0.94);
	pointer-events: none;
}

/* --------------------------------------------------------------------------
   Card glass material (ported from the design's liquid-glass system)
   ---------------------------------------------------------------------------
   ::before is the plate (tint + depth; readable translucent fallback when
   backdrop-filter is unsupported), ::after the static specular highlight.
   Both follow the card's actual radius and never intercept the pointer.
   -------------------------------------------------------------------------- */
.fw-hb-cta .fw-hb-cta__card::before,
.fw-hb-cta .fw-hb-cta__card::after {
	content: "";
	position: absolute;
	top: 0;
	right: 0;
	bottom: 0;
	left: 0;
	border-radius: inherit;
	pointer-events: none;
}

.fw-hb-cta .fw-hb-cta__card::before {
	z-index: -1;
	/* No-backdrop fallback: a stronger tint keeps the card readable (with
	   this card's 0.62 opacity the plate goes effectively solid, exactly as
	   the source material resolves). */
	background: rgba(var(--fw-glass-tint), calc(var(--fw-glass-opacity) * 2.5));
	/* Natural depth below the plate PLUS the bright rim / internal shadows. */
	box-shadow:
		0 24px 48px -16px rgba(var(--fw-glass-shadow-rgb), 0.30),
		0 6px 14px -6px  rgba(var(--fw-glass-shadow-rgb), 0.16),
		inset 0 0 0 1px rgba(255, 255, 255, calc(var(--fw-glass-border-opacity) * 0.5)),
		inset 0  1.5px 0.5px -1px rgba(255, 255, 255, calc(var(--fw-glass-border-opacity) * 1.2)),
		inset 0 -1.5px 0.5px -1px rgba(255, 255, 255, calc(var(--fw-glass-border-opacity) * 0.7)),
		inset 0  18px 30px -20px rgba(255, 255, 255, 0.40),
		inset 0 -16px 30px -22px rgba(var(--fw-glass-shadow-rgb), var(--fw-glass-inner-shadow-opacity)),
		var(--fw-glass-lens-glow);
}

/* The specular highlight: a fixed-radius circle so the light reads as a round
   reflection on every aspect ratio; clipped by border-radius: inherit. */
.fw-hb-cta .fw-hb-cta__card::after {
	z-index: 2;
	background: radial-gradient(
		circle var(--fw-glass-highlight-size) at var(--fw-glass-highlight-x) var(--fw-glass-highlight-y),
		rgba(255, 255, 255, calc(0.30 * var(--fw-glass-highlight-opacity))) 0%,
		rgba(255, 255, 255, calc(0.15 * var(--fw-glass-highlight-opacity))) 30%,
		rgba(255, 255, 255, calc(0.05 * var(--fw-glass-highlight-opacity))) 55%,
		rgba(255, 255, 255, 0) 72%
	);
}

/* Real glass where the browser can do it: blur + saturation behind the tint,
   plus a soft inner rim glow suggesting edge refraction. */
@supports ((-webkit-backdrop-filter: blur(1px)) or (backdrop-filter: blur(1px))) {
	.fw-hb-cta .fw-hb-cta__card::before {
		background: rgba(var(--fw-glass-tint), var(--fw-glass-opacity));
		-webkit-backdrop-filter: blur(var(--fw-glass-blur)) saturate(var(--fw-glass-saturation));
		backdrop-filter: blur(var(--fw-glass-blur)) saturate(var(--fw-glass-saturation));
	}

	.fw-hb-cta .fw-hb-cta__card {
		--fw-glass-lens-glow: inset 0 0 18px -8px rgba(255, 255, 255, calc(var(--fw-glass-border-opacity) * 0.55));
	}
}

/* --------------------------------------------------------------------------
   Card internals
   -------------------------------------------------------------------------- */
.fw-hb-cta__card-top {
	display: flex;
	align-items: flex-start;
	justify-content: space-between;
	gap: 20px;
}

.fw-hb-cta__portrait {
	flex: 0 0 auto;
	display: block;
	width: 168px;
	aspect-ratio: 1 / 1;
	border-radius: 34px;
	overflow: hidden;
	background: rgba(255, 255, 255, 0.08); /* placeholder before image paints */
}

.fw-hb-cta__portrait img,
.fw-hb-cta__img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: center top;
	border-radius: inherit;
}

.fw-hb-cta__person {
	display: flex;
	flex-direction: column;
	align-items: flex-end;
	text-align: right;
	gap: 8px;
	padding-top: 14px;
	min-width: 0;
}

.fw-hb-cta__name {
	display: inline-flex;
	align-items: center;
	gap: 12px;
	color: #ffffff;
	font-family: var(--fw-font-body);
	font-size: 27px;
	font-weight: 700;
	line-height: 1.15;
	letter-spacing: -0.01em;
}

.fw-hb-cta__name .fw-hb-cta__dot {
	width: 14px;
	height: 14px;
}

.fw-hb-cta__role {
	color: rgba(255, 255, 255, 0.78);
	font-family: var(--fw-font-body);
	font-size: 19px;
	font-weight: 500;
	line-height: 1.2;
}

.fw-hb-cta__inner-btn {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	margin-top: 6px;
	padding: 9px 18px;
	background-color: #ffffff;
	color: #0b0b0f;
	border-radius: 999px;
	font-family: var(--fw-font-body);
	font-size: 15px;
	font-weight: 700;
	line-height: 1.2;
	text-decoration: none;
	white-space: nowrap;
	transition: background-color 0.25s ease, color 0.25s ease, transform 0.25s ease;
}

.fw-hb-cta__inner-btn:hover,
.fw-hb-cta__inner-btn:focus-visible {
	background-color: #ededf0;
	color: #0b0b0f;
	transform: translateY(-1px);
}

.fw-hb-cta__inner-btn:focus-visible {
	outline: 2px solid rgba(255, 255, 255, 0.85);
	outline-offset: 2px;
}

.fw-hb-cta__arrow {
	flex: 0 0 auto;
}

.fw-hb-cta__email {
	color: #ffffff;
	font-family: var(--fw-font-body);
	font-size: 27px;
	font-weight: 500;
	line-height: 1.2;
	letter-spacing: -0.01em;
	overflow-wrap: anywhere;
}

/* --------------------------------------------------------------------------
   Responsive
   The card is viewport-capped (min(…, 86vw)) so it can never overflow a small
   screen; internals scale down with it. Every device opens the card the same
   way — a click/tap handled by hero-banner.js — so touch needs no special
   case here.
   -------------------------------------------------------------------------- */
@media (max-width: 991px) {
	.fw-hb-cta .fw-hb-cta__card {
		gap: 36px;
	}
	.fw-hb-cta__portrait {
		width: 140px;
		border-radius: 28px;
	}
	.fw-hb-cta__name {
		font-size: 24px;
	}
	.fw-hb-cta__role {
		font-size: 17px;
	}
	.fw-hb-cta__email {
		font-size: 23px;
	}
}

@media (max-width: 576px) {
	.fw-hb-cta {
		--fw-hcta-card-radius: 26px;
	}
	.fw-hb-cta .fw-hb-cta__card {
		top: -10px;
		left: -10px;
		width: min(var(--fw-hcta-card-max-w), calc(100vw - 12vw));
		padding: 20px;
		gap: 26px;
		transform-origin: 70px 40px;
	}
	.fw-hb-cta__default {
		padding: 12px 24px 11px;
	}
	.fw-hb-cta__default-text {
		font-size: 16px;
		white-space: normal;
	}
	.fw-hb-cta__availability {
		font-size: 13px;
	}
	.fw-hb-cta__card-top {
		gap: 14px;
	}
	.fw-hb-cta__portrait {
		width: 104px;
		border-radius: 22px;
	}
	.fw-hb-cta__person {
		padding-top: 6px;
		gap: 6px;
	}
	.fw-hb-cta__name {
		font-size: 19px;
		gap: 8px;
	}
	.fw-hb-cta__name .fw-hb-cta__dot {
		width: 11px;
		height: 11px;
	}
	.fw-hb-cta__role {
		font-size: 14px;
	}
	.fw-hb-cta__inner-btn {
		font-size: 14px;
		padding: 8px 15px;
	}
	.fw-hb-cta__email {
		font-size: 17px;
	}
}

/* --------------------------------------------------------------------------
   Accessibility preferences (ported with the material)
   -------------------------------------------------------------------------- */

/* Higher contrast: near-solid plate, no see-through blur, strong rim. */
@media (prefers-contrast: more) {
	.fw-hb-cta .fw-hb-cta__card::before {
		background: rgba(var(--fw-glass-tint), 0.92) !important;
		-webkit-backdrop-filter: none !important;
		backdrop-filter: none !important;
		box-shadow: inset 0 0 0 1px rgba(var(--fw-glass-shadow-rgb), 0.8) !important;
	}
	.fw-hb-cta .fw-hb-cta__card::after {
		background: none !important;
	}
}

/* Reduced transparency: mostly opaque plate, light blur only. */
@media (prefers-reduced-transparency: reduce) {
	.fw-hb-cta .fw-hb-cta__card::before {
		background: rgba(var(--fw-glass-tint), 0.88) !important;
		-webkit-backdrop-filter: blur(6px) !important;
		backdrop-filter: blur(6px) !important;
	}
}

/* Reduced motion — the swap still happens, the morph does not. */
@media (prefers-reduced-motion: reduce) {
	.fw-hb-cta__default,
	.fw-hb-cta .fw-hb-cta__card,
	.fw-hb-cta.is-open .fw-hb-cta__card {
		transition: opacity 0.01s linear, visibility 0.01s linear;
		transform: none;
	}
}

/* --------------------------------------------------------------------------
   Dark theme (parent ships body.dark) — pill flips to a dark plate; the
   glass card is theme-agnostic already.
   -------------------------------------------------------------------------- */
body.dark .fw-hb-cta {
	--fw-hcta-default-bg: #14141a;
	--fw-hcta-default-border: #2a2a33;
	--fw-hcta-title: #f5f5f7;
	--fw-hcta-muted: #a6a6b0;
}
