/**
 * Theme Name:   Hello Elementor Child
 * Theme URI:    https://adaptmy.biz
 * Description:  Adapt studio site. Child of Hello Elementor.
 * Author:       Adapt
 * Template:     hello-elementor
 * Version:      1.0.0
 * Text Domain:  hello-elementor-child
 */

/* ==========================================================================
   ADAPT - SITE STYLESHEET

   Only rules that Elementor's native controls cannot express live here.
   Colour, type, spacing and simple states are set in Site Settings and on
   the widgets themselves so they stay editable.

   1.  Tokens
   2.  Base
   3.  Wordmark and opening sequence
   4.  Header
   5.  Chapter rules
   6.  Hero
   7.  Duotone media
   8.  Tags
   9.  Statistics pair
   10. Quote track and filmstrip
   11. Principles track
   12. Capability columns
   13. Inquiry section
   14. Footer
   15. Motion primitives
   16. Reduced motion and no-JS fallbacks
   ========================================================================== */


/* 1. Tokens ---------------------------------------------------------------
   Mirrors Elementor's global colours so custom rules and widget controls
   never drift apart. Change a value in Site Settings, change it here too. */

:root {
	--adapt-ground:        #0B0E13;
	--adapt-char-900:      #14181F;
	--adapt-char-800:      #1D222B;
	--adapt-char-700:      #2B2F38;
	--adapt-char-500:      #707070;
	--adapt-char-300:      #9BA1AC;
	--adapt-char-100:      #E4E6EA;
	--adapt-blue-300:      #5FC2E8;
	--adapt-blue-500:      #0095C6;
	--adapt-blue-600:      #0076BE;
	--adapt-navy:          #003486;
	--adapt-magenta-300:   #E85C8A;
	--adapt-magenta-500:   #D50049;
	--adapt-oxblood:       #7A0030;

	--adapt-ink-on-dark:      rgba(255,255,255,.78);
	--adapt-ink-on-dark-mid:  rgba(255,255,255,.62);
	--adapt-ink-on-dark-low:  rgba(255,255,255,.45);
	--adapt-rule-on-dark:     rgba(255,255,255,.14);
	--adapt-rule-on-light:    #E4E6EA;

	--adapt-gutter:        48px;
	--adapt-header-h:      84px;

	--adapt-ease:          cubic-bezier(.2,.7,.2,1);
	--adapt-fast:          200ms;
	--adapt-base:          260ms;
	--adapt-slow:          560ms;
}

@media (max-width: 1024px) { :root { --adapt-gutter: 32px; } }
@media (max-width: 767px)  { :root { --adapt-gutter: 24px; --adapt-header-h: 76px; } }


/* 2. Base ----------------------------------------------------------------- */

html { scroll-behavior: smooth; }

body {
	background: var(--adapt-ground);
	-webkit-font-smoothing: antialiased;
	-moz-osx-font-smoothing: grayscale;
	overflow-x: clip;
}

::selection { background: var(--adapt-magenta-500); color: #fff; }

/* The design is square-cornered throughout. */
.elementor-button,
.adapt-tag,
.adapt-chip,
.adapt-book__panel { border-radius: 0; }

/* Anchored sections must clear the fixed header when jumped to. */
[id] { scroll-margin-top: calc(var(--adapt-header-h) + 16px); }

/* Keyboard focus is visible on both grounds. */
a:focus-visible,
button:focus-visible,
input:focus-visible,
textarea:focus-visible {
	outline: 2px solid var(--adapt-blue-500);
	outline-offset: 3px;
}


/* 3. Wordmark and opening sequence ---------------------------------------
   The mark animates letterform by letterform, so it has to be inline SVG.
   During the opening it is a fixed, transform-positioned overlay; it then
   docks into the header slot. Only transform and opacity are animated. */

.adapt-logo { display: block; }
.adapt-logo__svg { display: block; width: 100%; height: auto; overflow: visible; }
/* Deliberately not promoted - see the note in adapt-motion.js. */
.adapt-logo__svg path,
.adapt-logo__svg rect { will-change: auto; }

/* The animating instance. */
.adapt-logo-mark {
	position: fixed;
	left: 0;
	top: 0;
	width: 62vw;
	z-index: 140;
	color: #fff;
	pointer-events: none;
	transform-origin: 0 0;
	transform: translate3d(19vw, 38vh, 0);
	opacity: 0;
	will-change: transform, opacity;
	backface-visibility: hidden;
}
.adapt-logo-mark.is-docked { pointer-events: auto; }
.adapt-logo-mark a { display: block; }

/* Reserves the docked footprint so the nav never sits under the mark.
   Must stay in step with targetW in adapt-motion.js - the slot reserves the
   space, the script sizes the mark, and they have to agree. */
.adapt-logo-slot { width: 149px; height: 65px; flex: 0 0 auto; }

/* The header row never wraps. With the primary nav hidden below 767px this
   is logo + CTA only, but the rule protects the desktop row too. */
.adapt-header,
.adapt-header > .e-con-inner { flex-wrap: nowrap; }
.adapt-cta .elementor-button { white-space: nowrap; }

/* The header button is sized against the VISIBLE wordmark, not against the
   SVG box that contains it.

   That distinction is the whole thing. The mark's viewBox is 572x250.2 but
   its ink occupies 526.2x192 inside that, so roughly a tenth of the box is
   padding nobody can see. A 120px-wide mark renders a 52px box carrying only
   40.3px of actual letterform - which is how a 47px button ended up visibly
   TALLER than the logo while the box measurements said otherwise.

   Ink height is 0.3357 x the slot width. At 149px wide that is 50px of
   wordmark against a 44px button: the mark leads by 6px, and 44 is the touch
   minimum, so the button cannot go lower without costing usability.

   Measure the ink, not the box. getBBox() on the group gives it. */
.adapt-header .adapt-cta .elementor-button {
	min-height: 44px;
	display: inline-flex;
	align-items: center;
	justify-content: center;
}

@media (max-width: 767px) {
	/* No burger below 767px: this is a one-page site and the header carries
	   the mark and one action. Section links stay in the footer menu.

	   Written here rather than left to the widget's own hide_mobile setting.
	   That setting is applied - the element does carry .elementor-hidden-mobile
	   - but the only rule for that class anywhere in Elementor's frontend CSS
	   is scoped to .elementor-background-video-container. There is no general
	   one, so on its own the setting hides nothing here. Keep both: the
	   setting so the editor shows it as hidden, this rule so it actually is. */
	.adapt-header .elementor-widget-nav-menu { display: none; }

}

/* Full-bleed cover that holds the page still while the mark draws in. */
.adapt-opening {
	position: fixed;
	inset: 0;
	/* Below the header, deliberately.

	   The wordmark is a child of the header, so it cannot paint outside the
	   header's stacking context - its own z-index of 140 only orders it
	   against its siblings, not against this cover. With the cover above the
	   header, the whole opening morph ran hidden behind it and the mark only
	   appeared as the cover faded, part-way through docking.

	   Nothing else in the header shows during the opening: the nav is at
	   opacity 0 until it is revealed, and the bar's ground only arrives past
	   50px of scroll, which cannot happen while scrolling is locked. */
	z-index: 110;
	background: var(--adapt-ground);
	transition: opacity 1100ms ease;
}
.adapt-opening__bloom {
	position: absolute;
	inset: -20%;
	background:
		radial-gradient(46% 40% at 30% 34%, rgba(0,149,198,.5) 0%, rgba(0,149,198,0) 68%),
		radial-gradient(40% 38% at 70% 62%, rgba(213,0,73,.42) 0%, rgba(213,0,73,0) 70%),
		radial-gradient(60% 60% at 50% 50%, rgba(0,52,134,.55) 0%, rgba(11,14,19,0) 74%);
	/* Static: the opening's motion is the wordmark, not the backdrop. */
}
.adapt-opening__vignette {
	position: absolute;
	inset: 0;
	background: radial-gradient(70% 60% at 50% 50%, rgba(11,14,19,0) 30%, rgba(11,14,19,.72) 100%);
}
/* The sub line resolves rather than appearing.

   Two things at once. The whole line arrives over-tracked and draws in to its
   settled spacing - a continuous settling, which is what the sentence is about.
   And the two clauses fade separately, so the pause falls on the comma, exactly
   where the meaning turns.

   The clause spans are built by adapt-motion.js, which splits the line on its
   own comma. The copy therefore stays a single editable string in Elementor
   rather than being hardcoded as markup here.

   The settled tracking is whatever the widget's own typography says: JS reads
   the computed value into --adapt-cap-track and the wide start is that plus
   9px. Nothing here assumes a value the design system might change. */
/* The sub line is out of the opening.

   It was the only reason the sequence held still after the wordmark formed,
   and that hold was most of what made the opening feel long. The line is
   hidden rather than deleted: the copy is still in the Elementor container
   so it can be moved to the hero or the footer, where it can actually be
   read rather than glimpsed for under half a second.

   The JS that splits it on its comma and drives is-in / is-out is left in
   place and costs nothing against a hidden element - so restoring the line
   is a one-line change here, not a rebuild.

   The hide itself lives with the other .e-con overrides further down, which
   is the only place it can win - see the note there. */

.adapt-opening__caption {
	position: absolute;
	left: 0;
	right: 0;
	bottom: 16vh;
	text-align: center;
	transition: opacity 700ms ease;
}
.adapt-opening__caption [data-clause] {
	opacity: 0;
	letter-spacing: calc( var( --adapt-cap-track, 0px ) + 9px );
	transition: opacity 400ms ease, letter-spacing 700ms cubic-bezier(.2,.7,.2,1);
}
.adapt-opening__caption.is-in [data-clause] {
	opacity: 1;
	letter-spacing: var( --adapt-cap-track, 0px );
}
/* The delay list follows the property list, so only the fade of the second
   clause is held back - the tracking of both still settles as one movement. */
.adapt-opening__caption.is-in [data-clause="2"] { transition-delay: 220ms, 0ms; }

/* Exit is a plain fade of the whole line, so the tracking does not spring back
   open as the mark leaves for the header. */
.adapt-opening__caption.is-out { opacity: 0; }
.adapt-opening.is-gone { opacity: 0; pointer-events: none; }


/* 4. Header ---------------------------------------------------------------
   Transparent over dark passages, frosted white over light chapters. The
   surface swap is driven by adapt-motion.js watching the sections below. */

.adapt-header {
	position: fixed;
	top: 0;
	left: 0;
	right: 0;
	/* Above Elementor Pro's sticky effect, which uses 99. */
	z-index: 120;
	height: var(--adapt-header-h);
	border-bottom: 1px solid transparent;
	transition: border-color var(--adapt-base) ease;
}

/* The bar's ground and its blur live on a pseudo-element rather than on the
   header itself.

   Both `transform` and `backdrop-filter` make an element the containing block
   for its `position: fixed` descendants - and the wordmark is a fixed
   descendant of this header. With either property set here, the mark's offsets
   resolved against the header instead of the viewport and it sat 32px low.
   A pseudo-element has its own box, so the header stays transparent to that
   and the mark keeps its viewport coordinate space. */
.adapt-header::before {
	content: '';
	position: absolute;
	inset: 0;
	z-index: -1;
	background-color: transparent;
	transition: background-color var(--adapt-base) ease,
	            backdrop-filter var(--adapt-base) ease;
}

/* The bar earns a ground as soon as the page moves, so nothing scrolls
   visibly through it. Over the dark passages that ground is the brand ground;
   over a light chapter it is the frosted white below. At rest, at the very top
   of the page, the header stays completely clear - which is the design's
   intent and the only place it can afford to be, because nothing is behind it
   there yet. */
.adapt-header.is-scrolled::before {
	background-color: rgba(11,14,19,.82);
	-webkit-backdrop-filter: saturate(140%) blur(14px);
	backdrop-filter: saturate(140%) blur(14px);
}

/* Declared after the dark state so it wins when both classes are present. */
.adapt-header.is-solid::before { background-color: rgba(255,255,255,.93); }
.adapt-header.is-solid { border-bottom-color: var(--adapt-rule-on-light); }

/* The nav fades in once the opening sequence has finished. A full-width
   Elementor container defaults to width:100%, which pushes the call to
   action past the right gutter; it has to size to its own content. */
.e-con.adapt-nav { width: auto; flex: 0 1 auto; }
.adapt-nav { opacity: 0; transition: opacity 700ms ease; }
.adapt-nav.is-revealed { opacity: 1; }

/* --- Header nav colour ---------------------------------------------------
   The nav reads over two grounds: transparent over the dark passages, and
   frosted white over the light chapters. Elementor cannot express the second
   state, so the colour settings are deliberately left off the widget and both
   states are set here. Type, spacing and the mobile dropdown are still
   Elementor's - only colour lives in this block. */

.adapt-nav .elementor-nav-menu--main .elementor-item {
	color: rgba(255,255,255,.62);
	fill: rgba(255,255,255,.62);
	transition: color var(--adapt-fast) ease;
}
.adapt-nav .elementor-nav-menu--main .elementor-item:hover,
.adapt-nav .elementor-nav-menu--main .elementor-item:focus,
.adapt-nav .elementor-nav-menu--main .elementor-item.elementor-item-active {
	color: #fff;
	fill: #fff;
}

.adapt-header.is-solid .adapt-nav .elementor-nav-menu--main .elementor-item {
	color: var(--adapt-char-500);
	fill: var(--adapt-char-500);
}
.adapt-header.is-solid .adapt-nav .elementor-nav-menu--main .elementor-item:hover,
.adapt-header.is-solid .adapt-nav .elementor-nav-menu--main .elementor-item:focus,
.adapt-header.is-solid .adapt-nav .elementor-nav-menu--main .elementor-item.elementor-item-active {
	color: var(--adapt-char-900);
	fill: var(--adapt-char-900);
}

.adapt-header.is-solid .adapt-nav .elementor-menu-toggle { color: var(--adapt-char-900); }

/* --- The outlined call to action ----------------------------------------
   Hairline stroke, an accent fill that wipes in from the left, and an arrow
   that steps forward. Applied by adding `adapt-cta` to any button widget. */

.adapt-cta .elementor-button {
	position: relative;
	overflow: hidden;
	isolation: isolate;
	background: transparent;
	transition: border-color 220ms ease, color 220ms ease;
}
.adapt-cta .elementor-button::before {
	content: '';
	position: absolute;
	inset: 0;
	z-index: -1;
	background: var(--adapt-blue-500);
	transform: scaleX(0);
	transform-origin: left center;
	transition: transform 320ms var(--adapt-ease);
}
.adapt-cta .elementor-button:hover::before,
.adapt-cta .elementor-button:focus-visible::before { transform: scaleX(1); }

.adapt-cta .elementor-button-content-wrapper { position: relative; }
.adapt-cta .elementor-button-text::after {
	content: '\2192';
	display: inline-block;
	margin-left: 10px;
	font-size: 1.15em;
	transition: transform 320ms var(--adapt-ease);
}
.adapt-cta .elementor-button:hover .elementor-button-text::after,
.adapt-cta .elementor-button:focus-visible .elementor-button-text::after { transform: translateX(4px); }

/* No arrow on the header CTA.

   Scoped to the header on purpose: .adapt-cta is shared with the footer
   button, which keeps its arrow - there is room for it there and it is the
   page's closing action. In the bar the glyph widened the button enough to
   pull attention off the wordmark, which should lead. */
.adapt-header .adapt-cta .elementor-button-text::after { content: none; }

/* Light-ground variant, used when the header is frosted. */
.adapt-header.is-solid .adapt-cta .elementor-button {
	color: var(--adapt-char-900);
	border-color: var(--adapt-rule-on-light);
}
.adapt-header.is-solid .adapt-cta .elementor-button:hover { color: #fff; }


/* 5. Chapter rules --------------------------------------------------------
   The numbered dividers that open each chapter. */

.adapt-chapter {
	border-bottom: 1px solid var(--adapt-rule-on-light);
}
.adapt-chapter--dark { border-bottom-color: var(--adapt-rule-on-dark); }


/* 6. Hero -----------------------------------------------------------------
   Layered gradient fields behind the headline. Purely decorative, so the
   whole stack is inert to pointer events and hidden from assistive tech. */

.adapt-hero { position: relative; overflow: hidden; }

.adapt-hero__field {
	position: absolute;
	inset: 0;
	overflow: clip;
	pointer-events: none;
	isolation: isolate;
	contain: paint;
	transform: translateZ(0);
}
.adapt-hero__field > * { position: absolute; }

.adapt-hero__aurora {
	inset: -15%;
	background:
		radial-gradient(40% 36% at 26% 30%, rgba(0,149,198,.4) 0%, rgba(0,149,198,0) 70%),
		radial-gradient(36% 34% at 76% 68%, rgba(213,0,73,.32) 0%, rgba(213,0,73,0) 72%),
		radial-gradient(60% 60% at 50% 46%, rgba(0,52,134,.44) 0%, rgba(11,14,19,0) 76%);
	/* Static: full-screen, and its drift was imperceptible. */
}
.adapt-hero__orb--blue {
	left: -8%; top: -18%; width: 62vw; height: 62vw;
	background: radial-gradient(circle at 38% 36%, rgba(0,149,198,.5) 0%, rgba(0,52,134,.34) 46%, rgba(0,52,134,0) 74%);
	opacity: .85;
	animation: adaptShift1 15s ease-in-out infinite;
}
.adapt-hero__orb--magenta {
	right: -14%; bottom: -24%; width: 58vw; height: 58vw;
	background: radial-gradient(circle at 56% 48%, rgba(213,0,73,.42) 0%, rgba(122,0,48,.28) 48%, rgba(122,0,48,0) 76%);
	opacity: .8;
	animation: adaptShift2 19s ease-in-out infinite;
}
.adapt-hero__orb--pale {
	left: 34%; top: 22%; width: 34vw; height: 34vw;
	background: radial-gradient(circle at 50% 50%, rgba(95,194,232,.3) 0%, rgba(95,194,232,0) 70%);
	opacity: .75;
	animation: adaptShift1 11s ease-in-out infinite reverse;
}

/* --- Hero light field ----------------------------------------------------
   One WebGL canvas carrying the whole arc motif.

   A canvas is a single compositing layer whatever happens inside it, so the
   per-pixel lighting, bloom and drift cost nothing beyond this one texture -
   around 27MB at a 1728px viewport. That is the whole reason this can be rich
   and cheap at the same time: only area costs, never complexity.

   The static SVG below is the fallback for browsers without WebGL, and stands
   down the moment the canvas takes over. */

.adapt-hero__light {
	inset: 0;
	width: 100%;
	height: 100%;
	display: block;
	opacity: 0;
	transition: opacity 1400ms ease;
}
.adapt-hero__light.is-live { opacity: 1; }
.adapt-hero__field.has-light-field .adapt-hero__flow { display: none; }



/* Concentric arc segments on one shared centre - the wordmark's own
   geometry, recomposed. Paths are generated by adapt-motion.js. */
.adapt-hero__flow {
	inset: -8%;
	width: 116%;
	height: 116%;
	overflow: hidden;
	/* Static: rotating this cost 69MB, because a rotated layer must cover
	   the box the element sweeps, not the box it occupies. */
}
.adapt-hero__flow path { opacity: 0; transition: opacity 1200ms ease; }

/* Keeps the headline readable over the light field.

   Two layers: a soft wedge that holds the left third down, where the type
   sits, so an arc can burn as brightly as it likes on the open right side
   without crossing the reading line; and the original vignette to stop the
   field running out of the corners. The type never sits on a bright ground,
   which is the rule the design sets. */
.adapt-hero__scrim {
	position: absolute;
	inset: 0;
	pointer-events: none;
	background:
		linear-gradient(102deg,
			rgba(11,14,19,.88) 0%,
			rgba(11,14,19,.72) 26%,
			rgba(11,14,19,.34) 46%,
			rgba(11,14,19,0) 66%),
		radial-gradient(78% 72% at 40% 46%,
			rgba(11,14,19,0) 24%,
			rgba(11,14,19,.34) 78%,
			rgba(11,14,19,.66) 100%);
}

@media (max-width: 767px) {
	/* On a narrow screen the type spans the full width, so the wedge becomes
	   a straight veil. The first version started at 55% opacity at the very
	   top, which crushed the field everywhere - including the empty upper
	   half where the light is the whole point. It now stays clear until the
	   halfway mark and only closes over the reading line, which on a phone
	   begins at about 62%. The type still never sits on a bright ground. */
	.adapt-hero__scrim {
		background:
			linear-gradient(180deg,
				rgba(11,14,19,0)   0%,
				rgba(11,14,19,.06) 34%,
				rgba(11,14,19,.28) 54%,
				rgba(11,14,19,.72) 70%,
				rgba(11,14,19,.90) 100%);
	}
}

.adapt-scroll-cue__line {
	display: block;
	width: 1px;
	height: 44px;
	margin: 0 auto;
	background: linear-gradient(180deg, rgba(255,255,255,.5), rgba(255,255,255,0));
	animation: adaptCue 2.6s ease-in-out infinite;
}


/* 7. Duotone media --------------------------------------------------------
   The studio's signature photo treatment: desaturate, then lay a blue to
   magenta gradient over the top in `color` blend mode. Add `adapt-duotone`
   plus one variant class to any image widget or container. */

.adapt-duotone { position: relative; isolation: isolate; overflow: hidden; }
.adapt-duotone img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
	filter: grayscale(1) contrast(1.08);
}
.adapt-duotone::after {
	content: '';
	position: absolute;
	inset: 0;
	background: var(--adapt-duo, linear-gradient(165deg, #0095C6 0%, #D50049 100%));
	mix-blend-mode: color;
	opacity: .92;
	pointer-events: none;
}

.adapt-duotone--blue-magenta  { --adapt-duo: linear-gradient(165deg, #0095C6 0%, #D50049 100%); }
.adapt-duotone--navy-blue     { --adapt-duo: linear-gradient(165deg, #003486 0%, #0095C6 100%); }
.adapt-duotone--magenta-navy  { --adapt-duo: linear-gradient(165deg, #D50049 0%, #003486 100%); }
.adapt-duotone--blue-oxblood  { --adapt-duo: linear-gradient(165deg, #0095C6 0%, #7A0030 100%); }
.adapt-duotone--navy-magenta  { --adapt-duo: linear-gradient(165deg, #003486 0%, #D50049 100%); }
.adapt-duotone--charcoal-blue { --adapt-duo: linear-gradient(165deg, #14181F 0%, #0095C6 100%); }
.adapt-duotone--blue-navy     { --adapt-duo: linear-gradient(160deg, #0095C6 0%, #003486 100%); }
.adapt-duotone--navy-deep     { --adapt-duo: linear-gradient(150deg, #003486 0%, #0095C6 100%); }
.adapt-duotone--magenta-ox    { --adapt-duo: linear-gradient(160deg, #D50049 0%, #7A0030 100%); }
.adapt-duotone--navy-charcoal { --adapt-duo: linear-gradient(150deg, #003486 0%, #14181F 100%); }
.adapt-duotone--triad         { --adapt-duo: linear-gradient(140deg, #14181F 0%, #003486 60%, #D50049 100%); }

/* Fade to the ground colour, so an image can sit directly above dark type. */
.adapt-duotone--foot::before {
	content: '';
	position: absolute;
	inset: 0;
	z-index: 1;
	background: linear-gradient(180deg, rgba(11,14,19,0) 40%, rgba(11,14,19,.5) 100%);
	pointer-events: none;
}

.adapt-duotone--portrait { aspect-ratio: 4 / 5; background: var(--adapt-char-900); }


/* 8. Tags -----------------------------------------------------------------
   Square hairline pills. Used for partner names and project scope. */

.adapt-tags { display: flex; flex-wrap: wrap; gap: 10px; }
.adapt-tag {
	display: inline-block;
	font: 400 13px/1.2 'Inter', sans-serif;
	letter-spacing: .02em;
	color: var(--adapt-char-900);
	border: 1px solid var(--adapt-rule-on-light);
	padding: 8px 14px;
}
.adapt-tag--dark {
	font-size: 10px;
	letter-spacing: .16em;
	text-transform: uppercase;
	color: rgba(255,255,255,.8);
	border-color: rgba(255,255,255,.32);
	padding: 6px 10px;
}


/* 9. Statistics pair ------------------------------------------------------
   Two cells sharing a single hairline, achieved with a 1px grid gap over a
   coloured ground rather than borders that would double up. */

.adapt-stats {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: 1px;
	background: var(--adapt-rule-on-light);
}
.adapt-stats > * { background: #fff; }


/* 10. Quote track and filmstrip ------------------------------------------
   A tall track whose inner stage is pinned for its duration. Plates travel
   right to left as the track scrolls, each at its own rate, and the quote
   assembles word by word on top. */

.adapt-quote-track { position: relative; height: 320vh; background: var(--adapt-ground); }
.adapt-quote-stage { position: sticky; top: 0; height: 100vh; overflow: hidden; }

.adapt-filmstrip {
	position: absolute;
	left: 0;
	top: 50%;
	display: flex;
	align-items: center;
	gap: 5vw;
	padding: 0 34vw;
	transform: translateY(-50%);
}
.adapt-plate {
	position: relative;
	flex: 0 0 auto;
	width: 30vw;
	margin: 0;
}
.adapt-plate img { filter: grayscale(1) contrast(1.08) brightness(.72); }
.adapt-plate figcaption {
	position: absolute;
	left: 0;
	bottom: -30px;
	font: 400 10px/1.4 'Inter', sans-serif;
	letter-spacing: .22em;
	text-transform: uppercase;
	color: rgba(255,255,255,.42);
}

.adapt-quote-scrim {
	position: absolute;
	inset: 0;
	pointer-events: none;
	background: radial-gradient(58% 52% at 50% 50%, rgba(11,14,19,.94) 0%, rgba(11,14,19,.72) 46%, rgba(11,14,19,.4) 100%);
}

.adapt-quote {
	position: absolute;
	inset: 0;
	display: grid;
	place-items: center;
	pointer-events: none;
	text-align: center;
}
.adapt-quote__inner { max-width: 1100px; padding: 0 8vw; }
.adapt-quote__line { display: block; opacity: 0; }
.adapt-quote__word {
	display: inline-block;
	opacity: 0;
}
.adapt-quote__word + .adapt-quote__word { margin-left: .28em; }
.adapt-quote__rule {
	display: block;
	height: 1px;
	width: 0;
	margin: 40px auto 0;
	background: linear-gradient(90deg, rgba(255,255,255,0), rgba(255,255,255,.75), rgba(255,255,255,0));
}


/* 11. Principles track ----------------------------------------------------
   Five scenes cross-fading behind five headlines, pinned for the length of
   the track. Scroll position picks the scene; nothing is hijacked. */

.adapt-principles { position: relative; height: 520vh; background: var(--adapt-ground); }
.adapt-principles__stage { position: sticky; top: 0; height: 100vh; overflow: hidden; }

.adapt-scene {
	position: absolute;
	inset: 0;
	opacity: 0;
	transition: opacity 700ms ease;
}
.adapt-scene.is-active { opacity: 1; }
.adapt-scene img { transform: scale(1.06); filter: grayscale(1) contrast(1.1) brightness(.5); }
.adapt-scene::before {
	content: '';
	position: absolute;
	inset: 0;
	z-index: 2;
	background: linear-gradient(90deg, rgba(11,14,19,.9) 0%, rgba(11,14,19,.44) 55%, rgba(11,14,19,.72) 100%);
}

.adapt-principles__body { position: relative; height: 100%; }
.adapt-principle {
	position: absolute;
	top: 0;
	left: 0;
	right: 0;
	opacity: 0;
	transform: translateY(22px);
	transition: opacity 500ms ease, transform 700ms var(--adapt-ease);
}
.adapt-principle.is-active { opacity: 1; transform: translateY(0); }
.adapt-principle:first-child { position: relative; }

.adapt-principle-ticks { display: flex; flex-direction: column; gap: 14px; align-items: flex-end; }
.adapt-principle-tick {
	font: 500 11px/1.4 'Inter', sans-serif;
	letter-spacing: .18em;
	text-transform: uppercase;
	color: rgba(255,255,255,.34);
	transition: color 400ms ease;
}
/* Elementor sets each tick's colour at (0,3,0) via its own heading rule, so
   the active state has to be written against the heading title to win. */
.adapt-principles .adapt-principle-tick.is-active .elementor-heading-title {
	color: #fff;
	transition: color 400ms ease;
}

.adapt-principle-rail {
	position: relative;
	width: 1px;
	height: 120px;
	margin-top: 8px;
	background: rgba(255,255,255,.16);
}
.adapt-principle-rail__bar {
	position: absolute;
	left: 0;
	top: 0;
	width: 1px;
	height: 0;
	background: #fff;
}


/* 12. Capability columns --------------------------------------------------
   Six flex columns with vertical labels. The focused column grows and its
   project panel cross-fades in. Driven by flex-grow, so no layout property
   jumps and keyboard focus works the same as hover. */

.adapt-caps { display: flex; border: 1px solid var(--adapt-rule-on-light); border-right: 0; }

.adapt-cap {
	position: relative;
	flex: 1 1 0;
	height: 520px;
	min-width: 64px;
	background: #fff;
	border: 0;
	border-right: 1px solid var(--adapt-rule-on-light);
	padding: 0;
	font: inherit;
	color: inherit;
	cursor: pointer;
	overflow: hidden;
	transition: flex-grow var(--adapt-slow) var(--adapt-ease);
}
.adapt-cap.is-open { flex-grow: 6.2; }

.adapt-cap__label {
	position: absolute;
	inset: 0;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: space-between;
	padding: 22px 0;
	transition: opacity var(--adapt-base) ease;
}
.adapt-cap.is-open .adapt-cap__label { opacity: 0; }

.adapt-cap__index { font: 400 10px/1 'Inter', sans-serif; letter-spacing: .2em; color: var(--adapt-char-300); }
.adapt-cap__name {
	writing-mode: vertical-rl;
	transform: rotate(180deg);
	font: 500 12px/1 'Inter', sans-serif;
	letter-spacing: .22em;
	text-transform: uppercase;
	color: var(--adapt-char-900);
	white-space: nowrap;
}
.adapt-cap__plus { font-size: 13px; color: var(--adapt-char-300); }

.adapt-cap__panel {
	position: absolute;
	inset: 0;
	opacity: 0;
	transition: opacity 380ms ease;
}
.adapt-cap.is-open .adapt-cap__panel { opacity: 1; }
.adapt-cap__panel::before {
	content: '';
	position: absolute;
	inset: 0;
	z-index: 2;
	background: linear-gradient(180deg, rgba(11,14,19,.68) 0%, rgba(11,14,19,.24) 30%, rgba(11,14,19,.3) 46%, rgba(11,14,19,.92) 100%);
}
.adapt-cap__meta,
.adapt-cap__body { position: absolute; z-index: 3; left: 0; right: 0; }
.adapt-cap__meta {
	top: 0;
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: 16px;
	padding: 22px 26px;
	font: 400 10px/1.4 'Inter', sans-serif;
	letter-spacing: .2em;
	text-transform: uppercase;
	color: rgba(255,255,255,.72);
	white-space: nowrap;
}
.adapt-cap__year { color: rgba(255,255,255,.56); }
.adapt-cap__body { bottom: 0; padding: 26px; text-align: left; min-width: 34vw; }
.adapt-cap__client {
	display: block;
	font: 700 11px/1.4 'Inter', sans-serif;
	letter-spacing: .2em;
	text-transform: uppercase;
	color: #fff;
	margin-bottom: 12px;
}
.adapt-cap__claim {
	display: block;
	font: 600 24px/1.3 'Shippori Mincho', serif;
	letter-spacing: -.015em;
	color: #fff;
	max-width: 520px;
	text-wrap: pretty;
}
.adapt-cap__body .adapt-tags { margin-top: 18px; }


/* 13. Inquiry section -----------------------------------------------------
   Elementor Pro form on a translucent charcoal panel. Fields are underline
   only; the discipline chips are a styled checkbox group. */

.adapt-book { position: relative; overflow: hidden; }
.adapt-book__field { position: absolute; inset: 0; overflow: clip; pointer-events: none; }
.adapt-book__bloom {
	position: absolute;
	inset: -30% -10%;
	background:
		radial-gradient(38% 44% at 14% 18%, rgba(0,52,134,.62) 0%, rgba(0,52,134,0) 68%),
		radial-gradient(34% 40% at 88% 26%, rgba(0,149,198,.34) 0%, rgba(0,149,198,0) 70%),
		radial-gradient(46% 44% at 62% 104%, rgba(213,0,73,.32) 0%, rgba(213,0,73,0) 72%);
	/* Static: full-screen, and it sits behind a form. */
}
.adapt-book__scrim {
	position: absolute;
	inset: 0;
	background: linear-gradient(180deg, rgba(11,14,19,.55) 0%, rgba(11,14,19,.25) 40%, rgba(11,14,19,.8) 100%);
}
/* The ground for the inquiry section is the wordmark's own geometry: a single
   bowl - the same form the opening sequence turns into every other letter -
   at about the height of the section, cropped by the left edge. It replaced a
   set of evenly spaced vertical hairlines, which were the one thing on the
   page that could have belonged to any studio.

   Carried by the signal gradient rather than a flat tint, so the shape shifts
   blue to crimson across its own diagonal exactly as the mark does. It sits
   above the scrim - at this opacity anything below it disappears entirely. */
.adapt-book__mark {
	position: absolute;
	top: 50%;
	left: 0;
	height: 78%;
	width: auto;
	aspect-ratio: 1 / 1;
	/* Only a sliver is cropped. The first crop hid both the counter and the
	   square corner, which left an anonymous dark circle - and the bowl's right
	   edge landed as a hard vertical band, close to the very thing this
	   replaced. The form has to be legible as the letterform to be worth it. */
	/* Two units on purpose: the percentage is of the bowl's own width, so the
	   proportion of it that stays in frame holds at any size; the vw is a flat
	   nudge further off the left edge that does not scale with the shape. */
	transform: translate(calc(-18% - 6.5vw), -50%);
	opacity: .075;
}

/* Filled, deliberately.

   An outline version was tried and looked better in a compressed screenshot,
   which turned out to say more about the screenshot than the design: at 7.5%
   opacity on a near-black ground the fill spans six to eight steps of 8-bit
   value, and JPEG quantisation flattens precisely that range. On a real
   display it reads as intended. Judge this one in the browser, not from a
   capture.

   To see the outline instead: fill none, stroke url(#adapt-book-grad),
   stroke-width 1.4, vector-effect non-scaling-stroke, and opacity about .45. */

/* Narrow screens stack the copy over the form, so the mark drops back and
   sits lower, well clear of the reading line. */
@media (max-width: 767px) {
	.adapt-book__mark {
		top: 62%;
		height: 58%;
		transform: translate(-22%, -50%);
		opacity: .06;
	}
}
.adapt-book__seam {
	position: absolute;
	left: 0;
	right: 0;
	top: 0;
	height: 1px;
	background: linear-gradient(90deg, rgba(0,149,198,0) 0%, rgba(0,149,198,.7) 30%, rgba(213,0,73,.7) 70%, rgba(213,0,73,0) 100%);
}

.adapt-book__panel {
	background: linear-gradient(160deg, rgba(29,34,43,.94) 0%, rgba(20,24,31,.9) 100%);
	-webkit-backdrop-filter: blur(10px);
	backdrop-filter: blur(10px);
	border: 1px solid rgba(255,255,255,.16);
	box-shadow: 0 32px 80px rgba(0,0,0,.45);
}

/* --- Form fields --------------------------------------------------------- */

.adapt-form .elementor-field-group { margin-bottom: 4px; }

.adapt-form .elementor-field-group > label {
	font: 500 10px/1.4 'Inter', sans-serif !important;
	letter-spacing: .2em;
	text-transform: uppercase;
	color: rgba(255,255,255,.45);
	margin-bottom: 8px;
}

/* Elementor has no focus control for form fields, and its own field rule is
   more specific than anything a stylesheet can reasonably write, so the focus
   underline is the one place this file needs !important. */
.adapt-form .elementor-field-group .elementor-field-textual:focus {
	border-bottom-color: var(--adapt-blue-500) !important;
	box-shadow: none !important;
	outline: none;
}
.adapt-form .elementor-field-textual::placeholder { color: rgba(255,255,255,.34); }
.adapt-form textarea.elementor-field-textual { resize: none; }
.adapt-form .elementor-field-group { margin-bottom: 4px; }

/* --- Discipline chips ----------------------------------------------------
   A checkbox group rendered as square toggles. The native input stays in the
   DOM for accessibility and is visually replaced by its label.

   Note: Elementor puts a field's CSS class on `.elementor-field-subgroup`
   itself, not on a wrapper around it, so `adapt-chips` is matched on that
   element rather than as an ancestor. */

.elementor-field-subgroup.adapt-chips {
	display: flex;
	flex-wrap: wrap;
	gap: 10px;
	margin-bottom: 14px;
}
.elementor-field-subgroup.adapt-chips .elementor-field-option {
	position: relative;
	width: auto;
	flex: 0 0 auto;
}
.elementor-field-subgroup.adapt-chips input[type="checkbox"] {
	position: absolute;
	inset: 0;
	opacity: 0;
	width: 100%;
	height: 100%;
	margin: 0;
	cursor: pointer;
}
.elementor-field-subgroup.adapt-chips input[type="checkbox"] + label {
	display: block;
	border: 1px solid rgba(255,255,255,.24);
	background: transparent;
	color: rgba(255,255,255,.75);
	font: 400 13px/1.2 'Inter', sans-serif;
	letter-spacing: .02em;
	padding: 12px 17px;
	cursor: pointer;
	transition: background-color var(--adapt-fast) ease,
	            border-color var(--adapt-fast) ease,
	            color var(--adapt-fast) ease;
}
.elementor-field-subgroup.adapt-chips input[type="checkbox"]:hover + label {
	border-color: rgba(255,255,255,.5);
	color: #fff;
}
.elementor-field-subgroup.adapt-chips input[type="checkbox"]:checked + label {
	background: var(--adapt-blue-500);
	border-color: var(--adapt-blue-500);
	color: #fff;
}
.elementor-field-subgroup.adapt-chips input[type="checkbox"]:focus-visible + label {
	outline: 2px solid var(--adapt-blue-500);
	outline-offset: 3px;
}

/* --- Submit, messages ---------------------------------------------------- */

.adapt-form .elementor-message {
	font: 400 13px/1.6 'Inter', sans-serif;
	margin-top: 14px;
}
.adapt-form .elementor-message-danger { color: var(--adapt-magenta-300); }
.adapt-form .elementor-message-success { color: var(--adapt-blue-300); }


/* 14. Footer -------------------------------------------------------------- */

.adapt-footer { border-top: 1px solid var(--adapt-rule-on-dark); }
.adapt-footer .elementor-nav-menu a {
	font: 500 11px/1.4 'Inter', sans-serif;
	letter-spacing: .16em;
	text-transform: uppercase;
	color: rgba(255,255,255,.4);
	transition: color var(--adapt-fast) ease;
}
.adapt-footer .elementor-nav-menu a:hover { color: #fff; }

.adapt-underline a,
a.adapt-underline {
	color: #fff;
	border-bottom: 1px solid rgba(255,255,255,.35);
	transition: border-color var(--adapt-fast) ease;
}
.adapt-underline a:hover,
a.adapt-underline:hover { border-bottom-color: #fff; }


/* 15. Motion primitives ---------------------------------------------------
   Every keyframe animates transform, opacity or a filter only. */

@keyframes adaptCue {
	0%   { transform: translateY(0);   opacity: .25; }
	50%  { transform: translateY(9px); opacity: 1; }
	100% { transform: translateY(0);   opacity: .25; }
}
@keyframes adaptBloom {
	0%   { transform: translate3d(0,0,0); }
	50%  { transform: translate3d(5%,-4%,0); }
	100% { transform: translate3d(0,0,0); }
}
@keyframes adaptShift1 {
	0%   { transform: translate3d(-5%,3%,0); }
	33%  { transform: translate3d(7%,-6%,0); }
	66%  { transform: translate3d(-3%,7%,0); }
	100% { transform: translate3d(-5%,3%,0); }
}
@keyframes adaptShift2 {
	0%   { transform: translate3d(4%,-3%,0); }
	40%  { transform: translate3d(-8%,6%,0); }
	75%  { transform: translate3d(5%,5%,0); }
	100% { transform: translate3d(4%,-3%,0); }
}
@keyframes adaptSpin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }


/* 16. Reduced motion and no-JS fallbacks ---------------------------------
   Nothing here is load-bearing for content: if the script never runs, every
   pinned or faded element resolves to its visible state. */

html:not(.adapt-js) .adapt-opening { display: none; }
html:not(.adapt-js) .adapt-logo-mark {
	position: absolute;
	width: 104px;
	opacity: 1;
	transform: translate3d(var(--adapt-gutter), 19px, 0);
}
html:not(.adapt-js) .adapt-nav { opacity: 1; }
html:not(.adapt-js) .adapt-quote__line,
html:not(.adapt-js) .adapt-quote__word,
html:not(.adapt-js) .adapt-principle { opacity: 1; transform: none; }
html:not(.adapt-js) .adapt-quote__rule { width: 100%; }
html:not(.adapt-js) .adapt-quote-track,
html:not(.adapt-js) .adapt-principles { height: auto; }
html:not(.adapt-js) .adapt-quote-stage,
html:not(.adapt-js) .adapt-principles__stage { position: static; height: auto; padding: 14vh 0; }
html:not(.adapt-js) .adapt-quote { position: static; }
html:not(.adapt-js) .adapt-filmstrip { position: static; transform: none; overflow-x: auto; padding: 0 var(--adapt-gutter) 40px; }
html:not(.adapt-js) .adapt-principle { position: static; margin-bottom: 10vh; }
html:not(.adapt-js) .adapt-scene:first-of-type { opacity: 1; }
html:not(.adapt-js) .adapt-principle-ticks { display: none; }
html:not(.adapt-js) .adapt-cap:first-of-type { flex-grow: 6.2; }
html:not(.adapt-js) .adapt-cap:first-of-type .adapt-cap__panel { opacity: 1; }
html:not(.adapt-js) .adapt-cap:first-of-type .adapt-cap__label { opacity: 0; }

@media (prefers-reduced-motion: reduce) {

	html { scroll-behavior: auto; }

	*, *::before, *::after {
		animation-duration: .01ms !important;
		animation-iteration-count: 1 !important;
		transition-duration: .01ms !important;
	}

	/* Both scroll tracks collapse to a single static screen. */
	.adapt-quote-track,
	.adapt-principles { height: auto; }
	.adapt-quote-stage,
	.adapt-principles__stage { position: static; height: auto; }

	.adapt-quote { position: static; padding: 18vh 0; }
	.adapt-quote__line,
	.adapt-quote__word { opacity: 1 !important; transform: none !important; filter: none !important; }
	.adapt-quote__rule { width: 100% !important; }
	.adapt-filmstrip { display: none; }

	.adapt-principles__stage { padding: 12vh 0; }
	.adapt-principle {
		position: static !important;
		opacity: 1 !important;
		transform: none !important;
		margin-bottom: 12vh;
	}
	.adapt-scene { display: none; }
	.adapt-principle-ticks { display: none; }
}


/* --- Responsive ----------------------------------------------------------
   Tracks unpin and stack; the capability row becomes a vertical accordion. */

@media (max-width: 1024px) {

	.adapt-cap { height: 420px; }
	.adapt-cap.is-open { flex-grow: 4.4; }
	.adapt-cap__body { min-width: 46vw; padding: 20px; }
	.adapt-cap__claim { font-size: 19px; }

	.adapt-plate { width: 44vw; }
	.adapt-filmstrip { padding: 0 28vw; }
}

@media (max-width: 767px) {

	.adapt-logo-mark { width: 78vw; }

	/* Pinned tracks are a desktop affordance. On touch they read as a stack. */
	.adapt-quote-track { height: auto; }
	.adapt-quote-stage { position: static; height: auto; padding: 14vh 0; }
	.adapt-quote { position: static; }
	.adapt-quote__line,
	.adapt-quote__word { opacity: 1 !important; transform: none !important; filter: none !important; }
	.adapt-quote__rule { width: 60% !important; }

	.adapt-filmstrip {
		position: static;
		transform: none;
		padding: 0 var(--adapt-gutter) 40px;
		gap: 16px;
		overflow-x: auto;
		-webkit-overflow-scrolling: touch;
		scroll-snap-type: x mandatory;
		margin-bottom: 8vh;
	}
	.adapt-plate {
		width: 72vw;
		height: 46vh !important;
		transform: none !important;
		scroll-snap-align: center;
	}
	.adapt-plate figcaption { bottom: -24px; }

	/* Section 02 becomes full-height panels that snap. The structural rules are
	   in the .e-con block below - these two only undo the desktop cross-fade,
	   since every panel is now permanently visible and it is the scene behind
	   them that changes. */
	.adapt-principles { height: auto; }
	.adapt-principle { opacity: 1 !important; transform: none !important; }
	.adapt-principle-ticks { display: none; }
	.adapt-scene { position: fixed; }

	/* Section 03 becomes a carousel below 767px. The structural rules live in
	   the Elementor override block further down, qualified with .e-con so they
	   actually win - see the note there. Only the contents are handled here. */
	.adapt-cap__label { opacity: 0; }
	.adapt-cap__panel { opacity: 1; }
	.adapt-cap__body { min-width: 0; }
	.adapt-cap__meta { white-space: normal; }
}

/* --- Elementor integration ----------------------------------------------
   A handful of rules that let Elementor's wrappers carry the design's
   layered decoration without adding markup of their own. */

/* Decorative field widgets are full-bleed and inert. */
.adapt-hero__field,
.adapt-book__field,
.adapt-quote-scrim,
.adapt-hero__scrim { z-index: 0; }
/* The inquiry section is a boxed container, so Elementor caps its inner
   wrapper at the 1320px content width - and an absolutely positioned child
   resolves against that wrapper, not the section. That left the decorative
   field (the bloom, the scrim, the vertical grid lines and the seam along the
   top) stopping at the content edges with bare ground either side.

   Leaving the wrapper unpositioned hands the field back to the section, which
   is full width. The content still paints above the field without needing a
   z-index: the field is the first child in document order and carries none of
   its own. */
.adapt-book > .e-con-inner { position: static; }

/* The HTML widget is used only for decoration and for the two structures
   Elementor has no widget for. It should never introduce spacing. */
.adapt-decor,
.adapt-decor .elementor-widget-container { position: static; margin: 0; padding: 0; }

/* Image widgets inside a duotone frame fill it completely. */
.adapt-duotone .elementor-widget-image,
.adapt-duotone .elementor-widget-container,
.adapt-duotone figure { position: absolute; inset: 0; margin: 0; height: 100%; }

/* Containers that exist purely to be positioned by the stylesheet. */
.adapt-logo-mark > .e-con-inner,
.adapt-opening > .e-con-inner { display: block; height: 100%; }

/* Text widget paragraphs inherit their spacing from the container gap. */
.adapt-prose p { margin: 0 0 22px; }
.adapt-prose p:last-child { margin-bottom: 0; }



/* --- Positioning over Elementor's container defaults ---------------------
   Elementor sets `position: relative; display: flex; flex: ...` on every
   `.e-con`. The pinned tracks and layered panels have to win that at equal
   specificity, so the handful of structural properties are restated
   qualified by `.e-con`. Nothing here is a style choice - it is only
   structure, and the order below is deliberate: general first, specific
   last, because several elements carry more than one of these classes.
   (A duotone scene is both `.adapt-scene` and `.adapt-duotone`.) */

/* 1. General */
.e-con.adapt-duotone { position: relative; display: block; }

/* 2. Fixed chrome */
.e-con.adapt-opening { position: fixed; }
.e-con.adapt-logo-mark { position: fixed; display: block; }
.adapt-logo-mark .elementor-widget-shortcode,
.adapt-logo-mark .elementor-widget-container,
.adapt-logo-mark .adapt-logo { display: block; width: 100%; }
.e-con.adapt-header    { position: fixed; display: flex; }
/* The opening's sub line is retired: this is the single line that hides it,
   and the single line that would bring it back (display: block).

   It has to be here rather than beside the other caption rules, because this
   block loads last and carries the .e-con qualifier. A hide written further
   up - qualified or not - is silently outranked by this very rule. */
.e-con.adapt-opening__caption { position: absolute; display: none; }

/* 3. Pinned tracks */
.e-con.adapt-quote-stage,
.e-con.adapt-principles__stage { position: sticky; }

/* 4. Filmstrip */
.e-con.adapt-filmstrip {
	position: absolute;
	display: flex;
	gap: 5vw;
	padding: 0 34vw;
}
.e-con.adapt-quote__inner { padding: 0 8vw; }
.e-con.adapt-plate     { position: relative; flex: 0 0 auto; overflow: visible; }
.e-con.adapt-plate > .adapt-duotone { position: absolute; inset: 0; }
.adapt-plate__caption  { position: absolute; left: 0; bottom: -30px; z-index: 2; }

/* 5. Quote */
.e-con.adapt-quote { position: absolute; display: grid; place-items: center; }

/* 6. Principles */
.e-con.adapt-principles__body,
.e-con.adapt-principles__deck { position: relative; }
.e-con.adapt-principles__body { height: 100%; }
.e-con.adapt-principles__body > .e-con-inner { height: 100%; }
.e-con.adapt-principle { position: absolute; }
.e-con.adapt-principle:first-child { position: relative; }
.e-con.adapt-scene { position: absolute; display: block; }

/* 7. Capability columns */
.e-con.adapt-caps { display: flex; }
.e-con.adapt-cap  { position: relative; overflow: hidden; flex: 1 1 0; }
.e-con.adapt-cap.is-open { flex-grow: 6.2; }
.e-con.adapt-cap__label  { position: absolute; }
.e-con.adapt-cap__panel  { position: absolute; display: block; }
.e-con.adapt-cap__panel > .adapt-duotone { position: absolute; inset: 0; }

/* 8. Widget wrappers must not box in the decoration they carry. */
.adapt-decor,
.adapt-decor > .elementor-widget-container { position: static; margin: 0; padding: 0; }


/* --- Responsive and reduced-motion overrides of the above ---------------- */

@media (max-width: 1024px) {
	.e-con.adapt-cap.is-open { flex-grow: 4.4; }
}

@media (max-width: 767px) {
	.e-con.adapt-quote-stage,
	.e-con.adapt-principles__stage,
	.e-con.adapt-filmstrip,
	.e-con.adapt-quote { position: static; }

	/* Section 02: one principle per screen, snapped.

	   The desktop track pins a stage for 520vh and reads scroll position to
	   pick a scene. That whole path is off below 767px - readPrinciples returns
	   early for COMPACT - which left the principles as a plain stack with every
	   scene still at opacity 0. Nothing to look at and nothing to do.

	   Each principle is now its own viewport-height panel and an observer in
	   adapt-motion.js pairs whichever panel is on screen with its scene, using
	   the same index pairing the desktop path uses.

	   Snap is `proximity`, not `mandatory`, and it sits on the document rather
	   than on a nested scroller. Mandatory would drag the rest of the page
	   toward these four snap points from anywhere; a nested scroller would trap
	   the gesture. Proximity only engages when a panel is already close.

	   svh, not vh: on a phone vh is the LARGE viewport, so a 100vh panel sits
	   partly behind the browser chrome and the snap point lands off-screen. */
	html { scroll-snap-type: y proximity; }
	.e-con.adapt-principles__stage { height: auto; padding: 0; overflow: visible; }
	.e-con.adapt-principles__body { height: auto; }
	.e-con.adapt-principle,
	.e-con.adapt-principle:first-child {
		/* Positioned so the panels paint above the fixed scenes behind them. */
		position: relative;
		z-index: 2;
		min-height: 100vh;
		min-height: 100svh;
		display: flex;
		flex-direction: column;
		justify-content: center;
		margin: 0;
		padding: 0 var(--adapt-gutter);
		scroll-snap-align: center;
	}
	/* Section 03 is a contained carousel on mobile.

	   The stacking rules earlier in this file never took effect. Elementor's
	   own `.e-con { flex-direction: var(--flex-direction) }` carries the same
	   specificity as a bare `.adapt-caps { flex-direction: column }` and loads
	   after it, so the row stayed a row. Six columns at min-width 64px need
	   384px; a phone's content box is about 342px. That 40-odd px of overflow
	   was scrolling the entire page sideways.

	   Scrolling the cards is the wanted behaviour anyway, and it matches the
	   filmstrip in section 02. overscroll-behavior-x keeps the gesture in the
	   carousel instead of chaining out to the document. */
	.e-con.adapt-caps {
		flex-direction: row;
		overflow-x: auto;
		-webkit-overflow-scrolling: touch;
		scroll-snap-type: x mandatory;
		overscroll-behavior-x: contain;
		border-right: 1px solid var(--adapt-rule-on-light);
	}
	.e-con.adapt-cap,
	.e-con.adapt-cap.is-open {
		flex: 0 0 78%;
		height: 420px;
		scroll-snap-align: center;
	}
	.e-con.adapt-filmstrip { gap: 16px; padding: 0 24px 40px; }
	.e-con.adapt-quote__inner { padding: 0 24px; }
}

@media (prefers-reduced-motion: reduce) {
	.e-con.adapt-quote-stage,
	.e-con.adapt-principles__stage,
	.e-con.adapt-quote,
	.e-con.adapt-principle,
	.e-con.adapt-principle:first-child { position: static; }
	.e-con.adapt-filmstrip { display: none; }
}

html:not(.adapt-js) .e-con.adapt-opening { display: none; }
html:not(.adapt-js) .e-con.adapt-quote-stage,
html:not(.adapt-js) .e-con.adapt-principles__stage,
html:not(.adapt-js) .e-con.adapt-quote,
html:not(.adapt-js) .e-con.adapt-filmstrip,
html:not(.adapt-js) .e-con.adapt-principle,
html:not(.adapt-js) .e-con.adapt-principle:first-child { position: static; }

/* --- Admin bar offset ----------------------------------------------------
   Only ever applies to a logged-in editor; the public site is unaffected. */

.admin-bar .e-con.adapt-header,
.admin-bar .e-con.adapt-logo-mark,
.admin-bar .e-con.adapt-opening { top: 32px; }

@media (max-width: 782px) {
	.admin-bar .e-con.adapt-header,
	.admin-bar .e-con.adapt-logo-mark,
	.admin-bar .e-con.adapt-opening { top: 46px; }
}

/* Elementor writes its stock page-transition colour into the kit whether or
   not the feature is enabled. Nothing off-palette should ship. */
.elementor-kit-9 e-page-transition { background-color: #0B0E13; }


/* --- Scoped compositing -------------------------------------------------
   `will-change` is a promise that something is about to animate, not a
   general speed-up. Left on permanently it pins a texture in GPU memory for
   the life of the page - and for a rotated element the layer has to cover the
   rotated bounding box, which is far larger than the element looks.

   Measured on a 1728px viewport this file was asking the compositor for about
   850MB across 27 layers, which is well past what Chrome will keep resident.
   It evicts and re-rasterises, and that churn is what shows up as flicker on
   a large desktop display. A phone never hit it because every one of these
   elements is sized in viewport units and so is a fraction of the area.

   So: promote only what is animating, only while it is on screen. The
   scroller adds `is-live` to a track as it enters the viewport. */

.adapt-quote-track.is-live .adapt-filmstrip,
.adapt-quote-track.is-live .adapt-plate { will-change: transform; }
.adapt-quote-track.is-live .adapt-quote__word,
.adapt-quote-track.is-live .adapt-quote__line { will-change: transform, opacity; }

.adapt-principles.is-live .adapt-scene,
.adapt-principles.is-live .adapt-principle { will-change: opacity; }

/* --- Idle decoration -----------------------------------------------------
   The gradient fields are decorative and run forever. There is no reason for
   the inquiry section's field to be animating while it is several thousand
   pixels below the fold - a running animation holds its compositing layer
   resident whether or not anyone can see it. Pausing lets Chrome release it.
   adapt-motion.js toggles this class with an IntersectionObserver. */

.adapt-field-idle,
.adapt-field-idle * { animation-play-state: paused; }