/******* Do not edit this file *******
Simple Custom CSS and JS - by Silkypress.com
Saved: Oct 28 2026 | 09:29:15 */
/* ==========================================================================
   SITE STYLESHEET
   Impreza / WPBakery. Paste into Simple Custom CSS and JS as one CSS snippet.
   All px values assume this site's 1rem = 30px.
   --------------------------------------------------------------------------
   CONTENTS — search for the number to jump
     1.0   UTILITIES
       1.1   Text sizes
       1.2   Small blue text
       1.3   Outline text
       1.4   Text fill
		 1.4.1  Owl Dots
       1.5   White button
       1.6   Heading 1-6
     2.0   MOTION
       2.1   Entrances
       2.2   Exits
       2.3   Entrance modifiers
       2.4   Trigger and timelines
       2.5   Rows
       2.6   Hover
       2.7   Continuous
       2.8   Keyframes
       2.9   Snap motion
         2.9.1  row-in-snap — two columns meeting in the middle
         2.9.2  heading-in-snap-left / -right — one column
         2.9.3  row-in-bg — background photo wooshes up
         2.9.4  The clip
         2.9.5  Keyframes
         2.9.6  Reduced motion
     3.0   ARROW BUTTONS
       3.1   Tokens
       3.2   Direction
       3.3   The button
       3.4   Sizes and variants
       3.5   The stage (.arrow-group)
     4.0   HEADER
       4.1   Mega menu
         4.1.1  Menu item title rule
		 4.1.2  Footer Menu item title rule
       4.2   Header search
     5.0   COMPONENTS
       5.1   Media stage
       5.2   Split band
         5.2.1  Split band, inset variant
       5.3   Feature band
         5.3.1  Feature band, alt variant
       5.4   Capabilities cards
       5.5   Capability carousel
       5.6   Direction switcher
       5.7   Sector cards
       5.8   Sector specialisms
       5.9   Component gallery
       5.10  News cards
         5.10.1 News cards, landscape variant
       5.11  Testimonial cards
         5.11.1 Testimonial carousel
       5.12  Supplier band
       5.13  Accordion
       5.14  Text overlap
       5.15  Full-bleed image
     16.0  TEAM CARD
     17.0  NEWS SECTION
       17.1  News filters
       17.2  News hero (individual)
     --    WHY CARDS, LEGACY (unnumbered, superseded by 20.4)
     18.0  MOBILE OPTIMISATION
       18.1  Global guards
       18.2  Text size utilities
       18.3  Hero
       18.4  Sector cards
       18.6  Capabilities row
       18.7  Testimonials
       18.8  Footer
       18.5  Sector overview intro band   (sits after 18.8 in the file)
       18.9  Home hero
       18.10 Text fill, fixed-width copy block
       18.11 Direction switcher, multi-box panel
       18.12 Capability carousel
       18.13 Media stage, title
       18.14 Hero stage
       18.15 Media stage, toggle
     19.0  CAPABILITIES OVERVIEW — MOBILE
       19.1  Section gutters
       19.2  Hero margin
       19.3  copy-panel
       19.4  panel-arrow
       19.5  stack-row
       19.6  fluid-media
       19.7  flush-on-mobile
       19.8  Split band, mobile stack
       19.9  media-first
     --    MEGA MENU, NO INTERNAL SCROLL (unnumbered, after 19.9)
     20.0  CAREERS PAGE
       20.1  Tokens and shared type
         20.1.1 Tokens
         20.1.2 Section rhythm
         20.1.3 Section headings
       20.2  Hero
       20.3  Intro
       20.4  Why cards
         20.4.1 The lift maths
         20.4.2 The section
         20.4.3 The row
         20.4.4 The card
         20.4.5 Number and copy
         20.4.6 Hover photo
         20.4.7 Carousel (1200px and below)
       20.5  Why CTA — arrow and hover panel
         20.5.1 Position
         20.5.2 The arrow
         20.5.3 The panel
         20.5.4 The reveal
         20.5.5 Tablet, touch and mobile
       20.6  Story cards — employee stories and apprenticeships
         20.6.1 Section settings
         20.6.2 The row
         20.6.3 The card
         20.6.4 Photo and shade
         20.6.5 Role, arrow and name
         20.6.6 Bio
         20.6.7 Open state
         20.6.8 Carousel (900px and below)
         20.6.9 Carousel controls
       20.7  Current vacancies (Post List)
       20.8  Testimonials
       20.9  Supplier band
       20.10 White button size variants (fix)
       20.11 Reduced motion
       20.12 Footer at tablet size (site-wide)
     21.0  VACANCY PAGE
       21.1  Tokens and section rhythm
       21.2  Layout — role panel and sidebar
       21.3  Role panel
       21.4  Apply card (Forminator)
       21.5  Other vacancies
       21.6  Header between laptop and tablet (site-wide)
       21.7  Reduced motion
     22.0  CONTACT PAGE
       22.1  Tokens
       22.2  Hero section
       22.3  Layout — intro and form card
       22.4  Intro column
       22.5  Form card (Forminator)
       22.6  Map
       22.7  Reduced motion
     23.0  ABOUT PAGE
       23.1  Tokens and section rhythm
       23.2  Hero
       23.3  Intro
       23.4  Credentials (the four icon boxes)
       23.5  (removed: Our direction is back on 5.6 / 18.11)
       23.6  Meet the team: photo and blue band
       23.7  Team strip (1024px and below)
         23.7.1 Which list shows where
         23.7.2 The strip
         23.7.3 The card
         23.7.4 Photo and shade
         23.7.5 Role, arrow, name and LinkedIn
         23.7.6 Bio
         23.7.7 Open state
         23.7.8 Controls
       23.8  A little history
       23.9  Reduced motion
     24.0  SECTOR PAGE
       24.1  Hero badge
   --------------------------------------------------------------------------
   JS SNIPPETS THIS FILE PAIRS WITH
     heading-in / row-in trigger   2.4, and everything in 2.9
     woosh-in-left / right         2.1
     text-fill (Safari fallback)   1.4
     HEADER SEARCH                 4.2
     MOBILE MENU (close on anchor) 4.1
     MEDIA STAGE                   5.1
     CAPABILITY CAROUSEL           5.5
     DIRECTION SWITCHER            5.6
     SECTOR CARDS                  5.7
     SECTOR SPECIALISMS            5.8
     TESTIMONIAL CARDS             5.11.1
     WHY CARDS                     20.4.7
     STORY CARDS                   20.6
     TEAM STRIP                    23.7
     CONTACT FORM LABELS           22.5
   --------------------------------------------------------------------------
   THREE RULES THAT COME UP REPEATEDLY IN THIS FILE
   1. overflow: clip, never hidden. hidden creates a scroll container, which
      pins any scroll-driven animation inside it at 0%. clip crops identically
      without creating one.
   2. Repeated classes, never !important. Impreza's own rules load after this
      file, so equal weight loses on order alone. A class written twice is
      (0,2,0), three times (0,3,0), and so on — enough to clear the theme
      without blocking the transitions an !important would kill.
   3. translate / scale / rotate as individual properties where a transform is
      already in play. They compose; two transform declarations overwrite.
   --------------------------------------------------------------------------
   FILE ORDER IS LOAD-BEARING FROM 18.0 ONWARDS
   Several rules from 18.0 down beat earlier ones on ORDER rather than
   specificity — the text-size utilities in 1.1 and the responsive blocks
   inside 5.4 / 5.7 are the same selectors at the same weight. Anything
   appended after 18.0 needs to know that, and anything inserted BEFORE it
   must not reuse those selectors.
   ========================================================================== */

/* ==========================================================================
   1.0  UTILITIES
   REPLACES the whole of the previous 1.0, from its header down to the end
   of 1.6. What changed:
     1.5    new white-button-grey variant (About #5)
     1.7    NEW  spec type scale (Site Wide #16, #17, #18)
     1.8    NEW  paragraph spacing (Site Wide #10)
   1.1–1.4.1, the rest of 1.5, and 1.6 are unchanged.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1.1  TEXT SIZES
   One class per step. !important because these are meant to beat whatever
   the element arrived with from Design Options — that is the entire job.
   -------------------------------------------------------------------------- */
.xs-text   { font-size: 15px !important; }
.s-text    { font-size: 20px !important; }
.m-text    { font-size: 35px !important; }
.l-text    { font-size: 40px !important; }
.xl-text   { font-size: 75px !important; }
.xxl-text  { font-size: 90px !important; }
.xxxl-text { font-size: 180px !important; }

/* --------------------------------------------------------------------------
   1.2  SMALL BLUE TEXT
   The blue standfirst that sits above a heading in the split and feature
   bands. line-height matches the font size on purpose — it is always a
   single line, and the tight box keeps it close to the heading below.
   Deliberately NOT moved to the 32px spec. That spec is the blue intro copy
   BELOW a heading (.t-h3 in 1.7). This is the kicker above one, and the
   arrow offsets in 5.2 are measured against its current height.
   -------------------------------------------------------------------------- */
.small-blue-text {
    margin: 0;
    padding-right: 28px;
    font-size: 18px;
    font-weight: 400;
    line-height: 18px;
    letter-spacing: .01em;
    color: var(--color-blue);
}

/* --------------------------------------------------------------------------
   1.3  OUTLINE TEXT
   Hollow letterforms — the fill comes off and a stroke is drawn in its
   place. Add `outline-text` to a Text element's extra class field.
   -webkit-text-stroke, not the standard `text-stroke`. The unprefixed
   property still isn't implemented anywhere; the prefixed one is supported
   in every current browser including Firefox, so this is one of the rare
   cases where the vendor prefix is the real property rather than a legacy
   fallback.
   The stroke is drawn CENTRED on the glyph's edge, not outside it, so half
   of it eats into the letterform. That is why heavy weights survive this and
   light ones don't — at 300 weight a 2px stroke closes up the thin strokes
   entirely. The design uses a bold face for that reason.
   Colour is set on -webkit-text-fill-color, not `color`, because `color` is
   what -webkit-text-stroke-color falls back to when unset — zeroing one
   would take the other with it.
   -------------------------------------------------------------------------- */
.outline-text {
    --ot-stroke: 2px;
    --ot-ink:    #fff;
    --ot-fill:   transparent;
    -webkit-text-fill-color: var(--ot-fill);
    -webkit-text-stroke: var(--ot-stroke) var(--ot-ink);
}

/* The theme colours .w-text-h and any heading tag directly, and
   -webkit-text-fill-color beats `color` — but the STROKE colour still has to
   reach the inner element, or a nested h2 draws its stroke in the theme's
   colour while the parent's is ignored. */
.outline-text :is(.w-text-h, .w-text-value, h1, h2, h3, h4, h5, h6, p, span) {
    -webkit-text-fill-color: var(--ot-fill);
    -webkit-text-stroke: var(--ot-stroke) var(--ot-ink);
}

/* Thickness variants. The stroke does not scale with the font, so a value
   that looks right at 90px is invisible at 30px and clogged at 180px. */
.outline-text-thin.outline-text-thin   { --ot-stroke: 1px; }
.outline-text-thick.outline-text-thick { --ot-stroke: 3px; }

/* Filled on hover, for a link or heading that reacts. Add
   `outline-text-fill` alongside. */
.no-touch .outline-text-fill:hover,
.no-touch .outline-text-fill:hover :is(.w-text-h, .w-text-value, h1, h2, h3, h4, h5, h6, p, span) {
    --ot-fill: var(--ot-ink);
    transition: -webkit-text-fill-color .3s ease;
}

/* --------------------------------------------------------------------------
   1.4  TEXT FILL
   Copy sits dim and a band of white sweeps through it. Add to the text
   block's extra class field:
     text-fill          fills top to bottom, in reading order
     text-fill-across   fills left to right
     text-fill-load     runs once on load instead of on scroll
   WHY THIS TARGETS .wpb_wrapper AND NOT THE BLOCK ITSELF
   Impreza's design options write a background on .wpb_text_column with
   !important. Matching that with our own !important looks like it works —
   the gradient appears — but !important author declarations outrank
   animations in the cascade, so the keyframes can no longer move
   background-position and the fill freezes at frame zero.
   The inner .wpb_wrapper carries none of that, so the whole effect sits
   there instead and needs no !important anywhere. Nothing to override,
   nothing to freeze.
   The @supports guard matters: background-clip is what makes the text
   visible at all here, since the text itself is transparent. Without the
   guard, a browser that lacked it would render nothing.
   -------------------------------------------------------------------------- */
@supports ((-webkit-background-clip: text) or (background-clip: text)) {
    @media (prefers-reduced-motion: no-preference) {
        [class*="text-fill"] .wpb_wrapper {
            --tf-dim: #4a4a4a;      /* resting colour                        */
            --tf-lit: #ffffff;      /* filled colour                         */
            --tf-softness: 33%;     /* width of the blend, as a share of the
                                       sweep                                 */
            background-image: linear-gradient(
                180deg,
                var(--tf-lit) 0 var(--tf-softness),
                var(--tf-dim) calc(100% - var(--tf-softness)) 100%
            );
            background-size: 100% 300%;
            background-position: 0 100%;
            background-repeat: no-repeat;
            -webkit-background-clip: text;
            background-clip: text;
            color: transparent;
            animation: text-fill 1200ms linear both;
            animation-timeline: view();
            /* Starts once the block is a fifth of the way into the viewport,
               finishes as it reaches the middle. Tied to entry at both ends
               it completes down near the fold, long before the text is at
               reading height. */
            animation-range: entry 20% cover 50%;
        }

        /* The paragraph inherits a colour of its own from the block above,
           and inheritance loses to any declaration, so no !important here
           either. */
        [class*="text-fill"] .wpb_wrapper * {
            color: transparent;
        }

        .text-fill-across .wpb_wrapper {
            background-image: linear-gradient(
                90deg,
                var(--tf-lit) 0 var(--tf-softness),
                var(--tf-dim) calc(100% - var(--tf-softness)) 100%
            );
            background-size: 300% 100%;
            background-position: 100% 0;
        }

        .text-fill-load .wpb_wrapper {
            animation: text-fill 2000ms cubic-bezier(.4, 0, .3, 1) 300ms both;
            animation-timeline: auto;
            animation-range: normal;
        }
    }
}

/* view() attaches to the nearest ancestor scroll container, and
   overflow:hidden creates one — a scroll container whose position never
   changes, which pins the timeline at 0%. overflow:clip crops identically but
   is NOT a scroll container, so the timeline passes through it to the page
   scroll. */
@supports (animation-timeline: view()) {
    .l-section:has([class*="text-fill"]),
    .l-section-h:has([class*="text-fill"]),
    .vc_row:has([class*="text-fill"]),
    .wpb_column:has([class*="text-fill"]),
    .vc_column-inner:has([class*="text-fill"]) {
        overflow: clip;
    }
}

/* Safari and anything else without scroll-driven animation: the fill is held
   back until a class arrives, added by the companion JS snippet when the
   block enters the viewport. Browsers with animation-timeline never reach
   this. */
@supports not (animation-timeline: view()) {
    @media (prefers-reduced-motion: no-preference) {
        [class*="text-fill"] .wpb_wrapper {
            animation: none;
        }

        [class*="text-fill"].is-filling .wpb_wrapper {
            animation: text-fill 1600ms cubic-bezier(.4, 0, .3, 1) both;
        }
    }
}

@keyframes text-fill {
    to { background-position: 0 0; }
}

/* --------------------------------------------------------------------------
1.4.1  Owl Dots
---------------------------------------------------------------------------*/

.dotstyle_circle .owl-dot span {
    display: block;
    border-radius: 50%;
    background: white;
    width: 15px;
    height: 15px;
    margin: 6px;
    opacity: .33;
}

.dotstyle_circle .owl-dot.active span {
    background: var(--color-blue) !important;
    box-shadow: 0 0 0 2px var(--color-content-primary);
    opacity: 1;
}

/* --------------------------------------------------------------------------
   1.5  WHITE BUTTON
   A white outline pill that fills blue and widens on hover.
   --------------------------------------------------------------------------
   EDITOR SETUP
   Theme Options → Buttons → the style you want → extra class:
       white-button
   That one class is the whole hook. Any button on that style is a white
   button and needs nothing in its own extra-class field.
   Add `white-button-right` on an individual button to push it to the right
   edge of its container, for layouts where the wrapper has no align option.
   Add `white-button-alt` for the solid white fill, or `white-button-grey`
   for white with grey text — see the end of this section.
   --------------------------------------------------------------------------
   WHY FOUR REPEATS
   Impreza styles buttons at .us-btn-style_* (0,1,0) and
   .no-touch .us-btn-style_*:hover (0,2,0). If the style you attach this to
   ALSO carries arrow-btn — as us-btn-style_5 currently does — then the
   chains in 3.3 apply too, at (0,3,0) and (0,4,0). Four repeats here and
   five on hover clear the worst case; on a style with no arrow-btn they are
   simply more than needed, which costs nothing.
   Repeats do NOT clear Impreza's !important colour — see the note on the
   color declaration below.
   --------------------------------------------------------------------------
   THE WIDTH ANIMATES VIA PADDING
   `width: fit-content` has no numeric value to interpolate from, so a width
   transition would snap rather than glide. The inline padding is what grows,
   which produces the same movement and is the only property here that isn't
   composited — the button reflows each frame. Fine on a box this size; don't
   copy the approach onto anything with static siblings that would relayout
   with it.
   -------------------------------------------------------------------------- */
.white-button.white-button.white-button.white-button {
	--wb-ink: #fff;
	--wb-bg: transparent;
	--wb-border-color: var(--wb-ink);
	--wb-bg-hover: var(--color-blue, #00bfff);
	--wb-ink-hover: #000;
	--wb-pad-y: 0.7em;
	--wb-pad-x: 1.6em;
	--wb-pad-x-hover: 2.6em;
	--wb-border: 3px;
	--wb-radius: 999px;
	--wb-speed: .3s;
	--wb-ease: cubic-bezier(.22, .68, .3, 1);
	display: inline-flex;
	align-items: center;
	justify-content: center;
	inline-size: auto;
	block-size: auto;
	min-inline-size: 0;
	min-block-size: 0;
	max-inline-size: 100%;
	width: fit-content;
	padding: var(--wb-pad-y) var(--wb-pad-x);
	background: var(--wb-bg);
	border: var(--wb-border) solid var(--wb-border-color);
	border-radius: var(--wb-radius);
	box-shadow: none;
	/* !important, and it has to be. Impreza writes color:#fff !important on
	   .us-btn-style_*, which no amount of repeated selectors can outrank.
	   Without this the resting label is always Impreza's white — invisible
	   while --wb-ink is also white, and the reason white-button-alt's black
	   ink never appeared. */
	color: var(--wb-ink) !important;
	/* Not rem. :root sets --font-size: 30px on this site, so 1rem is 30px and
	   any rem value here comes out oversized. The size utilities in 1.1 are
	   !important, so .xs-text and friends still override this per button. */
	font-size: 16px;
	font-weight: 500;
	line-height: 1.2;
	letter-spacing: 0;
	text-transform: none;
	text-decoration: none;
	white-space: nowrap;
	overflow: visible;
	transition:
		padding var(--wb-speed) var(--wb-ease),
		background-color var(--wb-speed) ease,
		border-color var(--wb-speed) ease,
		color var(--wb-speed) ease;
}

/* If the style carries arrow-btn, these are its glyph and ring. Harmless
   where there is no arrow button. */
.white-button.white-button.white-button.white-button::before,
.white-button.white-button.white-button.white-button::after {
	content: none;
	display: none;
}

/* arrow-btn slides the label sideways on hover to clear its glyph. With the
   glyph gone that would read as a jitter. Also restores the label's own font
   size, which arrow-btn zeroes to hide it. */
.white-button.white-button.white-button.white-button .w-btn-label {
	display: inline-block;
	font-size: inherit;
	line-height: inherit;
	transform: none;
	translate: none;
}

/* Same !important story as the base colour, against Impreza's :hover rule.
   This chain is (0,5,0) to the base's (0,4,0), so between two !important
   declarations this one still wins. */
.no-touch .white-button.white-button.white-button.white-button:hover,
.white-button.white-button.white-button.white-button:focus-visible {
	padding-left: var(--wb-pad-x-hover);
	padding-right: var(--wb-pad-x-hover);
	background: var(--wb-bg-hover);
	border-color: var(--wb-bg-hover);
	color: var(--wb-ink-hover) !important;
	box-shadow: none;
}

/* arrow-btn offsets its focus ring to clear the ring pseudo-element, which
   no longer exists here. */
.white-button.white-button.white-button.white-button:focus-visible {
	outline: 2px solid var(--wb-ink);
	outline-offset: 3px;
}

/* arrow-btn's :active scale reads as a press on a 64px square; on a wide
   pill it reads as the button slipping sideways. */
.white-button.white-button.white-button.white-button:active {
	transform: none;
}

/* --- solid variant -------------------------------------------------------
   White fill, black label. Same blue hover as the outline version, so the
   two can sit side by side and react identically.
   --------------------------------------------------------------------------
   WHY --wb-border-color EXISTS
   The base rule used to draw its border in --wb-ink, which is also the label
   colour. That works while the two are the same, but here the label goes
   black and a black hairline round a white pill is not the intent. The
   border now reads its own token, defaulting to --wb-ink so nothing changes
   for the outline version.
   The border stays at 1px rather than 0 so the pill keeps the same outer
   dimensions as its outline sibling — a 0-width border would make this
   button 2px shorter and narrower than one sitting next to it.
   --------------------------------------------------------------------------
   Five repeats, one more than the base at (0,4,0). Custom properties cascade
   normally, so this is enough for the tokens — but note the tokens were
   never the problem with the black label. That was Impreza's !important
   colour on the base, now matched with !important there.
   The focus outline is restated because it reads --wb-ink, which is now
   black, and black on white is the wrong contrast against a page that is
   itself dark — it wants the blue.
   ------------------------------------------------------------------------- */
.white-button-alt.white-button-alt.white-button-alt.white-button-alt.white-button-alt {
	--wb-ink: #000;
	--wb-bg: #fff;
	--wb-border-color: #fff;
}

.white-button-alt.white-button-alt.white-button-alt.white-button-alt.white-button-alt:focus-visible {
	outline: 2px solid var(--wb-bg-hover);
	outline-offset: 3px;
}

/* --- grey variant (About #5) --------------------------------------------
   The XD button: white fill with grey text, turning grey with blue text on
   hover. Add `white-button-grey` to the button's extra class, on a style
   that already carries white-button.
   Same weight and reasoning as the solid variant above. Only the tokens
   change; the base and hover rules read them, so the padding widen and the
   transitions are inherited unchanged.
   The border follows the hover fill (the base hover rule sets border-color
   to --wb-bg-hover), so the pill never shows a white hairline round a grey
   fill.
   --------------------------------------------------------------------------
   SIZE
   15px up on the base button's 16px. The padding is in em, so the whole
   pill scales with it; --wb-grey-size is the one number to change. Steps
   down at 900px and 600px so it doesn't swamp a phone.
   The 1.1 size utilities are !important and still override this if one is
   added to the button.
   ------------------------------------------------------------------------- */
.white-button-grey.white-button-grey.white-button-grey.white-button-grey.white-button-grey {
	--wb-grey-size: 31px;
	--wb-ink: var(--color-dark-grey, #333);
	--wb-bg: #fff;
	--wb-border-color: #fff;
	--wb-bg-hover: var(--color-dark-grey, #333);
	--wb-ink-hover: var(--color-blue, #00bfff);
	font-size: var(--wb-grey-size);
}

@media (max-width: 900px) {
	.white-button-grey.white-button-grey.white-button-grey.white-button-grey.white-button-grey {
		--wb-grey-size: 24px;
	}
}

@media (max-width: 600px) {
	.white-button-grey.white-button-grey.white-button-grey.white-button-grey.white-button-grey {
		--wb-grey-size: 19px;
	}
}

.white-button-grey.white-button-grey.white-button-grey.white-button-grey.white-button-grey:focus-visible {
	outline: 2px solid var(--color-blue, #00bfff);
	outline-offset: 3px;
}

/* --- size variants ------------------------------------------------------
   Padding is in em, so the font size moves the whole pill and the two
   padding values only control the space around the label.
   These are (0,2,0) and lose to the base; 20.10 restates them at a weight
   that wins. Left here so the definitions sit together.
   ------------------------------------------------------------------------- */
.white-button-sm.white-button-sm { --wb-pad-y: 0.5em; --wb-pad-x: 1.15em; --wb-pad-x-hover: 1.9em; font-size: 14px; }
.white-button-lg.white-button-lg { --wb-pad-y: 0.85em; --wb-pad-x: 2em;   --wb-pad-x-hover: 3.2em; font-size: 18px; }

/* Right-aligned in a plain block container, where there is no flex parent
   for align-self to act on. */
.white-button-right.white-button-right {
	display: flex;
	margin-left: auto;
	margin-right: 0;
}

/* --- reduced motion ----------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
	.white-button.white-button.white-button.white-button {
		--wb-pad-x-hover: var(--wb-pad-x);
		transition-duration: 1ms;
	}
}

.rollover-button-footer:hover .w-btn-label {
	display: none !important;
}

.rollover-button-footer:hover::before {
	content: "Discuss your project" !important;
	position: static !important;
	inset: auto !important;
	transform: none !important;
	display: inline-block !important;
	width: auto !important;
	height: auto !important;
	margin: 0 !important;
	padding: 0 !important;
	border: 0 !important;
	border-radius: 0 !important;
	box-shadow: none !important;
	outline: none !important;
	background: none !important;
	font: inherit !important;
	color: inherit !important;
	opacity: 1 !important;
	visibility: visible !important;
	transition: none !important;
}

/* --------------------------------------------------------------------------
   1.6  Heading 1-6
  	Heading class that allows for the styling of a different heading
   -------------------------------------------------------------------------- */

/* Heading-1 typography applied to any element */
.heading-1:is(h1, h2, h3, h4, h6),
.wpb_text_column.heading-1 :is(h2, h3, h4, h5, h6),
.w-iconbox.heading-1 .w-iconbox-title {
    font-family: var(--h1-font-family, inherit);
    font-size: var(--h1-font-size, inherit);
    font-weight: var(--h1-font-weight, inherit);
    font-style: var(--h1-font-style, inherit);
    line-height: var(--h1-line-height, 1.4);
    letter-spacing: var(--h1-letter-spacing, inherit);
    text-transform: var(--h1-text-transform, inherit);
    margin-bottom: var(--h1-margin-bottom, 1.5rem);
	color: var(--h1-color, inherit);
}

/* Heading-2 typography applied to any element */
.heading-2:is(h1, h2, h3, h4, h6),
.wpb_text_column.heading-2 :is(h1, h3, h4, h5, h6),
.w-iconbox.heading-2 .w-iconbox-title {
    font-family: var(--h2-font-family, inherit);
    font-size: var(--h2-font-size, inherit);
    font-weight: var(--h2-font-weight, inherit);
    font-style: var(--h2-font-style, inherit);
    line-height: var(--h2-line-height, 1.4);
    letter-spacing: var(--h2-letter-spacing, inherit);
    text-transform: var(--h2-text-transform, inherit);
    margin-bottom: var(--h2-margin-bottom, 1.5rem);
	color: var(--h2-color, inherit);
}

/* Heading-3 typography applied to any element */
.heading-3:is(h1, h2, h3, h4, h6),
.wpb_text_column.heading-3 :is(h1, h2, h4, h5, h6),
.w-iconbox.heading-3 .w-iconbox-title {
    font-family: var(--h3-font-family, inherit);
    font-size: var(--h3-font-size, inherit);
    font-weight: var(--h3-font-weight, inherit);
    font-style: var(--h3-font-style, inherit);
    line-height: var(--h3-line-height, 1.4);
    letter-spacing: var(--h3-letter-spacing, inherit);
    text-transform: var(--h3-text-transform, inherit);
    margin-bottom: var(--h3-margin-bottom, 1.5rem);
	color: var(--h3-color, inherit);
}

/* Heading-4 typography applied to any element */
.heading-4:is(h1, h2, h3, h4, h6),
.wpb_text_column.heading-4 :is(h1, h2, h3, h5, h6),
.w-iconbox.heading-4 .w-iconbox-title {
    font-family: var(--h4-font-family, inherit);
    font-size: var(--h4-font-size, inherit);
    font-weight: var(--h4-font-weight, inherit);
    font-style: var(--h4-font-style, inherit);
    line-height: var(--h4-line-height, 1.4);
    letter-spacing: var(--h4-letter-spacing, inherit);
    text-transform: var(--h4-text-transform, inherit);
    margin-bottom: var(--h4-margin-bottom, 1.5rem);
	color: var(--h4-color, inherit);
}

/* Heading-5 typography applied to any element */
.heading-5:is(h1, h2, h3, h4, h6),
.wpb_text_column.heading-5 :is(h1, h2, h3, h4, h6),
.w-iconbox.heading-5 .w-iconbox-title {
    font-family: var(--h5-font-family, inherit);
    font-size: var(--h5-font-size, inherit);
    font-weight: var(--h5-font-weight, inherit);
    font-style: var(--h5-font-style, inherit);
    line-height: var(--h5-line-height, 1.4);
    letter-spacing: var(--h5-letter-spacing, inherit);
    text-transform: var(--h5-text-transform, inherit);
    margin-bottom: var(--h5-margin-bottom, 1.5rem);
	color: var(--h5-color, inherit);
}

/* Heading-6 typography applied to any element */
.heading-6:is(h1, h2, h3, h4, h6),
.wpb_text_column.heading-6 :is(h1, h2, h3, h4, h5),
.w-iconbox.heading-6 .w-iconbox-title {
    font-family: var(--h6-font-family, inherit);
    font-size: var(--h6-font-size, inherit);
    font-weight: var(--h6-font-weight, inherit);
    font-style: var(--h6-font-style, inherit);
    line-height: var(--h6-line-height, 1.4);
    letter-spacing: var(--h6-letter-spacing, inherit);
    text-transform: var(--h6-text-transform, inherit);
    margin-bottom: var(--h6-margin-bottom, 1.5rem);
	color: var(--h6-color, inherit);
}

/* --------------------------------------------------------------------------
   1.7  SPEC TYPE SCALE
   The XD type scale as classes, for Site Wide #16, #17 and #18. Glow's
   sizes are in px despite being written as pt.
       t-h1        60 / 78   weight pending (see below)
       t-display   60 / 78   extralight   — the white copy under a blue
                                             subheading (#17, About #7)
       t-h2        48 / 58   extralight   para spacing 40
       t-h3        32 / 40   regular      para spacing 20
       t-h4        24 / 32   regular
       t-body      24 / 32   regular      para spacing 20
       t-small     20 / 28   regular      dates, team roles
   Modifiers, stack freely:
       t-extralight t-light t-regular t-semibold t-bold t-extrabold
       t-blue t-white
   e.g. the About intro lead (48 light, blue) is:  t-h2 t-light t-blue
   --------------------------------------------------------------------------
   HOW IT WORKS
   Each class only sets custom properties. One shared rule reads them and
   applies them to the element AND to whatever the theme nests inside it
   (the heading tag in a Text block, .w-text-h in a Text element), since the
   theme sizes those directly and they would not inherit.
   The modifiers set the same properties, so they come after the sizes and
   win on order with no extra weight.
   !important for the same reason as 1.1: these exist to beat Design
   Options. They are new names, so nothing in 18.0 onwards collides with
   them (see the file-order note in the header).
   --------------------------------------------------------------------------
   THE H1 WEIGHT IS AN OPEN QUESTION
   Glow's spec says 60 extralight. Every hero is currently extra bold, which
   was a deliberate call. --t-h1-weight holds the current extra bold until
   Glow confirms; change the one number to 200 if they want extralight.
   --------------------------------------------------------------------------
   Sizes step down at 900px and 600px, keeping the same line-height ratios.
   The H1 steps match 18.3's hero sizes, so the two agree.
   -------------------------------------------------------------------------- */
:root {
    --t-h1-weight: 800;
}

.t-h1      { --t-size: 60px; --t-line: 1.3;   --t-weight: var(--t-h1-weight); }
.t-display { --t-size: 60px; --t-line: 1.3;   --t-weight: 200; }
.t-h2      { --t-size: 48px; --t-line: 1.21;  --t-weight: 200; --para-gap: 40px; }
.t-h3      { --t-size: 32px; --t-line: 1.25;  --t-weight: 400; --para-gap: 20px; }
.t-h4      { --t-size: 24px; --t-line: 1.333; --t-weight: 400; }
.t-body    { --t-size: 24px; --t-line: 1.333; --t-weight: 400; --para-gap: 20px; }
.t-small   { --t-size: 20px; --t-line: 1.4;   --t-weight: 400; }

:is(.t-h1, .t-display, .t-h2, .t-h3, .t-h4, .t-body, .t-small),
:is(.t-h1, .t-display, .t-h2, .t-h3, .t-h4, .t-body, .t-small)
    :is(h1, h2, h3, h4, h5, h6, p, li, span, .w-text-h, .w-text-value) {
    font-size: var(--t-size) !important;
    line-height: var(--t-line) !important;
    font-weight: var(--t-weight) !important;
    letter-spacing: 0;
}

/* --- weight modifiers --------------------------------------------------- */
.t-extralight { --t-weight: 200; }
.t-light      { --t-weight: 300; }
.t-regular    { --t-weight: 400; }
.t-semibold   { --t-weight: 600; }
.t-bold       { --t-weight: 700; }
.t-extrabold  { --t-weight: 800; }

/* --- colour modifiers ----------------------------------------------------
   Reach the nested elements too, for the same reason as the sizes. */
.t-blue,
.t-blue :is(h1, h2, h3, h4, h5, h6, p, li, span, .w-text-h, .w-text-value) {
    color: var(--color-blue, #00bfff) !important;
}

.t-white,
.t-white :is(h1, h2, h3, h4, h5, h6, p, li, span, .w-text-h, .w-text-value) {
    color: #fff !important;
}

/* --- tablets ------------------------------------------------------------- */
@media (max-width: 900px) {
    .t-h1      { --t-size: 44px; }
    .t-display { --t-size: 40px; }
    .t-h2      { --t-size: 36px; --para-gap: 28px; }
    .t-h3      { --t-size: 26px; --para-gap: 16px; }
    .t-h4      { --t-size: 20px; }
    .t-body    { --t-size: 19px; --para-gap: 16px; }
    .t-small   { --t-size: 17px; }
}

/* --- phones -------------------------------------------------------------- */
@media (max-width: 600px) {
    .t-h1      { --t-size: 32px; }
    .t-display { --t-size: 30px; }
    .t-h2      { --t-size: 28px; --para-gap: 22px; }
    .t-h3      { --t-size: 22px; --para-gap: 14px; }
    .t-h4      { --t-size: 18px; }
    .t-body    { --t-size: 17px; --para-gap: 14px; }
    .t-small   { --t-size: 16px; }
}

/* --------------------------------------------------------------------------
   1.8  PARAGRAPH SPACING (Site Wide #10)
   One gap between paragraphs across the site, 20px by default. The theme's
   own gap is 1.5rem, which on this site is 45px (1rem = 30px) and reads as
   a full blank line.
   --------------------------------------------------------------------------
   SCOPED TO .l-main
   The header and footer keep their own spacing. (0,1,1) beats the theme's
   bare `p`, and every component in 5.0 onwards that sets its own paragraph
   margin is heavier or later, so those are untouched.
   --------------------------------------------------------------------------
   --para-gap is inherited, so the 1.7 classes change the gap for their own
   copy by setting it (t-h2 uses 40, t-body 20). Set it on any section or
   block the same way to change the gap just there.
   --------------------------------------------------------------------------
   NOT CHANGED: the space BETWEEN separate Text blocks. That is the theme's
   --text-block-margin-bottom (also 1.5rem). It is better adjusted in Theme
   Options than here, since several layouts are tuned against it.
   -------------------------------------------------------------------------- */
:root {
    --para-gap: 20px;
}

.l-main p {
    margin-top: 0;
    margin-bottom: var(--para-gap);
}

.l-main p:last-child {
    margin-bottom: 0;
}

/* ==========================================================================
   2.0  MOTION
   ==========================================================================
   Entrance, exit, hover and continuous animation, applied by class from the
   extra class field. The "heading" prefix is historical — every class here
   works on any block.
   --------------------------------------------------------------------------
   CLASS REFERENCE

   Entrance
     heading-in                       fade and rise
     heading-in-fade                  fade with an 8% scale-down  (hero H1)
     heading-in-focus                 as -fade, snapping out of a blur
     heading-in-left / -right         slide in from that side
     heading-in-up / -down            travel up / down into place
     heading-in-zoom                  punch up from undersized
     heading-in-flip                  swing up from edge-on, hinged at the base
     heading-in-drop                  fall from above and bounce
     heading-in-track                 letter-spacing slams shut
     heading-in-woosh-left / -right   thrown in from off-screen
     heading-in-wipe                  revealed right to left      (hero H3)
     heading-in-wipe-right/-down/-up  revealed travelling that way
     heading-in-wipe-centre           opens from the middle, horizontally
     heading-in-wipe-open             opens from the middle, vertically

   Exit, leaving through the top of the viewport — pair with an entrance
     heading-out-fade / -left / -right / -up / -down / -zoom
     heading-out-woosh-left / -right

   Rows — on a container, choreographing its direct children
     row-in-left      from the left, first child first
     row-in-right     from the right, last child first
     row-in-centre    fan out from the middle, middle first
     row-in-split     converge from both edges, outer first
     row-in-meet      two halves slam together
     row-in-up        rise in order
     row-in-zoom      punch up in order
     row-in-open      the row itself opens from the centre (no choreography)

   Snap — solid the whole way, only the movement reads
     column-snap-left / -right   named for where the part ENDS UP
     column-snap-up / -down      named for the direction of travel
     row-in-snap                 stage: releases every part inside at once
     row-in-bg                   the background photo wooshes up

   Hover
     img-zoom img-zoom-out img-pan img-tilt img-colour   on the image widget
     hover-lift hover-grow hover-shrink                  on the block

   Continuous
     float pulse parallax-slow parallax-fast

   Modifiers — stack freely
     delay-1 … delay-5   wait after the trigger (rows: delays the sequence)
     fast slow slower    overall pace
     snap glide          movement speed on its own         (entrances)
     near far            travel distance
     sharp soft          remove / add a blur on the fade
     tight loose         gap between children              (rows)
     subtle bold         how much                          (hover, continuous)

   Hero: H1  heading-in-fade heading-out-fade
         H3  heading-in-wipe delay-3 heading-out-right
   --------------------------------------------------------------------------
   TRIGGERING
   Nothing runs on a timer, and nothing but parallax is tied to the
   scrollbar. The Animation JS adds:
     .is-in     when the element's top passes 75% down the viewport (100% at
                the foot of the page). Anything already above the line on
                load plays immediately — that is how the hero animates.
     .is-out    when an exit element's bottom rises above 20% from the top.
     .is-back   when it comes back down past that line.
   The JS measures layout offsets, not painted position, so an element
   parked off-screen on its opening frame still triggers where it will land.
   Its SEL must read:
     '[class*="heading-in"], [class*="row-in"], [class*="column-snap"],
      .float, .pulse'
   Every hold and release lives in one place, 2.8. If the script never runs
   nothing is held and everything plays on load — a mistimed entrance beats
   a page stuck at opacity 0.
   --------------------------------------------------------------------------
   WHY IT SNAPS
     1. The fade is over in about a quarter of a second, so you watch a solid
        object move rather than a ghost drifting.
     2. The movement curve is front-loaded — most of the distance is covered
        in the first third.
     3. The move keyframe overshoots by 5% of the travel (35% of any scale
        change) at 72%, then settles. It lives in the keyframe, not the
        easing, so it stays proportional at any distance. Set --hi-over /
        --ri-over to 0 to remove it.
   Fade, movement and wipe run as separate tracks because each wants its own
   duration and curve.
   --------------------------------------------------------------------------
   REDUCED MOTION
   Everything animated sits inside one no-preference query. A held opening
   frame under reduced motion would strand content at opacity 0, so there
   must be no animation at all rather than a disabled one. Only the clip
   (2.9) and the keyframes (2.10) sit outside, and both are inert alone.
   ========================================================================== */

@media (prefers-reduced-motion: no-preference) {

    /* ----------------------------------------------------------------------
       2.1  ENTRANCES
       The substring match means each variant stands alone: write
       heading-in-wipe, not heading-in heading-in-wipe. Don't combine plain
       heading-in with a variant — it would add its rise to the variant.
       Each variant declares its track list once, in --hi-anim. The base
       rule plays it and the exit rules in 2.2 append to it, so a new variant
       never needs a rule anywhere else.
       Zero lengths are written 0px, never 0: the overshoot multiplies them,
       and calc(0 * -.05) is a bare number, which translate() rejects.
       ---------------------------------------------------------------------- */
    [class*="heading-in"] {
        /* Where it starts. Variants override. */
        --hi-dist: 8rem;
        --hi-x: 0px;
        --hi-y: 0px;
        --hi-scale: 1;
        --hi-blur: 0px;

        /* Timing. */
        --hi-fade: 260ms;
        --hi-move: 620ms;
        --hi-delay: 0ms;
        --hi-fade-ease: cubic-bezier(.2, .6, .3, 1);
        --hi-move-ease: cubic-bezier(.12, .9, .18, 1);
        --hi-wipe-ease: cubic-bezier(.7, 0, .1, 1);   /* accelerate, brake hard */

        /* Overshoot, as a fraction of travel / of scale change. */
        --hi-over: -.05;
        --hi-over-s: -.35;

        /* Exit. The defaults are a no-op, so without an out class the
           element holds still even if it is given .is-out. */
        --ho-x: 0px;
        --ho-y: 0px;
        --ho-scale: 1;
        --ho-opacity: 1;
        --ho-dist: 10rem;
        --ho-time: 420ms;
        --ho-out-ease: cubic-bezier(.55, -.15, .8, .25);   /* pull back, launch */
        --ho-back-ease: cubic-bezier(.2, 1.3, .4, 1);      /* overshoot home */

        --hi-anim:
            heading-fade var(--hi-fade) var(--hi-fade-ease) var(--hi-delay) both,
            heading-move var(--hi-move) var(--hi-move-ease) var(--hi-delay) both;

        will-change: opacity, transform;
        animation: var(--hi-anim);
    }

    /* --- fade and move ---------------------------------------------------- */
    .heading-in       { --hi-y: 3rem; }
    .heading-in-left  { --hi-x: calc(-1 * var(--hi-dist)); }
    .heading-in-right { --hi-x: var(--hi-dist); }
    .heading-in-up    { --hi-y: calc(var(--hi-dist) / 2); }
    .heading-in-down  { --hi-y: calc(var(--hi-dist) / -2); }
    .heading-in-zoom  { --hi-y: 1.5rem; --hi-scale: .8; }

    /* Opacity plus a visible scale-down that dips just under size before it
       settles. Nothing is ever shown degraded, which keeps it clear of the
       low-vision question a blur raises. --hi-scale: 1 for a pure fade. */
    .heading-in-fade  { --hi-scale: 1.08; --hi-fade: 420ms; }

    /* The same, out of a heavy blur. */
    .heading-in-focus { --hi-scale: 1.06; --hi-fade: 450ms; --hi-blur: 18px; }

    /* --- wipes -------------------------------------------------------------
       Full opacity throughout — the edge does the work, so there is no fade
       track. One keyframe reads its starting box from --hi-clip, so a new
       direction is one line. Only these elements are clipped; a clip box on
       heading-in-focus would crop its blur halo. */
    [class*="heading-in-wipe"] {
        --hi-move: 560ms;
        --hi-clip: inset(0 0 0 100%);          /* plain -wipe: right to left */
        --hi-anim:
            heading-clip var(--hi-move) var(--hi-wipe-ease) var(--hi-delay) both;
    }

    .heading-in-wipe-right  { --hi-clip: inset(0 100% 0 0); }
    .heading-in-wipe-down   { --hi-clip: inset(0 0 100% 0); }
    .heading-in-wipe-up     { --hi-clip: inset(100% 0 0 0); }
    .heading-in-wipe-centre { --hi-clip: inset(0 50%); }
    .heading-in-wipe-open   { --hi-clip: inset(50% 0); }

    /* --- woosh -------------------------------------------------------------
       heading-in-left/right thrown hard: fully off-screen, solid almost the
       whole way. A horizontal stretch and a lean resolve as it decelerates,
       both square before the overshoot so it is readable when it lands.
       Dial back with --hw-stretch: 1, --hw-skew: 0deg, or .near. */
    [class*="heading-in-woosh"] {
        --hi-dist: 60vw;
        --hi-fade: 140ms;
        --hi-move: 560ms;
        --hi-fade-ease: linear;
        --hi-move-ease: cubic-bezier(.1, .9, .2, 1);
        --hw-stretch: 1.5;
        --hw-skew: 8deg;
        --hi-anim:
            heading-fade  var(--hi-fade) var(--hi-fade-ease) var(--hi-delay) both,
            heading-woosh var(--hi-move) var(--hi-move-ease) var(--hi-delay) both;
    }

    .heading-in-woosh-right { --hi-x: var(--hi-dist); }
    .heading-in-woosh-left  { --hi-x: calc(-1 * var(--hi-dist)); --hw-skew: -8deg; }

    /* --- flip --------------------------------------------------------------
       Hinged at the base. A see-through flip reads as a glitch, so the fade
       is short. The back-ease swings it a few degrees past upright. The
       perspective is in the keyframe, so no 3D parent is needed. */
    .heading-in-flip {
        --hi-fade: 180ms;
        --hi-move-ease: cubic-bezier(.25, 1.35, .45, 1);
        --hi-angle: 90deg;
        transform-origin: 50% 100%;
        --hi-anim:
            heading-fade var(--hi-fade) var(--hi-fade-ease) var(--hi-delay) both,
            heading-flip var(--hi-move) var(--hi-move-ease) var(--hi-delay) both;
    }

    /* --- drop --------------------------------------------------------------
       The bounce is in the keyframe, a fixed few pixels however far it fell.
       Linear timing so the keyframe percentages are honest. */
    .heading-in-drop {
        --hi-y: calc(-1 * var(--hi-dist));
        --hi-fade: 160ms;
        --hi-move: 700ms;
        --hi-anim:
            heading-fade var(--hi-fade) var(--hi-fade-ease) var(--hi-delay) both,
            heading-drop var(--hi-move) linear var(--hi-delay) both;
    }

    /* --- track -------------------------------------------------------------
       Best on short, large, single-line headings. Set --hi-track-end to the
       element's own tracking if it isn't 0. */
    .heading-in-track {
        --hi-fade: 300ms;
        --hi-move: 650ms;
        --hi-track-start: .5em;
        --hi-track-end: 0em;
        --hi-anim:
            heading-fade  var(--hi-fade) var(--hi-fade-ease) var(--hi-delay) both,
            heading-track var(--hi-move) var(--hi-move-ease) var(--hi-delay) both;
    }

    /* ----------------------------------------------------------------------
       2.2  EXITS
       Named for where the element goes TO.
       .is-out and .is-back each append one track to the entrance list. The
       entrance tracks keep their names and positions, so the browser carries
       them on rather than replaying them, and the appended track wins where
       it animates the same property.
       ---------------------------------------------------------------------- */
    .heading-out-fade        { --ho-opacity: 0; }
    .heading-out-left        { --ho-opacity: 0; --ho-x: calc(-1 * var(--ho-dist)); }
    .heading-out-right       { --ho-opacity: 0; --ho-x: var(--ho-dist); }
    .heading-out-up          { --ho-opacity: 0; --ho-y: calc(var(--ho-dist) / -2); }
    .heading-out-down        { --ho-opacity: 0; --ho-y: calc(var(--ho-dist) / 2); }
    .heading-out-zoom        { --ho-opacity: 0; --ho-scale: .7; }
    .heading-out-woosh-left  { --ho-opacity: 0; --ho-x: -60vw; --ho-time: 360ms; }
    .heading-out-woosh-right { --ho-opacity: 0; --ho-x: 60vw;  --ho-time: 360ms; }

    [class*="heading-in"].is-out {
        animation:
            var(--hi-anim),
            heading-out var(--ho-time) var(--ho-out-ease) both;
    }

    [class*="heading-in"].is-back {
        animation:
            var(--hi-anim),
            heading-return var(--ho-time) var(--ho-back-ease) both;
    }

    /* ----------------------------------------------------------------------
       2.3  ENTRANCE MODIFIERS
       Anchored to an entrance class so another plugin's .delay-2 can never
       pick these up. Stagger steps stay short — past about half a second a
       staggered pair stops reading as one event.
       ---------------------------------------------------------------------- */
    [class*="heading-in"].delay-1 { --hi-delay: 80ms; }
    [class*="heading-in"].delay-2 { --hi-delay: 160ms; }
    [class*="heading-in"].delay-3 { --hi-delay: 260ms; }
    [class*="heading-in"].delay-4 { --hi-delay: 380ms; }
    [class*="heading-in"].delay-5 { --hi-delay: 520ms; }

    [class*="heading-in"].fast    { --hi-fade: 160ms; --hi-move: 400ms;  --ho-time: 280ms; }
    [class*="heading-in"].slow    { --hi-fade: 450ms; --hi-move: 900ms;  --ho-time: 600ms; }
    [class*="heading-in"].slower  { --hi-fade: 700ms; --hi-move: 1300ms; --ho-time: 800ms; }

    [class*="heading-in"].snap    { --hi-move: 380ms; }
    [class*="heading-in"].glide   { --hi-move: 1000ms; }

    [class*="heading-in"].near    { --hi-dist: 3rem;  --ho-dist: 4rem; }
    [class*="heading-in"].far     { --hi-dist: 16rem; --ho-dist: 18rem; }

    [class*="heading-in"].sharp   { --hi-blur: 0px; }
    [class*="heading-in"].soft    { --hi-blur: 10px; }

    /* ----------------------------------------------------------------------
       2.4  ROWS
       The class goes on the container; the animation plays on its DIRECT
       children. If the builder wraps the columns in an inner div, put the
       class on that div or nothing will appear to happen.
       Each child works out its place from two counters: --ri-a counts from
       the start, --ri-b from the end. From those it knows which half it is
       on, how far it is from the edge and from the centre, without anything
       knowing how many siblings there are. Eight are counted; a ninth and
       beyond share the eighth's slot.
       The container carries .is-in, so the row is released at once and the
       stagger is a real delay.
       ---------------------------------------------------------------------- */
    [class*="row-in"] {
        --ri-dist: 6rem;
        --ri-step: 70ms;             /* gap between one child and the next */
        --ri-fade: 240ms;
        --ri-move: 560ms;
        --ri-blur: 0px;
        --row-delay: 0ms;            /* pushes the whole sequence back */
        --ri-fade-ease: cubic-bezier(.2, .6, .3, 1);
        --ri-move-ease: cubic-bezier(.12, .9, .18, 1);
        --ri-over: -.06;
        --ri-over-s: -.35;
    }

    [class*="row-in"] > * {
        --ri-a: 0;
        --ri-b: 0;
        --ri-x: 0px;
        --ri-y: 0px;
        --ri-scale: 1;
        --ri-i: var(--ri-a);                                        /* order, 0 first */
        --ri-side: clamp(-1, calc(var(--ri-b) - var(--ri-a)), 1);   /* 1 left, -1 right, 0 centre */
        --ri-delay: calc(var(--row-delay) + var(--ri-step) * var(--ri-i));
        will-change: opacity, transform;
        animation:
            row-fade var(--ri-fade) var(--ri-fade-ease) var(--ri-delay) both,
            row-move var(--ri-move) var(--ri-move-ease) var(--ri-delay) both;
    }

    [class*="row-in"] > :nth-child(2)        { --ri-a: 1; }
    [class*="row-in"] > :nth-child(3)        { --ri-a: 2; }
    [class*="row-in"] > :nth-child(4)        { --ri-a: 3; }
    [class*="row-in"] > :nth-child(5)        { --ri-a: 4; }
    [class*="row-in"] > :nth-child(6)        { --ri-a: 5; }
    [class*="row-in"] > :nth-child(7)        { --ri-a: 6; }
    [class*="row-in"] > :nth-child(n+8)      { --ri-a: 7; }

    [class*="row-in"] > :nth-last-child(2)   { --ri-b: 1; }
    [class*="row-in"] > :nth-last-child(3)   { --ri-b: 2; }
    [class*="row-in"] > :nth-last-child(4)   { --ri-b: 3; }
    [class*="row-in"] > :nth-last-child(5)   { --ri-b: 4; }
    [class*="row-in"] > :nth-last-child(6)   { --ri-b: 5; }
    [class*="row-in"] > :nth-last-child(7)   { --ri-b: 6; }
    [class*="row-in"] > :nth-last-child(n+8) { --ri-b: 7; }

    /* First child first, all from the left. */
    .row-in-left > *  { --ri-i: var(--ri-a); --ri-x: calc(-1 * var(--ri-dist)); }

    /* Last child first, all from the right. */
    .row-in-right > * { --ri-i: var(--ri-b); --ri-x: var(--ri-dist); }

    /* Middle first, fanning out. Order is half the gap between the
       counters: 0 for the middle of an odd row, ½ for the pair in an even
       one. Each child starts displaced toward the centre. */
    .row-in-centre > * {
        --ri-i: calc(max(calc(var(--ri-b) - var(--ri-a)), calc(var(--ri-a) - var(--ri-b))) / 2);
        --ri-x: calc(var(--ri-side) * var(--ri-dist));
    }

    /* Outer children first, each from its own edge, closing like curtains. */
    .row-in-split > * {
        --ri-i: min(var(--ri-a), var(--ri-b));
        --ri-x: calc(-1 * var(--ri-side) * var(--ri-dist));
    }

    /* Two solid halves launched on the same frame; the overshoot carries
       them a touch past each other, which reads as the impact. clip, not
       hidden, so the overhang is cropped without making a scroll container. */
    .row-in-meet {
        --ri-dist: 150%;
        --ri-step: 0ms;
        --ri-fade: 1ms;
        --ri-move: 520ms;
        overflow: clip;
    }

    .row-in-meet > * {
        --ri-i: 0;
        --ri-x: calc(-1 * var(--ri-side) * var(--ri-dist));
    }

    .row-in-up > *    { --ri-i: var(--ri-a); --ri-y: calc(var(--ri-dist) / 2); }
    .row-in-zoom > *  { --ri-i: var(--ri-a); --ri-y: 1.5rem; --ri-scale: .8; }

    /* The row itself opens from the centre. Borrows the heading wipe. */
    .row-in-open {
        --hi-clip: inset(0 50%);
        animation: heading-clip var(--ri-move) cubic-bezier(.7, 0, .1, 1) var(--row-delay) both;
    }

    /* Containers that match "row-in" but don't choreograph their children:
       the opening row, and the snap stage and background from 2.5. Their
       children would otherwise all fade in as one block. Snap parts keep
       their own animation. */
    :is(.row-in-open, .row-in-snap, .row-in-bg) > *:not([class*="column-snap"]) {
        animation: none;
        will-change: auto;
    }

    /* --- row modifiers — the same words as 2.3 where they mean the same --- */
    [class*="row-in"].delay-1 { --row-delay: 80ms; }
    [class*="row-in"].delay-2 { --row-delay: 160ms; }
    [class*="row-in"].delay-3 { --row-delay: 260ms; }
    [class*="row-in"].delay-4 { --row-delay: 380ms; }
    [class*="row-in"].delay-5 { --row-delay: 520ms; }

    [class*="row-in"].fast    { --ri-fade: 150ms; --ri-move: 380ms;  --ri-step: 45ms; }
    [class*="row-in"].slow    { --ri-fade: 400ms; --ri-move: 850ms;  --ri-step: 110ms; }
    [class*="row-in"].slower  { --ri-fade: 600ms; --ri-move: 1200ms; --ri-step: 160ms; }

    [class*="row-in"].tight   { --ri-step: 35ms; }
    [class*="row-in"].loose   { --ri-step: 140ms; }

    [class*="row-in"].near    { --ri-dist: 2rem; }
    [class*="row-in"].far     { --ri-dist: 12rem; }
    [class*="row-in"].soft    { --ri-blur: 8px; }

    /* ----------------------------------------------------------------------
       2.5  SNAP
       Fast, opaque entrances — no fade, only movement.
       --------------------------------------------------------------------
       column-snap-left goes on the part that ends up on the LEFT, so it
       starts off-screen left and travels right. Its partner mirrors it and
       the two meet in the middle. The vertical pair breaks the rule and is
       named for travel, since "top" and "bottom" mean nothing in a row.
       --------------------------------------------------------------------
       ANY SINGLE ELEMENT CAN SNAP ON ITS OWN. A text block, image or button
       with column-snap-left releases itself when its top crosses the line.
       Use the row-in-snap stage when several parts should launch on the same
       frame — a left/right pair, or parts far enough apart vertically that
       they would otherwise cross the fold at different moments.
           Section / Row / Wrapper  → row-in-snap
              Column (left)         → column-snap-left
              Column (right)        → column-snap-right
       Set that row's column gap to 0, or the halves stop either side of it
       and never meet.
       --------------------------------------------------------------------
       `translate`, NOT `transform`. Impreza's Design Options write transforms
       onto columns with !important from a later stylesheet, which silently
       overrides a transform keyframe. translate is a separate property and
       composes with it instead. (It is also why the 2.1 entrances don't
       work on columns.)
       Distances are in vw: 105vw is fully off-screen at any width with 5% to
       spare for fractional pixels. The clip in 2.9 hides the overhang.
       ---------------------------------------------------------------------- */
    [class*="column-snap"] {
        --cs-dist: 105vw;
        --cs-time: 560ms;
        --cs-ease: cubic-bezier(.16, 1, .3, 1);   /* front-loaded: the "snap" */
        --cs-delay: 0ms;
        will-change: translate;
        animation: col-snap var(--cs-time) var(--cs-ease) var(--cs-delay) both;
    }

    .column-snap-left  { --cs-x: calc(-1 * var(--cs-dist)); }
    .column-snap-right { --cs-x: var(--cs-dist); }

    .column-snap-up,
    .column-snap-down  { --cs-dist: 60vh; --cs-x: 0px; }
    .column-snap-up    { --cs-y: var(--cs-dist); }
    .column-snap-down  { --cs-y: calc(-1 * var(--cs-dist)); }

    /* Stagger several parts on one side. Past ~200ms they stop reading as
       one movement. */
    [class*="column-snap"].delay-1 { --cs-delay: 60ms; }
    [class*="column-snap"].delay-2 { --cs-delay: 120ms; }
    [class*="column-snap"].delay-3 { --cs-delay: 180ms; }
    [class*="column-snap"].delay-4 { --cs-delay: 240ms; }
    [class*="column-snap"].delay-5 { --cs-delay: 300ms; }

    [class*="column-snap"].fast    { --cs-time: 380ms; }
    [class*="column-snap"].slow    { --cs-time: 820ms; }
    [class*="column-snap"].near    { --cs-dist: 40vw; }

    /* Pace set on a stage reaches every part inside it. */
    .row-in-snap.fast [class*="column-snap"] { --cs-time: 380ms; }
    .row-in-snap.slow [class*="column-snap"] { --cs-time: 820ms; }

    /* --- row-in-bg — the background photo wooshes up ----------------------
       Goes on whatever carries the background: Section, Row, Column or
       Wrapper. Design Options writes the background with !important, and a
       background can't be transformed anyway, so the real photo stays put:
         ::before  a solid panel in the page colour, covering it
         ::after   background: inherit — an exact copy that travels up
       Because ::after inherits, change the photo in the editor and it
       follows.
       Set --bgw-cover if the element isn't on black, or a black band will
       retreat down the screen.
       ON A WRAPPER, CHECK WHAT'S INSIDE. The children are lifted above both
       layers with position: relative. arrow-group (3.5), media-stage (5.1),
       dir-panels (5.6) and text-overlap (5.14) force their wrappers static,
       so their content would paint under the cover panel. For those, put
       row-in-bg on the Section instead. */
    .row-in-bg {
        --bgw-dist: 100%;
        --bgw-time: 900ms;
        --bgw-ease: cubic-bezier(.16, 1, .3, 1);
        --bgw-delay: 0ms;
        --bgw-cover: var(--color-content-bg, #000);
        position: relative;
        isolation: isolate;
        overflow: clip;
    }

    .row-in-bg::before,
    .row-in-bg::after {
        content: "";
        position: absolute;
        inset: 0;
        z-index: 0;
        pointer-events: none;
    }

    .row-in-bg::before {
        background: var(--bgw-cover);
    }

    .row-in-bg::after {
        background: inherit;
        will-change: translate;
        animation: bg-woosh-up var(--bgw-time) var(--bgw-ease) var(--bgw-delay) both;
    }

    .row-in-bg > .l-section-overlay {
        position: absolute;
        inset: 0;
        z-index: 1;
    }

    .row-in-bg > .l-section-h,
    .row-in-bg:not(.l-section) > *:not(.l-section-overlay) {
        position: relative;
        z-index: 2;
    }

    .row-in-bg.fast { --bgw-time: 620ms; }
    .row-in-bg.slow { --bgw-time: 1300ms; }

    /* ----------------------------------------------------------------------
       2.6  HOVER
       Transitions, not animations, so they follow the pointer both ways.
       Only on devices that can actually hover.
       --------------------------------------------------------------------
       IN AND OUT ARE TIMED SEPARATELY
       A single transition runs its easing in reverse on the way out, so a
       curve that feels quick arriving lands slowly going back — a snap then
       a drift. Instead, --hv-t / --hv-e hold the OUT timing at rest and
       switch to the IN timing on :hover. A transition always uses the
       timing of the state it is heading into, so each direction gets its
       own. Out is longer, on a symmetrical curve, so it eases away rather
       than bolting.
       --------------------------------------------------------------------
       No will-change. scale, translate, rotate and opacity composite anyway,
       and toggling will-change on :hover destroys the layer mid-retreat.
       Individual transform properties, never `transform`, so they compose
       with the arrow buttons' :active press instead of overwriting it.
       Classes are listed explicitly rather than matched on "img-" or
       "hover-", which would catch the theme's own classes and the arrow
       direction classes.
       ---------------------------------------------------------------------- */
    @media (hover: hover) {

        :is(.img-zoom, .img-zoom-out, .img-pan, .img-tilt, .img-colour,
            .hover-lift, .hover-grow, .hover-shrink) {
            --hv-in-ease: cubic-bezier(.2, .7, .3, 1);     /* commit fast, long settle */
            --hv-out-ease: cubic-bezier(.4, 0, .25, 1);    /* even at both ends */
            --hv-t: var(--hv-out);
            --hv-e: var(--hv-out-ease);
        }

        :is(.img-zoom, .img-zoom-out, .img-pan, .img-tilt, .img-colour,
            .hover-lift, .hover-grow, .hover-shrink):hover {
            --hv-t: var(--hv-in);
            --hv-e: var(--hv-in-ease);
        }

        /* --- images ----------------------------------------------------------
           On the element that CONTAINS the picture — widget, figure, column —
           because that is what crops the zoom. On the <img> itself it grows
           past its box instead of into it.
           clip, not hidden: hidden makes a scroll container, which would
           become the scroller for any parallax inside it. */
        :is(.img-zoom, .img-zoom-out, .img-pan, .img-tilt, .img-colour) {
            --hv-zoom: 1.06;
            --hv-in: 520ms;
            --hv-out: 700ms;
            overflow: clip;
        }

        :is(.img-zoom, .img-zoom-out, .img-pan, .img-tilt, .img-colour) :is(img, picture, video) {
            display: block;
            transform-origin: 50% 50%;
            scale: 1;
            translate: 0 0;
            rotate: 0deg;
            transition-property: scale, translate, rotate, filter;
            transition-duration: var(--hv-t);
            transition-timing-function: var(--hv-e);
        }

        .img-zoom:hover     :is(img, picture, video) { scale: var(--hv-zoom); }

        /* Starts zoomed, settles when hovered — "comes into focus". */
        .img-zoom-out       :is(img, picture, video) { scale: var(--hv-zoom); }
        .img-zoom-out:hover :is(img, picture, video) { scale: 1; }

        /* A slow camera. The 1% drift is always covered by the zoom, so no
           edge is exposed. */
        .img-pan:hover :is(img, picture, video) {
            scale: calc(var(--hv-zoom) + .03);
            translate: -1% -1%;
        }

        /* The extra scale hides the corners the rotation pulls in. */
        .img-tilt:hover :is(img, picture, video) {
            scale: calc(var(--hv-zoom) + .04);
            rotate: 1.5deg;
        }

        /* A filter re-rasterises every frame and can't composite, so this
           one is quicker and the in/out gap narrower. Stretch it and large
           photos start to step. */
        .img-colour { --hv-in: 380ms; --hv-out: 460ms; }

        .img-colour :is(img, picture, video) { filter: grayscale(1); }

        .img-colour:hover :is(img, picture, video) {
            filter: grayscale(0);
            scale: calc(1 + (var(--hv-zoom) - 1) / 2);
        }

        /* --- blocks — cards, buttons, feature boxes ---------------------------
           Shorter than the images: a lift is a reply to the pointer, and past
           half a second a reply reads as lag. */
        :is(.hover-lift, .hover-grow, .hover-shrink) {
            --hv-lift: 6px;
            --hv-grow: 1.04;
            --hv-in: 340ms;
            --hv-out: 480ms;
            translate: 0 0;
            scale: 1;
            transition-property: translate, scale;
            transition-duration: var(--hv-t);
            transition-timing-function: var(--hv-e);
        }

        .hover-lift:hover   { translate: 0 calc(-1 * var(--hv-lift)); }
        .hover-grow:hover   { scale: var(--hv-grow); }
        .hover-shrink:hover { scale: calc(2 - var(--hv-grow)); }

        /* The shadow is drawn once and faded with opacity, which composites.
           A transitioned box-shadow repaints its blur every frame and is the
           main reason a lift feels sticky. It fades a little faster than the
           block moves so it reads as a consequence of the movement.
           position: relative is required — if the block contains absolutely
           positioned children, they will now anchor here. */
        .hover-lift {
            position: relative;
        }

        .hover-lift::after {
            content: "";
            position: absolute;
            inset: 0;
            z-index: -1;
            border-radius: inherit;
            box-shadow: 0 calc(var(--hv-lift) * 3) calc(var(--hv-lift) * 6) rgb(0 0 0 / .12);
            opacity: 0;
            transition: opacity calc(var(--hv-t) * .8) var(--hv-e);
            pointer-events: none;
        }

        .hover-lift:hover::after {
            opacity: 1;
        }

        /* --- hover modifiers --------------------------------------------------
           Keep out longer than in at every pace; that ratio is the smoothness. */
        :is(.img-zoom, .img-zoom-out, .img-pan, .img-tilt, .img-colour,
            .hover-lift, .hover-grow, .hover-shrink).subtle { --hv-zoom: 1.03; --hv-lift: 3px;  --hv-grow: 1.02; }

        :is(.img-zoom, .img-zoom-out, .img-pan, .img-tilt, .img-colour,
            .hover-lift, .hover-grow, .hover-shrink).bold   { --hv-zoom: 1.15; --hv-lift: 12px; --hv-grow: 1.08; }

        :is(.img-zoom, .img-zoom-out, .img-pan, .img-tilt, .img-colour,
            .hover-lift, .hover-grow, .hover-shrink).fast   { --hv-in: 220ms; --hv-out: 320ms; }

        :is(.img-zoom, .img-zoom-out, .img-pan, .img-tilt, .img-colour,
            .hover-lift, .hover-grow, .hover-shrink).slow   { --hv-in: 800ms; --hv-out: 1000ms; }
    }

    /* ----------------------------------------------------------------------
       2.7  CONTINUOUS
       Motion that never stops. Use it once per page, on the thing that
       matters most — a second floating element cancels the first. Held until
       scrolled into view like everything else; the first keyframe is the
       resting position, so the hold is invisible.
       ---------------------------------------------------------------------- */
    .float {
        --fl-dist: 8px;
        --fl-time: 5s;
        will-change: transform;
        animation: float var(--fl-time) ease-in-out infinite;
    }

    .pulse {
        --pu-scale: 1.04;
        --pu-time: 3s;
        will-change: transform;
        animation: pulse var(--pu-time) ease-in-out infinite;
    }

    .float.subtle { --fl-dist: 4px; }
    .float.bold   { --fl-dist: 16px; }
    .float.fast   { --fl-time: 2.5s; }
    .float.slow   { --fl-time: 9s; }

    .pulse.subtle { --pu-scale: 1.02; }
    .pulse.bold   { --pu-scale: 1.08; }
    .pulse.fast   { --pu-time: 1.6s; }
    .pulse.slow   { --pu-time: 5s; }

    /* Parallax: the one effect tied to the scrollbar rather than triggered
       by it. It drifts against the scroll for as long as it is in view,
       which reads as depth. Without scroll timelines it does nothing, which
       is the right fallback. */
    @supports (animation-timeline: view()) {
        .parallax-slow,
        .parallax-fast {
            --px-dist: 4rem;
            will-change: transform;
            animation: parallax linear both;
            animation-timeline: view();
            animation-range: cover 0% cover 100%;
        }

        .parallax-fast { --px-dist: 10rem; }

        :is(.parallax-slow, .parallax-fast).near { --px-dist: 2rem; }
        :is(.parallax-slow, .parallax-fast).far  { --px-dist: 16rem; }
    }

    /* ----------------------------------------------------------------------
       2.8  TRIGGER
       Everything above says WHAT moves. This says WHEN.
       Held with animation-play-state: paused. With `both` fill, a paused
       animation sits frozen on its first keyframe, and unpausing resumes its
       delay too — so delay-3 waits 260ms after the trigger, not after load.
       Last in the query on purpose: the `animation` shorthand resets
       play-state, so these must come after every rule that sets it.
       Scoped to .js-anim, which the script adds to <html> before anything
       else. No script, no hold.
       ---------------------------------------------------------------------- */
    .js-anim [class*="heading-in"]:not(.is-in),
    .js-anim [class*="row-in"]:not(.is-in) > *,
    .js-anim .row-in-open:not(.is-in),
    .js-anim .row-in-bg:not(.is-in)::after,
    .js-anim [class*="column-snap"]:not(.is-in),
    .js-anim .float:not(.is-in),
    .js-anim .pulse:not(.is-in) {
        animation-play-state: paused;
        /* A layer is only worth holding while something moves. Thirty
           permanent layers is what makes an unrelated hover stutter. */
        will-change: auto;
    }

    /* A stage that is in releases every part inside it on the same frame,
       including parts whose own top hasn't reached the line yet. */
    .js-anim .row-in-snap.is-in [class*="column-snap"] {
        animation-play-state: running;
        will-change: translate;
    }
}

/* ==========================================================================
   2.9  THE CLIP
   A snap part 105vw from its resting place is 105vw of overhang, and an
   unclipped overhang is a horizontal scrollbar for the length of the
   animation. clip, not hidden — hidden creates a scroll container.
   The JS measures layout offsets, so this clip has no effect on triggering.
   Outside the motion query; under reduced motion it is harmless.
   ========================================================================== */
.l-section:is([class*="column-snap"], :has([class*="column-snap"])) {
    overflow: clip;
}

/* .l-section-h caps content at --site-content-width and would crop parts at
   that edge rather than the viewport's, so on a wide screen they would pop
   into existence mid-air. */
.l-section:has([class*="column-snap"]) > .l-section-h {
    overflow: visible;
}

/* ==========================================================================
   LAYER ABOVE
   ==========================================================================
   Lifts an element over its neighbours, for overlaps done with negative
   margins. Put it on the SAME element as any entrance class (column-snap-*,
   heading-in-*, row-in-*).

   Three things can hide an overlap, so this handles all three:

   1. The entrance animation's transform makes the element its own stacking
      context, so a z-index on anything inside it can't reach the page.
      The lift goes on the animated element itself.

   2. The section is its own stacking context too, so the element can't rise
      above the section before it. The section is lifted as well.

   3. Slide-ins need the section to hide sideways overflow. With
      overflow-x: hidden the browser also clips vertically, which cuts off
      anything reaching up into the section above. overflow-x: clip hides
      the sideways overflow without touching the vertical, so the slide-in
      still doesn't cause a sideways scroll and the overlap is visible.
   ========================================================================== */

.layer-above {
    position: relative;
    z-index: 5 !important;
}

.l-section:has(.layer-above) {
    position: relative;
    z-index: 2;
    overflow-x: clip !important;
    overflow-y: visible !important;
}

.l-section:has(.layer-above) > .l-section-h {
    overflow: visible !important;
}

/* ==========================================================================
   2.10  KEYFRAMES
   Outside the motion query — an unreferenced keyframe costs nothing.
   Component keyframes live with their component in 5.0.
   ========================================================================== */

/* Ends on filter: none, not blur(0). Any held filter value makes the element
   a containing block for fixed-position children; none does not. */
@keyframes heading-fade {
    from { opacity: 0; filter: blur(var(--hi-blur)); }
    to   { opacity: 1; filter: none; }
}

/* Most of the way, overshoot at 72%, settle. The overshoot flips sign with
   the direction for free. */
@keyframes heading-move {
    0% {
        transform:
            translate(var(--hi-x), var(--hi-y))
            scale(var(--hi-scale));
    }
    72% {
        transform:
            translate(calc(var(--hi-x) * var(--hi-over)), calc(var(--hi-y) * var(--hi-over)))
            scale(calc(1 + (var(--hi-scale) - 1) * var(--hi-over-s)));
    }
    100% { transform: none; }
}

/* Travel, stretch and lean resolve together by 72%, then a 5% overshoot. */
@keyframes heading-woosh {
    0% {
        transform:
            translateX(var(--hi-x))
            scaleX(var(--hw-stretch))
            skewX(var(--hw-skew));
    }
    72% {
        transform:
            translateX(calc(var(--hi-x) * -.05))
            scaleX(1)
            skewX(0deg);
    }
    100% { transform: none; }
}

/* Every wipe, and row-in-open. The starting box comes from --hi-clip. */
@keyframes heading-clip {
    from { clip-path: var(--hi-clip); }
    to   { clip-path: inset(0); }
}

@keyframes heading-flip {
    from { transform: perspective(900px) rotateX(var(--hi-angle)); }
    to   { transform: perspective(900px) rotateX(0deg); }
}

/* Lands at 50%, bounces to -18px, lands, a 5px second bounce, settles. The
   fall eases in like gravity; each rebound eases out then in. */
@keyframes heading-drop {
    0%   { transform: translateY(var(--hi-y)); animation-timing-function: cubic-bezier(.55, 0, 1, .45); }
    50%  { transform: translateY(0);           animation-timing-function: cubic-bezier(0, .55, .45, 1); }
    68%  { transform: translateY(-18px);       animation-timing-function: cubic-bezier(.55, 0, 1, .45); }
    82%  { transform: translateY(0);           animation-timing-function: cubic-bezier(0, .55, .45, 1); }
    91%  { transform: translateY(-5px);        animation-timing-function: cubic-bezier(.55, 0, 1, .45); }
    100% { transform: none; }
}

@keyframes heading-track {
    from { letter-spacing: var(--hi-track-start); }
    to   { letter-spacing: var(--hi-track-end); }
}

@keyframes heading-out {
    from { opacity: 1; transform: none; }
    to   { opacity: var(--ho-opacity); transform: translate(var(--ho-x), var(--ho-y)) scale(var(--ho-scale)); }
}

@keyframes heading-return {
    from { opacity: var(--ho-opacity); transform: translate(var(--ho-x), var(--ho-y)) scale(var(--ho-scale)); }
    to   { opacity: 1; transform: none; }
}

@keyframes row-fade {
    from { opacity: 0; filter: blur(var(--ri-blur)); }
    to   { opacity: 1; filter: none; }
}

@keyframes row-move {
    0% {
        transform:
            translate(var(--ri-x), var(--ri-y))
            scale(var(--ri-scale));
    }
    72% {
        transform:
            translate(calc(var(--ri-x) * var(--ri-over)), calc(var(--ri-y) * var(--ri-over)))
            scale(calc(1 + (var(--ri-scale) - 1) * var(--ri-over-s)));
    }
    100% { transform: none; }
}

/* --cs-y and --cs-x fall back to 0, so each pair needs only its own axis. */
@keyframes col-snap {
    from { translate: var(--cs-x, 0px) var(--cs-y, 0px); }
    to   { translate: 0 0; }
}

@keyframes bg-woosh-up {
    from { translate: 0 var(--bgw-dist); }
    to   { translate: 0 0; }
}

@keyframes float {
    0%, 100% { transform: translateY(0); }
    50%      { transform: translateY(calc(-1 * var(--fl-dist))); }
}

@keyframes pulse {
    0%, 100% { transform: scale(1); }
    50%      { transform: scale(var(--pu-scale)); }
}

@keyframes parallax {
    from { transform: translateY(var(--px-dist)); }
    to   { transform: translateY(calc(-1 * var(--px-dist))); }
}


/* ==========================================================================
   3.0  ARROW BUTTONS
   Built for the Impreza theme (.w-btn / .us-btn-style_*).
   --------------------------------------------------------------------------
   EDITOR SETUP
   Theme Options → Buttons → the arrow style: its extra class must be
       arrow-btn
   That one class is the whole hook. Any button on that style is an arrow
   button and needs nothing in its own extra-class field. The style number is
   never mentioned below, so styles can be renumbered without touching this
   file.
   --------------------------------------------------------------------------
   POINTING IT SOMEWHERE
   The arrow points RIGHT. One class changes that:
       arrow-btn-right  →    arrow-btn-down  ↓    arrow-btn-ne  ↗
       arrow-btn-left   ←    arrow-btn-up    ↑    arrow-btn-sw  ↙
                             arrow-btn-nw    ↖    arrow-btn-se  ↘
   Compass shorthand works too — arrow-btn-e is arrow-btn-right, arrow-btn-n
   is arrow-btn-up.
   One direction class per button. Two on the same button and the file's order
   decides, which is nobody's idea of obvious.
   To make it swing on hover, add where it swings TO:
       <a class="w-btn arrow-btn arrow-btn-left arrow-btn-hover-nw">
   Inside an .arrow-group, the group's own direction class doubles as the
   hover target, so the arrow tips toward the panel it opens for free.
   --------------------------------------------------------------------------
   JUST THE ARROW
   arrow-btn-plain drops the blue tile, ring and glow, leaving the same glyph
   in white. On hover the shaft lengthens: the arrow slides forward and a
   line fills in behind it, so the head keeps its shape. Use it on a button
   that is on the arrow style, adding only this class:
       <a class="w-btn arrow-btn arrow-btn-plain">
   Direction classes still apply, and the line follows the arrow.
   Meant for dark backgrounds — on white it is invisible.
   --------------------------------------------------------------------------
   THE STAGE
   Section (bg image, overlay, Full height, valign Center)
   └ Column 12/12
      ├ Vertical Wrapper  — align Center
      │    ├ Text → H1
      │    └ Text → H3
      └ Vertical Wrapper  — extra class: arrow-group nw     ← the stage
           ├ Text block   — extra class: arrow-panel
           └ Button       — extra class: arrow-btn arrow-btn-left
   Add "reveal" to the stage classes if the panel should only appear on hover.
   Clear any Design Options positioning on the stage wrapper or the button —
   Impreza writes those with !important and no offsets.
   --------------------------------------------------------------------------
   DEPRECATED: arrow-btn-rest-*
   The glyph used to be drawn pointing LEFT, and arrow-btn-{dir} set the HOVER
   direction — so arrow-btn-right pointed left until you also added
   arrow-btn-rest-right. The glyph is now drawn pointing right, 0deg means
   east, and the class means what it says.
   The rest-* classes are kept as aliases so existing pages don't shift, and
   sit AFTER the plain direction block on purpose: where a button carries
   both, the rest- class is the one that was controlling the resting angle
   before, so it should still win.
   Worth tidying next time each page is open:
     Split band arrows   arrow-btn-left … arrow-btn-right arrow-btn-rest-right
                         → nothing at all, right is the default
     Media stage toggle  arrow-btn-nw arrow-btn-rest-nw
                         → arrow-btn-nw
     Hero arrow          arrow-btn-left nw
                         → arrow-btn-left  (the bare nw does nothing on the
                           button; the group's nw still aims the hover)
   Delete the alias block once that list is clear.
   --------------------------------------------------------------------------
   ONE MATCHING JS CHANGE
   One arrow on the site is built by script rather than placed in the editor,
   so it does not inherit the class from the button style. In the CAPABILITY
   CAROUSEL snippet:
     1. In setOpen():
            a.style.setProperty('--ab-rest', open ? '225deg' : '180deg');
        becomes
            a.style.setProperty('--ab-rest', open ? '45deg' : '0deg');
        Same two positions as before — right when shut, south-east when open —
        renumbered for the new glyph.
     2. Where it builds the button:
            a.className = 'cap-arrow arrow-btn-left arrow-btn-lg arrow-btn-rest-right';
        becomes
            a.className = 'cap-arrow arrow-btn arrow-btn-lg';
   Nothing else. The direction switcher draws its own glyph and is unrelated
   to this section; the testimonial arrow is built from parts in 5.11.
   ========================================================================== */

/* --------------------------------------------------------------------------
   3.1  TOKENS
   Impreza's button rules load after this file, so equal weight loses on order
   alone. .arrow-btn is repeated three times (0,3,0) to clear .us-btn-style_*,
   four times on hover states to clear ".no-touch .us-btn-style_*:hover".
   Impreza's own button variables are pre-loaded with our blue here, so even
   if a theme rule wins somewhere unanticipated it resolves to the right
   colour rather than the theme's #333.
   --ab-hover is deliberately NOT declared. A property set directly on an
   element beats one inherited from an ancestor, so declaring it would stop
   .arrow-group ever aiming the hover. It is read with a fallback instead:
   var(--ab-hover, var(--ab-rest)).
   -------------------------------------------------------------------------- */
.arrow-btn {
    --ab-size: 64px;
    --ab-blue: #00b7ff;
    --ab-ink: #000;
    --ab-radius: 25%;
    --ab-gap: 6px;
    --ab-ring: 2px;
    /* How much of the button the arrow fills. NOT `contain` — the artwork
       sits in the middle of a 64-unit viewBox with clear space around it, so
       `contain` stretches the MASK to the button and renders the arrow at
       about half its width. This is the number to raise if the arrow looks
       small; past ~75% the ends clip against the button edge.
       A glyph drawn edge to edge in its own viewBox wants 100% instead — see
       the capabilities cards in 5.4, which override the glyph and this
       together. */
    --ab-glyph-size: 62%;
    --ab-rest: 0deg;           /* where it points. 0 = right, as drawn */
    --ab-spin: 0deg;           /* extra revolutions on a hover turn    */
    --ab-speed: 480ms;
    --ab-ease: cubic-bezier(.34, 1.4, .64, 1);
    --ab-glow: 0 183 255;
    /* Impreza's button variables, overridden at the source. */
    --btn-background: var(--ab-blue);
    --btn-hover-background: var(--ab-blue);
    --btn-border-color: transparent;
    --btn-hover-border-color: transparent;
    --btn-border-width: 0px;
    /* Drawn pointing right, so the angles below read like a compass. */
    --ab-glyph: url("https://www.hec-precision.co.uk/wp-content/uploads/ARROW-RIGHT-PLAIN.svg");
}

/* --------------------------------------------------------------------------
   3.2  DIRECTION
   -------------------------------------------------------------------------- */

/* Where it points. Clockwise from east, because that is how the glyph is
   drawn. Written twice (0,2,0) so a stray single-class rule can't beat them. */
.arrow-btn-right.arrow-btn-right, .arrow-btn-e.arrow-btn-e { --ab-rest:    0deg; }
.arrow-btn-se.arrow-btn-se                                 { --ab-rest:   45deg; }
.arrow-btn-down.arrow-btn-down,  .arrow-btn-s.arrow-btn-s  { --ab-rest:   90deg; }
.arrow-btn-sw.arrow-btn-sw                                 { --ab-rest:  135deg; }
.arrow-btn-left.arrow-btn-left,  .arrow-btn-w.arrow-btn-w  { --ab-rest:  180deg; }
.arrow-btn-nw.arrow-btn-nw                                 { --ab-rest:  225deg; }
.arrow-btn-up.arrow-btn-up,      .arrow-btn-n.arrow-btn-n  { --ab-rest:  270deg; }
.arrow-btn-ne.arrow-btn-ne                                 { --ab-rest:  315deg; }

/* Deprecated aliases — see the header. Must stay below the block above. */
.arrow-btn-rest-right.arrow-btn-rest-right { --ab-rest:    0deg; }
.arrow-btn-rest-se.arrow-btn-rest-se       { --ab-rest:   45deg; }
.arrow-btn-rest-down.arrow-btn-rest-down   { --ab-rest:   90deg; }
.arrow-btn-rest-sw.arrow-btn-rest-sw       { --ab-rest:  135deg; }
.arrow-btn-rest-left.arrow-btn-rest-left   { --ab-rest:  180deg; }
.arrow-btn-rest-nw.arrow-btn-rest-nw       { --ab-rest:  225deg; }
.arrow-btn-rest-up.arrow-btn-rest-up       { --ab-rest:  270deg; }
.arrow-btn-rest-ne.arrow-btn-rest-ne       { --ab-rest:  315deg; }

/* Where it turns to on hover, if anywhere. */
.arrow-btn-hover-right.arrow-btn-hover-right { --ab-hover:    0deg; }
.arrow-btn-hover-se.arrow-btn-hover-se       { --ab-hover:   45deg; }
.arrow-btn-hover-down.arrow-btn-hover-down   { --ab-hover:   90deg; }
.arrow-btn-hover-sw.arrow-btn-hover-sw       { --ab-hover:  135deg; }
.arrow-btn-hover-left.arrow-btn-hover-left   { --ab-hover:  180deg; }
.arrow-btn-hover-nw.arrow-btn-hover-nw       { --ab-hover:  225deg; }
.arrow-btn-hover-up.arrow-btn-hover-up       { --ab-hover:  270deg; }
.arrow-btn-hover-ne.arrow-btn-hover-ne       { --ab-hover:  315deg; }

/* Inside a stage, the panel's direction aims the arrow. Inherited, so an
   arrow-btn-hover-* on the button itself still wins.
   A turn takes whichever route the two numbers imply, so left (180deg) to up
   (-90deg) spins 270 degrees the long way round. If you hit one of those,
   write the equivalent angle inline: style="--ab-hover: 270deg". */
.arrow-group.e  { --ab-hover:    0deg; }
.arrow-group.se { --ab-hover:   45deg; }
.arrow-group.s  { --ab-hover:   90deg; }
.arrow-group.sw { --ab-hover:  135deg; }
.arrow-group.w  { --ab-hover:  180deg; }
.arrow-group.nw { --ab-hover:  225deg; }
.arrow-group.n  { --ab-hover:  270deg; }
.arrow-group.ne { --ab-hover:  315deg; }

/* --------------------------------------------------------------------------
   3.3  THE BUTTON
   -------------------------------------------------------------------------- */
.arrow-btn.arrow-btn.arrow-btn {
    position: relative;
    display: inline-grid;
    place-items: center;
    inline-size: var(--ab-size);
    block-size: var(--ab-size);
    min-inline-size: 0;
    min-block-size: 0;
    max-inline-size: none;
    flex: none;
    padding: 0;                      /* Impreza sets 0.8em 1.8em             */
    border: 0;
    border-radius: var(--ab-radius); /* Impreza sets var(--site-border-radius) */
    background: var(--ab-blue);
    overflow: visible;               /* the ring lives outside the box       */
    cursor: pointer;
    text-decoration: none;
    vertical-align: middle;
    -webkit-tap-highlight-color: transparent;
    /* Hides any label. Impreza forces color:#fff !important, which can't be
       outranked without !important of our own — font-size:0 sidesteps that
       and keeps the label readable by assistive tech. Give the button a real
       label in the editor: it is the accessible name. */
    font-size: 0;
    line-height: 0;
    transition: box-shadow var(--ab-speed) ease, transform 90ms ease;
}

/* Impreza writes Design Options positioning onto the <a> as
   .us_custom_xxxxxxx { position: absolute !important }. With no offsets that
   pulls the button out of flow, collapses .w-btn-wrapper to 0x0, and leaves
   the panel anchored to a button that is no longer where it appears to be.
   Better cleared in the editor; this is the safety net. */
.arrow-group .arrow-btn {
    position: relative !important;
}

/* --- the glyph -----------------------------------------------------------
   The BOX fills the button so the rotation pivots on the button's centre;
   the MASK is what sizes the arrow inside it. Sizing the box instead would
   move the pivot and make the arrow orbit rather than turn on the spot.
   ------------------------------------------------------------------------- */
.arrow-btn.arrow-btn.arrow-btn::before {
    content: "";
    position: absolute;
    inset: 0;
    margin: 0;
    padding: 0;
    border: 0;
    background-color: var(--ab-ink);
    background-image: none;
    -webkit-mask: var(--ab-glyph) center / var(--ab-glyph-size) no-repeat;
    mask: var(--ab-glyph) center / var(--ab-glyph-size) no-repeat;
    transform: rotate(var(--ab-rest));
    transition: transform var(--ab-speed) var(--ab-ease);
    opacity: 1;
    pointer-events: none;
}

/* --- the ring ----------------------------------------------------------- */
.arrow-btn.arrow-btn.arrow-btn::after {
    content: "";
    position: absolute;
    inset: calc(-1 * (var(--ab-gap) + var(--ab-ring)));
    margin: 0;
    padding: 0;
    background: none;
    border: var(--ab-ring) solid var(--ab-blue);
    border-radius: var(--ab-radius);
    opacity: 0;
    transform: scale(1.3);
    pointer-events: none;
    transition:
        opacity var(--ab-speed) ease,
        transform var(--ab-speed) var(--ab-ease),
        box-shadow var(--ab-speed) ease;
}

/* --- hover / focus ------------------------------------------------------ */
.arrow-btn.arrow-btn.arrow-btn.arrow-btn:is(:hover, :focus-visible) {
    background: var(--ab-blue);
    box-shadow: 0 0 18px rgb(var(--ab-glow) / .45);
}

/* The turn. With no hover class this resolves to the resting angle, so
   nothing moves — the ring and glow are the whole hover by default. */
.arrow-btn.arrow-btn.arrow-btn.arrow-btn:is(:hover, :focus-visible)::before {
    transform: rotate(calc(var(--ab-hover, var(--ab-rest)) + var(--ab-spin)));
}

.arrow-btn.arrow-btn.arrow-btn.arrow-btn:is(:hover, :focus-visible)::after {
    opacity: 1;
    transform: scale(1);
    box-shadow: 0 0 12px rgb(var(--ab-glow) / .5),
                inset 0 0 8px rgb(var(--ab-glow) / .3);
}

/* Hovering the panel turns the arrow too, so the pair reads as one object.
   Harmless where there is no panel. */
.arrow-group:has(.arrow-panel:hover) .arrow-btn::before {
    transform: rotate(calc(var(--ab-hover, var(--ab-rest)) + var(--ab-spin)));
}

.arrow-btn.arrow-btn:active {
    transform: scale(.94);
}

.arrow-btn.arrow-btn:focus-visible {
    outline: 2px solid var(--ab-blue);
    outline-offset: calc(var(--ab-gap) + 6px);
}

/* --------------------------------------------------------------------------
   3.4  SIZES AND VARIANTS
   Only --ab-size changes; the arrow follows, since --ab-glyph-size is a
   percentage of the button rather than a fixed length.
   -------------------------------------------------------------------------- */
.arrow-btn-xs.arrow-btn-xs { --ab-size: 32px;  --ab-gap: 3px;  --ab-ring: 1.5px; }
.arrow-btn-sm.arrow-btn-sm { --ab-size: 44px;  --ab-gap: 4px; }
.arrow-btn-lg.arrow-btn-lg { --ab-size: 88px;  --ab-gap: 8px;  --ab-ring: 2.5px; }
.arrow-btn-xl.arrow-btn-xl { --ab-size: 120px; --ab-gap: 10px; --ab-ring: 3px; }

/* A full revolution on top of the hover turn. Does nothing on its own —
   there has to be a turn to add it to. */
.arrow-btn-spin.arrow-btn-spin { --ab-spin: 360deg; }

.arrow-btn-ghost.arrow-btn-ghost.arrow-btn-ghost {
    background: transparent;
    box-shadow: inset 0 0 0 var(--ab-ring) rgb(var(--ab-glow) / .35);
}

.arrow-btn-ghost.arrow-btn-ghost.arrow-btn-ghost::before {
    background-color: var(--ab-blue);
}

.arrow-btn-ghost.arrow-btn-ghost.arrow-btn-ghost.arrow-btn-ghost:is(:hover, :focus-visible) {
    background: rgb(var(--ab-glow) / .12);
    box-shadow: inset 0 0 0 var(--ab-blue),
                0 0 18px rgb(var(--ab-glow) / .35);
}

/* --- plain: just the arrow -----------------------------------------------
   White glyph, no tile, no ring, no glow. On hover it swaps to
   ARROW-RIGHT-LONG.svg: the same arrow with a 12-unit longer shaft, drawn in
   ::after. The long one starts pushed back by exactly that extra length and
   clipped at the short arrow's tail, so at the swap it looks identical.
   Then it slides forward while the clip opens by the same amount, so the
   head moves on and the tail stays planted.
   The maths assumes the short glyph renders at 62% of the button (as set in
   the tokens) and that the two SVGs share the 33.1-unit height. Change
   --ab-glyph-size and --ab-plain-w must change with it.
   ------------------------------------------------------------------------- */
.arrow-btn-plain.arrow-btn-plain {
	--ab-glyph-size: var(--ab-plain-w);                   /* both arrows, same px scale */
    --ab-ink: #fff;
    --ab-glyph-long: url("https://www.hec-precision.co.uk/wp-content/uploads/ARROW-RIGHT-LONG.svg");
    --ab-plain-w: calc(var(--ab-size) * .62);             /* short glyph width */
    --ab-plain-e: calc(var(--ab-plain-w) * 20.4 / 33.3);  /* the extra tail    */
    --ab-plain-ease: cubic-bezier(.25, .8, .3, 1);        /* no overshoot      */
    --btn-background: transparent;
    --btn-hover-background: transparent;
}

.arrow-btn.arrow-btn.arrow-btn.arrow-btn-plain {
    background: transparent;
    box-shadow: none;
    border-radius: 0;
}

.arrow-btn.arrow-btn.arrow-btn.arrow-btn-plain:active {
    transform: none;
}

/* Short arrow. Comes back only once the long one has shrunk. */
.arrow-btn.arrow-btn.arrow-btn.arrow-btn-plain::before {
    transition:
        transform var(--ab-speed) var(--ab-plain-ease),
        opacity 0s linear var(--ab-speed);
}

/* Long arrow. Box starts at the short arrow's tail and is exactly as wide as
   the long glyph; it pivots on the button's centre, half a short-width in. */
.arrow-btn.arrow-btn.arrow-btn.arrow-btn-plain::after {
    display: block;
    top: 0;
    bottom: 0;
    right: auto;
    left: calc(50% - var(--ab-plain-w) / 2);
    width: calc(var(--ab-plain-w) + var(--ab-plain-e));
    border: 0;
    border-radius: 0;
    box-shadow: none;
    background: var(--ab-ink);
        /* Sized by height, so the head always matches the short arrow exactly. */
    -webkit-mask: var(--ab-glyph-long) right center / auto calc(var(--ab-plain-w) * 33.1 / 33.3) no-repeat;
    mask: var(--ab-glyph-long) right center / auto calc(var(--ab-plain-w) * 33.1 / 33.3) no-repeat;
    opacity: 0;
    transform-origin: calc(var(--ab-plain-w) / 2) 50%;
    transform: rotate(var(--ab-rest)) translateX(calc(-1 * var(--ab-plain-e)));
    clip-path: inset(0 0 0 var(--ab-plain-e));
    transition:
        transform var(--ab-speed) var(--ab-plain-ease),
        clip-path var(--ab-speed) var(--ab-plain-ease),
        opacity 0s linear var(--ab-speed);
}

.arrow-btn.arrow-btn.arrow-btn.arrow-btn.arrow-btn-plain:is(:hover, :focus-visible) {
    background: transparent;
    box-shadow: none;
}

.arrow-btn.arrow-btn.arrow-btn.arrow-btn.arrow-btn-plain:is(:hover, :focus-visible)::before {
    opacity: 0;
    transition:
        transform var(--ab-speed) var(--ab-plain-ease),
        opacity 0s;
}

.arrow-btn.arrow-btn.arrow-btn.arrow-btn.arrow-btn-plain:is(:hover, :focus-visible)::after {
    opacity: 1;
    box-shadow: none;
    transform:
        rotate(calc(var(--ab-hover, var(--ab-rest)) + var(--ab-spin)))
        translateX(0px);
    clip-path: inset(0 0 0 0px);
    transition:
        transform var(--ab-speed) var(--ab-plain-ease),
        clip-path var(--ab-speed) var(--ab-plain-ease),
        opacity 0s;
}

.arrow-btn.arrow-btn.arrow-btn-plain:focus-visible {
    outline-color: var(--ab-ink);
    outline-offset: 4px;
}

/* --------------------------------------------------------------------------
   3.5  THE STAGE — .arrow-group
   Goes on the wrapper holding the panel and the button.
   The panel is anchored to the BUTTON, not the container: it shares the
   button's bottom/right anchor, then is pushed along the direction vector so
   its trailing corner sits against the button's leading corner. Move the
   button and the panel follows.
   -------------------------------------------------------------------------- */
.arrow-group {
    position: relative;
    display: block;
    width: 100%;
    min-height: clamp(200px, 30vh, 320px);
    --ab-size: 64px;           /* mirrors the button, see the sync below */
    --ab-bottom: 0;            /* button, from the bottom of the stage   */
    --ab-right: 0;             /* button, from the right of the stage    */
    --ap-gap: 14px;            /* clearance between button and panel     */
    /* How far the panel sits from the button, per axis. Both are less than
       the button's own size, which is what makes the button sit OVER the
       panel's trailing corner rather than clearing it. Raise --ap-dist-x past
       --ab-size to separate them; drop --ap-dist-y to 0 to sit the panel
       level with the button. */
    --ap-dist-x: calc(var(--ab-size) * .5);
    --ap-dist-y: calc(var(--ab-size) * .7);
    --ap-dx: -1;               /* direction vector, set by the classes  */
    --ap-dy: -1;
    --ap-origin: bottom right; /* corner the panel grows out of         */
    --ap-emerge: .78;          /* start position, fraction of --ap-dist */
}

/* Keep --ap-dist honest when the button uses a size variant. */
.arrow-group:has(.arrow-btn-xs) { --ab-size: 32px; }
.arrow-group:has(.arrow-btn-sm) { --ab-size: 44px; }
.arrow-group:has(.arrow-btn-lg) { --ab-size: 88px; }
.arrow-group:has(.arrow-btn-xl) { --ab-size: 120px; }

/* Panel direction. Origin is always the corner facing the button, so the
   panel appears to unfold out of it. The straight up/down pair clear the
   button fully — there is nothing to sit alongside, so a shallow lift would
   just overlap it. */
.arrow-group.n.n {
    --ap-dx: 0;
    --ap-dy: -1;
    --ap-origin: bottom center;
    --ap-dist-y: calc(var(--ab-size) + var(--ap-gap));
}

.arrow-group.ne.ne { --ap-dx:  1; --ap-dy: -1; --ap-origin: bottom left; }
.arrow-group.e.e   { --ap-dx:  1; --ap-dy:  0; --ap-origin: center left; }
.arrow-group.se.se { --ap-dx:  1; --ap-dy:  1; --ap-origin: top left; }

.arrow-group.s.s {
    --ap-dx: 0;
    --ap-dy: 1;
    --ap-origin: top center;
    --ap-dist-y: calc(var(--ab-size) + var(--ap-gap));
}

.arrow-group.sw.sw { --ap-dx: -1; --ap-dy:  1; --ap-origin: top right; }
.arrow-group.w.w   { --ap-dx: -1; --ap-dy:  0; --ap-origin: center right; }
.arrow-group.nw.nw { --ap-dx: -1; --ap-dy: -1; --ap-origin: bottom right; }

/* WPBakery inserts wrappers between a Row and its blocks. This stops any of
   them becoming the containing block and stealing the panel's anchor. */
.arrow-group :is(.wpb_wrapper, .vc_column-inner, .vc_column_container, .w-vwrapper, .w-hwrapper) {
    position: static;
}

.arrow-group .w-btn-wrapper {
    position: absolute;
    right: var(--ab-right);
    bottom: var(--ab-bottom);
    margin: 0;
    z-index: 3;
}

.arrow-group .arrow-panel {
    --ap-bg: var(--color-dark-grey);
    --ap-radius: 20px;
    --ap-pad: 1.25rem 1.5rem;
    position: absolute;
    right: var(--ab-right);
    bottom: var(--ab-bottom);
    width: 500px;
    line-height: 1.3;
    margin: 0;
    padding: var(--ap-pad);
    background: var(--ap-bg);
    border-radius: var(--ap-radius);
    z-index: 2;
    transform-origin: var(--ap-origin);
    transform:
        translate(calc(var(--ap-dx) * var(--ap-dist-x)),
                  calc(var(--ap-dy) * var(--ap-dist-y)));
}

/* Invisible bridge across the diagonal gap, so the panel doesn't snap shut
   while the cursor travels from the button to the text. Behind the panel; the
   button has a higher z-index and stays clickable. */
.arrow-group .arrow-panel::before {
    content: "";
    position: absolute;
    inset: calc(-1 * var(--ap-dist-x));
    z-index: -1;
}

/* --- optional: reveal the panel on hover ---------------------------------
   Add "reveal" to the stage classes.
   :has() is what lets the trigger sit somewhere completely different from the
   thing it reveals — a descendant :hover cannot do that.
   The panel starts short of its resting place and slightly undersized, with
   its origin on the corner nearest the button, so it unfolds out of the
   button rather than fading in on the spot.
   ------------------------------------------------------------------------- */
.arrow-group.reveal .arrow-panel {
    opacity: 0;
    visibility: hidden;
    transform:
        translate(calc(var(--ap-dx) * var(--ap-dist-x) * var(--ap-emerge)),
                  calc(var(--ap-dy) * var(--ap-dist-y) * var(--ap-emerge)))
        scale(.9);
    transition:
        opacity 180ms ease,
        transform 360ms cubic-bezier(.4, 0, .7, .3),
        visibility 0s linear 360ms;
}

.arrow-group.reveal:has(:is(.arrow-btn, .arrow-panel):is(:hover, :focus-visible))
    .arrow-panel {
    opacity: 1;
    visibility: visible;
    transform:
        translate(calc(var(--ap-dx) * var(--ap-dist-x)),
                  calc(var(--ap-dy) * var(--ap-dist-y)))
        scale(1);
    transition:
        opacity 220ms ease 60ms,
        transform var(--ab-speed) var(--ab-ease) 60ms,
        visibility 0s;
}

/* Without :has() the panel would never appear, so show it permanently. */
@supports not (selector(:has(*))) {
    .arrow-group.reveal .arrow-panel {
        opacity: 1;
        visibility: visible;
        transform:
            translate(calc(var(--ap-dx) * var(--ap-dist-x)),
                      calc(var(--ap-dy) * var(--ap-dist-y)));
    }
}

/* --- mobile --------------------------------------------------------------
   Absolute positioning gets cramped in a viewport-height hero on small
   screens, so both return to normal flow. The panel is forced visible: on
   touch there is no hover, so the copy would otherwise be unreachable.
   ------------------------------------------------------------------------- */
@media (max-width: 900px) {
    .arrow-group {
        min-height: 0;
    }

    .arrow-group .arrow-panel,
    .arrow-group .w-btn-wrapper {
        position: static;
        margin: 1.5rem auto 0;
    }

    .arrow-group .arrow-panel,
    .arrow-group.reveal .arrow-panel {
        width: 100%;
        opacity: 1;
        visibility: visible;
        transform: none;
    }

    .arrow-group .arrow-panel::before {
        display: none;
    }

    .arrow-group .w-btn-wrapper {
        display: flex;
        justify-content: center;
    }
}

/* --- reduced motion ------------------------------------------------------
   The arrow still lands on the right heading, just without the sweep or any
   extra spin, and the panel appears in place. The plain arrow still
   lengthens, but snaps rather than grows.
   ------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
    .arrow-btn,
    .arrow-btn::before,
    .arrow-btn::after,
    .arrow-panel {
        transition-duration: 1ms;
    }

    .arrow-btn.arrow-btn.arrow-btn.arrow-btn:is(:hover, :focus-visible)::before {
        transform: rotate(var(--ab-hover, var(--ab-rest)));
    }

    .arrow-btn.arrow-btn.arrow-btn.arrow-btn.arrow-btn-plain:is(:hover, :focus-visible)::before {
        transform:
            rotate(var(--ab-hover, var(--ab-rest)))
            translateX(var(--ab-extend));
    }

    .arrow-btn.arrow-btn.arrow-btn.arrow-btn.arrow-btn-plain:is(:hover, :focus-visible)::after {
        transform: rotate(var(--ab-hover, var(--ab-rest)));
    }

    .arrow-group.reveal .arrow-panel {
        --ap-emerge: 1;
        transform:
            translate(calc(var(--ap-dx) * var(--ap-dist-x)),
                      calc(var(--ap-dy) * var(--ap-dist-y)));
    }
}


/* ==========================================================================
   4.0  HEADER
   ========================================================================== */

/* ==========================================================================
   4.1  MEGA MENU
   The Capabilities dropdown: a white panel hanging off the header, holding a
   column of links beside an image, with a row of policy links underneath.
   Each link carries a rule that wipes in from the left on hover. No JS.
   --------------------------------------------------------------------------
   EDITOR SETUP
   Wrapper                     — class: mega-panel      ← wraps both rows
      ├ Wrapper                — class: mega-top
      │    ├ Vertical Wrapper  — class: mega-links
      │    │    └ the six Text elements (no class needed)
      │    └ Image             — class: mega-media
      └ Wrapper                — class: mega-policies
           └ the five Text elements (no class needed)
   The individual links need no classes. They are the only children of their
   wrappers, so a child selector reaches them — adding a seventh capability
   needs no CSS change at all.
   --------------------------------------------------------------------------
   THE PANEL SURFACE
   Impreza supplies a white background from --dropdown-bg-color for a menu
   built from menu items. It does NOT do so for a mega menu built from a
   Content Block — the block renders inside the dropdown without inheriting
   its surface, which is why the panel first came out transparent. So the
   surface is set here, by two selectors:
     .mega-panel                              a wrapper you add in the editor
     .w-nav-list:not(.level_1):has(.mega-top) the dropdown itself, found by
                                              what it contains
   The second is a safety net for the case where there is no single wrapper
   around both rows. It is scoped :not(.level_1) on purpose — without that it
   would also match the top-level menu list, since that list contains the mega
   menu too, and the whole navigation bar would turn into a white panel.
   The panel hangs off the header rather than floating as a card: square top
   corners, rounded bottom ones, no top margin, and a shadow cast downward
   only. A symmetrical shadow would draw a dark line along the join and make
   the panel look detached from the bar above it.
   --------------------------------------------------------------------------
   THE PANEL'S WIDTH AND POSITION
   Every mega menu dropdown is anchored to the header bar (.l-subheader-h),
   not to the menu item that opened it, and centred in it. So all of them
   open in exactly the same place, whichever item was hovered.
   Impreza makes every .w-nav-item position:relative and hangs the dropdown
   inside it. It also adds a drop_left class to the items nearer the right
   edge and positions those with its own rule. Between the two, Capabilities
   and the other items were opening in different places. So the item, the nav
   and the header cell holding it are all made static, which passes the
   anchor up to .l-subheader-h, and the dropdown selector is long enough to
   outrank the drop_left rule.
   The panel is as wide as the header's content area (100% of .l-subheader-h),
   so its edges line up with the logo and the "Get in touch" button, capped
   at --mm-panel-cap on very wide screens. Centring is left:0, right:0 and
   auto margins rather than a translate, because Impreza's dropdown animation
   already uses transform and the two would overwrite each other.
   The panel needs a width of its own for the grid inside it. Without one the
   1fr image track has nothing to divide and collapses to zero, which is how
   the image first disappeared.
   Scoped to 901px and up. Below that Impreza switches to the mobile menu,
   which has its own full-width panel.
   ========================================================================== */

/* --- the header type -----------------------------------------------------
   The menu had no font size of its own, so it was inheriting :root's
   --font-size of 30px while the search icon sat at 18px. Two repeats of
   .ush_menu_1 clears the theme's own .ush_menu_1 .w-nav-item.level_1 > a
   rules.
   The arrow needs its own mention: it is a SIBLING of the title inside the
   anchor, not a child of it, so it would not pick this up by inheritance.
   Better done in Theme Options → Header → Menu, where Impreza stores a value
   per breakpoint and keeps --dropdown-font-size in step with it. This is here
   because it was asked for in CSS; if you ever set it in the builder, delete
   this block or the builder will appear to do nothing.
   ------------------------------------------------------------------------- */
.ush_menu_1.ush_menu_1 .w-nav-title,
.ush_menu_1.ush_menu_1 .w-nav-arrow {
    font-size: 18px;
}

/* --- the panel ---------------------------------------------------------- */
.mega-panel,
.w-nav-list:not(.level_1):has(.mega-top) {
    --mm-panel-bg: #fff;
    --mm-panel-cap: 1400px;             /* the panel's widest. Below this it
                                           matches the header's content
                                           width, see below                  */
    --mm-panel-radius: 0 0 16px 16px;   /* square at the top — it is attached */
    --mm-panel-pad: 2.2rem 2.5rem 1.4rem;
    --mm-panel-shadow: 0 24px 40px -12px rgb(0 0 0 / .3);
    box-sizing: border-box;
    margin-top: 0;
    padding: var(--mm-panel-pad);
    background: var(--mm-panel-bg);
    border-radius: var(--mm-panel-radius);
    box-shadow: var(--mm-panel-shadow);
}

/* Anchored to the header bar and centred in it, so every dropdown opens in
   the same place. See the header note. */
@media (min-width: 901px) {
    /* The anchor. The theme already sets this, restated in case that ever
       changes. */
    .l-header .l-subheader.at_middle .l-subheader-h {
        position: relative;
    }

    /* Everything between the anchor and the dropdown steps aside, so none of
       them becomes the containing block instead. */
    .l-header .l-subheader-cell:has(.ush_menu_1),
    .ush_menu_1.ush_menu_1,
    .ush_menu_1.ush_menu_1 .w-nav-item.level_1:has(.mega-top) {
        position: static;
    }

    /* (0,7,0), which clears Impreza's drop_left positioning. top:100% is the
       bottom of the header bar, so the panel still hangs directly off it. */
    .ush_menu_1.ush_menu_1 .w-nav-item.level_1 > .w-nav-list.w-nav-list:has(.mega-top) {
        top: 100%;
        left: 0;
        right: 0;
        width: min(var(--mm-panel-cap, 1400px), 100%);
        max-width: none;
        margin-left: auto;
        margin-right: auto;
    }
}

li.menu-item.menu-item-type-custom.menu-item-object-custom.menu-item-has-children.w-nav-item.level_1 > ul.w-nav-list {
    max-width: 960px;
}

/* --- tokens for the contents -------------------------------------------- */
.mega-top,
.mega-policies {
    /* --- proportions ------------------------------------------------------
       links + gap + image = panel. Change one and the image takes up the
       slack, since it is the fr track. */
    --mm-links-w: 260px;                /* the links column. Wide enough for
                                           "Multiple Axis CNC Machining" on
                                           one line — it wraps below ~250px  */
    --mm-gap: 2rem;                     /* between links and image           */
    --mm-media-radius: 0px;             /* the image's corners               */
    /* --- the links -------------------------------------------------------
       The links spread to fill the image's height (see the links section),
       so this is the MINIMUM space between them, not the actual space. It
       only shows when the list is taller than the image. */
    --mm-link-size: 16px;
    --mm-link-weight: 600;
    --mm-link-gap: 1rem;
    --mm-link-ink: #111;
    --mm-link-ink-hover: #111;          /* the rule does the work, so the text
                                           holds its colour. Set this to the
                                           orange if you want both.          */
    /* --- the policy row --------------------------------------------------- */
    --mm-policy-size: 15px;
    --mm-policy-weight: 400;
    --mm-policy-ink: #333;
    --mm-policy-ink-hover: #333;
    --mm-policy-gap: 2rem;
    --mm-policy-rule: rgb(0 0 0 / .1);
    --mm-policy-pad: 1.4rem;            /* above the policy row              */
    /* --- the animated rule ------------------------------------------------ */
    --mm-rule-ink: #e8762d;             /* set this to the brand orange      */
    --mm-rule: 2px;                     /* thickness                         */
    --mm-rule-gap: .45em;               /* distance below the text           */
    --mm-rule-speed: 420ms;
    --mm-rule-ease: cubic-bezier(.22, .68, .3, 1);
    --mm-speed: 260ms;
}

/* --- the top half --------------------------------------------------------
   Grid rather than flex. The links column is a fixed track and the image
   takes the rest, which keeps the image's left edge in the same place
   whatever the longest link happens to be — with flex the column would size
   to its content and the image would shift every time the wording changed.
   The class is repeated because this wrapper is an Impreza Horizontal
   Wrapper, and the theme's own .w-hwrapper rule sets align-items at the same
   weight in a stylesheet that loads after this one. At (0,1,0) that rule
   won, the columns weren't stretched, and the links had no height to spread
   into. The mobile block further down also uses .mega-top.mega-top and comes
   later, so it still switches this to display:block below 900px.
   ------------------------------------------------------------------------- */
.mega-top.mega-top {
    display: grid;
    grid-template-columns: var(--mm-links-w) minmax(0, 1fr);
    /* stretch, not start. Both columns take the height of the taller one,
       which is what lets the links spread out to match the image, and the
       image fill the row if the list is ever the taller of the two. */
    align-items: stretch;
    gap: var(--mm-gap);
    width: 100%;
}

/* Impreza nests wrappers between an element and its blocks. Left alone these
   introduce their own widths and break the grid tracks. */
.mega-top > :is(.w-vwrapper, .w-hwrapper),
.mega-policies > :is(.w-vwrapper, .w-hwrapper) {
    min-width: 0;
}

/* --- the links -----------------------------------------------------------
   Reached as children of their wrapper rather than by a class on each one, so
   adding or removing a link is an editor-only change.
   The repeated class on the spacing rules is load-bearing. .mega-links is a
   .w-vwrapper carrying its own --vwrapper-gap from the editor, and each Text
   element also inherits --text-block-margin-bottom (1.5rem in your Theme
   Options) as a bottom margin. Those two stack on top of the gap set here,
   which is what opened the rows up to roughly 80px apart. Zeroing the margin
   at (0,3,0) clears both and leaves the gap below as the only thing setting
   the rhythm.
   ------------------------------------------------------------------------- */
.mega-links.mega-links {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 1rem;
    min-width: 0;
	height: max-content;
}

/* Spread down the full height of the row, so the first link sits level with
   the top of the image and the last with its bottom, the rest evenly spaced
   between.
   align-self:stretch makes the column as tall as the image. It repeats what
   the grid above asks for, set on the column itself so that no theme rule on
   the wrapper can undo it. Without that height there's no spare room, and
   space-between has nothing to distribute.
   justify-content then spreads the links through it. Three repeats because
   the wrapper also carries Impreza's valign_top class, and
   .w-vwrapper.valign_top sets justify-content: flex-start at (0,2,0).
   If the list is ever taller than the image, there is no spare room, and the
   gap above takes over as normal spacing.
   On mobile the column sits in a block, not a grid, so neither has any
   effect there. */
.mega-links.mega-links.mega-links {
	align-self: stretch;
    justify-content: space-between;
}

.mega-links.mega-links > * {
    margin: 0;
    padding: 0;
    font-size: var(--mm-link-size);
    font-weight: var(--mm-link-weight);
    line-height: 1.25;
}

/* The colour and weight go on .w-text-h as well as the wrapper. When a link
   is set, that element is an anchor, and the theme's own link styling would
   otherwise win over anything set on the parent. */
.mega-links > *,
.mega-links :is(.w-text-h, .w-text-value) {
    color: var(--mm-link-ink);
    font-weight: 400;
    text-decoration: none;
    transition: color var(--mm-speed) ease;
}

.no-touch .mega-links > *:hover :is(.w-text-h, .w-text-value),
.mega-links .w-text-h:focus-visible {
    color: var(--mm-link-ink-hover);
}

/* --- the rule ------------------------------------------------------------
   It hangs off .w-text-h rather than off an <a>. An Impreza Text element only
   renders an anchor when a link has been set on it, so a rule targeting <a>
   would work on the linked items and silently do nothing on any not yet
   linked. .w-text-h is always present — a span when unlinked, the anchor when
   linked — so the rule lands either way.
   That element also has to become inline-block. Left inline, an absolutely
   positioned pseudo on a wrapped link splits across line boxes and the rule
   lands in the wrong place; inline-block also makes it span the TEXT's width
   rather than the column's, which is what the design shows.
   transform-origin is LEFT, so the rule grows out of the start of the word
   and travels left to right. transform rather than an animated width: width
   triggers layout on every frame, scaleX runs on the compositor.
   The hover is taken from the whole Text element, not from .w-text-h — the
   element is the full-width row, so the pointer does not have to land exactly
   on the glyphs for the rule to fire.
   ------------------------------------------------------------------------- */
.mega-links .w-text-h,
.mega-policies .w-text-h {
    position: relative;
    display: inline-block;
}

.mega-links .w-text-h::after,
.mega-policies .w-text-h::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    top: calc(100% + var(--mm-rule-gap));
    height: var(--mm-rule);
    background: var(--mm-rule-ink);
    transform: scaleX(0);
    transform-origin: left center;
    transition: transform var(--mm-rule-speed) var(--mm-rule-ease);
    pointer-events: none;
}

.no-touch .mega-links > *:hover .w-text-h::after,
.no-touch .mega-policies > *:hover .w-text-h::after,
.mega-links .w-text-h:focus-visible::after,
.mega-policies .w-text-h:focus-visible::after {
    transform: scaleX(1);
}

/* --- the image -----------------------------------------------------------
   The Image element carries a 21:9 aspect ratio from Design Options, written
   !important. At the panel's current width that makes the image the taller
   of the two columns, so it sets the row's height and the links spread out
   to match it (see the links section). To change how tall the image is,
   change that ratio in the editor.
   If the list is ever the taller column, the image fills the row instead:
   height:100% resolves because the grid item is stretched, so its height is
   definite. object-fit:cover crops the photograph to whatever shape the row
   is, rather than letterboxing it.
   ------------------------------------------------------------------------- */
.mega-media {
    display: block;
    width: 100%;
    height: 100%;
    margin: 0;
    min-width: 0;
}

.mega-media .w-image-h {
    display: block;
    width: 100%;
    height: 100%;
    border-radius: var(--mm-media-radius);
    /* clip, not hidden — hidden creates a scroll container. */
    overflow: clip;
}

.mega-media img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: center;
}

/* --- the policy row ------------------------------------------------------
   space-between rather than a fixed gap, so the row spans the panel's full
   width and the first and last items sit flush with its edges — which is what
   makes it read as a footer to the panel rather than a stray line of links.
   ------------------------------------------------------------------------- */
.mega-policies.mega-policies {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    align-items: baseline;
    gap: .6rem var(--mm-policy-gap);
    width: 100%;
    margin: var(--mm-policy-pad) 0 0;
    padding-top: var(--mm-policy-pad);
    border-top: 1px solid var(--mm-policy-rule);
}

.mega-policies.mega-policies > * {
    margin: 0;
    padding: 0;
    font-size: var(--mm-policy-size);
    font-weight: var(--mm-policy-weight);
    line-height: 1.3;
    white-space: nowrap;
}

.mega-policies > *,
.mega-policies :is(.w-text-h, .w-text-value) {
    color: var(--mm-policy-ink);
    font-weight: inherit;
    text-decoration: none;
    transition: color var(--mm-speed) ease;
}

.no-touch .mega-policies > *:hover :is(.w-text-h, .w-text-value),
.mega-policies .w-text-h:focus-visible {
    color: var(--mm-policy-ink-hover);
}

/* --- mobile --------------------------------------------------------------
   Below the menu's own breakpoint the dropdown becomes a stacked panel inside
   the mobile menu: one column of links with a blue rule down their left edge,
   the image full width underneath, then the policy row, centred.
   900px matches $us.navOptions.mobileWidth in your theme settings, which is
   where Impreza switches the menu to its mobile layout. Changing one without
   the other would leave a band where neither layout applies.
   --------------------------------------------------------------------------
   THE PANEL SURFACE comes off, because the mobile menu already sits on its
   own dark panel. The ink tokens are redeclared for that dark surface. The
   rules further up read them, so they follow.
   --------------------------------------------------------------------------
   WHY THE LINK TEXT WAS INVISIBLE
   Theme Options → Custom CSS contains
       @media (max-width:768px) { a.w-text-h span { display:none } }
   which hides the text of every linked Text element on phones. The menu
   links are <a class="w-text-h"><span class="w-text-value">, so their rows
   kept their height but showed nothing. The policy items are unlinked
   <span>s, so the rule never matched them. The override below is (0,3,1)
   against that rule's (0,1,2), scoped to the menu so it doesn't affect
   anything else the theme rule is meant for.
   ------------------------------------------------------------------------- */
@media (max-width: 900px) {
    .mega-panel,
    .w-nav-list:not(.level_1):has(.mega-top) {
        padding: 0;
        background: none;
        border-radius: 0;
        box-shadow: none;
    }

    /* Retokened for the dark mobile panel. Same selectors as the token block
       above, so these win on order. */
    .mega-top,
    .mega-policies {
        --mm-link-size: 16px;
        --mm-link-weight: 400;
        --mm-link-ink: #fff;
        --mm-link-ink-hover: var(--color-blue, #00bfff);
        --mm-policy-size: 13px;
        --mm-policy-ink: rgb(255 255 255 / .55);
        --mm-policy-ink-hover: #fff;
        --mm-policy-rule: rgb(255 255 255 / .12);
        --mm-policy-gap: 28px;                      /* between items, across */
        --mm-policy-row-gap: 14px;                  /* between wrapped lines */
        --mm-policy-pad: 20px;                      /* above and below       */
        --mm-m-indent: 16px;                        /* links in from the rule */
        --mm-m-rule: var(--color-blue, #00bfff);    /* the rule itself       */
        --mm-m-radius: 10px;                        /* the image's corners   */
    }

    /* Stacked: links, then image. Same weight as the desktop grid rule and
       later in the file, so this wins below 900px. The rule and indent sit on
       the links, not here, so the rule doesn't run down beside the photo. */
    .mega-top.mega-top {
        display: block;
        margin: 4px 0 0;
        padding: 0;
    }

    /* --- the links ---------------------------------------------------------
       One column. The spacing is padding on the link rather than a gap, so
       each row is a full-width tap target of about 44px. */
    .mega-links.mega-links {
        display: flex;
        flex-direction: column;
        align-items: stretch;
        gap: 0;
        padding-left: var(--mm-m-indent);
        border-left: 2px solid var(--mm-m-rule);
    }

    .mega-links.mega-links > * {
        min-width: 0;
        line-height: 1.3;
    }

    /* Puts the text back. See the header note. */
    .mega-links a.w-text-h .w-text-value,
    .mega-policies a.w-text-h .w-text-value {
        display: inline;
    }

    .mega-links.mega-links .w-text-h {
        display: block;
        padding: 12px 0;
        color: var(--mm-link-ink);
        text-decoration: none;
    }

    .mega-links.mega-links .w-text-h:is(:active, :focus-visible) {
        color: var(--mm-link-ink-hover);
    }

    .mega-links.mega-links .w-text-h:focus-visible {
        outline: 2px solid var(--mm-link-ink-hover);
        outline-offset: 2px;
    }

    /* No hover on touch, so the underline rule would either never fire or
       stick on after a tap. The colour change on press stands in for it. */
    .mega-links .w-text-h::after,
    .mega-policies .w-text-h::after {
        content: none;
    }

    /* --- the image ---------------------------------------------------------
       Full width under the links. Its shape comes from the Image element's
       own aspect ratio in Design Options (currently 21:9), which is set
       !important. Change it in the editor on the Tablets/Mobiles tab rather
       than here.
       Menus still using the placeholder image hide it, so they don't show an
       empty grey box. */
    .mega-media.mega-media {
        display: block;
        width: 100%;
        height: auto;
        margin: 16px 0 0;
        border-radius: var(--mm-m-radius);
        overflow: clip;
    }

    .mega-media .w-image-h {
        border-radius: var(--mm-m-radius);
    }

    .mega-media.mega-media:has(img.g-placeholder) {
        display: none;
    }

    /* --- the policy row ----------------------------------------------------
       Muted, small and centred under the image, so it reads as a footnote to
       the section rather than a second list of destinations. text-align
       keeps an item centred if its own text wraps onto a second line, which
       justify-content alone doesn't cover.
       The spacing is three tokens in the block above: --mm-policy-gap across,
       --mm-policy-row-gap between wrapped lines, --mm-policy-pad above and
       below the row.
       To drop it from the mobile menu entirely, replace this rule's contents
       with display: none. */
    .mega-policies.mega-policies {
        justify-content: center;
        gap: var(--mm-policy-row-gap) var(--mm-policy-gap);
        margin: var(--mm-policy-pad) 0 0;
        padding: var(--mm-policy-pad) 0;
        text-align: center;
    }

    .mega-policies.mega-policies > * {
        white-space: normal;
    }
}

/* --- reduced motion ----------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
    .mega-links :is(.w-text-h, .w-text-value),
    .mega-policies :is(.w-text-h, .w-text-value),
    .mega-links .w-text-h::after,
    .mega-policies .w-text-h::after {
        transition-duration: 1ms;
    }
}

/* ==========================================================================
   4.1.1  HEADER MENU — animated rule on the top-level items
   The same wipe-in rule as the mega menu links (4.1), on the main nav items
   in the header bar. Blue rather than orange, the label turns blue with it
   rather than holding its colour, and the text rises off the rule as it
   wipes in.
   --------------------------------------------------------------------------
   THE RULE HANGS OFF .w-nav-title, NOT THE ANCHOR
   The anchor also contains .w-nav-arrow, which is a SIBLING of the title, so
   a rule drawn on the anchor would run under the arrow as well. The title is
   the only element that wraps the words alone.
   That element has to become inline-block for two reasons: an absolutely
   positioned pseudo on an inline box splits across line boxes, and
   inline-block also makes the rule as wide as the TEXT rather than the
   anchor's padding box.
   --------------------------------------------------------------------------
   WHY THE LINE-HEIGHT IS RESET
   .l-subheader sets line-height to var(--header-area-height) — 110px at rest,
   70px sticky — and the title inherits it. Left alone, the title's box is the
   full height of the header bar, so a rule positioned at `top: 100%` would
   land 110px below the words. Pinning it to 1 makes the box the text itself,
   which is what --hm-rule-gap is then measured from. The anchor centres its
   contents, so nothing moves vertically.
   --------------------------------------------------------------------------
   HOW THE TEXT LIFTS AND THE RULE DOESN'T
   A pseudo-element is painted inside its parent's box, so moving the title
   carries the rule up with it. The rule is therefore pushed DOWN by the same
   distance, which cancels the parent's movement out and leaves it sitting
   still while the text rises off it. Both read --hm-lift, so there is no
   second number to keep in step, and both share a duration and easing — with
   different curves the two diverge mid-transition and the rule visibly
   drifts before settling.
   `translate` rather than `transform` throughout: the rule needs a transform
   of its own for the scaleX wipe, and the two are separate properties that
   compose rather than overwrite. translate is also visual only, so the
   anchor's box and the header's height are untouched.
   --------------------------------------------------------------------------
   Desktop only. Below 901px Impreza switches to the mobile menu, where there
   is no hover for the rule to fire on and the items are full-width rows.
   ========================================================================== */
@media (min-width: 901px) {
    .l-header .ush_menu_1 {
        --hm-rule-ink: var(--color-blue, #00bfff);
        --hm-ink-hover: var(--color-blue, #00bfff);
        --hm-rule: 2px;                 /* thickness                        */
        --hm-rule-gap: .45em;           /* distance below the text, at rest.
                                           The gap grows by --hm-lift on
                                           hover, since the rule stays put
                                           and the text moves away from it  */
        --hm-lift: 3px;                 /* how far the text rises           */
        --hm-lift-speed: 320ms;
        --hm-rule-speed: 420ms;
        --hm-rule-ease: cubic-bezier(.22, .68, .3, 1);
        --hm-speed: 260ms;
    }

    .l-header .ush_menu_1 .w-nav-item.level_1 > .w-nav-anchor .w-nav-title {
        position: relative;
        display: inline-block;
        line-height: 1;
        translate: 0 0;
        transition:
            color var(--hm-speed) ease,
            translate var(--hm-lift-speed) var(--hm-rule-ease);
    }

    /* transform-origin LEFT, so the rule grows out of the start of the word
       and travels left to right. scaleX rather than an animated width: width
       triggers layout on every frame, scaleX runs on the compositor. */
    .l-header .ush_menu_1 .w-nav-item.level_1 > .w-nav-anchor .w-nav-title::after {
        content: "";
        position: absolute;
        left: 0;
        right: 0;
        top: calc(100% + var(--hm-rule-gap));
        height: var(--hm-rule);
        background: var(--hm-rule-ink);
        transform: scaleX(0);
        transform-origin: left center;
        translate: 0 0;
        transition:
            transform var(--hm-rule-speed) var(--hm-rule-ease),
            translate var(--hm-lift-speed) var(--hm-rule-ease);
        pointer-events: none;
    }

    /* Fires on the ITEM, not the anchor, so the rule is already in when the
       pointer reaches the dropdown and stays in while the panel is open.
       (0,8,0) — Impreza's own hover rule is (0,6,0) and would otherwise win
       on the colour. */
    .no-touch .l-header .ush_menu_1.ush_menu_1 .w-nav-item.level_1:is(:hover, .opened) > .w-nav-anchor:not(.w-btn) .w-nav-title,
    .l-header .ush_menu_1.ush_menu_1 .w-nav-item.level_1 > .w-nav-anchor:not(.w-btn):focus-visible .w-nav-title {
        color: var(--hm-ink-hover);
        translate: 0 calc(-1 * var(--hm-lift));
    }

    /* The counter-move. Positive, against the title's negative. */
    .no-touch .l-header .ush_menu_1 .w-nav-item.level_1:is(:hover, .opened) > .w-nav-anchor .w-nav-title::after,
    .l-header .ush_menu_1 .w-nav-item.level_1 > .w-nav-anchor:focus-visible .w-nav-title::after {
        transform: scaleX(1);
        translate: 0 var(--hm-lift);
    }

    /* The arrow is a sibling of the title and doesn't inherit the colour set
       above, so it's matched separately or the two fall out of step. It has
       no rule beneath it, so it doesn't lift — add the same translate here
       if you'd rather it rose with the words. */
    .no-touch .l-header .ush_menu_1.ush_menu_1 .w-nav-item.level_1:is(:hover, .opened) > .w-nav-anchor:not(.w-btn) .w-nav-arrow {
        color: var(--hm-ink-hover);
        transition: color var(--hm-speed) ease;
    }
}

/* --- reduced motion ------------------------------------------------------
   The lift comes off entirely rather than just running quickly — at 3px the
   movement IS the effect, so a 1ms version of it is a jump rather than a
   subtler animation. The rule still wipes in; only the travel goes.
   ------------------------------------------------------------------------- */
@media (min-width: 901px) and (prefers-reduced-motion: reduce) {
    .l-header .ush_menu_1 {
        --hm-lift: 0px;
    }

    .l-header .ush_menu_1 .w-nav-title,
    .l-header .ush_menu_1 .w-nav-title::after {
        transition-duration: 1ms;
    }
}
/* ==========================================================================
   4.1.2  FOOTER — the animated rule from the header menu, on two elements
   Port of 4.1.1 to the footer, minus the lift. Same wipe-in rule, same blue,
   on:
     a) the Simple Menu items   (.w-menu:is(.us_menu_1, .us_menu_2) .menu > li > a)
        — both footer menus: Website and Legal
     b) the iconbox titles      (.w-iconbox .w-iconbox-title)
   The iconbox icon turns blue alongside its title but has no rule — it's a
   sibling of the meta block, so it's matched separately, as the header
   arrow is.
   --------------------------------------------------------------------------
   ADDING ANOTHER FOOTER MENU
   Add its class to every :is(.us_menu_1, .us_menu_2) below. :is() takes the
   weight of its heaviest entry, which is one class, so adding names never
   changes the specificity.
   --------------------------------------------------------------------------
   WHERE HOVER FIRES
   Menu: on the anchor. It wraps the words alone — no arrow sibling, no title
   span — so the rule hangs straight off it. The anchor has no padding of its
   own; Impreza applies the element's indents further out.
   Iconbox: on the BOX, not the title. The h4 holds the text directly, so when
   an iconbox is linked the anchor is the whole .w-iconbox. Firing on the box
   also means the icon and title react together when the pointer is on either.
   Both become inline-block for the reason the header title did: an absolute
   pseudo on an inline box splits across line boxes, and inline-block makes
   the rule as wide as the text rather than the row.
   --------------------------------------------------------------------------
   WHERE THE RULE SITS
   A pseudo at top: 100% hangs off the bottom of the LINE BOX, which is half
   the leading below the letters — at the theme's heading line-height that's
   most of the visible gap. 4.1.1 solved this by forcing line-height: 1 on the
   title, but that shrinks the h4's box here and drives the rule into the
   line below. Instead the half-leading, (1lh - 1em) / 2, is subtracted from
   the position, so --fm-rule-gap is measured from where the letters actually
   end and the box is untouched. The plain top: calc(100% + gap) line before
   it is the fallback for anything that doesn't know the lh unit (pre-2023
   browsers) — they'll drop the second declaration and keep the first.
   --------------------------------------------------------------------------
   THE ICONBOX TITLE PADDING
   When an iconbox has description text, Impreza spaces the title from it
   with padding-bottom: .5em on the h4 (.w-iconbox-title:not(:empty)).
   Padding is inside the box, so the pseudo hangs below it and the rule
   lands halfway to the next line. The same .5em is moved to margin-bottom:
   identical spacing, but outside the box, so the rule sits under the words.
   ========================================================================== */
.l-footer {
    --fm-rule-ink: var(--color-blue, #00bfff);
    --fm-ink-hover: var(--color-blue, #00bfff);
    --fm-rule: 2px;
    --fm-rule-gap: .25em;
    --fm-rule-speed: 420ms;
    --fm-rule-ease: cubic-bezier(.22, .68, .3, 1);
    --fm-speed: 260ms;
}

/* --- the text: menu anchor, iconbox title -------------------------------- */
.l-footer .w-menu:is(.us_menu_1, .us_menu_2) .menu > li > a,
.l-footer .w-iconbox .w-iconbox-title {
    position: relative;
    display: inline-block;
    transition: color var(--fm-speed) ease;
}

/* Padding to margin, see above. Only fires where the theme's own padding
   rule does, so titles in no_text iconboxes are left alone. */
.l-footer .w-iconbox .w-iconbox-title:not(:empty) {
    padding-bottom: 0;
    margin-bottom: .5em;
}

/* --- the rule ------------------------------------------------------------
   transform-origin LEFT so it grows out of the start of the word. scaleX
   rather than width: width lays out every frame, scaleX runs on the
   compositor. */
.l-footer .w-menu:is(.us_menu_1, .us_menu_2) .menu > li > a::after,
.l-footer .w-iconbox .w-iconbox-title::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    top: calc(100% + var(--fm-rule-gap));
    top: calc(100% - (1lh - 1em) / 2 + var(--fm-rule-gap));
    height: var(--fm-rule);
    background: var(--fm-rule-ink);
    transform: scaleX(0);
    transform-origin: left center;
    transition: transform var(--fm-rule-speed) var(--fm-rule-ease);
    pointer-events: none;
}

/* --- hover: colour -------------------------------------------------------
   Chained classes for headroom over Impreza's own link and iconbox hover
   colours — .w-menu doubled here stands in for the doubled menu class the
   single-menu version used, so the weight is unchanged. text-decoration:
   none guards against the Simple Menu's "links" style, which underlines on
   hover and would double up with the rule. */
.no-touch .l-footer .w-menu.w-menu:is(.us_menu_1, .us_menu_2) .menu > li > a:hover,
.l-footer .w-menu.w-menu:is(.us_menu_1, .us_menu_2) .menu > li > a:focus-visible,
.no-touch .l-footer .w-iconbox.w-iconbox:hover .w-iconbox-title,
.l-footer a.w-iconbox.w-iconbox:focus-visible .w-iconbox-title {
    color: var(--fm-ink-hover);
    text-decoration: none;
}

/* --- hover: the wipe ----------------------------------------------------- */
.no-touch .l-footer .w-menu:is(.us_menu_1, .us_menu_2) .menu > li > a:hover::after,
.l-footer .w-menu:is(.us_menu_1, .us_menu_2) .menu > li > a:focus-visible::after,
.no-touch .l-footer .w-iconbox:hover .w-iconbox-title::after,
.l-footer a.w-iconbox:focus-visible .w-iconbox-title::after {
    transform: scaleX(1);
}

/* --- the iconbox icon ----------------------------------------------------
   The <i> is included because Impreza sets the glyph colour on it directly
   for some icon styles; SVG icons pick up currentColor from the same rule. */
.l-footer .w-iconbox .w-iconbox-icon,
.l-footer .w-iconbox .w-iconbox-icon i {
    transition: color var(--fm-speed) ease;
}

.no-touch .l-footer .w-iconbox.w-iconbox.w-iconbox:hover .w-iconbox-icon,
.no-touch .l-footer .w-iconbox.w-iconbox.w-iconbox:hover .w-iconbox-icon i,
.l-footer a.w-iconbox.w-iconbox.w-iconbox:focus-visible .w-iconbox-icon,
.l-footer a.w-iconbox.w-iconbox.w-iconbox:focus-visible .w-iconbox-icon i {
    color: var(--fm-ink-hover);
}

/* --- reduced motion ------------------------------------------------------ */
@media (prefers-reduced-motion: reduce) {
    .l-footer .w-menu:is(.us_menu_1, .us_menu_2) .menu > li > a,
    .l-footer .w-menu:is(.us_menu_1, .us_menu_2) .menu > li > a::after,
    .l-footer .w-iconbox .w-iconbox-title,
    .l-footer .w-iconbox .w-iconbox-title::after,
    .l-footer .w-iconbox .w-iconbox-icon,
    .l-footer .w-iconbox .w-iconbox-icon i {
        transition-duration: 1ms;
    }
}

/* ==========================================================================
   4.2  HEADER SEARCH
   The search icon in the header opens a dark bar over the menu holding a
   white pill: blue magnifier on the left, the input, an outlined "Search"
   button on the right, and a white X after the pill to close it.
   --------------------------------------------------------------------------
   PAIRS WITH the HEADER SEARCH JS snippet, which adds the Search button. The
   header Search element outputs only the input and the close button, with
   no submit button. Without the script the pill still works: Enter submits.
   --------------------------------------------------------------------------
   MARKUP (Impreza, layout "fullwidth")
   .w-search.ush_search_1                 gets .active while open
      ├ a.w-search-open                   the icon in the header
      └ .w-search-form                    the bar
           └ form.w-form-row              made static, see below
                ├ .w-form-row-field       the pill
                │    ├ input[name="s"]
                │    └ button.hs-submit   added by the JS
                └ button.w-search-close   the X
   --------------------------------------------------------------------------
   WHERE THE BAR SITS
   Anchored to the header bar (.l-subheader-h), like the mega menu in 4.1.
   The header cell and the search element step aside so neither becomes the
   containing block.
   Its height is var(--header-area-height), the variable Impreza changes
   when the header goes sticky (110px → 70px on desktop, 90px → 60px on
   phones). So the bar is always exactly the height of the header as it is
   right now, and animates with it.
   On desktop the bar starts just clear of the logo (--hs-logo-clear), so the
   logo stays visible. Below 900px it covers the whole row, logo included.
   --------------------------------------------------------------------------
   VERTICAL CENTRING
   The pill and the X are each positioned directly against the bar: top:50%
   puts their top edge at the middle, and translate -50% lifts them back by
   half their own height. That doesn't depend on the form in between, which
   is made static so it can't get in the way.
   Earlier versions centred them as a flex row inside the form. The theme
   positions the X and the form itself, and those rules won, so the X stayed
   centred while the pill drifted. The positioning properties here carry
   !important for that reason. Nothing else does.
   The pill also shrinks to fit a short header (--hs-h below). It is never
   taller than the header minus --hs-breathe above and below, so the sticky
   header can't clip it.
   --hs-nudge moves both a pixel or two, if it looks a touch off centre.
   --------------------------------------------------------------------------
   OPEN AND CLOSE
   Impreza's own fullwidth layout animates the form's height. That is
   replaced with a fade and a short drop, keyed off the .active class
   Impreza already puts on the element. visibility waits for the fade on the
   way out, so the hidden bar can't catch taps.
   --------------------------------------------------------------------------
   WHY THE BUTTON COLOUR IS !important
   Theme Options styles every [type=submit] that isn't a .w-btn with
   color:#fff !important, and a darker colour on hover. The added button is
   a plain submit, so its ink has to be !important to beat that.
   ========================================================================== */

/* --- tokens ------------------------------------------------------------- */
.l-header .ush_search_1 {
    --hs-bar-bg: var(--color-dark-dark-grey, #333);   /* the bar, match the
                                                          header             */
    --hs-logo-clear: 190px;             /* bar starts here, clear of the logo */
    --hs-pill-left: max(24px, 12%);     /* pill's start, in from the bar's
                                           left edge (% of the bar's width)   */
    --hs-pill-h: 54px;                  /* the pill at its tallest            */
    --hs-breathe: 10px;                 /* at least this much header above and
                                           below the pill, so the sticky
                                           header never clips it              */
    --hs-nudge: 0px;                    /* moves the pill and X up (negative)
                                           or down (positive)                 */
    --hs-drop: 6px;                     /* how far they drop in on open       */
    --hs-pill-bg: #fff;
    --hs-ink: #111;
    --hs-placeholder: #8a8a8a;
    --hs-blue: var(--color-blue, #00bfff);
    --hs-icon: 26px;                    /* the magnifier                      */
    --hs-icon-x: 20px;                  /* its distance in from the pill edge */
    --hs-text: 18px;                    /* what's typed. 16px or more, or iOS
                                           zooms the page on focus            */
    --hs-btn-w: 150px;                  /* the Search button, minimum width   */
    --hs-btn-text: 17px;
    --hs-close: 40px;                   /* the X at its largest               */
    --hs-gap: 16px;                     /* between the pill and the X         */
    --hs-speed: 280ms;
    --hs-ease: cubic-bezier(.22, .68, .3, 1);
    /* --- worked out from the above. Don't set these directly. ----------- */
    --hs-h: min(var(--hs-pill-h),
                calc(var(--header-area-height, 80px) - 2 * var(--hs-breathe)));
    --hs-x: min(var(--hs-close), var(--hs-h));
    /* The magnifier's colour is set inside the SVG (%2300bfff is #00bfff).
       Change it there if the brand blue ever moves. */
    --hs-glass: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2300bfff' stroke-width='2' stroke-linecap='round'%3E%3Ccircle cx='10.5' cy='10.5' r='7.5'/%3E%3Cpath d='M21 21l-5-5'/%3E%3C/svg%3E");
    --hs-arrow: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12h14'/%3E%3Cpath d='M13 6l6 6-6 6'/%3E%3C/svg%3E");
    /* Theme input variables, overridden at the source, so any theme input
       rule that still lands resolves to the pill rather than grey on grey. */
    --inputs-background: transparent;
    --inputs-focus-background: transparent;
    --inputs-border-width: 0px;
    --inputs-border-color: transparent;
    --inputs-focus-border-color: transparent;
    --inputs-text-color: var(--hs-ink);
    --inputs-focus-text-color: var(--hs-ink);
    --inputs-padding: 0px;
}

/* --- the anchor ---------------------------------------------------------
   The header bar is the containing block. The cell and the search element
   step aside. Harmless where the theme already has them static. */
.l-header .l-subheader.at_middle .l-subheader-h {
    position: relative;
}

.l-header .l-subheader-cell:has(.ush_search_1),
.l-header .ush_search_1.ush_search_1 {
    position: static;
}

/* --- the bar ------------------------------------------------------------
   Pinned to the top of the header and exactly as tall as it is right now.
   The height transition matches Impreza's own header shrink, so the two
   move together on scroll. */
.l-header .ush_search_1.ush_search_1 .w-search-form {
    --hs-drop-now: calc(-1 * var(--hs-drop));
    position: absolute;
    top: 0 !important;
    bottom: auto !important;
    left: var(--hs-logo-clear);
    right: 0;
    z-index: 5;
    box-sizing: border-box;
    display: block;
    width: auto;
    height: var(--header-area-height, 100%) !important;
    min-height: 0;
    max-height: none;
    margin: 0;
    padding: 0;
    overflow: visible;
    background: var(--hs-bar-bg);
    color: var(--hs-ink);
    line-height: normal;
    border-radius: 0;
    box-shadow: none;
    transform: none !important;
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transition:
        opacity var(--hs-speed) ease,
        height .3s cubic-bezier(.78, .13, .15, .86),
        visibility 0s linear var(--hs-speed);
}

.l-header .ush_search_1.ush_search_1.active .w-search-form {
    --hs-drop-now: 0px;
    opacity: 1;
    visibility: visible;
    pointer-events: auto;
    transition:
        opacity var(--hs-speed) ease,
        height .3s cubic-bezier(.78, .13, .15, .86),
        visibility 0s;
}

/* --- the form ------------------------------------------------------------
   Made static, so the pill and the X position against the bar rather than
   against the form, whatever size or position the theme gives the form. */
.l-header .ush_search_1.ush_search_1 .w-search-form form {
    position: static !important;
    display: block;
    width: 100%;
    height: 100%;
    margin: 0;
    padding: 0;
    line-height: normal;
    transform: none;
    translate: none;
}

/* --- the pill ------------------------------------------------------------
   Centred in the bar (see the header note). It runs from --hs-pill-left to
   just short of the X.
   The magnifier is a background image on the pill, so it needs no element
   of its own. The left padding clears it. */
.l-header .ush_search_1.ush_search_1 .w-form-row-field {
    position: absolute !important;
    top: 50% !important;
    bottom: auto !important;
    left: var(--hs-pill-left);
    right: calc(var(--hs-x) + var(--hs-gap));
    box-sizing: border-box;
    display: flex;
    align-items: center;
    gap: 12px;
    width: auto;
    min-width: 0;
    height: var(--hs-h);
    margin: 0 !important;
    padding: 5px 5px 5px calc(var(--hs-icon-x) * 2 + var(--hs-icon));
    background-color: var(--hs-pill-bg);
    background-image: var(--hs-glass);
    background-repeat: no-repeat;
    background-position: var(--hs-icon-x) center;
    background-size: var(--hs-icon);
    border-radius: 999px;
    box-shadow: 0 0 0 0 transparent;
    line-height: normal;
    transform: none !important;
    translate: 0 calc(-50% + var(--hs-nudge) + var(--hs-drop-now, 0px));
    transition:
        translate var(--hs-speed) var(--hs-ease),
        height .3s cubic-bezier(.78, .13, .15, .86),
        box-shadow var(--hs-speed) ease;
}

/* A soft blue halo while typing, since the input itself has no outline. */
.l-header .ush_search_1.ush_search_1 .w-form-row-field:focus-within {
    box-shadow: 0 0 0 3px rgb(0 191 255 / .45);
}

/* --- the input ---------------------------------------------------------- */
.l-header .ush_search_1.ush_search_1 input[type="text"] {
    position: static;
    box-sizing: border-box;
    flex: 1 1 auto;
    min-width: 0;
    width: 100%;
    height: 100%;
    margin: 0;
    padding: 0;
    background: transparent;
    border: 0;
    border-radius: 0;
    box-shadow: none;
    outline: 0;
    color: var(--hs-ink);
    font-family: var(--font-family, inherit);
    font-size: var(--hs-text);
    font-weight: 400;
    line-height: normal;
}

.l-header .ush_search_1.ush_search_1 input[type="text"]:focus {
    background: transparent;
    box-shadow: none;
    outline: 0;
}

.l-header .ush_search_1 input::placeholder {
    color: var(--hs-placeholder);
    opacity: 1;
}

/* --- the Search button, added by the JS ---------------------------------- */
.l-header .ush_search_1.ush_search_1 .hs-submit {
    position: relative;
    box-sizing: border-box;
    flex: none;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    height: 100%;
    min-width: var(--hs-btn-w);
    margin: 0;
    padding: 0 1.6em;
    background: transparent;
    border: 1px solid var(--hs-blue);
    border-radius: 999px;
    box-shadow: none;
    color: var(--hs-ink) !important;
    font-family: var(--font-family, inherit);
    font-size: var(--hs-btn-text);
    font-weight: 400;
    line-height: 1;
    letter-spacing: 0;
    text-transform: none;
    cursor: pointer;
    transition:
        background-color var(--hs-speed) ease,
        border-color var(--hs-speed) ease;
}

.no-touch .l-header .ush_search_1.ush_search_1 .hs-submit.hs-submit:hover,
.l-header .ush_search_1.ush_search_1 .hs-submit.hs-submit:focus-visible {
    background: var(--hs-blue);
    border-color: var(--hs-blue);
    color: #000 !important;
}

.l-header .ush_search_1.ush_search_1 .hs-submit:focus-visible {
    outline: 2px solid var(--hs-ink);
    outline-offset: 2px;
}

/* --- the X ---------------------------------------------------------------
   At the right-hand end of the bar, centred the same way as the pill and
   moved by the same nudge and drop, so the two always stay level.
   Impreza draws it with an icon-font glyph. It's redrawn here as two bars so
   it doesn't depend on the icon font. */
.l-header .ush_search_1.ush_search_1 .w-search-close {
    position: absolute !important;
    top: 50% !important;
    bottom: auto !important;
    right: 0 !important;
    left: auto !important;
    box-sizing: border-box;
    display: block;
    width: var(--hs-x);
    height: var(--hs-x);
    margin: 0 !important;
    padding: 0;
    background: transparent;
    border: 0;
    border-radius: 50%;
    color: #fff;
    font-size: 0;
    line-height: 0;
    opacity: 1;
    transform: none !important;
    translate: 0 calc(-50% + var(--hs-nudge) + var(--hs-drop-now, 0px));
    cursor: pointer;
    transition:
        translate var(--hs-speed) var(--hs-ease),
        background-color var(--hs-speed) ease,
        color var(--hs-speed) ease;
}

.l-header .ush_search_1.ush_search_1 .w-search-close::before,
.l-header .ush_search_1.ush_search_1 .w-search-close::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    width: 45%;
    height: 2px;
    margin: 0;
    background: currentColor;
    border-radius: 2px;
    font-family: inherit;
    translate: -50% -50%;
    rotate: 45deg;
}

.l-header .ush_search_1.ush_search_1 .w-search-close::after {
    rotate: -45deg;
}

.no-touch .l-header .ush_search_1.ush_search_1 .w-search-close:hover,
.l-header .ush_search_1.ush_search_1 .w-search-close:focus-visible {
    background: rgb(255 255 255 / .1);
    color: var(--hs-blue);
}

.l-header .ush_search_1.ush_search_1 .w-search-close:focus-visible {
    outline: 2px solid var(--hs-blue);
    outline-offset: 2px;
}

/* --- laptops between 901 and 1200 ----------------------------------------
   21.6 shrinks the logo here, so the bar can start further left. */
@media (min-width: 901px) and (max-width: 1200px) {
    .l-header .ush_search_1 {
        --hs-logo-clear: 150px;
        --hs-pill-left: max(24px, 8%);
        --hs-pill-h: 50px;
        --hs-btn-w: 130px;
    }
}

/* --- tablets and phones (900 and below) ----------------------------------
   The bar covers the whole header row, logo included. There isn't room for
   both, and the search is what the visitor asked for. */
@media (max-width: 900px) {
    .l-header .ush_search_1 {
        --hs-pill-left: 0px;
        --hs-pill-h: 48px;
        --hs-breathe: 8px;
        --hs-icon: 20px;
        --hs-icon-x: 16px;
        --hs-text: 16px;
        --hs-btn-w: 110px;
        --hs-btn-text: 15px;
        --hs-close: 40px;
        --hs-gap: 10px;
    }

    .l-header .ush_search_1.ush_search_1 .w-search-form {
        left: 0;
        right: 0;
    }

    .l-header .ush_search_1.ush_search_1 .w-form-row-field {
        gap: 8px;
        padding: 4px 4px 4px calc(var(--hs-icon-x) * 2 + var(--hs-icon) - 4px);
    }

    .l-header .ush_search_1.ush_search_1 .hs-submit {
        padding: 0 1.2em;
    }
}

/* --- phones (600 and below) ----------------------------------------------
   The Search button becomes a round blue arrow, which gives the typing
   space back to the input. The word stays in the button for screen
   readers, just hidden from view. */
@media (max-width: 600px) {
    .l-header .ush_search_1 {
        --hs-pill-h: 46px;
        --hs-icon: 18px;
        --hs-icon-x: 14px;
        --hs-close: 36px;
        --hs-gap: 8px;
    }

    .l-header .ush_search_1.ush_search_1 .hs-submit {
        width: calc(var(--hs-h) - 8px);
        min-width: 0;
        padding: 0;
        background: var(--hs-blue);
        border-color: var(--hs-blue);
        border-radius: 50%;
    }

    /* The arrow. Pinned to the middle of the circle with top/left 50% and a
       -50% translate, rather than left to the button's flex centring, which
       a theme button style was overriding and leaving the arrow top-left.
       The button is position:relative, so this measures against it. The
       repeated class clears any theme ::before rule on submit buttons. */
    .l-header .ush_search_1.ush_search_1 .hs-submit.hs-submit::before {
        content: "";
        position: absolute;
        top: 50%;
        left: 50%;
        display: block;
        width: 18px;
        height: 18px;
        margin: 0;
        background-color: currentColor;
        -webkit-mask: var(--hs-arrow) center / contain no-repeat;
        mask: var(--hs-arrow) center / contain no-repeat;
        transform: none;
        translate: -50% -50%;
    }

    .l-header .ush_search_1 .hs-submit-label {
        position: absolute;
        width: 1px;
        height: 1px;
        margin: -1px;
        padding: 0;
        overflow: hidden;
        clip-path: inset(50%);
        white-space: nowrap;
        border: 0;
    }
}

/* --- reduced motion ----------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
    .l-header .ush_search_1 .w-search-form,
    .l-header .ush_search_1 .w-form-row-field,
    .l-header .ush_search_1 .hs-submit,
    .l-header .ush_search_1 .w-search-close {
        transition-duration: 1ms;
    }
}


/* ==========================================================================
   5.0  COMPONENTS
   ========================================================================== */

/* ==========================================================================
   5.1  MEDIA STAGE
   An image or video that expands to full-bleed on click. Pairs with the
   arrow-btn block in 3.0.
   The companion JS snippet is REQUIRED — it is the only thing that adds
   .is-open, and it also handles the auto-close.
   --------------------------------------------------------------------------
   EDITOR SETUP
   Section  "Precision Engineering Solutions"
   └ Column 12/12  — extra class: media-stage
        ├ Text → H2   — extra class: media-title
        ├ Image       — extra class: media-frame
        └ Button      — extra class: media-toggle arrow-btn-nw
                        (the button style supplies arrow-btn; the deprecated
                        arrow-btn-rest-nw can come off — see 3.0)
   When the real video arrives, swap the Image element for Impreza's Video
   element and put media-frame on that instead. The selectors below match
   .w-image and .w-video, and img / video / iframe inside either.
   --------------------------------------------------------------------------
   WHAT HAPPENS WHEN
   hover / focus   The blue box turns 45° into a diamond and a white ring
                   blooms out around it. The arrow itself holds still — its
                   direction is not what changes, so it should not move.
   open (click)    The frame grows to fill the viewport, the title fades out,
                   and the button hides. Closing happens on a second click
                   anywhere on the frame, on Escape, or automatically once the
                   section scrolls out of view.
   The open state deliberately has NO button treatment of its own, because the
   button is not visible then.
   --------------------------------------------------------------------------
   TWO LAYOUT NOTES
   The title and the button are both out of flow, anchored to the frame's
   corners and offset by half the frame's width. That is what makes them ride
   the frame as it grows, with no second set of coordinates for the open
   state.
   Because they are out of flow, the frame alone sets the stage's height. That
   is intentional: it means the frame's top and bottom edges are also the
   stage's, so the title needs no allowance for a heading above it and the
   button needs no allowance for anything below.
   ========================================================================== */
.media-stage {
    /* --- size ------------------------------------------------------------ */
    --ms-w-closed: min(72vw, 1100px);   /* resting width of the frame        */
    --ms-gutter-x: 0px;                 /* clearance left/right when open    */
    --ms-gutter-y: 2rem;                /* clearance top/bottom when open    */
    /* The ratio is split into two unitless numbers rather than written as
       "16 / 9", because --ms-w-open has to divide by it and a shorthand ratio
       is a single token that cannot be used in calc(). Change both. */
    --ms-ratio-w: 16;
    --ms-ratio-h: 9;
    --ms-radius: 10px;
    /* Capped on BOTH axes. Width alone is not enough: the frame is a fixed
       ratio, so its height follows its width, and a frame wide enough to fill
       a 1440px viewport is 810px tall — off the bottom of plenty of screens.
       The second term works backwards from the available height to the width
       that produces it, and min() takes whichever limit bites first.
       svh, not vh: on mobile vh ignores browser chrome, so a vh-derived
       height runs under the address bar. */
    --ms-w-open: min(
        calc(100vw - var(--ms-gutter-x)),
        calc((100svh - var(--ms-gutter-y)) * var(--ms-ratio-w) / var(--ms-ratio-h))
    );
    /* --- the title, measured in from the frame's TOP-LEFT corner --------- */
    --ms-title-x: 2.5rem;
    --ms-title-y: 1.5rem;               /* raise this number to move the
                                           title further down the frame      */
    /* --- the button, measured from the frame's BOTTOM-RIGHT corner -------
       The button is centred on the corner at 0 0. Positive x moves it right,
       positive y moves it down — away from the frame in both cases. */
    --ms-btn-x: 0px;
    --ms-btn-y: 0px;
    --ms-btn-turn: 45deg;               /* box rotation on hover. 0deg keeps
                                           it a rounded square.              */
    --ms-btn-spin: 0deg;                /* extra revolutions on top of the
                                           turn. Try 360deg for a full spin
                                           before it lands on the diamond.   */
    --ms-btn-scale: 1.06;               /* slight swell as it turns, so the
                                           movement has some weight to it    */
    --ms-btn-speed: 560ms;              /* slower than the ring's 480ms, so
                                           the box settles last              */
    --ms-btn-ease: cubic-bezier(.34, 1.4, .64, 1);
                                        /* overshoots past the diamond and
                                           settles back                      */
    --ms-ring: #fff;                    /* the ring colour                   */
    /* --- motion ---------------------------------------------------------- */
    --ms-speed: 620ms;
    --ms-ease: cubic-bezier(.22, .68, .3, 1);
    --ms-fade: 260ms;
    /* --- resolved state. Do not set this directly. ------------------------ */
    --ms-w: var(--ms-w-closed);
    position: relative;
}

.media-stage.is-open {
    --ms-w: var(--ms-w-open);
}

/* Impreza nests .vc_column-inner / .wpb_wrapper between the column and its
   blocks. Neither should become the containing block, or the title and button
   anchor to a wrapper instead of the stage. Same guard used on .arrow-group
   and .dir-panels. */
.media-stage :is(.vc_column-inner, .wpb_wrapper, .w-vwrapper, .w-hwrapper) {
    position: static;
}

/* --- the frame -----------------------------------------------------------
   Centred with a calculated margin rather than a translate. Auto margins
   cannot centre a box wider than its parent, and a -50% translate can — but
   only if nothing else ever sets `translate` or `transform` on this element,
   which is fragile inside a theme that writes transforms from Design Options.
   The margin approach needs no such promise: when --ms-w exceeds 100% the
   margin simply goes negative and the frame overhangs both sides equally.
   ------------------------------------------------------------------------- */
.media-stage .media-frame {
    display: block;
    width: var(--ms-w);
    max-width: none;
    margin-left: calc((100% - var(--ms-w)) / 2);
    margin-right: 0;
    translate: none;
    transition:
        width var(--ms-speed) var(--ms-ease),
        margin-left var(--ms-speed) var(--ms-ease);
}

/* overflow:clip rather than hidden — hidden creates a scroll container, which
   pins any scroll-driven animation inside it at 0%. */
.media-stage .media-frame :is(.w-image-h, .w-video-h) {
    display: block;
    width: 100%;
    border-radius: var(--ms-radius);
    overflow: clip;
}

.media-stage .media-frame :is(img, video, iframe) {
    display: block;
    width: 100%;
    height: auto;
    aspect-ratio: var(--ms-ratio-w) / var(--ms-ratio-h);
    object-fit: cover;
}

/* The frame is the close target once open. */
.media-stage.is-open .media-frame {
    cursor: zoom-out;
}

/* Impreza's placeholder SVG is tiny and looks soft stretched wide. Delete
   this rule once a real asset is in. */
.media-stage .media-frame img.g-placeholder {
    object-fit: contain;
    background: rgb(255 255 255 / .04);
}

/* --- the title -----------------------------------------------------------
   Anchored to the frame's top-left corner and offset in, so it sits over the
   image rather than above it, and travels with the corner as the frame grows.
   pointer-events:none so it never intercepts the click that closes the frame.
   The visibility delay is what makes the fade work in both directions: going
   out, visibility waits for the opacity to finish; coming back, it switches
   immediately so the fade-in is visible.
   ------------------------------------------------------------------------- */
.media-stage .media-title {
    position: absolute;
    top: var(--ms-title-y);
    left: calc((100% - var(--ms-w)) / 2 + var(--ms-title-x));
    z-index: 2;
    max-width: calc(var(--ms-w) - 2 * var(--ms-title-x));
    margin: 0;
    translate: none;
    pointer-events: none;
    transition:
        left var(--ms-speed) var(--ms-ease),
        max-width var(--ms-speed) var(--ms-ease),
        opacity var(--ms-fade) ease,
        visibility 0s;
}

.media-stage.is-open .media-title {
    opacity: 0;
    visibility: hidden;
    transition:
        left var(--ms-speed) var(--ms-ease),
        max-width var(--ms-speed) var(--ms-ease),
        opacity var(--ms-fade) ease,
        visibility 0s linear var(--ms-fade);
}

/* --- the button, position ------------------------------------------------
   Anchored to the frame's bottom-right corner with `right` and `bottom`, then
   nudged out by half its own size so it sits centred ON the corner rather
   than inside it. The translate here is a fixed 50% 50% — it carries no
   layout arithmetic, so there is nothing in it to go wrong if --ms-w changes
   units.
   ------------------------------------------------------------------------- */
.media-stage .w-btn-wrapper:has(.media-toggle) {
    position: absolute;
    bottom: var(--ms-btn-y);
    right: calc((100% - var(--ms-w)) / 2 + var(--ms-btn-x));
    left: auto;
    margin: 0;
    z-index: 3;
    translate: 50% 50%;
    transition:
        right var(--ms-speed) var(--ms-ease),
        opacity var(--ms-fade) ease,
        visibility 0s;
}

/* Gone once open. Nothing below styles an open button, because there is not
   one to see. */
.media-stage.is-open .w-btn-wrapper:has(.media-toggle) {
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transition:
        opacity var(--ms-fade) ease,
        visibility 0s linear var(--ms-fade);
}

/* --- the button, hover and focus ----------------------------------------
   THE MOST SPECIFICITY-SENSITIVE BLOCK IN THIS FILE.
   The base arrow-btn rules in 3.0 chain .arrow-btn four deep to outrank
   Impreza. These use .media-stage plus FOUR repeats of .media-toggle, which
   is (0,5,0) and clears them. If the base chains in 3.0 ever gain a level,
   lengthen these to match — the failure is silent: the box would snap
   straight to the diamond with no transition rather than turning.
   ------------------------------------------------------------------------- */

/* The ring, recoloured. Its geometry, radius and bloom all come from the base
   arrow-btn ::after — only the colour changes here. */
.media-stage .media-toggle.media-toggle.media-toggle::after {
    border-color: var(--ms-ring);
}

.media-stage .media-toggle.media-toggle.media-toggle.media-toggle:is(:hover, :focus-visible) {
    background: var(--ab-blue);
    box-shadow: 0 0 18px rgb(var(--ab-glow) / .45);
    rotate: calc(var(--ms-btn-turn) + var(--ms-btn-spin));
    scale: var(--ms-btn-scale);
}

/* Two things at once: hold the arrow at its resting angle, overriding the
   base rule's turn to --ab-hover, and counter-rotate it against the box so it
   keeps pointing ↖ while the box becomes a diamond. `rotate` and `transform`
   are separate properties and compose, so both can be set here.
   The counter-rotation MUST use the same duration and easing as the box, or
   the two curves diverge mid-turn and the arrow visibly wobbles inside the
   diamond instead of sitting still. */
.media-stage .media-toggle.media-toggle.media-toggle.media-toggle:is(:hover, :focus-visible)::before {
    transform: rotate(var(--ab-rest));
    rotate: calc(-1 * (var(--ms-btn-turn) + var(--ms-btn-spin)));
}

.media-stage .media-toggle.media-toggle.media-toggle.media-toggle:is(:hover, :focus-visible)::after {
    opacity: 1;
    transform: scale(1);
    box-shadow: 0 0 12px rgb(255 255 255 / .45),
                inset 0 0 8px rgb(255 255 255 / .25);
}

/* The transitions.
   These carry four repeats of .media-toggle for the same reason. The base
   rules set the button's transition at .arrow-btn repeated three times, which
   is (0,3,0). A plain `.media-stage .media-toggle` is only (0,2,0), so it
   LOSES — and because the base list covers box-shadow and transform but not
   `rotate` or `scale`, the turn would end up with no transition and snap
   straight to the diamond. The ring is unaffected either way, since its bloom
   is opacity and transform, both of which the base list does cover. */
.media-stage .media-toggle.media-toggle.media-toggle.media-toggle {
    transition:
        rotate var(--ms-btn-speed) var(--ms-btn-ease),
        scale var(--ms-btn-speed) var(--ms-btn-ease),
        box-shadow var(--ab-speed, 480ms) ease,
        transform 90ms ease;
}

.media-stage .media-toggle.media-toggle.media-toggle.media-toggle::before {
    transition:
        transform var(--ab-speed, 480ms) var(--ab-ease, ease),
        rotate var(--ms-btn-speed) var(--ms-btn-ease);
}

/* --- the section ---------------------------------------------------------
   .l-section-h caps content at --site-content-width and the frame has to
   escape it, so that stays visible. The section clips horizontally, which is
   what stops the open frame producing a horizontal scrollbar. It does not
   clip vertically in practice: the frame is in flow, so the section grows
   taller with it.
   ------------------------------------------------------------------------- */
.l-section:has(.media-stage) {
    overflow: clip;
}

.l-section-h:has(.media-stage) {
    overflow: visible;
}

/* --- mobile ------------------------------------------------------------- */
@media (max-width: 900px) {
    .media-stage {
        --ms-w-closed: calc(100vw - 3rem);
        --ms-gutter-y: 1rem;
        --ms-radius: 0px;
        --ms-title-x: 1.25rem;
        --ms-title-y: 1.25rem;
    }
}

/* --- reduced motion ----------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
    .media-stage .media-frame,
    .media-stage .media-title,
    .media-stage .w-btn-wrapper:has(.media-toggle),
    .media-stage .media-toggle,
    .media-stage .media-toggle::before,
    .media-stage .media-toggle::after {
        transition-duration: 1ms;
    }
}

/* ==========================================================================
   5.2  SPLIT BAND
   Photograph left, dark panel over it, bleeding off to the right. No JS.
   --------------------------------------------------------------------------
   EDITOR SETUP
   Section / Horizontal Wrapper -> split-band     (hwrapper gap 0)
      Image             -> band-media
      Vertical Wrapper  -> band-panel
        Button          -> band-arrow
        Text            -> small-blue-text
        Text (H2)       -> media-title
        Text block      -> the copy
        Button          -> the CTA
   Add band-inset alongside split-band for the reversed arrangement — 5.2.1.
   --------------------------------------------------------------------------
   THE ARROW SITS IN ONE OF TWO PLACES IN THE MARKUP
   Normally it's a child of .band-panel. But when the two halves are animated
   as column-snap parts (2.9), the panel becomes a permanent stacking context
   — will-change: translate creates one, and so does the filled animation's
   translate: 0 0, which is a non-none value. An arrow inside the panel is
   then trapped at the panel's level and can never paint above a photo that
   outranks it.
   On those bands the arrow is moved OUT of the panel in the editor and
   becomes a direct child of the .w-hwrapper. Same approach as the feature
   band in 5.3.
   Both placements are styled at every width below, and neither affects the
   other — the two rules differ by their combinator, so only one can ever
   match a given button. Move the button in the editor and the styling
   follows it.
   --------------------------------------------------------------------------
   THREE LAYOUTS, AND WHERE THE ARROW GOES IN EACH
   desktop (1321+)   Photo and panel side by side. The arrow straddles the
                     vertical seam between them, level with the heading —
                     NOT centred on the row. --sb-arrow-y is that height,
                     measured down from the panel's top edge.
   tablet (901-1320) Same arrangement, tightened. The arrow is still on the
                     seam; --sb-arrow-y comes down with the panel's padding.
   mobile (≤900)     Photo and panel stack, and the panel covers the photo's
                     lower edge. There is no vertical seam left, so the arrow
                     goes INSIDE the panel's padding box, top-left, above the
                     standfirst. Both placements resolve to the same result:
                     the in-panel one returns to normal flow, and the moved
                     out one is absolutely positioned into the panel's
                     corner.
   --------------------------------------------------------------------------
   WHY THE OUT-OF-PANEL ARROW CAN USE --sb-arrow-y AT ALL
   It's positioned against the ROW, and --sb-arrow-y is measured from the
   PANEL's top edge — different origins. They coincide because the panel is
   align-self:center in a row whose height the photo sets, so the panel's top
   is not the row's top.
   --sb-arrow-out-y therefore carries the row-relative equivalent. It's the
   one value in this section that has to be eyeballed rather than derived,
   because the panel's height isn't knowable in CSS from outside it. If the
   copy length or --sb-media-ratio changes materially, re-measure it.
   --------------------------------------------------------------------------
   THIS SECTION HAS BEEN DUPLICATED BEFORE. An earlier file carried two
   near-identical copies, and the out-of-panel arrow rule was later added
   twice more with a stray brace between the copies — same selector, same
   weight, so the last one won silently and every edit to the others appeared
   to do nothing. If the arrow ever stops responding to edits again, search
   the file for a second copy before changing anything.
   ========================================================================== */
.split-band {
    --sb-media-w: 64%;
    --sb-media-ratio: 7 / 5;
    --sb-media-radius: 0 20px 20px 0;
    --sb-overlap: 180px;                /* how far the panel sits over the
                                           photo                             */
    --sb-panel-bg: rgb(51 51 51 / .9);
    --sb-panel-radius: 20px 0 0 20px;   /* right corners are off-screen      */
    --sb-panel-pad-block: 40px;
    --sb-panel-pad-inline: 96px;
    --sb-panel-gap: 16px;
    --sb-arrow-size: 64px;
    /* Arrow centre, down from the PANEL's top edge. In-panel arrow. */
    --sb-arrow-y: 85px;
    /* Arrow centre, down from the ROW's top edge. Moved-out arrow. See the
       header for why this can't be derived from the one above. */
    --sb-arrow-out-y: 175px;
    /* The seam the arrow straddles, from the row's left edge. 5.2.1 moves
       it. */
    --sb-join: calc(var(--sb-media-w) - var(--sb-overlap));
    position: relative;                 /* anchors a moved-out arrow         */
    display: flex;
    flex-wrap: nowrap;
    gap: 0;
    width: 100%;
}

/* Stop Impreza's inner wrappers claiming a width or anchoring the arrow. */
.split-band :is(.vc_column-inner, .wpb_wrapper) {
    position: static;
    min-width: 0;
}

/* --- the photograph ----------------------------------------------------- */
.split-band .band-media {
    flex: 0 0 var(--sb-media-w);
    width: var(--sb-media-w);
    max-width: none;
    min-width: 0;
    margin: 0;
}

/* clip, not hidden — hidden creates a scroll container, which pins any
   scroll-driven animation inside it at 0%. */
.split-band .band-media .w-image-h {
    display: block;
    width: 100%;
    border-radius: var(--sb-media-radius);
    overflow: clip;
}

/* Fixed crop, so a portrait photo can't double the height of the band. */
.split-band .band-media img {
    display: block;
    width: 100%;
    height: auto;
    aspect-ratio: var(--sb-media-ratio);
    object-fit: cover;
}

/* --- the panel -----------------------------------------------------------
   Centred on the photo (align-self, since Impreza sets align-self on the
   children), pulled left over it, and bled out to the viewport edge with
   50% - 50vw. Padding is !important only because Design Options is.
   ------------------------------------------------------------------------- */
.split-band .band-panel.band-panel {
    align-self: center;
    position: relative;
    z-index: 3;
    flex: 1 1 0;
    min-width: 0;
    margin-right: calc(50% - 50vw);
    margin-block: 0;
    gap: var(--sb-panel-gap);
    padding: var(--sb-panel-pad-block) var(--sb-panel-pad-inline) !important;
    border-radius: var(--sb-panel-radius);
    background: var(--sb-panel-bg);
}


.split-band .band-panel > * {
    max-width: none;
}

/* The gap sets the rhythm, so the heading drops its 45px theme margin. */
.split-band .band-panel h2 {
    margin: 0;
}

.split-band .band-panel .wpb_text_column {
    margin: 8px 0 0;
}

.split-band .band-panel > :last-child {
    margin-bottom: 0;
}

/* Only needed while the copy is one paragraph split by a <br>. Splitting it
   into two paragraphs in the editor makes this redundant. */
.split-band .band-panel .wpb_text_column br {
    display: block;
    content: "";
    margin-bottom: .8em;
}

/* --- the arrow, inside the panel -----------------------------------------
   Centred on the panel's own left edge: left:0 is the panel's PADDING box,
   so this ignores the inline padding and lands on the visible edge.
   translate, not transform — the base arrow-btn uses transform for its
   :active scale and the two would overwrite each other.
   The .band-panel in the chain keeps this off a moved-out arrow.
   ------------------------------------------------------------------------- */
.split-band .band-panel .w-btn-wrapper:has(.band-arrow) {
    position: absolute;
    top: var(--sb-arrow-y);
    left: 0;
    right: auto;
    width: auto;
    max-width: none;
    margin: 0;
    translate: -50% -50%;
    z-index: 3;
}

/* --- the arrow, moved out of the panel -----------------------------------
   Editor structure:
       Horizontal Wrapper  split-band … row-in-snap
          Button           band-arrow                    ← moved out
          Image            band-media column-snap-left
          Vert Wrapper     band-panel column-snap-right
   Anchored to the row, so it's free of the panel's stacking context and its
   z-index:3 clears the photo's z-index:2.
   ------------------------------------------------------------------------- */
.split-band > .w-btn-wrapper:has(.band-arrow) {
    position: absolute;
    top: var(--sb-arrow-out-y);
    left: var(--sb-join);
    right: auto;
    width: auto;
    max-width: none;
    margin: 0;
    translate: -50% -50%;
    z-index: 3;
}

/* Repeated class to outrank the arrow-btn size variants at (0,2,0). */
.split-band .band-arrow.band-arrow.band-arrow {
    --ab-size: var(--sb-arrow-size, 64px);
}

/* The section crops the bleed; the content wrapper must let it out first.
   :is() so this works whether split-band is on the section or inside it. */
.l-section:is(.split-band, :has(.split-band)) {
    overflow: clip;
}

.l-section:is(.split-band, :has(.split-band)) > .l-section-h {
    overflow: visible;
}

/* --- tablet (901–1320) ---------------------------------------------------
   Same side-by-side arrangement, tightened. The panel's padding comes down,
   so both arrow offsets follow it.
   ------------------------------------------------------------------------- */
@media (max-width: 1320px) {
    .split-band {
        --sb-panel-pad-block: 32px;
        --sb-panel-pad-inline: 56px;
        --sb-overlap: 120px;
        --sb-arrow-size: 56px;
        --sb-arrow-y: 68px;
        --sb-arrow-out-y: 130px;
    }
}

/* --- mobile (≤900) -------------------------------------------------------
   Photo and panel stack, panel tucked under the photo's rounded corner. The
   arrow moves INSIDE the panel's padding box, top-left, above the
   standfirst — there's no vertical seam left to straddle, and a button
   hanging half off the screen edge is an unreachable tap target.
   The panel's top padding grows to make room for it, so the standfirst isn't
   pushed down by an element that's out of flow.
   --------------------------------------------------------------------------
   BOTH PLACEMENTS ARE HANDLED. The in-panel arrow is already inside the
   panel's box, so it just needs pinning to the corner. The moved-out one is
   a sibling of the panel, so it's positioned against the ROW instead — its
   offsets are the panel's own inset plus however far down the row the panel
   starts, which on a stack is the photo's height minus the -32px pull.
   The photo has a known aspect ratio and fills the row, so that height IS
   derivable: 100% width ÷ the ratio. No eyeballed number needed here.
   ------------------------------------------------------------------------- */
@media (max-width: 900px) {
    .split-band {
        --sb-panel-pad-block: 28px;
        --sb-panel-pad-inline: 24px;
        --sb-arrow-size: 44px;
        /* Inset of the arrow's CENTRE from the panel's top-left corner. */
        --sb-arrow-m-x: calc(var(--sb-panel-pad-inline) + var(--sb-arrow-size) / 2);
        --sb-arrow-m-y: calc(var(--sb-panel-pad-block) + var(--sb-arrow-size) / 2);
        /* Where the panel's top edge sits, down the row. The photo is full
           width at a fixed ratio, less the panel's -32px overlap. */
        --sb-panel-top: calc(100vw / (var(--sb-media-ratio)) - 32px);
        display: block;
    }

    .split-band .band-media {
        width: 100%;
        max-width: none;
    }

    /* Extra top padding clears the arrow, which is out of flow and can't
       push the standfirst down by itself. */
    .split-band .band-panel.band-panel {
        margin: -32px 0 0;
        padding-top: calc(var(--sb-panel-pad-block) + var(--sb-arrow-size) + 16px) !important;
        border-radius: 20px;
    }

    /* In-panel: stays absolute, repinned to the panel's corner. */
    .split-band .band-panel .w-btn-wrapper:has(.band-arrow) {
        top: var(--sb-arrow-m-y);
        left: var(--sb-arrow-m-x);
        translate: -50% -50%;
    }

    /* Moved out: positioned against the row, into the same corner. */
    .split-band > .w-btn-wrapper:has(.band-arrow) {
        top: calc(var(--sb-panel-top) + var(--sb-arrow-m-y));
        left: var(--sb-arrow-m-x);
        translate: -50% -50%;
    }
}

/* --------------------------------------------------------------------------
   5.2.1  INSET VARIANT — band-inset, added alongside split-band
   The panel stops at the content edge instead of bleeding, and the photo sits
   OVER the panel rather than under it. The seam therefore moves from the
   panel's left edge to the photo's right edge, which is what --sb-join
   carries.
   -------------------------------------------------------------------------- */
.split-band.band-inset {
    --sb-media-w: 50%;
    --sb-media-radius: 20px;
    --sb-panel-radius: 20px;
    --sb-panel-bg: var(--color-dark-dark-grey);
    --sb-panel-pad-block: 64px;
    --sb-arrow-y: 140px;                /* 116 to the heading + 24 padding   */
    --sb-arrow-out-y: 200px;
    --sb-join: var(--sb-media-w);       /* the photo's right edge            */
}

/* The photo comes to the front. */
.band-inset .band-media {
    position: relative;
}

/* z-index back to auto, or the panel becomes a stacking context and traps an
   in-panel arrow behind the photo. No bleed, and the left padding clears the
   overlap so the copy starts beside the photo rather than under it. */
.band-inset .band-panel.band-panel {
    z-index: auto;
    margin-right: 0;
}

@media (max-width: 1320px) {
    .split-band.band-inset {
        --sb-panel-pad-block: 44px;
        --sb-arrow-y: 108px;
        --sb-arrow-out-y: 155px;
    }
}

@media (max-width: 900px) {
    .band-inset .band-panel.band-panel {
        padding-left: var(--sb-panel-pad-inline) !important;
    }
}

/* --- mobile (≤900) -------------------------------------------------------
   Photo above, panel tucked 32px under it. The arrow straddles the horizontal
   seam between the two — half on the photo, half on the panel — mirroring
   what it does on the vertical seam at desktop.
   --------------------------------------------------------------------------
   TOP:0 IS THE SEAM
   The panel is pulled up 32px over the photo, so its top edge IS the join. An
   absolutely positioned child measures from the panel's PADDING box and the
   panel has no border, so top:0 lands exactly on that edge. translate then
   pulls the button back by half its own height, which is what splits it 50/50
   across the two. No arithmetic, and nothing to re-measure if the photo's
   ratio or the -32px overlap ever change.
   --------------------------------------------------------------------------
   THREE LATER RULES HAVE TO BE CLEARED, ALL AT (0,4,0) AND ALL !important OR
   LATER IN THE FILE, SO ORDER ALONE LOSES
     19.8   padding: 32px 28px !important on the panel — wipes any padding-top
            set here, so it's restated at (0,5,0).
     19.4   .w-btn-wrapper:has(.panel-arrow) { position: static } — this band's
            arrow carries panel-arrow as well as band-arrow, so the wrapper
            has to be put back to absolute explicitly.
     19.4   the same wrapper's 28px padding-inline. Not actually matched here
            (its :not(.band-panel *) excludes an in-panel arrow) but zeroed
            anyway, so the moved-out placement below behaves identically.
   If any of those selectors gains a level, lengthen these to match. The
   failure is visible rather than silent.
   --------------------------------------------------------------------------
   The old padding-left line is gone — the base rule in 5.2 already sets the
   panel's inline padding, and 19.8 overrides it regardless.
   ------------------------------------------------------------------------- */
@media (max-width: 900px) {
    .split-band.band-inset {
        /* The panel's ACTUAL inline padding here, which 19.8 forces to 28px.
           The arrow's horizontal inset is measured against this rather than
           --sb-panel-pad-inline, so its left edge lines up with the copy
           below it. Change it here AND in 19.8 together, or the two drift. */
        --sb-pad-inline-m: 28px;
        /* Arrow centre, in from the panel's left edge. */
        --sb-arrow-m-x: calc(var(--sb-pad-inline-m) + var(--sb-arrow-size) / 2);
        /* Air between the bottom of the arrow and the standfirst. */
        --sb-arrow-clear: 18px;
    }

    /* Top padding clears the lower half of the arrow, which is out of flow
       and can't push the standfirst down by itself. */
    .split-band.band-inset.band-inset .band-panel.band-panel {
        padding-top: calc(var(--sb-arrow-size) / 2 + var(--sb-arrow-clear)) !important;
    }

    /* In-panel: the usual placement in the editor. */
    .split-band.band-inset .band-panel .w-btn-wrapper:has(.band-arrow) {
        position: absolute;
        top: 0;
        left: var(--sb-arrow-m-x);
        right: auto;
        bottom: auto;
        margin: 0;
        padding: 0;
        translate: -50% -50%;
        z-index: 3;
    }

    /* Moved out of the panel (a column-snap build). Positioned against the
       ROW, so the panel's top edge has to be measured down it: the photo is
       full width at a fixed ratio, less the -32px overlap. Assumes the row
       runs edge to edge — in a section with gutters this reads a few pixels
       long. The in-panel rule above needs no such assumption. */
    .split-band.band-inset > .w-btn-wrapper:has(.band-arrow) {
        position: absolute;
        top: calc(100vw / (var(--sb-media-ratio)) - 32px);
        left: var(--sb-arrow-m-x);
        right: auto;
        bottom: auto;
        margin: 0;
        padding: 0;
        translate: -50% -50%;
        z-index: 3;
    }
	
	.split-band.band-inset .band-panel.band-panel {
		border-radius: 0 0 20px 20px !important;
	}
}

/* ==========================================================================
   5.3  FEATURE BAND — .feature-band on the Horizontal Wrapper, nothing else
   Dark panel right, photo left overlapping ON TOP of it, blue arrow sitting
   on the photo's top-right corner. No JS.
   --------------------------------------------------------------------------
   EDITOR SETUP
   Horizontal Wrapper  -> feature-band          (gap 0)
      Button           -> arrow-btn             (the blue arrow)
      Image                                     (the photo)
      Vertical Wrapper                          (the panel)
        Text                                    (the heading)
        Text block                              (the blue lead)
        Text block                              (the body copy)
        Button                                  (the CTA)
   ORDER IS THE ONLY THING IDENTIFYING THESE ELEMENTS. The arrow is the Button
   sitting directly in the band; the CTA is the Button inside the panel.
   Reorder them in the editor and the styling follows the new order, not the
   content.
   --------------------------------------------------------------------------
   THE ARROW IS AN ARROW-BTN. Its box, glyph, ring, hover and sizing all come
   from 3.0; only two variables are overridden below. This section used to
   draw its own arrow with its own mask, which is why it never matched the
   rest of the site and why changes to the shared glyph appeared to do nothing
   here.
   THE PANEL IS THE TALLER ELEMENT. That is why the photo is given a fixed
   HEIGHT rather than an aspect-ratio — a ratio derives the height from the
   width, which made the photo the tallest thing in the row and left the panel
   looking like the smaller of the two. With a fixed height the photo is
   always shorter than the panel's min-height, and the arrow's position can be
   worked out from it.
   ========================================================================== */
.feature-band {
    --fb-media-w:        50%;
    --fb-media-h:        520px;         /* the photo. Always < the panel's
                                           min-height                        */
    --fb-media-radius:   20px;
    --fb-overlap:        120px;         /* how far the photo sits over the
                                           panel                             */
    --fb-panel-bg:       #2c2c2c;
    --fb-panel-radius:   20px;
    --fb-panel-min-h:    660px;         /* the panel is the taller element   */
    --fb-panel-pad:      64px;
    --fb-panel-pad-left: 184px;         /* overlap + pad, so the copy clears
                                           the photo                         */
    --fb-heading-size:   48px;
    --fb-lead-size:      21px;
    --fb-body-size:      17px;
    --fb-gap:            28px;
    --fb-arrow-size:     64px;
    --fb-accent:         #29a5e3;
    position: relative;                 /* the arrow anchors to this         */
    display: flex;
    flex-wrap: nowrap;
    align-items: center;
    gap: 0;
    width: 100%;
}

/* Stop Impreza's inner wrappers claiming a width or anchoring the arrow. */
.feature-band :is(.vc_column-inner, .wpb_wrapper) {
    position: static;
    min-width: 0;
}

/* --- the photograph ------------------------------------------------------
   Fixed height, centred in the row, and in front of the panel — which is what
   makes the panel's left corner tuck behind it. It needs position for z-index
   to apply.
   The radius and clip are on this element as well as on .w-image-h below,
   because img-zoom (2.6) puts its own overflow:clip on .w-image — the outer
   box. Without a matching radius there, a zoom escapes the rounded corners
   and squares them off.
   ------------------------------------------------------------------------- */
.feature-band > .w-image {
    position: relative;
    z-index: 2;
    flex: 0 0 var(--fb-media-w);
    width: var(--fb-media-w);
    max-width: none;
    min-width: 0;
    align-self: center;
    margin: 0;
    border-radius: var(--fb-media-radius);
    overflow: clip;
}

/* clip, not hidden — hidden would create a scroll container. */
.feature-band > .w-image .w-image-h {
    display: block;
    width: 100%;
    height: var(--fb-media-h);
    border-radius: var(--fb-media-radius);
    overflow: clip;
}

.feature-band > .w-image img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

/* --- the panel -----------------------------------------------------------
   Sits BEHIND the photo, so the negative margin goes on the panel's own left
   edge rather than pulling it over the image. z-index stays auto — giving it
   one would create a stacking context and trap the arrow behind the photo.
   Repeated class because Impreza writes align-self and padding onto wrappers
   from Design Options.
   ------------------------------------------------------------------------- */
.feature-band > .w-vwrapper.w-vwrapper {
    position: relative;
    z-index: auto;
    flex: 1 1 0;
    min-width: 0;
    min-height: var(--fb-panel-min-h);
    align-self: center;
    justify-content: center;
    margin-left: calc(-1 * var(--fb-overlap));
    margin-right: 0;
    margin-block: 0;
    gap: var(--fb-gap);
    padding: var(--fb-panel-pad) var(--fb-panel-pad)
             var(--fb-panel-pad) var(--fb-panel-pad-left);
    background: var(--fb-panel-bg);
    border-radius: var(--fb-panel-radius);
}

.feature-band > .w-vwrapper > * {
    max-width: none;
    margin: 0;
}

/* --- type ----------------------------------------------------------------
   The heading is the Text element; the lead and the body are the two Text
   blocks, matched in order. Colours go on the inner elements too, since the
   theme colours those directly.
   ------------------------------------------------------------------------- */
.feature-band .w-text,
.feature-band .w-text .w-text-h {
    color: #fff;
    font-size: var(--fb-heading-size);
    font-weight: 100;
    line-height: 1.2;
    text-decoration: none;
}

.feature-band .wpb_text_column:nth-of-type(1),
.feature-band .wpb_text_column:nth-of-type(1) :is(h1, h2, h3, h4, h5, h6, p) {
    color: var(--fb-accent);
    font-size: var(--fb-lead-size);
    font-weight: 400;
    line-height: 1.35;
}

.feature-band .wpb_text_column:nth-of-type(2),
.feature-band .wpb_text_column:nth-of-type(2) p {
    color: #fff;
    font-size: var(--fb-body-size);
    font-weight: 400;
    line-height: 1.5;
}

.feature-band .wpb_text_column :is(h1, h2, h3, h4, h5, h6, p) {
    margin: 0 0 1em;
}

.feature-band .wpb_text_column :is(h1, h2, h3, h4, h5, h6, p):last-child {
    margin-bottom: 0;
}

/* --- the arrow -----------------------------------------------------------
   Sat on the photo's TOP-RIGHT corner. The photo is centred and has a known
   height, so its top edge is half its height above the row's centre line —
   which is what the top calculation says. Its right edge is --fb-media-w
   across. translate then centres the button on that corner.
   translate, not transform — the arrow-btn uses transform for its :active
   scale and the two would overwrite each other.
   ------------------------------------------------------------------------- */
.feature-band > .w-btn-wrapper {
    position: absolute;
    top: calc(50% - var(--fb-media-h) / 2);
    left: var(--fb-media-w);
    right: auto;
    width: auto;
    max-width: none;
    margin: 0;
    translate: -50% -50%;
    z-index: 3;
}

/* Everything else about this button comes from 3.0 — including
   --ab-glyph-size, which is what controls how large the arrow renders inside
   its box.
   Four repeats to clear that section's own (0,4,0) hover chain; the
   .feature-band ancestor adds a level the base rules don't have, but the
   repeats keep this winning even on the hover states. */
.feature-band .arrow-btn.arrow-btn.arrow-btn.arrow-btn {
    --ab-size: var(--fb-arrow-size);
    --ab-blue: var(--fb-accent);
}

/* --- mobile ------------------------------------------------------------- */
@media (max-width: 900px) {
    .feature-band {
        --fb-media-h: 320px;
        --fb-panel-min-h: 0;
        --fb-panel-pad: 30px;
        --fb-panel-pad-left: 30px;
        --fb-arrow-size: 44px;
        --fb-heading-size: 28px;
        --fb-lead-size: 19px;
        display: block;
    }

    .feature-band > .w-image {
        width: 100%;
        max-width: none;
    }

    .feature-band > .w-vwrapper.w-vwrapper {
        margin: -40px 0 0;
    }

    .feature-band > .w-btn-wrapper {
        position: static;
        translate: none;
        margin: 0 0 12px;
    }
}

/* --------------------------------------------------------------------------
   5.3.1  FEATURE BAND — ALT
   Same layout, minus the dark panel. Add alongside the base class:
   `feature-band feature-band-alt` on the Horizontal Wrapper.
   With no panel to sit against, three things follow from that one change: the
   copy no longer needs padding to clear a background, the overlap between
   photo and text is dropped so the two sit side by side, and the panel's
   min-height goes — it existed to make the panel taller than the photo, which
   only mattered when it was a visible box.
   The heading's colour is left alone: it inherits white from the section,
   same as it did on the dark panel.
   -------------------------------------------------------------------------- */
.feature-band.feature-band-alt {
    --fb-overlap:        0px;
    --fb-panel-bg:       transparent;
    --fb-panel-radius:   0px;
    --fb-panel-min-h:    0;
    --fb-panel-pad:      64px;
    --fb-panel-pad-left: 64px;
}

/* The panel keeps its flex sizing and vertical centring from the base rule;
   only the box comes off. Repeated class to match the base rule's
   .feature-band > .w-vwrapper.w-vwrapper at (0,3,0). */
.feature-band-alt > .w-vwrapper.w-vwrapper {
    min-height: 0;
    background: none;
    border-radius: 0;
}

/* --- full-bleed photo ----------------------------------------------------
   The image escapes the content wrapper with 50% - 50vw, which is the
   distance from its own left edge out to the viewport's. That works from
   inside a centred container without needing to know its width.
   Radius only on the two edges that are still on screen — square where it
   meets the viewport, rounded where it faces the copy. Set on both boxes for
   the img-zoom reason noted on the base rule.
   ------------------------------------------------------------------------- */
.feature-band-alt > .w-image {
    margin-left: calc(50% - 50vw);
    border-radius: 0 var(--fb-media-radius) var(--fb-media-radius) 0;
}

.feature-band-alt > .w-image .w-image-h {
    border-radius: 0 var(--fb-media-radius) var(--fb-media-radius) 0;
}

/* The section crops the bleed; the content wrapper has to let it out first.
   Without the second rule the image is clipped at 1600px and the bleed does
   nothing. */
.l-section:has(.feature-band-alt) {
    overflow: clip;
}

.l-section:has(.feature-band-alt) > .l-section-h {
    overflow: visible;
}

/* --- mobile --------------------------------------------------------------
   The base rule pulls the panel up by -40px to tuck it under the photo's
   rounded corner. With no panel background there's nothing to tuck, so that
   becomes a plain gap instead.
   ------------------------------------------------------------------------- */
@media (max-width: 900px) {
    .feature-band.feature-band-alt {
        --fb-panel-pad-left: 0px;
    }

    .feature-band-alt > .w-vwrapper.w-vwrapper {
        margin: 40px 0 0;
    }
}

/* ==========================================================================
   5.4  CAPABILITIES CARDS — .capabilities-row on the Section
   Heading sits directly in the column; the cards are the .w-vwrapper children
   of the .w-hwrapper below it, each holding:
     Image → Text .cap-title → Text .cap-desc → Button .arrow-btn
   HOVER: the card lifts by --cap-lift and fills with --cap-bg-hover. The
   border takes the same colour so it disappears into the fill. Title and
   description switch to --cap-ink-hover, the icon is forced to white, and
   the arrow slides from the left of the card to the right.
   ========================================================================== */
.capabilities-row {
    --cap-columns:      5;
    --cap-gap:          40px;
    --cap-bg:           #000;
    --cap-bg-hover:     #36bdf6;
    --cap-border:       #29a5e3;
    --cap-border-hover: var(--cap-bg-hover);
    --cap-radius:       20px;
    --cap-pad:          34px;
    --cap-min-height:   450px;
    --cap-lift:         -18px;
    --cap-accent:       #29a5e3;
    --cap-ink-hover:    #2d2d2d;
    --cap-icon:         96px;
    --cap-icon-gap:     48px;
    --cap-title-size:   24px;
    --cap-title-lh:     1.2;
    --cap-desc-size:    20px;
    --cap-desc-gap:     27px;
    --cap-arrow:        50px;
    --cap-arrow-speed:  .5s;
    --cap-speed:        .3s;
}

/* --- the row of cards ----------------------------------------------------
   Repeated class to clear Impreza's own .w-hwrapper rules. Grid rather than
   the theme's flex, so all five columns are exactly equal whatever the copy
   length.
   ------------------------------------------------------------------------- */
.capabilities-row .w-hwrapper.w-hwrapper {
    display: grid;
    grid-template-columns: repeat(var(--cap-columns), minmax(0, 1fr));
    gap: var(--cap-gap);
    align-items: stretch;
    width: 100%;
    margin: 0;
}

/* --- the card ------------------------------------------------------------
   THIS RULE IS ALSO A hover-lift TARGET.
   The cards carry hover-lift from 2.6, but that rule is (0,1,0) and this one
   is (0,3,0), so a transition declared here REPLACES the shared one rather
   than adding to it. The movement properties are therefore repeated here.
   The resting rule carries the OUT timing and the hover rule below carries
   the IN, the same split as 2.6.
   The fallbacks matter: --hv-in and friends are declared inside a
   (hover: hover) query in 2.6, so on a touch device they don't exist.
   The hover rule sets translate itself, which outranks 2.6's lift distance.
   That makes --cap-lift the one place to tune how far these cards rise.
   The scale from 2.6 is untouched.
   ------------------------------------------------------------------------- */
.capabilities-row .w-hwrapper > .w-vwrapper {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 0;                             /* the margins below set the rhythm  */
    height: 100%;
    min-height: var(--cap-min-height);
    min-width: 0;
    margin: 0;
    padding: var(--cap-pad);
    background: var(--cap-bg);
    border: 3px solid var(--cap-border);
    border-radius: var(--cap-radius);
    transition:
        background-color var(--cap-speed) ease,
        border-color     var(--cap-speed) ease,
        translate var(--hv-out, 480ms) var(--hv-out-ease, ease),
        scale     var(--hv-out, 480ms) var(--hv-out-ease, ease);
}

.no-touch .capabilities-row .w-hwrapper > .w-vwrapper:hover {
    translate: 0 var(--cap-lift);
    background-color: var(--cap-bg-hover);
    border-color: var(--cap-border-hover);
    transition:
        background-color var(--cap-speed) ease,
        border-color     var(--cap-speed) ease,
        translate var(--hv-in, 340ms) var(--hv-in-ease, ease),
        scale     var(--hv-in, 340ms) var(--hv-in-ease, ease);
}

/* --- icon ----------------------------------------------------------------
   The BOX is a fixed square, not the image. Each icon then sits inside that
   square at its own proportions, anchored top-left. That way five icons of
   five different shapes all occupy identical space, and every title below
   them starts at the same height.
   On hover the filter flattens whatever colour the icon is drawn in to pure
   white, so it works for any single-colour line icon.
   ------------------------------------------------------------------------- */
.capabilities-row .w-hwrapper .w-image,
.capabilities-row .w-hwrapper .w-image-h {
    display: block;
    flex: none;
    width: var(--cap-icon);
    height: var(--cap-icon);
    max-width: none;
    margin: 0;
    padding: 0;
}

.capabilities-row .w-hwrapper .w-image img {
    display: block;
    width: 100%;
    height: 100%;
    max-width: none;
    margin: 0;
    object-fit: contain;
    object-position: left top;
    transition: filter var(--cap-speed) ease;
}

.no-touch .capabilities-row .w-hwrapper > .w-vwrapper:hover .w-image img {
    filter: brightness(0) invert(1);
}

/* --- title ---------------------------------------------------------------
   Two lines are always reserved, so the descriptions line up across all five
   cards whether the title runs to one line or two.
   ------------------------------------------------------------------------- */
.capabilities-row .cap-title {
    display: block;
    margin: var(--cap-icon-gap) 0 0;
    min-height: calc(var(--cap-title-size) * var(--cap-title-lh) * 2);
    font-size: var(--cap-title-size);
    font-weight: 500;
    line-height: var(--cap-title-lh);
}

.capabilities-row .cap-title,
.capabilities-row .cap-title .w-text-h {
    color: var(--cap-accent);
    text-decoration: none;
    transition: color var(--cap-speed) ease;
}

/* --- description --------------------------------------------------------- */
.capabilities-row .cap-desc {
    display: block;
    margin: var(--cap-desc-gap) 0 0;
    font-size: var(--cap-desc-size);
    font-weight: 300;
    line-height: 1.4;
}

.capabilities-row .cap-desc,
.capabilities-row .cap-desc .w-text-h {
    color: var(--cap-accent);
    text-decoration: none;
    transition: color var(--cap-speed) ease;
}

/* --- text on hover ------------------------------------------------------- */
.no-touch .capabilities-row .w-hwrapper > .w-vwrapper:hover .cap-title,
.no-touch .capabilities-row .w-hwrapper > .w-vwrapper:hover .cap-title .w-text-h,
.no-touch .capabilities-row .w-hwrapper > .w-vwrapper:hover .cap-desc,
.no-touch .capabilities-row .w-hwrapper > .w-vwrapper:hover .cap-desc .w-text-h {
    color: var(--cap-ink-hover);
}

/* --- arrow ---------------------------------------------------------------
   An arrow-btn, so the glyph, sizing and rotation come from 3.0. Only three
   things change here: a thinner arrow, no blue box, no ring.
   Four repeats of .arrow-btn to clear its own (0,3,0) and (0,4,0) chains.
   translate, not transform: the base arrow-btn uses transform for its
   :active scale, and the two would overwrite each other.
   The ink stays white in both states, since it reads on black and on the
   fill.
   THE SLIDE: the wrapper is stretched to the card's full inner width and
   made a size container. 100cqw is then that width, so the arrow travels
   exactly (inner width − arrow width) and stops flush with the right-hand
   padding at every breakpoint. No magic numbers are needed.
   ------------------------------------------------------------------------- */
.capabilities-row .w-btn-wrapper {
    display: block;
    align-self: stretch;                /* full width, despite flex-start    */
    width: 100%;
    margin: auto 0 0;                   /* pins the arrow to the card's foot */
    text-align: left;
    container-type: inline-size;
}

.capabilities-row .arrow-btn.arrow-btn.arrow-btn.arrow-btn {
    --ab-size: var(--cap-arrow);
    --ab-ink: #fff;
    --ab-glyph-size: 60%;
    --ab-glyph: url("https://www.hec-precision.co.uk/wp-content/uploads/ARROW-RIGHT-PLAIN.svg");
    background: transparent;
    box-shadow: none;
    transition: translate var(--cap-arrow-speed) cubic-bezier(.65, 0, .35, 1);
}

/* The ring would draw a box around the arrow on hover. */
.capabilities-row .arrow-btn.arrow-btn.arrow-btn.arrow-btn::after {
    display: none;
}

.no-touch .capabilities-row .w-vwrapper:hover .arrow-btn.arrow-btn.arrow-btn.arrow-btn {
    translate: calc(100cqw - var(--cap-arrow)) 0;
}

/* Older browsers without container units fall back to the original nudge. */
@supports not (width: 1cqw) {
    .no-touch .capabilities-row .w-vwrapper:hover .arrow-btn.arrow-btn.arrow-btn.arrow-btn {
        translate: 8px 0;
    }
}

/* --- responsive ---------------------------------------------------------- */
@media (max-width: 1320px) {
    .capabilities-row {
        --cap-columns: 3;
        --cap-gap: 28px;
    }
}

@media (max-width: 900px) {
    .capabilities-row {
        --cap-columns: 2;
        --cap-pad: 26px;
        --cap-icon: 72px;
        --cap-icon-gap: 34px;
        --cap-min-height: 380px;
        --cap-lift: -12px;
    }
}

@media (max-width: 600px) {
    .capabilities-row {
        --cap-columns: 1;
        --cap-min-height: 0;
    }

    .capabilities-row .cap-title {
        min-height: 0;
    }
}

/* ==========================================================================
   5.5  CAPABILITY CAROUSEL
   Centre slide shows its title, copy and button; the slides either side dim
   back to just their image. The companion JS marks the centre slide with
   .is-centre — see that snippet for why the detection isn't done here.
   --------------------------------------------------------------------------
   MEASURED FROM THE LIVE PAGE — what Owl is actually doing
   At a 1920 viewport: items 3, margin 30, centre mode OFF, loop OFF,
   stagePadding 0. Container 1600, slide 1504.
   Owl computes stage and slide widths in JS at init, from those settings,
   before any of this runs. So this section deliberately does NOT set the
   carousel's width and does not try to make slides spill out of it. An
   earlier version did both — a max-width on .cap-carousel plus
   overflow:visible on the stage — which is what several rounds went into
   fighting. Horizontal geometry belongs to Owl; everything inside the slide
   belongs here.
   STILL UNRESOLVED: 3 items in a 1600 container with a 30 margin should give
   roughly 513 per slide, but a slide measures 1504. Something is overriding
   items at this breakpoint — check the carousel's responsive settings in the
   editor. Until that is settled the numbers below are shapes, not final
   sizes.
   ========================================================================== */
.cap-carousel {
    /* --- set these from the design --------------------------------------- */
    --cap-radius: 18px;      /* corner radius on the slide image             */
    --cap-width: 1000px;     /* width of the CAROUSEL. Owl sizes its slides
                                from the container at init, so narrowing the
                                container narrows the slide and, with it, the
                                distance between slides — which is what brings
                                the neighbours in close enough to show.
                                Depends on the resize event the JS dispatches;
                                without it Owl keeps its original geometry.   */
    --cap-slide-w: 1000px;   /* width of the slide's CONTENTS, as a max. Now
                                that the carousel is capped above, the slide
                                already arrives at the right width and this
                                rarely bites — it stays as a backstop for
                                breakpoints where Owl hands over more.        */
    --cap-img-ratio: 16 / 9; /* image shape. Replaces an earlier fixed
                                height: that meant slide width and image
                                shape drifted apart whenever either moved.
                                Tying them means one number controls both.
                                At the slide's full 1504 width a 4/3 ratio
                                made an 1128px-tall image, which is what went
                                wrong first time.                            */
    --cap-arrow-size: 78px;
    --cap-overlap: 38px;     /* how far the meta rides up over the image     */
    --cap-arrow-x: 32px;     /* arrow offset: positive moves it right        */
    --cap-arrow-y: -28px;    /* arrow offset: negative moves it up           */
    /* --- settled ---------------------------------------------------------- */
    --cap-dim: .25;          /* how far the side slides fade back            */
    --cap-scale: .94;        /* and how far they sit back                    */
    --cap-accent: #00b7ff;
    --cap-speed: 520ms;
    --cap-ease: cubic-bezier(.22, .68, .3, 1);
}

/* Only .owl-item. An earlier version also listed .w-grid-item and
   .swiper-slide for portability across Impreza's carousel types, but on this
   markup a .w-grid-item nested inside an .owl-item would have matched both and
   compounded — .25 x .25 opacity, .94 x .94 scale. The probe confirmed there
   are none here (gridItem=0), so the extra selectors are all risk and no
   benefit. */
.cap-carousel .owl-item {
    opacity: var(--cap-dim);
    transform: scale(var(--cap-scale));
    transition:
        opacity var(--cap-speed) var(--cap-ease),
        transform var(--cap-speed) var(--cap-ease);
}

.cap-carousel .owl-item.is-centre {
    opacity: 1;
    transform: none;
}

/* --- the meta block ------------------------------------------------------
   Collapsed on the side slides rather than hidden, so the carousel's height
   doesn't jump as it moves — the 0fr to 1fr trick, animating to the natural
   height without needing to know it.
   cap-btn sits on the <a> itself, so the collapse goes on its wrapper;
   applying grid to the link would break the button's own layout.
   ------------------------------------------------------------------------- */
.cap-carousel .cap-title,
.cap-carousel .cap-text,
.cap-carousel .w-btn-wrapper:has(.cap-btn) {
    display: grid;
    grid-template-rows: 0fr;
    opacity: 0;
    transition:
        grid-template-rows var(--cap-speed) var(--cap-ease),
        opacity 300ms ease;
}

.cap-carousel .cap-title > *,
.cap-carousel .cap-text > *,
.cap-carousel .w-btn-wrapper:has(.cap-btn) > * {
    overflow: hidden;
}

.cap-carousel .is-open .cap-title,
.cap-carousel .is-open .cap-text,
.cap-carousel .is-open .w-btn-wrapper:has(.cap-btn) {
    grid-template-rows: 1fr;
    opacity: 1;
}

.cap-carousel .is-open .cap-title { transition-delay: 0s, 120ms; }
.cap-carousel .is-open .cap-text  { transition-delay: 0s, 180ms; }
.cap-carousel .is-open .w-btn-wrapper:has(.cap-btn) { transition-delay: 0s, 240ms; }

/* The slide puts title, copy and button in a horizontal wrapper. The design
   lays them out around the arrow instead, with the whole block pulled up so
   the arrow and title straddle the image's bottom edge. */
.cap-carousel .w-hwrapper {
    display: grid;
    grid-template-columns: auto 1fr auto;
    grid-template-areas:
        "arrow title title"
        ".     text  text"
        ".     .     button";
    align-items: end;
    gap: .5rem 1.5rem;
    width: 100%;
    margin-top: calc(-1 * var(--cap-overlap));
}

/* --- the arrow -----------------------------------------------------------
   An arrow-btn from 3.0, so glyph, ring, sizing and rotation all come from
   there. Direction is carried inline by the JS, which writes --ab-rest on
   click — the one place on the site that sets an arrow angle by hand rather
   than with a class.
   ------------------------------------------------------------------------- */

/* --cap-arrow-size was declared in an earlier version but never referenced by
   anything, so tuning it did nothing — the arrow was sized entirely by
   arrow-btn-lg's --ab-size: 88px, set at (0,2,0) on the element itself. This
   is the rule that connects them. Repeated class plus the descendant gives
   (0,3,0), which clears it; the 88px fallback keeps the arrow correct if the
   variable is ever removed. */
.cap-carousel .cap-arrow.cap-arrow.cap-arrow {
    --ab-size: var(--cap-arrow-size, 88px);
}

/* align-self: start is what stops the arrow drifting down when a slide opens.
   The wrapper is align-items: end, so everything sits on the bottom of its
   row — but the title shares row 1 with the arrow and expands from zero
   height on open, making the row taller. A bottom-aligned arrow gets carried
   down with the row's new floor. Anchored to the top of the row instead, it
   does not move, because the row's top edge never does.
   Offset with the `translate` property, not `transform`. The base arrow
   button sets transform: scale(.94) on :active, which would overwrite a
   transform-based offset and make the arrow jump back to its unoffset
   position on every click. `translate` is a separate property, so the two
   compose instead of fighting. */
.cap-carousel .cap-arrow {
    grid-area: arrow;
    align-self: start;
    translate: var(--cap-arrow-x) var(--cap-arrow-y);
    padding: 0;
    border: 0;
    cursor: pointer;
    background: rgb(255 255 255 / .12);
}

.cap-carousel .cap-title  { grid-area: title; align-self: end; }
.cap-carousel .cap-text   { grid-area: text; }
.cap-carousel .w-btn-wrapper:has(.cap-btn) { grid-area: button; }

/* The base button shrinks to scale(.94) while pressed. In the hero that reads
   as a press; here the arrow is top-aligned in its grid cell, so shrinking
   moves its edges and reads as the arrow slipping rather than being pushed.
   Suppressed for this arrow only — the hero keeps its press feedback.
   Repeated classes plus the descendant to clear .arrow-btn.arrow-btn:active,
   which is (0,2,0). */
.cap-carousel .cap-arrow.cap-arrow.cap-arrow:active {
    transform: none;
}

.cap-carousel .cap-arrow::before {
    background-color: rgb(255 255 255 / .5);
}

/* The base hover rule turns the glyph to --ab-hover. Here the direction is
   meaningful — it says whether the panel is open — so hover must leave it
   alone and hold the resting angle the JS has written inline. Repeated
   classes to outrank that rule's four-deep chain. */
.cap-carousel .cap-arrow.cap-arrow.cap-arrow:is(:hover, :focus-visible)::before {
    transform: rotate(var(--ab-rest));
}

.cap-carousel .owl-item.is-centre .cap-arrow {
    background: var(--cap-accent);
}

.cap-carousel .owl-item.is-centre .cap-arrow::before {
    background-color: #000;
}

.cap-carousel .owl-item.is-centre .cap-arrow::after {
    opacity: 1;
    transform: scale(1);
}

/* --- slide contents ------------------------------------------------------
   Photos arrive at whatever shape they were shot in, so they are cropped to a
   consistent ratio — otherwise a portrait shot makes one slide twice the
   height of its neighbours.
   The cap is applied to the image block and the meta rather than to the slide
   itself, so Owl's stage arithmetic is left alone — the slide box stays
   whatever width Owl computed, and the contents sit centred inside it. That
   keeps this working whichever way the items setting is eventually resolved.
   ------------------------------------------------------------------------- */
.cap-carousel .w-image,
.cap-carousel .w-hwrapper {
    max-width: var(--cap-slide-w);
    margin-inline: auto;
}

.cap-carousel .w-image,
.cap-carousel .w-image-h {
    display: block;
    width: 100%;
}

.cap-carousel .w-image-h img {
    display: block;
    width: 100%;
    height: auto;
    aspect-ratio: var(--cap-img-ratio);
    object-fit: cover;
    border-radius: var(--cap-radius);
}

/* Some Impreza image blocks wrap the img in a link or an inner div that can
   crop the corners back to square. Clipping the wrapper too makes the radius
   hold whichever markup the block produces. clip, not hidden. */
.cap-carousel .w-image-h {
    border-radius: var(--cap-radius);
    overflow: clip;
}

/* The slide's own wrappers shrink to their content by default, which is what
   was squeezing the copy into a narrow column. */
.cap-carousel .owl-item > .w-vwrapper,
.cap-carousel .w-hwrapper {
    width: 100%;
}

.cap-carousel .cap-text,
.cap-carousel .cap-text .wpb_wrapper {
    min-width: 0;
    width: 100%;
}

.cap-carousel .cap-title {
    margin: 1.2rem 0 .6rem;
    font-size: 30px;
    font-weight: 700;
    line-height: 1.2;
    color: #fff;
}

.cap-carousel .cap-text {
    max-width: none;
    font-size: 16px;
    line-height: 1.5;
    color: #fff;
}

/* --- peeking: showing half a neighbour each side -------------------------
   Two rules working together.
   First, the carousel is narrowed. Owl divides the container to size its
   slides, so a 1000px container gives a 1000px slide and a pitch of 1030 with
   the 30 margin — instead of the 1504 slide and 1534 pitch it computes from
   the full 1600 container, which parks the neighbours off screen entirely.
   This only takes effect because the JS dispatches a resize event after init;
   Owl measures once and will otherwise keep its first answer.
   Second, the stage clip is released so the neighbours can leave the
   carousel's box, and the section crops them instead. Clipping on the
   carousel itself is no good — it crops at exactly the stage width, so
   nothing peeks.
   How much shows is then (viewport - slide) / 2 per side, less the margin:
   about 430px at a 1920 viewport, a little under half a slide. Narrow
   --cap-width to show more of them, widen it to show less.
   ------------------------------------------------------------------------- */
.cap-carousel {
    max-width: var(--cap-width);
    margin-inline: auto;
}

.cap-carousel .owl-stage-outer {
    overflow: visible;
}

/* clip, not hidden — hidden would make the section a scroll container, which
   pins any scroll-driven animation inside it at 0%. */
.l-section:has(.cap-carousel) {
    overflow: clip;
}

/* .l-section-h is the content-width wrapper. It has to stay visible, or it
   crops at the carousel's own edge — the one place the neighbours must be
   able to escape. */
.l-section-h:has(.cap-carousel) {
    overflow: visible;
}

/* --- reduced motion ----------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
    .cap-carousel .owl-item,
    .cap-carousel .cap-title,
    .cap-carousel .cap-text,
    .cap-carousel .w-btn-wrapper:has(.cap-btn) {
        transition-duration: 1ms;
    }
}


/* ==========================================================================
   5.6  DIRECTION SWITCHER
   REPLACES the whole of the previous 5.6, from its header down to the end of
   its reduced-motion block. The desktop rules are unchanged; only the header
   and everything under STACKED LAYOUT are new.
   ALSO DELETE 18.11 (Direction switcher, multi-box panel) in full — both of
   its media blocks. It rewrote the panel for the old carousel and fights
   everything below. Leave a one-line comment in its place so the numbering
   holds.
   --------------------------------------------------------------------------
   Three words on the left, stacked panels on the right. Clicking a word turns
   it blue, slides its arrow out, swaps the panel. That is the layout at
   1440px and up.
   Below 1440 the same two columns stack: the words become a row of tabs
   across the top of the section, with a rule under the open one, and the
   panel sits full width beneath. Same words, same panels, same click. The
   copy is never collapsed, nothing scrolls sideways, and nothing is moved in
   the DOM — the JS is the same at every width, so there is no size at which
   markup and styling can disagree.
   --------------------------------------------------------------------------
   EDITOR SETUP (unchanged)
     dir-word     each of the three Text blocks in the left column
     dir-panels   the right column
     dir-panel    each panel inside it, in the same order as the words
   The three words carry xxxl-text from an earlier round. It no longer does
   anything — the size is set here at every width — so it can come off, but it
   does no harm left on.
   --------------------------------------------------------------------------
   PAIRS WITH the DIRECTION SWITCHER JS snippet, which pairs words to panels,
   draws the arrows, wraps each block of copy in .dir-reveal, and adds .dir-js
   to <html>. Until that lands, every panel is shown in flow so the copy is
   never unreachable.
   --------------------------------------------------------------------------
   WHY THE SPLIT LAYOUT STOPS AT 1440
   Every alignment constant in it — where the first icon box starts, how far
   the four boxes span, where the single icon is pinned — was measured against
   the arrows at 120px words. Expressed as ratios they survive a little
   shrinking and then drift. It runs at the size it was tuned at; the stacked
   layout takes everything below.
   ========================================================================== */

/* --- tokens --------------------------------------------------------------
   Declared on both roots rather than a shared ancestor, because the words and
   the panels are separate Impreza columns and there is no element between
   them that wraps only this component.
   ------------------------------------------------------------------------- */
.dir-word,
.dir-panels {
    --dir-word-size: 120px;
    --dir-accent: #00b7ff;
    --dir-blue: #00b7ff;
    --dir-title-size: 19px;
    --dir-text-size: 17px;
    --dir-lead-size: 21px;
    --dir-hero-size: 30px;
    --dir-reveal-speed: 520ms;
    --dir-ease: cubic-bezier(.22, 1, .3, 1);
    /* The glyph the word arrow masks. Defined here, not in the JS, so the
       arrow still draws if the script is edited or replaced. Any single
       colour SVG works — it is used as a mask, so only its alpha matters. */
    --dir-glyph: url("https://www.hec-precision.co.uk/wp-content/uploads/ARROW-RIGHT.svg");
}

.dir-word {
    /* !important because the size utilities in 1.1 are, which makes this
       section the single source of truth for the word size. */
    font-size: var(--dir-word-size) !important;
    line-height: 1;
    /* A grid rather than a flex row, so the arrow sits in a fixed column
       instead of trailing whatever the word happens to be. That is what makes
       all three land in the same place — "Vision" and "Mission" are different
       widths, and flex would put their arrows different distances from the
       left.
       --dir-col is in em so it tracks the word size: 3.7em is a shade wider
       than "Mission", the longest of the three. Re-measure if you add a
       longer word. */
    display: grid;
    grid-template-columns: var(--dir-col, 3.7em) auto;
    align-items: center;
    cursor: pointer;
    color: #fff;
    transition: color 320ms ease;
    -webkit-user-select: none;
    user-select: none;
}

.dir-word .w-text-h,
.dir-word h1,
.dir-word h2,
.dir-word h3,
.dir-word p,
.dir-word span {
    font-size: inherit;
    font-weight: inherit;
    line-height: inherit;
    color: inherit;
    margin: 0;
}

.dir-word:hover,
.dir-word.is-active {
    color: var(--dir-accent);
}

.dir-word:focus-visible {
    outline: 2px solid var(--dir-accent);
    outline-offset: 6px;
}

/* --- the word arrow, built by the JS -------------------------------------
   Resting flush against the word, sliding out to the right when active. The
   distance is in em so it scales with the headline.
   ------------------------------------------------------------------------- */
.dir-arrow {
    --dir-size: .55em;
    position: relative;
    flex: none;
    width: var(--dir-size);
    height: var(--dir-size);
    border-radius: 22%;
    background: rgb(255 255 255 / .09);
    opacity: 0;
    transform: translateX(-.45em);
    transition:
        opacity 260ms ease,
        transform 620ms var(--dir-ease),
        background-color 320ms ease;
}

.dir-word:hover .dir-arrow,
.dir-word:focus-visible .dir-arrow {
    opacity: 1;
    transform: none;
}

.dir-arrow::before {
    content: "";
    position: absolute;
    inset: 22%;
    background-color: rgb(255 255 255 / .55);
    -webkit-mask: var(--dir-glyph) center / contain no-repeat;
    mask: var(--dir-glyph) center / contain no-repeat;
    transition: background-color 320ms ease;
}

/* The ring, drawn outside the box like the hero arrow's. */
.dir-arrow::after {
    content: "";
    position: absolute;
    inset: -7%;
    border: 2px solid var(--dir-accent);
    border-radius: 26%;
    opacity: 0;
    transform: scale(1.25);
    transition:
        opacity 320ms ease,
        transform 620ms var(--dir-ease);
}

/* Active holds the hovered position — no extra travel, or the three would
   stop in different places again. */
.dir-word.is-active .dir-arrow {
    opacity: 1;
    transform: none;
    background: var(--dir-accent);
}

.dir-word.is-active .dir-arrow::before {
    background-color: #000;
}

.dir-word.is-active .dir-arrow::after {
    opacity: 1;
    transform: scale(1);
}

/* --- the panels ---------------------------------------------------------- */
.dir-panels {
    position: relative;
    min-height: calc(var(--dir-word-size) * 4.667);
}

/* Impreza's own nesting sits between the column and the panels. Neither
   wrapper should become the containing block, and with the panels out of flow
   there is nothing left to give them height — so they collapse to zero and
   take the panels' inset:0 down with them. */
.dir-panels .vc_column-inner,
.dir-panels .wpb_wrapper {
    position: static;
    min-height: 100%;
}

.dir-panel {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    /* Top-aligned, not centred, so the first icon box sits on the same line
       as the first word and its arrow. */
    justify-content: flex-start;
    /* margin, not padding — this needs to accept negative values to pull the
       panel up level with the first word. */
    margin-top: var(--dir-panel-shift, 0px);
    opacity: 0;
    visibility: hidden;
    transform: translateY(14px);
    transition:
        opacity 420ms ease,
        transform 620ms var(--dir-ease),
        visibility 0s linear 420ms;
    /* --- panel contents --------------------------------------------------
       Each icon box carries its own alignment, size and colour from Impreza's
       design options, written as inline styles — which is why they arrive
       uneven and why the rules below need !important to land. */
    --dir-icon: calc(var(--dir-word-size) * .917);
    --dir-measure: 27ch;     /* width of the text column — drives the wrap   */
}

.dir-panel.is-active {
    opacity: 1;
    visibility: visible;
    transform: none;
    transition-delay: 0s, 0s, 0s;
}

/* No script, no hiding. Every panel sits in normal flow, every reveal open. */
html:not(.dir-js) .dir-panel {
    position: static;
    opacity: 1;
    visibility: visible;
    transform: none;
    height: auto;
    margin-bottom: 3rem;
}

/* Icon boxes and headings bring the theme's dark text with them, which is
   invisible on a black section. Set once here rather than per element. */
.dir-panel,
.dir-panel :is(h1, h2, h3, h4, h5, h6, p, li, span, div) {
    color: #fff;
}

/* --- the reveal wrapper --------------------------------------------------
   The JS wraps each .w-iconbox-text in one of these. It exists so the
   single-box panel can position the copy as one block (below). Always open —
   nothing collapses it any more.
   ------------------------------------------------------------------------- */
.dir-reveal {
    display: grid;
    grid-template-rows: 1fr;
    transition: grid-template-rows var(--dir-reveal-speed) var(--dir-ease);
}

.dir-reveal > * {
    overflow: hidden;
    min-height: 0;
}

/* A two-column grid with a fixed first track is what makes the icon boxes
   line up: every icon occupies exactly the same width whatever the icon
   itself is, so the text edges agree down the whole list. */
.dir-panel .w-iconbox {
    display: grid !important;
    /* The text track is capped rather than 1fr. Left to fill the column the
       descriptions run out as one long line; the design has them over two,
       and the measure is what does that — not the font size. */
    grid-template-columns: var(--dir-icon) minmax(0, var(--dir-measure, 27ch));
    align-items: center;
    gap: 2rem;
    margin: 0 0 2.2rem !important;
    padding: 0 !important;
    text-align: left !important;
}

.dir-panel .w-iconbox:last-child {
    margin-bottom: 0 !important;
}

.dir-panel .w-iconbox-icon {
    display: grid !important;
    place-items: center;
    width: var(--dir-icon) !important;
    height: var(--dir-icon) !important;
    margin: 0 !important;
    font-size: var(--dir-icon) !important;
    line-height: 1 !important;
    color: var(--dir-blue) !important;
    background: none !important;
    border: 0 !important;
}

/* Font icons, inline SVG and uploaded SVG all size differently by default, so
   each is pinned to the box. currentColor is what lets the colour above reach
   an inline SVG. */
.dir-panel .w-iconbox-icon i {
    font-size: inherit !important;
    line-height: 1 !important;
    color: inherit !important;
}

.dir-panel .w-iconbox-icon svg {
    width: 100% !important;
    height: 100% !important;
    fill: currentColor;
    stroke: currentColor;
}

.dir-panel .w-iconbox-icon img {
    width: 100% !important;
    height: 100% !important;
    object-fit: contain;
}

/* The text column. Grid handles the left edge, so these only need to not
   reintroduce spacing of their own. */
.dir-panel .w-iconbox-title {
    margin: 0 0 .4rem !important;
    font-size: var(--dir-title-size);
    font-weight: 700;
    line-height: 1.3;
    text-align: left !important;
}

.dir-panel .w-iconbox-text,
.dir-panel .w-iconbox-text p {
    margin: 0 !important;
    font-size: var(--dir-text-size);
    font-weight: 400;
    line-height: 1.5;
    text-align: left !important;
}

/* --- multi-box panels ----------------------------------------------------
   Four icon boxes spread so the first icon sits level with the first word's
   arrow and the last with the last word's. space-between distributes the gaps
   evenly, which means the panel needs a fixed height rather than the inset:0
   the single-box ones use — the height IS the alignment.
     --dir-boxes-top    from the top of the column to the first box
     --dir-boxes-span   first box top to last box bottom
   Ratios of the word size, because both were measured against the arrows and
   the arrows are sized in em off the word.
   ------------------------------------------------------------------------- */
.dir-panel:has(.w-iconbox ~ .w-iconbox) {
    --dir-boxes-top: calc(var(--dir-word-size) * .875);
    --dir-boxes-span: calc(var(--dir-word-size) * 5.375);
    top: var(--dir-boxes-top);
    bottom: auto;
    height: var(--dir-boxes-span);
    margin-top: 0;
    justify-content: space-between;
}

.dir-panel:has(.w-iconbox ~ .w-iconbox) .w-iconbox {
    margin: 0 !important;
}

/* space-between distributes every child, so anything in the panel that isn't
   an icon box steals a share of the gaps. The heading is lifted out of flow
   into the space above the panel, and separators are removed outright. */
.dir-panel:has(.w-iconbox ~ .w-iconbox) > .w-separator {
    display: none;
}

.dir-panel:has(.w-iconbox ~ .w-iconbox) > .w-text {
    position: absolute;
    bottom: 100%;
    left: 0;
    width: 100%;
    margin: 0 0 var(--dir-title-gap, 1.4rem);
    font-size: var(--dir-lead-size);
    font-weight: 400;
    line-height: 1.35;
    text-align: center;
}

/* The panel is itself a .w-vwrapper carrying valign_top, and Impreza's
   .w-vwrapper.valign_top { justify-content: flex-start } has the same
   specificity as the rule above but loads after it — so it wins, and the
   boxes bunch at the top instead of spreading. Repeating the class outranks
   it without !important, which would block the transitions. */
.dir-panel.dir-panel:has(.w-iconbox ~ .w-iconbox) {
    justify-content: space-between;
    height: var(--dir-boxes-span);
}

/* --- single-box panels ---------------------------------------------------
   A panel with only one icon box gets the centred treatment: title promoted
   to a heading, icon below it, copy under that. The selector reads "has an
   icon box, but not one with another icon box after it" — how you ask for
   exactly one without counting.
   ------------------------------------------------------------------------- */
.dir-panel:has(.w-iconbox):not(:has(.w-iconbox ~ .w-iconbox)) {
    --dir-icon: calc(var(--dir-word-size) * .8);
    /* Distance from the top of the panel to the top of the icon. The only
       alignment value that matters here: the icon is pinned, the heading
       grows upward from it and the copy sits below, so headings of two and
       three lines both leave the icon in the same place. Measured against the
       middle word's arrow — 3.31 × the word size, 397px at 120px. */
    --dir-icon-y: calc(var(--dir-word-size) * 3.31);
    --dir-gap: 2rem;
    --dir-panel-shift: 0px;
    justify-content: flex-start;
}

.dir-panel:has(.w-iconbox):not(:has(.w-iconbox ~ .w-iconbox)) .w-iconbox {
    position: relative;
    display: block !important;
    /* Without this the box collapses, and the absolutely positioned heading
       and copy resolve their width against nothing. */
    width: 100%;
    min-height: calc(var(--dir-word-size) * 3.5);
    margin: 0 !important;
    text-align: center !important;
}

/* Impreza wraps the title and text in .w-iconbox-meta. Dissolving it makes
   them children of the icon box, so they can be positioned against it. */
.dir-panel:has(.w-iconbox):not(:has(.w-iconbox ~ .w-iconbox)) .w-iconbox-meta {
    display: contents;
}

.dir-panel:has(.w-iconbox):not(:has(.w-iconbox ~ .w-iconbox)) .w-iconbox-icon {
    position: absolute;
    top: var(--dir-icon-y);
    left: 50%;
    transform: translateX(-50%);
    margin: 0 !important;
}

/* Bottom edge one gap above the icon, so extra lines push the heading up
   rather than pushing the icon down. */
.dir-panel:has(.w-iconbox):not(:has(.w-iconbox ~ .w-iconbox)) .w-iconbox-title {
    position: absolute;
    bottom: calc(100% - var(--dir-icon-y) + var(--dir-gap));
    left: 50%;
    transform: translateX(-50%);
    width: 18ch;
    max-width: 100%;
    margin: 0 !important;
    font-size: var(--dir-hero-size);
    font-weight: 400;
    line-height: 1.3;
    text-align: center !important;
}

/* The reveal wrapper is what gets positioned, not the text inside it. */
.dir-panel:has(.w-iconbox):not(:has(.w-iconbox ~ .w-iconbox)) .dir-reveal {
    position: absolute;
    top: calc(var(--dir-icon-y) + var(--dir-icon) + var(--dir-gap));
    left: 50%;
    transform: translateX(-50%);
    width: 34ch;
    max-width: 100%;
}

.dir-panel:has(.w-iconbox):not(:has(.w-iconbox ~ .w-iconbox)) .w-iconbox-text,
.dir-panel:has(.w-iconbox):not(:has(.w-iconbox ~ .w-iconbox)) .w-iconbox-text p {
    margin: 0 auto !important;
    text-align: center !important;
	font-size: 24px;
}

/* Hide all panels in a group unless JS marks them active */
.dir-js .dir-panels .dir-panel:not(.is-active) {
    display: none !important;
}

/* ==========================================================================
   STACKED LAYOUT — 1439px and below
   The two columns stack. The words become a row across the top, the open
   one underlined in blue; the panel sits full width under a hairline. The
   arrows, the fixed spans and the pinned icon all belong to the split layout
   and are switched off here.
   --------------------------------------------------------------------------
   WHY A MEDIA QUERY, NOT A CLASS
   The old carousel needed the JS to rearrange the DOM, so the mode had to be
   a class the JS set at the same moment. Nothing moves now — this is the
   same markup restyled — so the breakpoint lives here and the JS has no
   opinion about width.
   --------------------------------------------------------------------------
   WHY THE COLUMNS NEEDED WIDENING
   The words sit in a vc_col-sm-6, which is 50% from 601px up whatever its
   sibling is doing. The old carousel was being squeezed into that half
   column — most of what made it clunky. Both columns are 100% here.
   --------------------------------------------------------------------------
   SPECIFICITY
   The desktop rules above are built on :has() chains that run to (0,5,0).
   Everything here that undoes one of them is prefixed with .dir-panels and
   repeats .dir-panel, which clears them by at least a level. The word-size
   rule is doubled with !important because 18.2 resets xxxl-text with
   !important below 900px and would otherwise win on order.
   ========================================================================== */
@media (max-width: 1439px) {

    /* --- tokens ------------------------------------------------------------ */
    .dir-word,
    .dir-panels {
        --dir-word-ink: rgb(255 255 255 / .55);   /* the two words not open   */
        --dir-word-ink-hover: #fff;
        --dir-rule: 3px;                           /* under the open word      */
        --dir-rule-gap: .14em;                     /* between word and rule    */
        --dir-divider: rgb(255 255 255 / .14);     /* hairline under the row   */
        --dir-words-gap: clamp(24px, 3vw, 48px);   /* between the words        */
        --dir-stack-gap: clamp(24px, 3vw, 40px);   /* hairline to panel        */
        --dir-grid-cols: 2;                        /* icon boxes across, Values */
        --dir-grid-gap: clamp(24px, 3vw, 40px) clamp(28px, 4vw, 56px);
        --dir-box-gap: clamp(16px, 2vw, 28px);     /* icon to its text         */
        --dir-copy: 52ch;                          /* single-box measure       */
        --dir-lead-w: 40ch;                        /* the Values standfirst    */
        --dir-icon-hero: 96px;                     /* Mission / Vision icon    */
        --dir-title-size: 20px;
        --dir-text-size: 17px;
        --dir-hero-size: 30px;
        --dir-speed: 320ms;
    }

    .dir-word {
        --dir-word-size: 72px;
    }

    /* --- the row: both columns full width ----------------------------------
       The panels column takes the hairline on its inner wrapper rather than
       the column itself, because the column's box runs 1rem past the content
       on each side (Impreza's negative row margin) and the line would
       overhang the words.
       (0,6,0) on the column rule clears Impreza's phone stacking margins at
       (0,4,1) as well as the 50% width at (0,1,0).
       ---------------------------------------------------------------------- */
    .g-cols.via_flex:has(> .dir-panels) {
        flex-wrap: wrap;
    }

    .g-cols.via_flex:has(> .dir-panels) > .wpb_column.wpb_column {
        flex: 0 0 100%;
        width: 100%;
        max-width: 100%;
        min-width: 0;
        margin-top: 0;
        margin-bottom: 0;
    }

    .dir-panels.dir-panels > .vc_column-inner {
        padding-top: var(--dir-stack-gap);
        border-top: 1px solid var(--dir-divider);
    }

    /* --- the words, as a row -----------------------------------------------
       The wrapper holds the "Our direction" heading, the three words and two
       separators. It becomes a wrapping flex row: the heading keeps a full
       line, the separators go (the hairline and --dir-stack-gap do their
       job), the words sit side by side on the line below.
       ---------------------------------------------------------------------- */
    .wpb_wrapper:has(> .dir-word) {
        display: flex;
        flex-wrap: wrap;
        align-items: baseline;
        gap: 4px var(--dir-words-gap);
    }

    .wpb_wrapper:has(> .dir-word) > :not(.dir-word) {
        flex: 0 0 100%;
    }

    .wpb_wrapper:has(> .dir-word) > .w-separator {
        display: none;
    }

    .dir-word.dir-word {
        position: relative;
        display: inline-flex;
        flex: 0 0 auto;
        grid-template-columns: none;
        align-items: center;
        margin: 0;
        padding: 0 0 var(--dir-rule-gap);
        font-size: var(--dir-word-size) !important;
        line-height: 1;
        color: var(--dir-word-ink);
        transition: color var(--dir-speed) ease;
		padding: 10px;
    }

    /* The rule under the open word. Grows from the left, the same wipe as
       the header menu in 4.1.1, so the two read as one family of control.
       scaleX rather than an animated width: width triggers layout on every
       frame, scaleX runs on the compositor. */
    .dir-word.dir-word::after {
        content: "";
        position: absolute;
        left: 0;
        right: 0;
        bottom: 0;
        height: var(--dir-rule);
        background: var(--dir-accent);
        transform: scaleX(0);
        transform-origin: left center;
        transition: transform 420ms var(--dir-ease);
        pointer-events: none;
    }

    .no-touch .dir-word.dir-word:hover,
    .dir-word.dir-word:focus-visible {
        color: var(--dir-word-ink-hover);
    }

    .dir-word.dir-word.is-active {
        color: var(--dir-accent);
    }

    .dir-word.dir-word.is-active::after {
        transform: scaleX(1);
    }

    .dir-word.dir-word:focus-visible {
        outline-offset: 4px;
    }

    /* The strip rule is the indicator now; a second one would be noise. */
    .dir-word .dir-arrow {
        display: none;
    }

    /* --- the panels, in flow -----------------------------------------------
       One shown at a time, the rest display:none so they take no height.
       Scoped to .dir-js, so without the script every panel stays visible.
       ---------------------------------------------------------------------- */
    .dir-panels.dir-panels {
        min-height: 0;
    }

    .dir-panels .dir-panel {
        position: static;
        inset: auto;
        height: auto;
        min-height: 0;
        margin: 0;
        opacity: 1;
        visibility: visible;
        transform: none;
        transition: none;
        --dir-icon: 72px;
        --dir-measure: 1fr;      /* the text track fills the box now         */
    }

    html.dir-js .dir-panels .dir-panel:not(.is-active) {
        display: none;
    }

    /* display:none can't be transitioned, so the incoming panel runs a short
       keyframe instead. It restarts on every switch, which is the point. */
    html.dir-js .dir-panels .dir-panel.is-active {
        animation: dir-panel-in 420ms var(--dir-ease) both;
    }

    /* --- multi-box: a grid of icon boxes -----------------------------------
       The fixed span and the spreading were the alignment with the words.
       With the words above, the boxes tile instead: two across on tablets
       and laptops, one on phones. The standfirst spans the top row.
       ---------------------------------------------------------------------- */
    .dir-panels .dir-panel.dir-panel:has(.w-iconbox ~ .w-iconbox) {
        display: grid;
        grid-template-columns: repeat(var(--dir-grid-cols), minmax(0, 1fr));
        align-items: start;
        justify-content: normal;
        gap: var(--dir-grid-gap);
        top: auto;
        bottom: auto;
        height: auto;
    }

    .dir-panels .dir-panel.dir-panel:has(.w-iconbox ~ .w-iconbox) > .w-text {
        grid-column: 1 / -1;
        position: static;
        width: auto;
        max-width: var(--dir-lead-w);
        margin: 0;
        text-align: left;
    }

    .dir-panels .dir-panel .w-iconbox {
        gap: var(--dir-box-gap);
    }

    .dir-panels .dir-panel.dir-panel:has(.w-iconbox ~ .w-iconbox) .w-iconbox {
        margin: 0 !important;
        align-items: center;
    }

    /* --- single-box: a centred stack ---------------------------------------
       Icon, then title, then copy — the desktop arrangement without the
       pinning. Every absolutely positioned piece above is put back in flow
       and the flex gap sets the rhythm.
       ---------------------------------------------------------------------- */
    .dir-panels .dir-panel.dir-panel:has(.w-iconbox):not(:has(.w-iconbox ~ .w-iconbox)) {
        --dir-icon: var(--dir-icon-hero);
        --dir-panel-shift: 0px;
        align-items: center;
        text-align: center;
    }

    .dir-panels .dir-panel.dir-panel:has(.w-iconbox):not(:has(.w-iconbox ~ .w-iconbox)) .w-iconbox {
        position: static;
        display: flex !important;
        flex-direction: column;
        align-items: center;
        gap: clamp(16px, 2vw, 24px);
        width: 100%;
        max-width: var(--dir-copy);
        min-height: 0;
        margin: 0 auto !important;
    }

    .dir-panels .dir-panel.dir-panel:has(.w-iconbox):not(:has(.w-iconbox ~ .w-iconbox)) :is(.w-iconbox-icon, .w-iconbox-title, .dir-reveal) {
        position: static;
        top: auto;
        bottom: auto;
        left: auto;
        transform: none;
    }

    .dir-panels .dir-panel.dir-panel:has(.w-iconbox):not(:has(.w-iconbox ~ .w-iconbox)) .w-iconbox-title {
        width: auto;
        max-width: 26ch;
        font-size: clamp(22px, 2.4vw, var(--dir-hero-size));
        line-height: 1.25;
        text-wrap: balance;
    }

    .dir-panels .dir-panel.dir-panel:has(.w-iconbox):not(:has(.w-iconbox ~ .w-iconbox)) .dir-reveal {
        width: 100%;
        max-width: 100%;
    }
}

/* --- tablets (768–1023) -------------------------------------------------- */
@media (max-width: 1023px) {
    .dir-word {
        --dir-word-size: 52px;
    }

    .dir-panels {
        --dir-icon-hero: 84px;
        --dir-title-size: 19px;
    }

    .dir-panels .dir-panel {
        --dir-icon: 64px;
    }
}

/* --- phones (767 and below) ----------------------------------------------
   The words scale with the screen so all three stay on one line down to a
   360px phone: 6vw is about 23px there, and three words at 23px with the
   gaps come to just under the content width. If a longer word is ever added
   the row simply wraps.
   ------------------------------------------------------------------------- */
@media (max-width: 767px) {
    .dir-word,
    .dir-panels {
        --dir-grid-cols: 1;
        --dir-words-gap: clamp(16px, 5vw, 32px);
        --dir-stack-gap: 24px;
        --dir-grid-gap: 24px;
        --dir-box-gap: 16px;
        --dir-icon-hero: 72px;
        --dir-title-size: 18px;
        --dir-text-size: 16px;
    }

    .dir-word {
        --dir-word-size: clamp(22px, 6.4vw, 48px);
    }

    .dir-panels .dir-panel {
        --dir-icon: 56px;
    }
}

/* --- reduced motion -----------------------------------------------------
   The panel switch included: with motion off it appears in place.
   ------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
    .dir-word,
    .dir-word::after,
    .dir-arrow,
    .dir-arrow::before,
    .dir-arrow::after,
    .dir-panel,
    .dir-reveal {
        transition-duration: 1ms;
    }

    html.dir-js .dir-panels .dir-panel.is-active {
        animation-duration: 1ms;
    }
}

/* --- keyframes ----------------------------------------------------------- */
@keyframes dir-panel-in {
    from { opacity: 0; translate: 0 8px; }
    to   { opacity: 1; translate: 0 0; }
}

/* ==========================================================================
   5.7  SECTOR CARDS
   Expanding cards for the sector post list. "sector-cards" goes on the Post
   List element; the companion JS sets the images and accent colour per card
   and builds the two controls.
   The toggle and the pill are NOT Impreza buttons. The theme's default button
   style carries the arrow treatment from 3.0, whose selectors chain four deep
   to outrank Impreza — undoing that on a per-card basis was a losing battle,
   so the JS strips those buttons out and builds plain elements instead.
   Nothing below inherits from anything.
   ========================================================================== */
.sector-cards .w-grid-item {
    --card-accent: #0a84ff;
    --card-ratio: 3 / 4.1;
    --card-radius: 20px;
    --card-pad: 14px;
    --card-speed: 560ms;
    --card-ease: cubic-bezier(.22, .68, .3, 1);
    /* How much colour sits over the photo on a closed card. Higher shows
       more colour and less photo. */
    --card-tint-strength: .72;
}

.sector-cards .w-grid-item-h {
    position: relative;
    display: block;
    aspect-ratio: var(--card-ratio);
    padding: var(--card-pad);
    border-radius: var(--card-radius);
    /* clip, not hidden — hidden creates a scroll container, which pins any
       scroll-driven animation inside it at 0%. */
    overflow: clip;
    cursor: pointer;
    isolation: isolate;
}

/* The featured image is promoted to a background, so the element itself is
   dead weight — and in flow it pushes the teaser down the card. */
.sector-cards .w-grid-item-h .w-post-elm.post_image {
    display: none;
}

/* Two stacked layers so the image swap cross-fades rather than pops. */
.sector-cards .w-grid-item-h::before,
.sector-cards .w-grid-item-h::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -2;
    background-size: cover;
    background-position: center;
    transition: opacity var(--card-speed) var(--card-ease);
}

.sector-cards .w-grid-item-h::before {
    background-image: var(--card-img-closed, none);
    opacity: 1;
}

.sector-cards .w-grid-item-h::after {
    background-image: var(--card-img-open, var(--card-img-closed, none));
    opacity: 0;
}

.sector-cards .is-open .w-grid-item-h::before { opacity: 0; }
.sector-cards .is-open .w-grid-item-h::after  { opacity: 1; }

/* Flat accent colour over the photo. Normal blending, not multiply:
   multiply can only darken, so it pulled every card towards black. */
.sector-cards .card-tint {
    position: absolute;
    inset: 0;
    z-index: -1;
    background: var(--card-accent);
    mix-blend-mode: normal;
    opacity: var(--card-tint-strength);
    transition: opacity var(--card-speed) var(--card-ease);
    pointer-events: none;
}

.sector-cards .is-open .card-tint {
    opacity: 0;
}

/* Dark gradient behind the copy. Off on closed cards, where the tint gives
   the title its contrast. Fades in as a card opens, when the tint fades
   out and the white copy sits over the raw photo. */
.sector-cards .card-scrim {
    position: absolute;
    inset: 0;
    z-index: -1;
    background: linear-gradient(180deg, rgb(0 0 0 / .5) 0 30%, rgb(0 0 0 / 0) 62%);
    opacity: 0;
    transition: opacity var(--card-speed) var(--card-ease);
    pointer-events: none;
}

.sector-cards .is-open .card-scrim {
    opacity: 1;
}

/* Title and toggle share a line. The title reserves space on the right so
   long sector names wrap rather than running under the toggle. */
.sector-cards .card-title {
    margin: 0;
    padding-right: 28px;
    font-size: 24px;
    font-weight: 300;
    line-height: 18px;
    letter-spacing: .01em;
    color: #fff;
	padding-top: 10px
}

.sector-cards .card-teaser {
    display: grid;
    grid-template-rows: 0fr;
    margin-top: .45rem;
    opacity: 0;
    color: #fff;
    font-size: 20px;
    font-weight: 700;
    line-height: 1.3;
    transition:
        grid-template-rows var(--card-speed) var(--card-ease),
        opacity 240ms ease;
	padding-top: 10px
}

.sector-cards .card-teaser > * {
    overflow: hidden;
    margin: 0;
}

.sector-cards .is-open .card-teaser {
    grid-template-rows: 1fr;
    opacity: 1;
    transition-delay: 0s, 160ms;
}

/* --- toggle, built by the JS ---------------------------------------------
   Sits on the same 18px line box as the title, so the two are optically
   aligned rather than one floating below the other.
   ------------------------------------------------------------------------- */
.sector-cards .card-x {
    position: absolute;
    top: var(--card-pad);
    right: var(--card-pad);
    width: 40px;
    height: 40px;
    padding: 0;
    border: 3px solid #fff;
    border-radius: 50%;
    background: none;
    cursor: pointer;
    z-index: 3;
    pointer-events: none;
}

/* Plus to minus: two bars, one rotates away to leave the other. */
.sector-cards .card-x::before,
.sector-cards .card-x::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    width: 20px;
    height: 3px;
    background: #fff;
    transform: translate(-50%, -50%);
    transition: transform var(--card-speed) var(--card-ease);
}

.sector-cards .card-x::after {
    transform: translate(-50%, -50%) rotate(90deg);
}

.sector-cards .is-open .card-x::after {
    transform: translate(-50%, -50%) rotate(0deg);
}

/* --- pill, built by the JS -----------------------------------------------
   Hidden while the card is closed. Opening the card fades it in already in
   its hover state — filled, dark ink, wide padding — so there's no separate
   resting look to hover from. The :hover/:focus rule below is kept so the
   pill reads the same if it's ever tabbed to while closed.
   ------------------------------------------------------------------------- */
.sector-cards .card-cta {
    position: absolute;
    right: var(--card-pad);
    bottom: var(--card-pad);
    --wb-ink: #fff;
    --wb-bg: transparent;
    --wb-border-color: var(--wb-ink);
    --wb-bg-hover: var(--color-blue, #00bfff);
    --wb-ink-hover: #000;
    --wb-pad-y: 0.7em;
    --wb-pad-x: 1.6em;
    --wb-pad-x-hover: 2.6em;
    --wb-border: 1px;
    --wb-radius: 999px;
    --wb-speed: .3s;
    --wb-ease: cubic-bezier(.22, .68, .3, 1);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    inline-size: auto;
    block-size: auto;
    min-inline-size: 0;
    min-block-size: 0;
    max-inline-size: 100%;
    width: fit-content;
    padding: var(--wb-pad-y) var(--wb-pad-x);
    background: var(--wb-bg);
    border: var(--wb-border) solid var(--wb-border-color);
    border-radius: var(--wb-radius);
    box-shadow: none;
    /* !important, and it has to be. Impreza writes color:#fff !important on
       .us-btn-style_*, which no amount of repeated selectors can outrank.
       Without this the resting label is always Impreza's white — invisible
       while --wb-ink is also white, and the reason white-button-alt's black
       ink never appeared. */
    color: var(--wb-ink) !important;
    /* Not rem. :root sets --font-size: 30px on this site, so 1rem is 30px and
       any rem value here comes out oversized. The size utilities in 1.1 are
       !important, so .xs-text and friends still override this per button. */
    font-size: 16px;
    font-weight: 500;
    line-height: 1.2;
    letter-spacing: 0;
    text-transform: none;
    text-decoration: none;
    white-space: nowrap;
    overflow: visible;
    /* Hidden until the card opens. */
    opacity: 0;
    transform: translateY(6px);
    pointer-events: none;
    transition:
        opacity var(--wb-speed) ease,
        transform var(--wb-speed) var(--wb-ease),
        padding var(--wb-speed) var(--wb-ease),
        background-color var(--wb-speed) ease,
        border-color var(--wb-speed) ease,
        color var(--wb-speed) ease;
}

.sector-cards .card-cta:hover,
.sector-cards .card-cta:focus {
    padding-left: var(--wb-pad-x-hover);
    padding-right: var(--wb-pad-x-hover);
    background: var(--wb-bg-hover);
    border-color: var(--wb-bg-hover);
    color: var(--wb-ink-hover) !important;
    box-shadow: none;
}

/* Open card: reveal the pill and land it straight in its hover state. */
.sector-cards .is-open .card-cta {
    opacity: 1;
    transform: translateY(0);
    pointer-events: auto;
    padding-left: var(--wb-pad-x-hover);
    padding-right: var(--wb-pad-x-hover);
    background: var(--wb-bg-hover);
    border-color: var(--wb-bg-hover);
    color: var(--wb-ink-hover) !important;
    transition-delay: 100ms;
}

.sector-cards .w-grid-item-h:focus-visible {
    outline: 2px solid #fff;
    outline-offset: 3px;
}

/* Data carriers the JS reads and removes — hidden here in case it doesn't. */
.sector-cards .card-data-img,
.sector-cards .card-data-teaser,
.sector-cards .card-data-accent {
    display: none;
}

/* Fallback only. The right place to set this is the Post List element's own
   column gap in the editor. */
.sector-cards .w-grid {
    gap: 20px;
}

@media (max-width: 900px) {
    .sector-cards .w-grid-item {
        --card-ratio: 3 / 3.6;
    }
}

@media (prefers-reduced-motion: reduce) {
    .sector-cards .w-grid-item-h::before,
    .sector-cards .w-grid-item-h::after,
    .sector-cards .card-tint,
    .sector-cards .card-scrim,
    .sector-cards .card-teaser,
    .sector-cards .card-cta,
    .sector-cards .card-x::before,
    .sector-cards .card-x::after {
        transition-duration: 1ms;
    }
}

/* --- hover --------------------------------------------------------------
   Card lifts, photo eases in, tint thins out so more of the photo shows,
   and the toggle fills. Hover only runs on devices with a real pointer, so
   a tap on a phone doesn't leave a card stuck in its hover state. The same
   look is given to keyboard focus.
   Paste this after 5.7 so it follows the existing rules.
   ------------------------------------------------------------------------- */
.sector-cards .w-grid-item-h {
    transition:
        transform var(--card-speed) var(--card-ease),
        box-shadow var(--card-speed) var(--card-ease);
}

/* The photo layers need transform in their transition as well as opacity,
   or the zoom would snap back when the pointer leaves. */
.sector-cards .w-grid-item-h::before,
.sector-cards .w-grid-item-h::after {
    transition:
        opacity var(--card-speed) var(--card-ease),
        transform 900ms var(--card-ease);
}

.sector-cards .card-x {
    transition:
        background-color var(--card-speed) var(--card-ease),
        transform var(--card-speed) var(--card-ease);
}

@media (hover: hover) and (pointer: fine) {
    .sector-cards .w-grid-item-h:hover {
        transform: translateY(-6px);
        box-shadow: 0 18px 40px -12px rgb(0 0 0 / .35);
    }

    .sector-cards .w-grid-item-h:hover::before,
    .sector-cards .w-grid-item-h:hover::after {
        transform: scale(1.06);
    }

    /* Closed cards only. An open card's tint is already at 0. */
    .sector-cards .w-grid-item:not(.is-open) .w-grid-item-h:hover .card-tint {
        opacity: calc(var(--card-tint-strength) - .18);
    }

    .sector-cards .w-grid-item-h:hover .card-x {
        background: #fff;
        transform: scale(1.08);
    }

    .sector-cards .w-grid-item-h:hover .card-x::before,
    .sector-cards .w-grid-item-h:hover .card-x::after {
        background: var(--card-accent);
    }
}

/* Keyboard users get the same cues. */
.sector-cards .w-grid-item-h:focus-visible {
    transform: translateY(-6px);
    box-shadow: 0 18px 40px -12px rgb(0 0 0 / .35);
}

.sector-cards .w-grid-item-h:focus-visible .card-x {
    background: #fff;
}

.sector-cards .w-grid-item-h:focus-visible .card-x::before,
.sector-cards .w-grid-item-h:focus-visible .card-x::after {
    background: var(--card-accent);
}

/* --- pill colours ---------------------------------------------------------
   Open card: white pill, black text. Hovered or focused: blue, black text.
   The open-card rule in 5.7 sets the colour with !important and matches the
   plain :hover rule's weight, so these need the extra .is-open to win.
   ------------------------------------------------------------------------- */
.sector-cards .is-open .card-cta {
    background: #fff;
    border-color: #fff;
    color: #000 !important;
}

.sector-cards .is-open .card-cta:hover,
.sector-cards .is-open .card-cta:focus-visible {
    background: var(--wb-bg-hover);
    border-color: var(--wb-bg-hover);
    color: #000 !important;
}

@media (prefers-reduced-motion: reduce) {
    .sector-cards .w-grid-item-h:hover,
    .sector-cards .w-grid-item-h:focus-visible,
    .sector-cards .w-grid-item-h:hover::before,
    .sector-cards .w-grid-item-h:hover::after,
    .sector-cards .w-grid-item-h:hover .card-x {
        transform: none;
    }
}

/* ==========================================================================
   5.8  SECTOR SPECIALISMS
   REPLACES the whole of the previous 5.8, from its header down to the end
   of 5.8.1 — including the "stacked, panel under its card, below 1142px"
   block that was appended in the middle of it, and the spec-panel-in
   keyframes, which nothing uses any more. 5.8.1 is carried over unchanged
   at the end of this file. Nothing outside 5.8 changes.
   --------------------------------------------------------------------------
   Square cards with a title bar. Hovering a card makes the bar's colour
   rise up to fill it, revealing the description in the top corner.
   Clicking a card opens its panel underneath; clicking it again closes it;
   clicking another card switches. One open at a time, and the first card is
   open on load. The space under the cards stays reserved, so the page never
   jumps.
   Below 1142px the cards stack, each panel sits directly under its own card,
   and opens and closes as a drawer. Nothing is open until tapped.
   --------------------------------------------------------------------------
   PAIRS WITH the SECTOR SPECIALISMS JS snippet, which is what makes the cards
   clickable. It adds:
     .spec-live     on the stage, once it is running
     .is-active     on the open card and on its panel
     .spec-drawer   a wrapper round each panel, used by the stacked layout
     --spec-bar     on each card: the title bar's measured height
   Without the script nothing is lost: hover still raises the wash and swaps
   the panels as it used to, and the stacked layout shows every panel.
   --------------------------------------------------------------------------
   EDITOR SETUP (unchanged)
   Row              -> spec-row
      Horiz Wrapper -> spec-card    (x3, one per column)
        Vert Wrapper               (Impreza adds this)
          Image
          Text                     (title, no class)
          Text      -> spec-desc
   Horiz Wrapper    -> spec-panel   (x3, siblings of the Row)
   Cards and panels are matched BY POSITION — first card, first panel — so the
   order in the editor is what matters. If the wrong panel opens, that is
   where to look.
   --------------------------------------------------------------------------
   HOW THE RISE WORKS
   The resting title bar and the hover wash are the same layer: the card's
   ::after. At rest it is clipped down to the bar's height, so it IS the bar.
   On hover the clip opens upward to the full card. One surface, so there's
   no darker band where two translucent layers overlap mid-rise, and no
   flash of photo under the bar as it starts.
   The bar's height depends on how the title wraps, which CSS can't know, so
   the JS measures it into --spec-bar. Without the script the title keeps its
   own background and the wash simply rises over it.
   ========================================================================== */
.spec-card,
.spec-panel {
    --spec-ratio:      1 / 1;      /* the CARD, image and title together     */
    --spec-radius:     20px;
    --spec-gap:        30px;       /* between cards                          */
    /* NAME IS A MISNOMER. This is the wash colour, not necessarily blue —
       the spec-yellow variant below overrides it. The bar and the wash both
       read it, so they cannot fall out of step. */
    --spec-blue:       rgb(110 137 166 / .85);
    --spec-title:      30px;
    --spec-title-pad:  34px;
    --spec-desc:       26px;
    --spec-desc-pad:   34px;
    --spec-panel-h:    440px;      /* room reserved for the tallest panel    */
    --spec-col:        420px;      /* the panel's left column                */
    --spec-panel-gap:  80px;
    --spec-stack-gap:  60px;       /* between cards, stacked layout          */
    --spec-speed:      .4s;
    --spec-rise:       .6s;        /* the wash rising and falling            */
    --spec-ease:       cubic-bezier(.22, .68, .3, 1);
}

/* --- colour variants -----------------------------------------------------
   Add alongside spec-card and spec-panel on every card and panel in the
   section — the variables are declared on those elements, not on an
   ancestor, so they have to land on each of them.
   ------------------------------------------------------------------------- */
.spec-yellow.spec-yellow {
    --spec-blue: color-mix(in srgb, var(--color-yellow) 85%, transparent);
}

/* --- the stage -----------------------------------------------------------
   Holds the Row and the panels. The panels are out of flow, so nothing would
   reserve height for them — padding does it, and they hang inside. This is
   the gap that stays put whether a panel is open or not.
   ------------------------------------------------------------------------- */
.wpb_wrapper:has(> .spec-row) {
    position: relative;
    padding-bottom: calc(440px + 60px);
}

/* --- the row -------------------------------------------------------------
   Grid rather than the theme's flex, so the three columns are exactly equal
   whatever the copy length. Four repeats to clear
   .g-cols.via_flex.type_default at (0,3,0).
   ------------------------------------------------------------------------- */
.spec-row.spec-row.spec-row.spec-row {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--spec-gap, 30px);
    width: 100%;
    margin: 0;
}

/* The columns are grid tracks now, so a leftover vc_col percentage would
   fight them. min-width:0 because a grid item won't shrink below its content
   by default. */
.spec-row.spec-row.spec-row > .wpb_column {
    width: auto;
    max-width: none;
    min-width: 0;
    margin: 0;
}

/* Impreza's column wrappers must not become the containing block, or the
   card's contents anchor to a wrapper instead of the card. */
.spec-row :is(.vc_column-inner, .wpb_wrapper) {
    position: static;
    min-width: 0;
}

/* --- the card ------------------------------------------------------------
   The ratio lives here. Repeated class because .w-hwrapper carries its own
   display:flex and gap from the editor.
   ------------------------------------------------------------------------- */
.spec-card.spec-card {
    position: relative;
    display: block;
    aspect-ratio: var(--spec-ratio);
    width: 100%;
    margin: 0;
    border-radius: var(--spec-radius);
    overflow: clip;
    isolation: isolate;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
}

/* Keyboard focus only — :focus-visible never fires on a mouse click or a
   tap, so nobody using a pointer sees this ring. */
.spec-card.spec-card:focus-visible {
    outline: 2px solid #fff;
    outline-offset: 4px;
}

/* The vwrapper generates no box, so its three children resolve their absolute
   positions against the card. Without this the whole section collapses to a
   plain stacked rectangle. */
.spec-card > .w-vwrapper {
    display: contents;
}

/* --- the photograph ------------------------------------------------------
   Three repeats to clear the theme's margin on .w-image — on an inset:0 box a
   bottom margin is subtracted from the height rather than pushing anything
   around, leaving a strip along the bottom.
   ------------------------------------------------------------------------- */
.spec-card .w-image.w-image.w-image {
    position: absolute;
    inset: 0;
    z-index: 0;
    width: auto;
    max-width: none;
    margin: 0;
}

.spec-card .w-image-h {
    display: block;
    width: 100%;
    height: 100%;
}

/* cover, not contain — the card is square and the photos are not, so
   something has to give and cropping is the intent in the design. */
.spec-card .w-image img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: center;
}

/* --- the wash ------------------------------------------------------------
   Clipped from the top down to --spec-bar, so at rest only the strip behind
   the title shows. Opening the clip to inset(0) is what makes it rise. A
   clip-path, not a scaleY: scaling would squash the bar's colour band into
   nothing at rest, and a clip keeps the bottom edge exactly where it is.
   --spec-bar falls back to 0px, so without the script the wash rises from
   nothing over the title's own background.
   ------------------------------------------------------------------------- */
.spec-card::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 1;
    background: var(--spec-blue);
    clip-path: inset(calc(100% - var(--spec-bar, 0px)) 0 0 0);
    transition: clip-path var(--spec-rise) var(--spec-ease);
    pointer-events: none;
}

.no-touch .spec-card:hover::after,
.spec-card:focus-visible::after,
.spec-card.is-active::after {
    clip-path: inset(0);
}

/* --- the card's copy -----------------------------------------------------
   Both absolute, so they sit OVER the photo rather than under it. There are
   only two Text blocks in a card, so naming one names the other.
   ------------------------------------------------------------------------- */
.spec-card .w-text {
    position: absolute;
    left: 0;
    right: 0;
    z-index: 2;
    margin: 0;
    color: #fff;
}

/* The title bar. Its own background is the no-script fallback only; once the
   script is running the wash draws the bar (below). */
.spec-card .w-text:not(.spec-desc) {
    bottom: 0;
    padding: var(--spec-title-pad);
    background: var(--spec-blue);
    font-size: var(--spec-title);
    line-height: 1.2;
    transition: background-color var(--spec-speed) var(--spec-ease);
}

/* No script: the bar's own background lets go once the wash has risen past
   it, so the two don't stack into a darker strip for long. */
.no-touch .wpb_wrapper:not(.spec-live) .spec-card:hover .w-text:not(.spec-desc) {
    background: transparent;
    transition-delay: calc(var(--spec-rise) * .6);
}

/* Script running: the wash is the bar, so the title has no background of its
   own. The right padding clears the plus sign. */
.spec-live .spec-card .w-text:not(.spec-desc) {
    background: transparent;
    padding-right: calc(var(--spec-title-pad) * 1.5 + .6em);
}

/* --- the plus sign -------------------------------------------------------
   Says "this opens". Two bars drawn with gradients, so it needs no icon font
   and takes the title's colour. A quarter turn makes it an ×, which is how
   the open card shows it's the open one.
   Only with the script running, since without it nothing opens on click.
   ------------------------------------------------------------------------- */
.spec-live .spec-card .w-text:not(.spec-desc)::after {
    content: "";
    position: absolute;
    top: 50%;
    right: var(--spec-title-pad);
    width: .6em;
    height: .6em;
    translate: 0 -50%;
    background:
        linear-gradient(currentColor 0 0) center / 100% 2px no-repeat,
        linear-gradient(currentColor 0 0) center / 2px 100% no-repeat;
    transition: rotate var(--spec-speed) var(--spec-ease);
}

.spec-live .spec-card.is-active .w-text:not(.spec-desc)::after {
    rotate: 45deg;
}

/* The default card, held open. Clicking it does nothing while it's the one
   showing, so it doesn't offer an × it won't honour. The sign fades back as
   soon as another card is opened. */
.spec-live .spec-card.is-held .w-text:not(.spec-desc)::after {
    opacity: 0;
}

.spec-live .spec-card .w-text:not(.spec-desc)::after {
    transition:
        rotate var(--spec-speed) var(--spec-ease),
        opacity var(--spec-speed) ease;
}

/* Top-left corner. right:auto and a max-width so a long line wraps in the
   corner rather than spanning the card. */
.spec-card .spec-desc {
    top: 0;
    bottom: auto;
    right: auto;
    max-width: 78%;
    padding: var(--spec-desc-pad);
    font-size: var(--spec-desc);
    line-height: 1.3;
    text-align: left;
    opacity: 0;
    translate: 0 -8px;
    transition:
        opacity var(--spec-speed) var(--spec-ease),
        translate var(--spec-speed) var(--spec-ease);
}

/* Waits for the wash to get most of the way up before it appears, so the
   words land on colour rather than on the photo. Leaves without waiting. */
.no-touch .spec-card:hover .spec-desc,
.spec-card:focus-visible .spec-desc,
.spec-card.is-active .spec-desc {
    opacity: 1;
    translate: none;
    transition-delay: calc(var(--spec-rise) * .35);
}

/* The theme colours .w-text-h directly, so it must inherit or its own rule
   wins. The title also carries a us_custom_* colour from Design Options —
   clear that in the editor if you ever change --spec-blue to something that
   needs dark text. */
.spec-card .w-text-h {
    color: inherit;
    font-size: inherit;
    line-height: inherit;
    text-decoration: none;
}

/* --- the panels ----------------------------------------------------------
   Stacked in the reserved space. Out of flow they contribute no height, so
   switching between a short panel and a long one cannot shift the page.
   The incoming panel waits a beat, so the outgoing one has started to fade
   before it arrives — a crossfade rather than two sets of words at once.
   ------------------------------------------------------------------------- */
.spec-panel.spec-panel {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: var(--spec-panel-h);
    display: grid;
    grid-template-columns: var(--spec-col) minmax(0, 1fr);
    gap: var(--spec-panel-gap);
    align-items: start;
    margin: 0;
    opacity: 0;
    visibility: hidden;
    translate: 0 12px;
    /* Visibility waits for the fade going out and switches at once coming
       back, so the fade is visible in both directions. */
    transition:
        opacity var(--spec-speed) var(--spec-ease),
        translate .5s var(--spec-ease),
        visibility 0s linear var(--spec-speed);
}

.spec-panel.spec-panel.is-active {
    opacity: 1;
    visibility: visible;
    translate: none;
    transition-delay: .15s, .15s, 0s;
}

.spec-panel > .w-vwrapper {
    min-width: 0;
    width: 100%;
    margin: 0;
}

/* The button sits well clear of the heading in the design; the wrapper's own
   gap is too small to do it. */
.spec-panel .w-btn-wrapper {
    margin-top: 70px;
}

/* --- the drawer ----------------------------------------------------------
   Added round each panel by the script. Up here it must not exist as a box,
   or the panel would anchor to it instead of the stage. display:contents
   does exactly that. The stacked layout below turns it into a real box.
   ------------------------------------------------------------------------- */
.spec-drawer {
    display: contents;
}

/* --- no script: the old hover reveal --------------------------------------
   One pair per position. Each fires when EITHER that card or that panel is
   hovered, which is what keeps the panel open while the pointer travels down
   to its button. Only applies until .spec-live lands.
   ------------------------------------------------------------------------- */
.no-touch .wpb_wrapper:not(.spec-live):has(.spec-row > .wpb_column:nth-child(1) .spec-card:hover)
    > :nth-child(1 of .spec-panel),
.no-touch .wpb_wrapper:not(.spec-live):has(> :nth-child(1 of .spec-panel):hover)
    > :nth-child(1 of .spec-panel),
.no-touch .wpb_wrapper:not(.spec-live):has(.spec-row > .wpb_column:nth-child(2) .spec-card:hover)
    > :nth-child(2 of .spec-panel),
.no-touch .wpb_wrapper:not(.spec-live):has(> :nth-child(2 of .spec-panel):hover)
    > :nth-child(2 of .spec-panel),
.no-touch .wpb_wrapper:not(.spec-live):has(.spec-row > .wpb_column:nth-child(3) .spec-card:hover)
    > :nth-child(3 of .spec-panel),
.no-touch .wpb_wrapper:not(.spec-live):has(> :nth-child(3 of .spec-panel):hover)
    > :nth-child(3 of .spec-panel) {
    opacity: 1;
    visibility: visible;
    translate: none;
    transition-delay: 0s, 0s, 0s;
}

/* --- laptops (1320 and below) --------------------------------------------
   Three cards still fit, but the panel's fixed left column starts crowding
   the copy — both columns become proportional so they shrink together. The
   reserved height goes up, because the same words wrap onto more lines in a
   narrower panel.
   ------------------------------------------------------------------------- */
@media (max-width: 1320px) {
    .spec-card,
    .spec-panel {
        --spec-gap:        24px;
        --spec-title:      26px;
        --spec-title-pad:  28px;
        --spec-desc:       22px;
        --spec-desc-pad:   28px;
        --spec-panel-gap:  48px;
        --spec-panel-h:    520px;
    }

    .wpb_wrapper:has(> .spec-row) {
        padding-bottom: calc(520px + 50px);
    }

    .spec-panel.spec-panel {
        grid-template-columns: minmax(0, .8fr) minmax(0, 1.2fr);
    }

    .spec-panel .w-btn-wrapper {
        margin-top: 50px;
    }
}

/* ==========================================================================
   STACKED — 1141px and below
   --------------------------------------------------------------------------
   HOW THE PANELS END UP UNDER THEIR CARDS
   In the markup the three panels come after the whole card row. Here the
   row is set to display:contents, so its three columns and the panels all
   become items of one flex column, and order interleaves them:
       card 1, panel 1, card 2, panel 2, card 3, panel 3
   With the script running the panels are inside drawers, so the drawers are
   what get ordered; without it the bare panels are. The ~ chains cover both.
   --------------------------------------------------------------------------
   HOW THE OPEN STAYS SMOOTH
   The panel is always laid out fully open inside its drawer, and nothing
   about it changes when it opens or closes. Only the drawer's height moves,
   set by the script, so the panel is revealed rather than rebuilt. The
   drawer's overflow:hidden crops it while closed. Spacing is padding on the
   panel rather than margin, so it is always inside what gets measured.
   --------------------------------------------------------------------------
   The 1141 is mirrored nowhere else. The script never reads the width; it
   asks whether the drawer is display:contents, which only this file decides.
   ========================================================================== */
@media (max-width: 1141px) {

    /* --- the stack ------------------------------------------------------- */
    .wpb_wrapper:has(> .spec-row) {
        display: flex;
        flex-direction: column;
        padding-bottom: 0;
    }

    /* The separator between the row and the panels would be ordered to the
       top of the stack, above the first card. */
    .wpb_wrapper:has(> .spec-row) > .w-separator {
        display: none;
    }

    .spec-row.spec-row.spec-row.spec-row {
        display: contents;
    }

    /* (0,6,0) to clear Impreza's own stacking widths and margins, which
       reach (0,4,1) at phone sizes. */
    .spec-row.spec-row.spec-row.spec-row > .wpb_column.wpb_column {
        flex: none;
        width: 100%;
        max-width: 100%;
        margin: var(--spec-stack-gap, 60px) 0 0;
    }

    .spec-row.spec-row.spec-row.spec-row > .wpb_column.wpb_column:first-child {
        margin-top: 0;
    }

    /* The row's negative side margins are gone, so drop the matching column
       padding or the cards sit narrower than the panels. */
    .spec-row.spec-row.spec-row > .wpb_column > .vc_column-inner.vc_column-inner {
        padding-left: 0;
        padding-right: 0;
    }

    /* --- interleave cards and panels ------------------------------------- */
    .spec-row > .wpb_column:nth-child(1) { order: 1; }
    .spec-row > .wpb_column:nth-child(2) { order: 3; }
    .spec-row > .wpb_column:nth-child(3) { order: 5; }

    .spec-row ~ :is(.spec-panel, .spec-drawer) { order: 2; }
    .spec-row ~ :is(.spec-panel, .spec-drawer) ~ :is(.spec-panel, .spec-drawer) { order: 4; }
    .spec-row ~ :is(.spec-panel, .spec-drawer) ~ :is(.spec-panel, .spec-drawer) ~ :is(.spec-panel, .spec-drawer) { order: 6; }

    /* --- panels: in flow, always laid out open --------------------------- */
    .spec-panel.spec-panel,
    .spec-panel.spec-panel.is-active {
        position: static;
        height: auto;
        margin: 0;
        padding: 30px 0 10px;
        opacity: 1;
        visibility: visible;
        translate: none;
        transition: none;
    }

    /* --- the drawer ------------------------------------------------------
       Height is inline, from the script. Visibility waits for the collapse
       going out and switches at once coming back, so the closing panel stays
       visible while it shrinks but can't be tabbed into once shut. */
    .spec-drawer {
        display: block;
        width: 100%;
        overflow: hidden;
        transition:
            height .5s cubic-bezier(.4, 0, .2, 1),
            visibility 0s linear .5s;
    }

    .spec-drawer:not(.is-open) {
        visibility: hidden;
    }

    .spec-drawer.is-open {
        visibility: visible;
        transition:
            height .5s cubic-bezier(.4, 0, .2, 1),
            visibility 0s;
    }
}

/* --- tablets and below (≤900) --------------------------------------------
   Type steps down and the panel's two columns stack.
   ------------------------------------------------------------------------- */
@media (max-width: 900px) {
    .spec-card,
    .spec-panel {
        --spec-gap:        20px;
        --spec-title:      30px;
        --spec-title-pad:  30px;
        --spec-desc:       24px;
        --spec-desc-pad:   30px;
        --spec-panel-gap:  0px;
    }

    .spec-panel.spec-panel {
        grid-template-columns: minmax(0, 1fr);
    }

    .spec-panel > .w-vwrapper:first-child {
        margin-bottom: 30px;
    }

    .spec-panel .w-btn-wrapper {
        margin-top: 24px;
    }
}

/* --- mobiles (≤600) ------------------------------------------------------
   Type down a step, and the card stops being square: a full-width 1/1 card on
   a phone runs most of a viewport tall, which pushes the title bar off
   screen. 4/3 keeps the whole card visible with the bar at its foot.
   ------------------------------------------------------------------------- */
@media (max-width: 600px) {
    .spec-card,
    .spec-panel {
        --spec-ratio:      4 / 3;
        --spec-radius:     16px;
        --spec-title:      26px;
        --spec-title-pad:  22px;
        --spec-desc:       20px;
        --spec-desc-pad:   22px;
        --spec-stack-gap:  40px;
    }

    .spec-card .spec-desc {
        max-width: 100%;
    }

    .spec-panel .w-btn-wrapper {
        margin-top: 20px;
    }
}

/* --- reduced motion -----------------------------------------------------
   The drawers are handled by the script, which opens and closes them without
   animating when this is on.
   ------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
    .spec-card.spec-card,
    .spec-card::after,
    .spec-card .w-text,
    .spec-card .w-text::after,
    .spec-panel.spec-panel {
        transition-duration: 1ms;
        transition-delay: 0s;
    }
}

/* --- first paint ---------------------------------------------------------
   The script adds .spec-still while it sets up and removes it two frames
   later, so the bar switching from its own background to the wash, and the
   first card arriving open, happen without animating on load.
   ------------------------------------------------------------------------- */
.spec-still .spec-card.spec-card,
.spec-still .spec-card::after,
.spec-still .spec-card .w-text,
.spec-still .spec-card .w-text::after,
.spec-still .spec-panel.spec-panel {
    transition: none;
}

/* --------------------------------------------------------------------------
   5.8.1  CARDS FLUSH TO THE GRID
   Unchanged from the previous file.
   Impreza pads every column's inner wrapper by 1.5rem a side (45px here) and
   normally cancels it with a negative margin on the row. 5.8 zeroes that
   margin, so the padding was left over and each card sat 45px inside its
   track. With it gone the first card starts on the grid's left edge, the
   last ends on its right, and the gap below is the only space between them.

   Width and margin are pinned too, because Design Options writes those on
   the column with !important. Resize the cards with the gap, not a width.
   -------------------------------------------------------------------------- */
.spec-row.spec-row.spec-row.spec-row {
    gap: 30px;                      /* space between the cards */
}

.spec-row.spec-row.spec-row > .wpb_column > .vc_column-inner {
    width: 100% !important;
    max-width: none !important;
    margin-left: 0 !important;
    margin-right: 0 !important;
    padding-left: 0 !important;
    padding-right: 0 !important;
}

/* ==========================================================================
   5.9  COMPONENT GALLERY — .component-gallery on the Post List (Carousel)
   White cards holding a part on white, greying out on hover to reveal the
   part name and a line of copy. Impreza / Owl. No JS.
   --------------------------------------------------------------------------
   GRID LAYOUT
   Vertical Wrapper
      Post Image                  (Aspect Ratio: Original)
      Post Title    -> cg-title
      Post Content  -> cg-desc
   --------------------------------------------------------------------------
   HOW THE OVERLAY IS LAID OUT
   The image is pulled OUT of flow and pinned to the card, which leaves the
   vwrapper holding nothing but the two text blocks — so it can be a plain
   centred flex column and the copy sits in the middle of the card without any
   positioning arithmetic. A long description simply pushes the title up;
   nothing needs re-tuning.
   That does mean the vwrapper covers the whole card and would swallow the
   clicks meant for the image's link, hence the pointer-events pair below.
   The scrim is the card's own ::after rather than an injected element, so the
   Grid Layout stays free of empty blocks.
   ========================================================================== */
.component-gallery {
    --cg-ratio:        1 / 1;      /* card shape                             */
    --cg-radius:       20px;
    --cg-bg:           #fff;
    --cg-pad:          30px;       /* white space around the part            */
    --cg-text-pad:     34px;       /* keeps the copy off the card edges      */
    --cg-zoom:         1.12;       /* how far the part pushes in on hover    */
    --cg-scrim:        rgb(0 0 0 / .45);   /* over white this reads grey     */
    --cg-title-size:   30px;
    --cg-desc-size:    19px;
    --cg-text-gap:     8px;
    --cg-speed:        520ms;
    --cg-ease:         cubic-bezier(.22, .68, .3, 1);
}

/* --- the card ------------------------------------------------------------
   clip, not hidden — hidden would make this a scroll container, which pins
   any scroll-driven animation inside it at 0%.
   isolation: isolate makes the card its own stacking context, so the scrim
   can sit above the image without competing with anything outside the card.
   ------------------------------------------------------------------------- */
.component-gallery .w-grid-item-h {
    position: relative;
    display: block;
    aspect-ratio: var(--cg-ratio);
    border-radius: var(--cg-radius);
    background: var(--cg-bg);
    overflow: clip;
    isolation: isolate;
}

/* --- the text column -----------------------------------------------------
   position:static so the image below anchors to the card rather than to this
   wrapper. Repeated class because Impreza writes gap and align onto vwrappers
   from the Grid Layout editor.
   ------------------------------------------------------------------------- */
.component-gallery .w-grid-item-h > .w-vwrapper.w-vwrapper {
    position: static;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--cg-text-gap);
    height: 100%;
    margin: 0;
    padding: var(--cg-text-pad);
    text-align: center;
    /* The wrapper spans the whole card, so without this it would sit over the
       image's link and nothing would be clickable. */
    pointer-events: none;
}

/* --- the part ------------------------------------------------------------
   Out of flow and pinned to the card. Three repeats of the class to clear
   Impreza's 25px bottom margin on .w-post-elm — on an inset:0 box that margin
   is subtracted from the height rather than pushing anything around, so it
   would leave a strip along the bottom.
   ------------------------------------------------------------------------- */
.component-gallery .post_image.post_image.post_image {
    position: absolute;
    inset: 0;
    z-index: 0;
    width: auto;
    height: auto;
    margin: 0;
    padding: 0;
    aspect-ratio: auto;
    pointer-events: auto;   /* puts the link back, see the wrapper above     */
}

.component-gallery .post_image :is(a, .w-post-elm-h) {
    display: block;
    width: 100%;
    height: 100%;
}

/* contain, not cover — these are parts photographed on white and cropping
   them would cut the ends off. The padding is what keeps them clear of the
   card edges as they scale.
   `scale`, not `transform: scale()`. Impreza writes transforms onto post
   elements from Design Options, and a transform here would be overwritten by
   one. The individual property composes instead of colliding. */
.component-gallery .post_image img {
    box-sizing: border-box;
    display: block;
    width: 100%;
    height: 100%;
    padding: var(--cg-pad);
    object-fit: contain;
    object-position: center;
    scale: 1;
    transition: scale var(--cg-speed) var(--cg-ease);
}

/* --- the scrim ----------------------------------------------------------- */
.component-gallery .w-grid-item-h::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 1;
    background: var(--cg-scrim);
    opacity: 0;
    transition: opacity var(--cg-speed) var(--cg-ease);
    pointer-events: none;
}

/* --- the copy ------------------------------------------------------------
   z-index puts both above the scrim. They need position for that to apply,
   and relative leaves them in the flex flow.
   ------------------------------------------------------------------------- */
.component-gallery :is(.cg-title, .cg-desc) {
    position: relative;
    z-index: 2;
    max-width: 100%;
    margin: 0;
    color: #fff;
    opacity: 0;
    translate: 0 10px;
    transition:
        opacity var(--cg-speed) var(--cg-ease),
        translate var(--cg-speed) var(--cg-ease);
}

/* The inner elements are covered too: a Post Title renders an anchor and Post
   Content renders paragraphs, both of which bring their own colour and
   margins from the theme. */
.component-gallery .cg-title,
.component-gallery .cg-title :is(a, h1, h2, h3, h4, h5, h6, span) {
    color: #fff;
    font-size: var(--cg-title-size);
    font-weight: 700;
    line-height: 1.2;
    text-decoration: none;
}

.component-gallery .cg-desc,
.component-gallery .cg-desc :is(p, span, div) {
    margin: 0;
    color: #fff;
    font-size: var(--cg-desc-size);
    font-weight: 400;
    line-height: 1.3;
}

/* --- the hover -----------------------------------------------------------
   Keyed off .w-grid-item — the whole card — so pointing anywhere on it fires
   all three at once. No :has() needed: the card is an ANCESTOR of everything
   that reacts, so a plain descendant selector reaches them.
   .no-touch is what Impreza puts on <html> for non-touch devices. Without it,
   tapping a card on a tablet leaves it stuck open until you tap elsewhere.
   The :focus-within pair keeps it reachable by keyboard.
   ------------------------------------------------------------------------- */
.no-touch .component-gallery .w-grid-item:hover .post_image img,
.component-gallery .w-grid-item:focus-within .post_image img {
    scale: var(--cg-zoom);
}

.no-touch .component-gallery .w-grid-item:hover .w-grid-item-h::after,
.component-gallery .w-grid-item:focus-within .w-grid-item-h::after {
    opacity: 1;
}

.no-touch .component-gallery .w-grid-item:hover :is(.cg-title, .cg-desc),
.component-gallery .w-grid-item:focus-within :is(.cg-title, .cg-desc) {
    opacity: 1;
    translate: none;
}

/* The description follows the title in rather than arriving with it. */
.no-touch .component-gallery .w-grid-item:hover .cg-desc,
.component-gallery .w-grid-item:focus-within .cg-desc {
    transition-delay: 90ms;
}

/* --- touch ---------------------------------------------------------------
   No hover, so the copy would never be reachable. Shown permanently instead,
   with the scrim on so it stays legible.
   ------------------------------------------------------------------------- */
@media (hover: none) {
    .component-gallery .w-grid-item-h::after {
        opacity: 1;
    }

    .component-gallery :is(.cg-title, .cg-desc) {
        opacity: 1;
        translate: none;
    }
}

/* --- mobile ------------------------------------------------------------- */
@media (max-width: 600px) {
    .component-gallery {
        --cg-pad: 20px;
        --cg-text-pad: 22px;
        --cg-title-size: 24px;
        --cg-desc-size: 17px;
    }
}

/* --- reduced motion ----------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
    .component-gallery .post_image img,
    .component-gallery .w-grid-item-h::after,
    .component-gallery :is(.cg-title, .cg-desc) {
        transition-duration: 1ms;
    }
}

.component-gallery.component-gallery.component-gallery .post_image img {
    box-sizing: border-box;
    display: block;
    width: 100%;
    height: 100%;
    aspect-ratio: auto;
    padding: var(--cg-pad);
    object-fit: contain;
    object-position: center;
    scale: 1;
    transition: scale var(--cg-speed) var(--cg-ease);
}

.component-gallery.component-gallery.component-gallery .post_image {
    margin: 0;
}

/* --- height:auto is what makes the ratio bite -----------------------------
   Impreza sets `height: 100%` on .w-grid-item-h. aspect-ratio only sizes a
   box when the OTHER dimension is auto, so with a definite height the ratio
   is computed and then discarded — the card falls back to content height and
   the square collapses to a strip the height of the title.
   Measured: a 206px-wide card came out 80.59px tall, which is the title's
   line box exactly.
   This sits in the same rule as the ratio rather than a rule of its own,
   because the two only make sense together.
   ------------------------------------------------------------------------- */
.component-gallery .w-grid-item-h {
    height: auto;
}

/* ==========================================================================
   COMPONENT GALLERY — no arrows
   ==========================================================================
   The arrows are also turned off in the element settings. This keeps them
   hidden if that setting is changed back.
   ========================================================================== */

.component-gallery .owl-nav {
    display: none !important;
}


/* ==========================================================================
   5.10  NEWS CARDS — post grid with card-level hover
   Built for the Impreza theme's Post List element (.w-grid / .w-grid-item).
   No JavaScript needed for the hovers — see the note under HOVER below. The
   show-more button has its own separate snippet.
   --------------------------------------------------------------------------
   EDITOR SETUP
   On the Post List element itself:  news-cards
   Grid Layout: layout_blog_1
   In the Grid Layout editor, in this order:
     Vertical Wrapper        — class: card-media      ← ADD THIS WRAPPER
        ├ Post Image         — class: card-image
        └ Categories         — class: card-cat
     Date of creation        — class: card-date
     Post Title              — class: card-title
     Read More button        — class: card-more
   The wrapper is the one structural change. The pill has to sit over the
   bottom-left corner of the image, and an element that is a SIBLING of the
   image cannot anchor itself to the image's box — percentages on `top`
   resolve against the container's height, not the image's. Nesting both
   inside a wrapper makes the wrapper the positioning context, so the pill is
   simply bottom:0 left:0 and the maths disappears. The wrapper also gives the
   zoom something to clip against.
   --------------------------------------------------------------------------
   HOVER
   Both effects key off .w-grid-item:hover — the whole card — not off the
   image or the title. That is why no :has() and no JS are needed: the card is
   an ANCESTOR of both things that react, so a plain descendant selector
   reaches them. (:has() would only be needed the other way round, for a
   parent reacting to a child.)
   The rules are prefixed with .no-touch, which Impreza puts on <html> for
   non-touch devices. Without it, tapping a card on a tablet leaves it stuck
   in its hover state until you tap elsewhere.
   ========================================================================== */
.news-cards {
    /* --- the image -------------------------------------------------------- */
    --nc-ratio-w: 1;                    /* crop shape of the post image      */
    --nc-ratio-h: 1;
    --nc-radius: 12px;
    --nc-zoom: 1.06;                    /* how far the image pushes in on
                                           hover. Keep it small — past about
                                           1.12 the softening shows.         */
    --nc-outline: 2px;                  /* the white stroke around the image */
    --nc-outline-ink: rgb(255 255 255 / .9);
    --nc-outline-gap: 0px;              /* raise for a gap between the stroke
                                           and the image edge                */
    /* --- the category pill ------------------------------------------------ */
    --nc-cat-bg: #fff;
    --nc-cat-ink: #111;
    --nc-cat-size: 16px;
    --nc-cat-pad: .55em 1.15em;
    --nc-cat-radius: 10px;              /* the top-right corner. The other
                                           three sit flush in the image's
                                           corner.                           */
    /* --- type ------------------------------------------------------------- */
    --nc-date-size: 13px;
    --nc-date-ink: rgb(255 255 255 / .7);
    --nc-title-size: 17px;
    --nc-title-ink: #fff;                              /* at rest           */
    --nc-title-ink-hover: var(--color-blue, #00bfff);  /* on card hover     */
    /* --- the underline ---------------------------------------------------- */
    --nc-rule: 3px;                     /* thickness                         */
    --nc-rule-gap: .35em;               /* distance below the text           */
    /* --- the divider under each card -------------------------------------- */
    --nc-divider: rgb(255 255 255 / .4);
    --nc-divider-gap: 1.6rem;
    /* --- motion ----------------------------------------------------------- */
    --nc-speed: 620ms;
    --nc-ease: cubic-bezier(.22, .68, .3, 1);
}

/* --------------------------------------------------------------------------
   5.10.1  NEWS CARDS — LANDSCAPE VARIANT
   Add alongside the base class: `news-cards news-cards-2` on the Post List.
   The only difference is the image crop — everything else (the pill, the
   date, the title rule, the divider, the hover) comes from the base rules
   and is untouched.
   Repeated class so it clears the base declaration at (0,1,0). The ratio is
   read by .news-cards .card-image img, which is (0,2,0), but these are
   variables on the same element the base sets them on, so one extra class
   is enough.
   -------------------------------------------------------------------------- */
.news-cards-2.news-cards-2 {
    --nc-ratio-w: 2;
    --nc-ratio-h: 1;
}

/* --- the card ------------------------------------------------------------ */
.news-cards .w-grid-item-h {
    position: relative;
    display: block;
    padding: 0;
}

.news-cards-2.news-cards-2 .w-grid-item-h::after {
    display: none;
}

/* --- the media wrapper ---------------------------------------------------
   clip, not hidden. hidden would make this a scroll container, which pins any
   scroll-driven animation inside it at 0%.
   ------------------------------------------------------------------------- */
.news-cards .card-media {
    position: relative;
    display: block;
    border-radius: var(--nc-radius);
    overflow: clip;
    /* `outline`, not `border`. A border participates in layout, so with
       box-sizing:border-box it would inset the image by its own width and
       shave a pixel off the crop; an outline is drawn outside the box and
       costs nothing. It follows border-radius, and outline-offset gives a gap
       for free if the design wants one. */
    outline: var(--nc-outline) solid var(--nc-outline-ink);
    outline-offset: var(--nc-outline-gap);
    /* The wrapper is a .w-vwrapper and will carry a gap from the editor. Its
       only children are the image and an absolutely positioned pill, so a gap
       here would just add dead space under the image. */
    gap: 0;
}

.news-cards .card-image,
.news-cards .card-image :is(a, .w-post-elm-h) {
    display: block;
    width: 100%;
}

/* aspect-ratio + object-fit rather than a fixed height: posts arrive with
   whatever shape the photo was shot in, and without a crop one card in the
   row ends up twice the height of its neighbours.
   `scale`, not `transform: scale()`. Impreza writes transforms onto post
   elements from Design Options, and a transform here would be overwritten by
   one. The individual property composes instead of colliding. */
.news-cards .card-image img {
    display: block;
    width: 100%;
    height: auto;
    aspect-ratio: var(--nc-ratio-w) / var(--nc-ratio-h);
    object-fit: cover;
    scale: 1;
    transform-origin: center;
    transition: scale var(--nc-speed) var(--nc-ease);
}

/* --- the category pill ---------------------------------------------------
   Flush into the image's bottom-left corner: three corners square, only the
   top-right rounded, so it reads as cut out of the image rather than floating
   on it. z-index keeps it above the image while the image scales.
   ------------------------------------------------------------------------- */
.news-cards .card-cat {
    position: absolute;
    left: 0;
    bottom: 0;
    z-index: 2;
    margin: 0;
    padding: var(--nc-cat-pad);
    border-radius: 0 var(--nc-cat-radius) 0 0;
    background: var(--nc-cat-bg);
    font-weight: 700;
    font-size: var(--nc-cat-size);
    line-height: 1.2;
    white-space: nowrap;
}

.news-cards .card-cat,
.news-cards .card-cat :is(a, span, div) {
    color: var(--nc-cat-ink);
    text-decoration: none;
}

/* --- date and title ------------------------------------------------------ */
.news-cards .card-date {
    margin: 1.1rem 0 .3rem;
    font-size: var(--nc-date-size);
    line-height: 1.3;
    color: var(--nc-date-ink);
}

/* Consolidated. This was previously split across two rules twenty lines
   apart — both applied, but editing one and wondering why nothing changed was
   only a matter of time. */
.news-cards .card-title {
    margin: 0;
    font-size: var(--nc-title-size);
    font-weight: 400;
    line-height: 1.35;
    color: var(--nc-title-ink);
}

/* inline-block so the underline pseudo-element gets a box to span. Left
   inline, an absolutely positioned pseudo on a wrapped link splits across
   line boxes and the underline lands in the wrong place.
   Impreza's post_title carries color_link_inherit, which sets the link colour
   from the element rather than the theme — so the colour has to be set on the
   <a> as well, or that inherit rule wins. */
.news-cards .card-title a {
    position: relative;
    display: inline-block;
    color: var(--nc-title-ink);
    text-decoration: none;
    transition: color var(--nc-speed) var(--nc-ease);
}

/* --- the Read more button ------------------------------------------------
   Only size and alignment are set here. The pill shape, white border and blue
   hover all come from us-btn-style_9 in Theme Options.
   WHERE THIS CLASS LANDS
   In Impreza's Grid Layout editor, a Button element puts its extra class on
   the <a class="w-btn"> ITSELF, not on a wrapping post element. So .card-more
   IS the button. An earlier version set display:flex with
   justify-content:flex-end on .card-more, which made the anchor a full-width
   flex container with its label shoved to the right edge — the pill spanning
   the whole column with "Read More" hanging off the end.
   The block below covers both shapes:
     a.card-more            the class is on the anchor    (the usual case)
     .card-more .w-btn      the class is on a wrapper     (fallback)
   fit-content plus margin-left:auto rather than align-self alone, because the
   parent may or may not be a flex container depending on whether the layout
   uses a Vertical Wrapper. A block-level box with a fit-content width and an
   auto left margin pushes right in BOTH cases.
   ------------------------------------------------------------------------- */
.news-cards a.card-more,
.news-cards .card-more .w-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    width: fit-content;
    min-width: 0;
    max-width: 100%;
    flex: none;
    align-self: flex-end;
    margin: 1.1rem 0 0 auto;
    white-space: nowrap;
}

/* If it did land on a wrapper, the wrapper still needs to stop stretching and
   the .w-btn-wrapper Theme Options puts inside it needs its block display
   undone. Harmless when there is no wrapper. */
.news-cards .card-more:not(a) {
    display: flex;
    justify-content: flex-end;
    width: 100%;
}

.news-cards .card-more:not(a) .w-btn-wrapper {
    display: flex;
    justify-content: flex-end;
    width: 100%;
    margin: 0;
}

/* --- the divider ---------------------------------------------------------
   On the card, not between grid tracks, so it stays put whatever the column
   count is and does not need a :last-child exception per breakpoint.
   ------------------------------------------------------------------------- */
.news-cards .w-grid-item-h::after {
    content: "";
    display: block;
    height: 2px;
    margin-top: var(--nc-divider-gap);
    background: var(--nc-divider);
}

/* --- the two hover effects -----------------------------------------------
   Both scoped to .w-grid-item:hover — the card — so pointing anywhere on the
   card fires both at once.
   ------------------------------------------------------------------------- */

/* 1. The image pushes in. The wrapper clips, so the image grows into its own
      frame rather than pushing the layout around. */
.no-touch .news-cards .w-grid-item:hover .card-image img,
.news-cards .w-grid-item:focus-within .card-image img {
    scale: var(--nc-zoom);
}

/* 2. The title turns blue and the blue rule wipes in under it, left to right.
      transform-origin plus scaleX rather than an animated width: width would
      trigger layout on every frame, scaleX runs on the compositor. */
.news-cards .card-title a::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    top: calc(100% + var(--nc-rule-gap));
    height: var(--nc-rule);
    background: var(--nc-title-ink-hover);
    transform: scaleX(0);
    transform-origin: left center;
    transition: transform var(--nc-speed) var(--nc-ease);
}

.no-touch .news-cards .w-grid-item:hover .card-title a,
.news-cards .w-grid-item:focus-within .card-title a {
    color: var(--nc-title-ink-hover);
}

.no-touch .news-cards .w-grid-item:hover .card-title a::after,
.news-cards .w-grid-item:focus-within .card-title a::after {
    transform: scaleX(1);
}

/* --- show more -----------------------------------------------------------
   Pairs with the news-more JS snippet, which hides everything past the first
   three and reveals the rest on click.
   display:none rather than visibility or opacity, for two reasons: a hidden
   grid item still occupies a grid cell under the other three, and browsers
   skip loading lazy images inside a display:none subtree, so the unrevealed
   photos cost nothing until they are shown.
   ------------------------------------------------------------------------- */
.news-cards .w-grid-item.nc-hidden {
    display: none;
}

/* display:none cannot be transitioned, so newly shown items run a keyframe
   animation instead. The stagger index comes from the JS as --nc-i, counting
   from the first REVEALED item rather than from the top of the list, so the
   delay starts at zero on item four instead of already being three steps
   in. */
.news-cards .w-grid-item.nc-in {
    animation: nc-in 620ms cubic-bezier(.22, .68, .3, 1) both;
    animation-delay: calc(var(--nc-i, 0) * 70ms);
}

/* The attribute rather than a class, so the button is hidden from assistive
   tech too and not just visually. */
.news-more[hidden] {
    display: none;
}

.news-more {
    width: fit-content;
    margin-inline: auto;
    align-self: center;
}

/* --- mobile --------------------------------------------------------------
   A full-width single column reads better with the button under the title
   rather than pushed to a far edge.
   ------------------------------------------------------------------------- */
@media (max-width: 600px) {
    .news-cards {
        --nc-divider-gap: 1.2rem;
    }

    .news-cards a.card-more,
    .news-cards .card-more .w-btn {
        align-self: flex-end;
        margin-left: auto;
        margin-right: 0;
    }
}

/* --- reduced motion ----------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
    .news-cards .card-image img,
    .news-cards .card-title a,
    .news-cards .card-title a::after {
        transition-duration: 1ms;
    }

    .news-cards .w-grid-item.nc-in {
        animation-duration: 1ms;
        animation-delay: 0s;
    }
}

/* --- keyframes ----------------------------------------------------------- */
@keyframes nc-in {
    from {
        opacity: 0;
        transform: translateY(18px);
    }
    to {
        opacity: 1;
        transform: none;
    }
}

/* ==========================================================================
   5.11  TESTIMONIAL CARDS
   Built for the Impreza theme's Post List element (.w-grid / .w-grid-item).
   Card styling and the carousel were two separate sections in the previous
   file; they describe one component and are merged here.
   --------------------------------------------------------------------------
   EDITOR SETUP
   On the Post List element:  testimonial-cards
                              Type: Grid  (NOT Carousel — see WHY NOT
                              IMPREZA'S CAROUSEL below)
                              Pagination: None
   In the Grid Layout:
     Post Image                        — class: tc-avatar
     Post Content                      — class: tc-quote
     Testimonial Fields: Author        — class: tc-author
     Horizontal Wrapper                — class: tc-meta
        ├ Testimonial Fields: Job Title — class: tc-role
        └ Testimonial Fields: Company   — class: tc-company
   Below the post list, a Button:  tc-next
                                   text "none"
   THE ARROW'S CLASS LIST MATTERS. tc-next must be the only class on that
   button — it does not build on the arrow-btn system at all. If arrow-btn
   (from the button style) or arrow-btn-right / arrow-btn-rest-right are still
   present, they apply the base box, the blue fill and a rotation on top of
   what is drawn below. Give the button a style that carries no arrow-btn
   class, or remove it from the style's extra class field.
   --------------------------------------------------------------------------
   THE OPTIONAL AVATAR
   WordPress puts has-post-thumbnail on the <article> only when the post
   actually has a featured image, and Impreza passes those post classes
   straight through to .w-grid-item. So the avatar can be collapsed with a
   plain :not() — no JS, no per-post setting, and nothing to remember when
   adding a testimonial.
   Impreza also renders a placeholder SVG in the image element on some
   configurations rather than rendering nothing, which would leave an empty
   grey circle. The second selector below catches that case too.
   display:none rather than a zero height: the card is a flex column with a
   gap, and a zero-height child still gets its share of the gap, leaving a
   visible dent above the quote.
   ========================================================================== */
.testimonial-cards {
    /* --- the card --------------------------------------------------------- */
    --tc-radius: 26px;
    --tc-pad: 2.2rem;
    --tc-border: 2px;
    --tc-border-ink: rgb(255 255 255);
    --tc-bg: transparent;
    /* --- the avatar ------------------------------------------------------- */
    --tc-avatar-size: 96px;
    --tc-avatar-gap: 1.8rem;            /* space below it, when present      */
    /* --- type ------------------------------------------------------------- */
    --tc-quote-size: 17px;
    --tc-quote-line: 1.55;
    --tc-quote-ink: #fff;
    --tc-author-size: 15px;
    --tc-author-ink: #fff;
    --tc-meta-size: 15px;
    --tc-meta-ink: var(--color-blue, #00bfff);
    --tc-meta-dash: "–";                /* en dash between role and company  */
    /* --- the carousel ----------------------------------------------------- */
    --tc-visible: 3;                    /* cards in view at once             */
    --tc-gap: 1.5rem;                   /* space between cards               */
    --tc-peek: 0px;                     /* raise to show a sliver of the next
                                           card as a hint that there is more */
}

/* --- the card ------------------------------------------------------------
   height:100% so every card in the row matches the tallest, whatever the
   quote length. Without it each card shrinks to its own content and the
   bottoms stagger.
   ------------------------------------------------------------------------- */
.testimonial-cards .w-grid-item-h {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    height: 100%;
    padding: var(--tc-pad);
    border: var(--tc-border) solid var(--tc-border-ink);
    border-radius: var(--tc-radius);
    background: var(--tc-bg);
}

/* If the layout wraps the elements in a Vertical Wrapper, that wrapper
   becomes the flex column instead and needs the same treatment. Harmless when
   there is no wrapper. */
.testimonial-cards .w-grid-item-h > .w-vwrapper {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    flex: 1;
    width: 100%;
}

/* --- the avatar ---------------------------------------------------------- */
.testimonial-cards .tc-avatar {
    display: block;
    width: var(--tc-avatar-size);
    margin: 0 0 var(--tc-avatar-gap);
    flex: none;
}

.testimonial-cards .tc-avatar :is(a, .w-post-elm-h) {
    display: block;
}

.testimonial-cards .tc-avatar img {
    display: block;
    width: var(--tc-avatar-size);
    height: var(--tc-avatar-size);
    aspect-ratio: 1;
    object-fit: cover;
    border-radius: 50%;
}

/* Collapsed when there is no headshot — see the header note. */
.testimonial-cards .w-grid-item:not(.has-post-thumbnail) .tc-avatar,
.testimonial-cards .tc-avatar:has(img.g-placeholder) {
    display: none;
}

/* --- the quote -----------------------------------------------------------
   flex:1 pushes the attribution to the bottom of the card, so names line up
   across a row of unequal quotes. Delete this line if the name should sit
   directly under the quote instead.
   ------------------------------------------------------------------------- */
.testimonial-cards .tc-quote {
    flex: 1;
    width: 100%;
    margin: 0 0 1.4rem;
    font-size: var(--tc-quote-size);
    line-height: var(--tc-quote-line);
    color: var(--tc-quote-ink);
}

.testimonial-cards .tc-quote :is(p, div, span) {
    margin: 0 0 .8em;
    font-size: inherit;
    line-height: inherit;
    color: inherit;
}

.testimonial-cards .tc-quote > :last-child,
.testimonial-cards .tc-quote :is(p, div):last-child {
    margin-bottom: 0;
}

/* --- the attribution ----------------------------------------------------- */
.testimonial-cards .tc-author {
    width: 100%;
    margin: 0 0 .2rem;
    font-size: var(--tc-author-size);
    font-weight: 700;
    line-height: 1.35;
    color: var(--tc-author-ink);
}

/* nowrap, not wrap. On a narrow card the role and company were breaking onto
   separate lines, which left the dash orphaned at the start of the second
   line reading like a typo. Ellipsis is the better failure mode here. */
.testimonial-cards .tc-meta {
    display: flex;
    flex-wrap: nowrap;
    align-items: baseline;
    gap: 0 .4em;
    width: 100%;
    margin: 0;
    font-size: var(--tc-meta-size);
    line-height: 1.35;
    color: var(--tc-meta-ink);
}

.testimonial-cards .tc-meta :is(.tc-role, .tc-company),
.testimonial-cards .tc-meta :is(.tc-role, .tc-company) :is(a, span, div) {
    margin: 0;
    font-size: inherit;
    line-height: inherit;
    color: inherit;
}

.testimonial-cards .tc-meta :is(.tc-role, .tc-company) {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* The dash lives on the company rather than between the two elements, because
   a gap-based separator would need a third element in the layout.
   Guarded with :has() so a testimonial with no job title does not leave a dash
   dangling — Impreza still renders the element when the field is empty, it
   just has no text in it. */
.testimonial-cards .tc-meta .tc-company::before {
    content: var(--tc-meta-dash) " ";
}

.testimonial-cards .tc-meta:has(.tc-role:empty) .tc-company::before,
.testimonial-cards .tc-meta:not(:has(.tc-role)) .tc-company::before {
    content: none;
}

/* --- optional: typographic quote marks -----------------------------------
   Commented out on purpose. If whoever enters the testimonial types the
   quotation marks into the content field — the likelier habit — this would
   double them up. Uncomment only if the content is stored bare.
.testimonial-cards .tc-quote > :first-child::before { content: "\201C"; }
.testimonial-cards .tc-quote > :last-child::after  { content: "\201D"; }
   ------------------------------------------------------------------------- */

/* --------------------------------------------------------------------------
   5.11.1  THE CAROUSEL
   Three cards visible, the rest reachable by swipe, scroll, or the arrow.
   Pairs with the testimonial-carousel JS snippet.
   --------------------------------------------------------------------------
   WHY NOT IMPREZA'S CAROUSEL TYPE
   Impreza's carousel is Owl, which measures its container and computes stage
   and slide widths in JS at init, before any stylesheet can weigh in. That is
   the whole problem documented in 5.5 — narrowing the track needs a
   dispatched resize event, the slide width and the container width drift
   apart, and the numbers in those comments are still marked unresolved.
   A scroll-snap track has none of that. The browser owns the scrolling, the
   card width is a CSS calculation, swipe and trackpad gestures work with no
   code, and keyboard focus scrolls an off-screen card into view by itself.
   The JS only moves the scroll position when the arrow is clicked; if it
   fails to load, the track still scrolls.
   -------------------------------------------------------------------------- */

/* --- the track -----------------------------------------------------------
   THREE repeats of .testimonial-cards, giving (0,4,0). Impreza styles this
   same element at .w-grid.type_grid .w-grid-list, which is (0,3,0) — a plain
   `.testimonial-cards .w-grid-list` is only (0,2,0) and LOSES, leaving
   display:grid and a track that does not scroll at all. Confirmed from the
   console: getComputedStyle(...).display returned 'grid'.
   Four levels rather than the three needed to break the tie, because this is
   the rule the entire carousel depends on and the theme's own selector could
   gain a level in an update.
   overscroll-behavior-x: contain stops a swipe that reaches the end of the
   track from continuing on to navigate the page back, which is the default on
   iOS and feels like a bug.
   The scrollbar is hidden because the arrow is the intended control. It is
   hidden visually only — the track is still a real scroll container, so
   wheel, trackpad, swipe and keyboard all still work.
   ------------------------------------------------------------------------- */
.testimonial-cards.testimonial-cards.testimonial-cards .w-grid-list {
    display: flex;
    flex-wrap: nowrap;
    gap: var(--tc-gap);
    overflow-x: auto;
    overflow-y: visible;
    overscroll-behavior-x: contain;
    scroll-snap-type: x mandatory;
    /* Inert once display is flex, but cleared so nothing is left half-applied
       if this is ever switched back to a grid. */
    grid-template-columns: none;
    /* Room for the cards' focus outlines, which the scroll container's own
       box would otherwise clip. */
    padding-block: 4px;
    scrollbar-width: none;
    -ms-overflow-style: none;
}

.testimonial-cards .w-grid-list::-webkit-scrollbar {
    display: none;
}

/* --- the cards -----------------------------------------------------------
   Width is derived from --tc-visible rather than written per breakpoint: the
   gaps between N cards number N-1, so the available width is the track minus
   those, divided by N.
   width and max-width are cleared as well as the flex basis being set —
   Impreza sizes grid items from its --columns setting, and a leftover width
   would fight the basis once the track is flex.
   min-width:0 because a flex item defaults to min-width:auto, which refuses
   to shrink below its content — a long unbroken word in a quote would push
   the card wider than its share and throw the whole row out.
   Flex items stretch by default, so equal card heights come free here anmd the
   height:100% on the card does the rest.
   ------------------------------------------------------------------------- */
.testimonial-cards.testimonial-cards.testimonial-cards .w-grid-item {
    flex: 0 0 calc(
        (100% - (var(--tc-visible) - 1) * var(--tc-gap) - var(--tc-peek))
        / var(--tc-visible)
    );
    width: auto;
    max-width: none;
    min-width: 0;
    scroll-snap-align: start;
}

/* ==========================================================================
   TESTIMONIAL CARDS — tablet and mobile widths
   ==========================================================================
   Pairs with the TESTIMONIAL CARDS JS snippet (looping carousel).

   The cards were being sized as if three always had to fit, so on narrow
   screens each card ended up around 145px wide and very tall. Here the track
   is forced to a flex row and every card is sized from --tc-per-view:

     601–900px   heading goes above the cards, 2 cards in view
     600 and below                             1 card in view

   The JS measures the card spacing from the cards themselves, so the arrow
   and the loop keep working at these widths without changes.
   ========================================================================== */

@media (max-width: 900px) {

    /* Heading column above the cards instead of squeezed beside them */
    .l-section:has(.testimonial-cards) > .l-section-h > .g-cols.via_flex > .wpb_column {
        width: 100%;
    }

    .testimonial-cards.w-grid .w-grid-list {
        --tc-per-view: 2;
        --tc-gap: var(--gap, 1.5rem);

        display: flex !important;
        flex-wrap: nowrap !important;
        gap: var(--tc-gap) !important;
        overflow-x: auto;
        overscroll-behavior-x: contain;
        scroll-snap-type: x mandatory;
    }

    .testimonial-cards.w-grid .w-grid-list > .w-grid-item {
        flex: 0 0 calc((100% - (var(--tc-per-view) - 1) * var(--tc-gap)) / var(--tc-per-view)) !important;
        width: auto !important;
        max-width: none !important;
        min-width: 0;
        margin: 0 !important;
        scroll-snap-align: start;
    }
}

@media (max-width: 600px) {

    .testimonial-cards.w-grid .w-grid-list {
        --tc-per-view: 1;
    }
}
/* ==========================================================================
   5.12  SUPPLIER BAND
   A wide bordered banner with a background image and a bordered logo box
   sitting over it. Runs inside a Grid Layout on a Post List element. No JS.
   --------------------------------------------------------------------------
   EDITOR SETUP
   Post List element   class: supplier-adverts
                       Columns: 1
                       Pagination: None
   In the Grid Layout:
     Vertical Wrapper                        — class: supplier-band
        ├ Advert Fields: Advert BG Image        — class: sb-bg
        ├ Advert Fields: Advert BG Image Mobile — class: sb-bg-mobile
        └ Advert Fields: Advert Client Logo     — class: sb-logo
   IMPORTANT — clear any Design Options sizing on all three images. Impreza
   writes those as .us_custom_xxxxxxx rules with !important, which beat
   everything below.
   --------------------------------------------------------------------------
   TWO THINGS THAT LEFT A BLACK STRIP ALONG THE BOTTOM
   Both worth knowing, because both look identical on screen and neither is
   obvious from the markup.
   1. HEIGHT AS A PERCENTAGE. The obvious build stretches the field element to
      the band and gives the image width:100%; height:100%. That fails
      whenever Impreza's inner wrapper is not one you anticipated: height:100%
      resolves against the PARENT, and if that parent's own height is auto the
      percentage has nothing to resolve against, so the image falls back to
      its natural ratio and comes up short. The image is therefore positioned
      directly with inset:0, which needs no percentage to resolve, and every
      wrapper in between is forced static so none can intercept the anchor.
   2. MARGIN ON AN ABSOLUTE BOX. An absolutely positioned element with both
      top:0 and bottom:0 takes its height from
      containing block − top − bottom − MARGINS. Impreza gives .w-post-elm a
      25px bottom margin, which came straight off the bottom of the band — a
      measured 221.141px inside a 246.141px band, exactly 25px short. Zeroing
      it needs to actually win, hence the repeated classes below rather than a
      plain descendant selector.
   --------------------------------------------------------------------------
   THE MOBILE SWAP
   Both background fields are output on every page load; CSS picks which one
   is displayed. The breakpoint is 900px, matching the point where the band's
   ratio squares up — a wide desktop crop stops working at the same width the
   band stops being wide.
   The hidden one costs nothing to speak of PROVIDED Impreza emits
   loading="lazy" on these images: a lazy image inside a display:none subtree
   never intersects the viewport, so it is never fetched. Without that
   attribute both files download on every device.
   The breakpoint is written literally in the media queries because media
   queries cannot read custom properties. If you move it, move it in all three
   places below.
   ========================================================================== */
.supplier-band {
    /* --- the band --------------------------------------------------------- */
    --sb-ratio-w: 13;                   /* the band's shape. 13/2 is the
                                           6.5:1 in the design — change both */
    --sb-ratio-h: 2;
    --sb-radius: 0px;
    --sb-bg-pos: center;                /* which strip of the photo survives */
    /* --- the borders ------------------------------------------------------ */
    --sb-border: 3px;
    --sb-border-ink: #fff;
    --sb-logo-border: 3px;
    --sb-logo-border-ink: #fff;
    /* --- the logo box ----------------------------------------------------
       --sb-logo-img-h is the ONLY size control. The outline wraps whatever
       the logo turns out to be at that height, plus the padding. */
    --sb-logo-img-h: 46px;
    --sb-logo-x: 2.5rem;                /* in from the band's left edge      */
    --sb-logo-y: 2.5rem;                /* down from the band's top edge     */
    --sb-logo-pad: 1.1rem;
    --sb-logo-bg: transparent;
    position: relative;
    display: block;
    width: 100%;
    aspect-ratio: var(--sb-ratio-w) / var(--sb-ratio-h);
    border: var(--sb-border) solid var(--sb-border-ink);
    border-radius: var(--sb-radius);
    /* clip, not hidden — hidden creates a scroll container, which pins any
       scroll-driven animation inside it at 0%. */
    overflow: clip;
    gap: 0;
}

/* --- the grid around it --------------------------------------------------
   The band is a post in a Post List, so there is a grid and a grid item
   between it and the page. Neither should introduce its own width, padding or
   positioning context.
   Three repeats of .supplier-adverts gives (0,4,0), clearing Impreza's
   .w-grid.type_grid .w-grid-list at (0,3,0). Two would tie on the columns
   rule and win only on load order.
   ------------------------------------------------------------------------- */
.supplier-adverts.supplier-adverts.supplier-adverts .w-grid-list {
    display: block;
    grid-template-columns: none;
    gap: 0;
}

.supplier-adverts .w-grid-item,
.supplier-adverts .w-grid-item-h {
    position: static;
    display: block;
    width: auto;
    max-width: none;
    padding: 0;
    margin: 0;
}

/* Impreza nests wrappers between the element and its blocks. None should
   become the containing block, or the logo anchors to a wrapper instead of
   the band. Same guard used on .arrow-group and .dir-panels. */
.supplier-band :is(.vc_column-inner, .wpb_wrapper, .w-vwrapper, .w-hwrapper) {
    position: static;
}

/* --- the photographs -----------------------------------------------------
   Three repeats of the class, giving (0,4,0). Impreza's margin on
   .w-post-elm sits above a plain descendant selector, and on an absolutely
   positioned box that margin is subtracted from the height rather than
   pushing anything around — see note 2 in the header. This is the rule that
   closes the strip along the bottom.
   ------------------------------------------------------------------------- */
.supplier-band .sb-bg.sb-bg.sb-bg,
.supplier-band .sb-bg-mobile.sb-bg-mobile.sb-bg-mobile {
    position: absolute;
    inset: 0;
    display: block;
    width: auto;
    height: auto;
    margin: 0;
    padding: 0;
    border: 0;
    z-index: 1;
}

/* Every wrapper between the field element and the image is forced static with
   no box of its own, so the image anchors to the field element and nothing in
   between can intercept it. The universal selector is deliberate — the point
   is to catch wrappers this file does not know the name of. */
.supplier-band :is(.sb-bg, .sb-bg-mobile) * {
    position: static;
    display: block;
    width: auto;
    height: auto;
    margin: 0;
    padding: 0;
    border: 0;
}

/* The image positioned directly rather than filling a wrapper. inset:0 needs
   no percentage to resolve, so it cannot fall back to the natural ratio. */
.supplier-band :is(.sb-bg, .sb-bg-mobile) img {
    position: absolute;
    inset: 0;
    display: block;
    width: 100%;
    height: 100%;
    margin: 0;
    object-fit: cover;
    object-position: var(--sb-bg-pos);
}

/* Desktop first: the mobile crop is out until the breakpoint calls for it. */
.supplier-band .sb-bg-mobile.sb-bg-mobile.sb-bg-mobile {
    display: none;
}

/* --- the logo box --------------------------------------------------------
   THE OUTLINE WRAPS THE LOGO, NOT THE OTHER WAY ROUND
   The image is given ONE dimension, its height, and takes its width from its
   own intrinsic ratio. The box is fit-content in both axes, so it wraps
   whatever the image turns out to be, plus padding. Nothing is constrained,
   so nothing can overflow.
   inline-grid rather than grid or block: those would still stretch to the
   available width, and the border would wrap the wrapper instead of the logo.
   Repeated classes here too — the same .w-post-elm margin would otherwise
   push the box down and out of alignment with --sb-logo-y.
   ------------------------------------------------------------------------- */

.supplier-band .sb-logo.sb-logo.sb-logo {
    position: absolute;
	top: var(--sb-logo-y);
    left: var(--sb-logo-x);
    bottom: auto;
    right: auto;
    z-index: 2;
    display: inline-grid;
    place-items: center;
    width: fit-content;
    height: calc(100%-30px);
    min-width: 0;
    min-height: 0;
    max-width: calc(100% - var(--sb-logo-x) * 2);
    margin: 0;
    padding: var(--sb-logo-pad);
    border: var(--sb-logo-border) solid var(--sb-logo-border-ink);
    background: var(--sb-logo-bg);
}

@media (min-width: 901px) {
	.supplier-band .sb-logo.sb-logo.sb-logo{
		top: 50%;
		transform: translateY(-50%);
	}
}

/* Every wrapper between the field element and the logo shrink-wraps too, or
   one of them stretches and the border ends up around the wrapper rather than
   the logo. Same universal-selector reasoning as the backgrounds. */
.supplier-band .sb-logo * {
    display: block;
    width: fit-content;
    height: auto;
    max-width: 100%;
    margin: 0;
    padding: 0;
    border: 0;
}

/* Height set, width auto — that is what makes the shrink-wrap work: give an
   image one dimension and it derives the other from its intrinsic ratio.
   contain rather than none. With width:auto honoured there is nothing to fit
   and contain does nothing; if anything ever forces a width, contain scales
   the logo down instead of cropping the middle out of it. */
.supplier-band .sb-logo img {
    display: block;
    width: auto;
    height: var(--sb-logo-img-h);
    max-width: 100%;
    margin: 0;
    object-fit: contain;
}

/* --- responsive ----------------------------------------------------------
   A 6.5:1 band on a phone is a 55px sliver with a logo box that does not fit
   inside it. The ratio squares up as the viewport narrows, and the logo comes
   down with it — one number, since the box follows the image.
   The background swaps at the same 900px point. Doing it anywhere else would
   leave either a wide crop in a squared-up band or the reverse.
   ------------------------------------------------------------------------- */
@media (max-width: 900px) {
    .supplier-band {
        --sb-ratio-w: 5;
        --sb-ratio-h: 2;
        --sb-logo-img-h: 38px;
        --sb-logo-pad: .9rem;
        --sb-logo-x: 1.5rem;
        --sb-logo-y: 1.5rem;
    }

    .supplier-band .sb-bg.sb-bg.sb-bg {
        display: none;
    }

    .supplier-band .sb-bg-mobile.sb-bg-mobile.sb-bg-mobile {
        display: block;
    }

    /* If no mobile image has been set on a given advert, Impreza still
       renders the element — just with no <img> inside it. Swapping to an
       empty element would leave a blank band, so the desktop crop is put back
       when the mobile one has nothing in it. Must stay after the pair above. */
    .supplier-band:has(.sb-bg-mobile:not(:has(img))) .sb-bg.sb-bg.sb-bg {
        display: block;
    }

    .supplier-band:has(.sb-bg-mobile:not(:has(img))) .sb-bg-mobile.sb-bg-mobile.sb-bg-mobile {
        display: none;
    }
}

@media (max-width: 600px) {
    .supplier-band {
        --sb-ratio-w: 3;
        --sb-ratio-h: 2;
        --sb-border: 1px;
        --sb-logo-border: 1px;
        --sb-logo-img-h: 30px;
        --sb-logo-pad: .7rem;
        --sb-logo-x: 1rem;
        --sb-logo-y: 1rem;
    }
}

/* ==========================================================================
   5.13  ACCORDION — .hec-accordion
   A nested accordion: machine groups at level 1, individual machines at
   level 2, each opening to a detail panel with copy and up to two images.
   Everything is driven by the variables in the first block.
   --------------------------------------------------------------------------
   Pairs with the accordion JS, which owns the panel heights and the
   aria-expanded state. This section styles what the script produces.
   ========================================================================== */
.hec-accordion {
    --hec-fg:            #ffffff;
    --hec-accent:        #2fa8e8;
    --hec-rule:          rgb(255 255 255 / .9);
    --hec-rule-item:     rgb(255 255 255 / .9);
    --hec-card-bg:       #2c2c2c;
    --hec-card-radius:   18px;
    --hec-card-pad:      2.75rem;
    --hec-group-size:    clamp(1.5rem, 2.4vw, 2.25rem);
    --hec-item-size:     clamp(1.125rem, 1.5vw, 1.5rem);
    --hec-gap-group:     2.75rem;
    --hec-gap-item:      1.75rem;
    --hec-icon:          2.5rem;
    --hec-icon-gap:      1.25rem;
    --hec-media-gap:     2rem;
    --hec-media-height:  30rem;
    --hec-body-size:     1rem;
    /* Width of the short rule under a closed machine title. */
    --hec-rule-width:    26rem;
    --hec-speed:         .4s;
    --hec-ease:          cubic-bezier(.4, 0, .2, 1);
    color: var(--hec-fg);
}

/* Zeroing the duration rather than the transition itself, so the JS-driven
   height still lands on its final value — it just gets there instantly. */
@media (prefers-reduced-motion: reduce) {
    .hec-accordion {
        --hec-speed: 0s;
    }
}

/* --------------------------------------------------------------------------
   PANELS
   The height is set by the JS; this only supplies the transition and the
   closed state.
   -------------------------------------------------------------------------- */
.hec-acc__panel {
    height: 0;
    overflow: hidden;
    transition: height var(--hec-speed) var(--hec-ease);
}

.hec-acc__panel[hidden] {
    display: none;
}

.hec-acc__panel--group > .hec-acc__panel-inner {
    padding-top: var(--hec-gap-item);
}

/* --------------------------------------------------------------------------
   TRIGGERS
   Closed, the button hugs its own text so the underline stops with the title.
   Open, it stretches full width and pushes the arrow out to the right.
   -------------------------------------------------------------------------- */
.hec-acc__head {
    margin: 0;
    font-weight: inherit;
}

.hec-acc__trigger {
    display: flex;
    align-items: center;
    gap: var(--hec-icon-gap);
    width: max-content;
    max-width: 100%;
    margin: 0;
    padding: 0 0 1.1rem;
    background: none;
    border: 0;
    border-bottom: 1px solid var(--hec-rule);
    border-radius: 0;
    color: inherit;
    font: inherit;
    text-align: left;
    cursor: pointer;
    appearance: none;
}

.hec-acc__trigger:focus-visible {
    outline: 2px solid var(--hec-accent);
    outline-offset: 6px;
}

.hec-acc__label {
    line-height: 1.15;
}

/* --- level 1: the group -------------------------------------------------- */
.hec-acc__group {
    margin-bottom: var(--hec-gap-group);
}

.hec-acc__trigger--group {
    font-size: var(--hec-group-size);
    font-weight: 300;
    letter-spacing: -.01em;
}

.hec-acc__trigger--group[aria-expanded="true"] {
    width: 100%;
    justify-content: space-between;
}

/* --- level 2: the machine ------------------------------------------------ */
.hec-acc__item {
    margin-bottom: var(--hec-gap-item);
}

.hec-acc__trigger--item {
    color: var(--hec-accent);
    font-size: var(--hec-item-size);
    font-weight: 700;
    padding-bottom: 0;
    border-bottom: 0;
}

.hec-acc__trigger--item[aria-expanded="true"] {
    width: 100%;
    justify-content: space-between;
}

/* The short rule sits under the machine, open or closed. It is a separate
   element rather than the trigger's own border, because the trigger shrinks
   to its text when closed and this needs a width of its own. */
.hec-acc__rule {
    display: block;
    width: var(--hec-rule-width);
    max-width: 100%;
    height: 1px;
    margin-top: var(--hec-gap-item);
    background: var(--hec-rule-item);
}

/* When open, the whole machine becomes the dark card from the design. */
.hec-acc__card {
    padding: 0;
    background: transparent;
    border-radius: var(--hec-card-radius);
    transition:
        background-color var(--hec-speed) var(--hec-ease),
        padding var(--hec-speed) var(--hec-ease);
}

.hec-acc__item.is-open > .hec-acc__card {
    padding: var(--hec-card-pad);
    background: var(--hec-card-bg);
}

/* --------------------------------------------------------------------------
   ICONS
   -------------------------------------------------------------------------- */
.hec-acc__icon {
    flex: 0 0 auto;
    display: inline-flex;
    width: var(--hec-icon);
    height: var(--hec-icon);
    transition: transform var(--hec-speed) var(--hec-ease);
}

.hec-acc__icon svg {
    display: block;
    width: 100%;
    height: 100%;
}

.hec-acc__trigger[aria-expanded="true"] .hec-acc__icon {
    transform: rotate(180deg);
}

/* The machine icons sit a step smaller than the group ones. */
.hec-acc__trigger--item .hec-acc__icon {
    --hec-icon: 2.125rem;
}

/* --------------------------------------------------------------------------
   MACHINE DETAIL LAYOUT
   -------------------------------------------------------------------------- */
.hec-acc__layout {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr);
    gap: 2.5rem;
    align-items: center;
    padding-top: 2rem;
}

.hec-acc__item--no-media .hec-acc__layout {
    grid-template-columns: minmax(0, 1fr);
}

/* Two machines need real room, so the media column takes the larger share. */
.hec-acc__item--multi-media .hec-acc__layout {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.9fr);
    gap: 3rem;
}

/* --- the copy ------------------------------------------------------------ */
.hec-acc__body {
    max-width: 62ch;
    font-size: var(--hec-body-size);
    line-height: 1.5;
}

.hec-acc__body > :first-child {
    margin-top: 0;
}

.hec-acc__body > :last-child {
    margin-bottom: 0;
}

.hec-acc__body :is(h2, h3, h4, h5, h6) {
    margin: 2rem 0 1rem;
    color: var(--hec-accent);
    font-size: 24px;
    font-weight: 700;
    letter-spacing: .01em;
}

.hec-acc__body p {
    margin: 0 0 1rem;
}

.hec-acc__body ul {
    margin: 0 0 1rem;
    padding-left: 1.4rem;
    list-style: disc;
}

.hec-acc__body li {
    margin-bottom: .35rem;
}

.hec-acc__body li::marker {
    color: var(--hec-accent);
	font-size: 24px;
}

/* --- the images ----------------------------------------------------------
   Scoped to .hec-accordion and sized with flex-basis rather than width, so a
   theme rule like `img { width: 100% }` can't push these onto separate rows.
   ------------------------------------------------------------------------- */
.hec-accordion .hec-acc__media {
    align-self: center;
    display: flex;
    flex-direction: row;
    flex-wrap: nowrap;
    align-items: center;
    justify-content: center;
    gap: var(--hec-media-gap);
}

.hec-accordion .hec-acc__media > .hec-acc__img {
    flex: 1 1 0;
    min-width: 0;
    max-width: 100%;
    height: var(--hec-media-height);
    object-fit: contain;
    object-position: center;
}

/* A lone image just fills its column at its natural proportions. */
.hec-accordion .hec-acc__media[data-count="1"] > .hec-acc__img {
    flex: 1 1 auto;
    height: auto;
    object-fit: fill;
}

/* --------------------------------------------------------------------------
   RESPONSIVE
   -------------------------------------------------------------------------- */
@media (max-width: 900px) {
    .hec-accordion {
        --hec-card-pad: 1.5rem;
        --hec-gap-group: 2rem;
        --hec-icon: 2rem;
        --hec-icon-gap: .85rem;
        --hec-rule-width: 100%;
    }

    .hec-acc__layout,
    .hec-acc__item--multi-media .hec-acc__layout {
        grid-template-columns: minmax(0, 1fr);
        gap: 1.5rem;
    }

    .hec-accordion .hec-acc__media {
        --hec-media-height: 16rem;
        --hec-media-gap: 1.25rem;
    }

    /* Titles wrap on narrow screens, so keep the rule full width throughout
       rather than only when open. */
    .hec-acc__trigger {
        width: 100%;
        justify-content: space-between;
    }
}

/* Below this width two machines side by side get too small to read, so they
   stack instead. */
@media (max-width: 600px) {
    .hec-accordion .hec-acc__media {
        flex-wrap: wrap;
    }

    .hec-accordion .hec-acc__media > .hec-acc__img {
        flex: 1 1 100%;
        height: auto;
        max-height: var(--hec-media-height);
        object-fit: contain;
    }
}

/* ==========================================================================
   5.14 - TEXT OVERLAP
   A photo with a copy panel overlapping it. The base class carries the
   layout; a numbered variation sets the arrangement.
   --------------------------------------------------------------------------
   EDITOR SETUP
   Section  -> text-overlap text-overlap-1
      Row
         Column  6/12          (the photo)
            Image
         Column  6/12          (the panel)
            Vertical Wrapper
               Button -> arrow-btn      (the blue arrow on the join)
               Text   -> small-blue-text
               Text (H2)
               Text block
               Button                   (the CTA)
   Add the base class AND a variation class. The base alone lays nothing out.
   --------------------------------------------------------------------------
   THE SHAPE
   The photo and the panel are staggered, not aligned. The panel starts higher
   and ends higher; the photo starts lower and runs past the panel's bottom
   edge. The panel also overlaps the photo horizontally and bleeds off the
   right edge of the viewport.
   That is why the row is top-aligned rather than centred — centring would
   average the two heights out and lose the stagger completely.
   --------------------------------------------------------------------------
   THE CLASS IS ON THE SECTION, NOT THE ROW
   Impreza renders:
     section.text-overlap > .l-section-h > .g-cols > .wpb_column
   so the columns sit three levels below the class. Every rule below reaches
   them via .g-cols rather than a direct-child selector.
   --------------------------------------------------------------------------
   WHY THE COLUMN SELECTORS ARE SO LONG
   The reset rule below has to be (0,5,0) to clear Impreza's
   .g-cols.via_flex.type_default > div[class*="vc_col"]. That means any rule
   setting a margin on those same columns must be LONGER than the reset, not
   just !important — when both declarations are !important, specificity is
   what decides.
   The reset therefore zeroes margin-block only, and each column carries its
   own margin rule at (0,6,0).
   --------------------------------------------------------------------------
   WHY IT RAN OFF THE SCREEN ON PHONES
   1. Impreza gives the row negative side margins and the columns matching
      padding, so the two cancel out. This section zeroes the column padding,
      which left the row's negative margins pulling everything past both
      screen edges. The section is width_full, so there was no section
      gutter to hide it either. Below 900px the row's margins are reset and
      the row carries its own gutter (--to-gutter).
   2. The arrow BUTTON carries Design Options positioning of its own
      (absolute, top 80px, translateX(-50%), all !important). Releasing only
      its wrapper left the button hanging half off the panel's left edge.
      Below 900px the button is released too.
   --------------------------------------------------------------------------
   THE ARROW ON DESKTOP
   Its desktop position is the wrapper's --to-arrow-y PLUS that 80px Design
   Options offset on the button. Left as it is so desktop doesn't move. If
   you ever clear the button's Design Options, set --to-arrow-y to about
   176px to keep the arrow where it is now.
   --------------------------------------------------------------------------
   CLEAR DESIGN OPTIONS ON THIS SECTION
   Impreza writes Design Options as .us_custom_xxxxxxx { ... !important } in a
   stylesheet that loads after this one, so anything set there beats
   everything below. The !important declarations here exist only to fight
   those. Clear them in the editor — on every breakpoint tab, Impreza stores
   them per-breakpoint — and the !importants can come off.
   --------------------------------------------------------------------------
   ADDING A VARIATION
   Copy the .text-overlap-1 block, renumber it, change only the variables and
   the corner radii. A mirrored version also needs the order rules shown in
   the note at the end.
   ========================================================================== */
.text-overlap {
    /* --- the photo -------------------------------------------------------- */
    --to-media-w: 56%;              /* the photo's share of the row           */
    --to-media-ratio: 3 / 2;
    --to-media-drop: 70px;          /* how far below the panel's top the
                                       photo starts                           */
    /* --- the panel -------------------------------------------------------- */
    --to-overlap: 200px;            /* how far the panel rides over the photo */
    --to-panel-bg: rgb(51 51 51);
    --to-panel-pad-block: 56px;
    /* Must stay LARGER than --to-overlap, or the copy starts on top of the
       photo rather than beside it. */
    --to-panel-pad-inner: 260px;
    /* The panel bleeds to the viewport edge, so this is padding against the
       edge of the screen — not the content edge. Keep it generous. */
    --to-panel-pad-outer: 120px;
    --to-panel-gap: 14px;
    /* --- the arrow -------------------------------------------------------- */
    --to-arrow-y: 96px;             /* centre, down from the panel's top      */
    /* --- tablets and phones (used below 900px only) ----------------------- */
    --to-gutter: 32px;              /* row in from the screen edges           */
    --to-pad-m: 28px;               /* panel padding, sides and bottom        */
    --to-arrow-m: 48px;             /* the arrow                              */
    /* --- shared ----------------------------------------------------------- */
    --to-radius: 20px;
}

/* --- the row -------------------------------------------------------------
   Top-aligned. See THE SHAPE above.
   ------------------------------------------------------------------------- */
.text-overlap .g-cols.g-cols.g-cols.g-cols {
    display: flex !important;
    flex-wrap: nowrap !important;
    align-items: flex-start !important;
    gap: 0 !important;
    width: 100%;
}

/* Deliberately does NOT reset the inline margins — the two columns set their
   own below and this rule would outrank them. See WHY THE COLUMN SELECTORS
   ARE SO LONG above. */
.text-overlap .g-cols.g-cols.g-cols.g-cols > .wpb_column {
    width: auto !important;
    max-width: none !important;
    min-width: 0;
    margin-block: 0 !important;
}

/* Impreza's inner wrappers must not claim a width, carry padding, or become
   the containing block the arrow anchors to. */
.text-overlap :is(.vc_column-inner, .wpb_wrapper) {
    position: static;
    min-width: 0;
    padding: 0 !important;
}

/* --- the photo column ----------------------------------------------------
   Pushed down so the panel's top edge clears it. The photo then runs past the
   panel's bottom, which is what gives the two their stagger.
   Behind the panel, so this stays at z-index 1.
   ------------------------------------------------------------------------- */
.text-overlap .g-cols.g-cols.g-cols.g-cols > .wpb_column:first-child {
    position: relative;
    z-index: 1;
    flex: 0 0 var(--to-media-w) !important;
    margin-top: var(--to-media-drop) !important;
}

/* aspect-ratio and height are cleared on the wrapper because Design Options
   puts a 3/2 ratio there as well as on the image. With both set, a change to
   --to-media-ratio would leave the wrapper at the old shape. */
.text-overlap .w-image.w-image {
    display: block;
    width: 100% !important;
    max-width: none !important;
    height: auto !important;
    max-height: none !important;
    aspect-ratio: auto !important;
    margin: 0 !important;
}

/* clip, not hidden — hidden creates a scroll container, which pins any
   scroll-driven animation inside it at 0%. */
.text-overlap .w-image .w-image-h {
    display: block;
    width: 100%;
    overflow: clip;
}

/* The Image element carries has_aspect_ratio from the editor, which sets a
   ratio of its own. This overrides it so --to-media-ratio is the one control. */
.text-overlap .w-image img {
    display: block;
    width: 100%;
    height: auto;
    aspect-ratio: var(--to-media-ratio) !important;
    object-fit: cover;
}

/* --- the panel column ----------------------------------------------------
   Pulled left over the photo, and bled off the right edge of the viewport.
   50% - 50vw is the distance from the column's own right edge out to the
   viewport's, which works from inside a centred container without needing to
   know its width.
   The negative left margin goes on the COLUMN, not the panel, so the panel's
   own box stays whole and its inner edge is a real edge the arrow can anchor
   to.
   ------------------------------------------------------------------------- */
.text-overlap .g-cols.g-cols.g-cols.g-cols > .wpb_column:last-child {
    position: relative;
    z-index: 2;
    flex: 1 1 0 !important;
    margin-left: calc(-1 * var(--to-overlap)) !important;
    margin-right: calc(50% - 50vw) !important;
}

/* The panel is the .w-vwrapper inside that column. Repeated class because
   Impreza writes gap and align onto vwrappers from the editor. */
.text-overlap .w-vwrapper.w-vwrapper {
    position: relative !important;
    margin: 0 !important;
    gap: var(--to-panel-gap) !important;
    padding: var(--to-panel-pad-block) var(--to-panel-pad-outer)
             var(--to-panel-pad-block) var(--to-panel-pad-inner) !important;
    background: var(--to-panel-bg) !important;
}

/* The gap sets the rhythm, so the heading drops the theme's own margin. */
.text-overlap .w-vwrapper > * {
    max-width: none;
    margin: 0 !important;
}

.text-overlap .wpb_text_column {
    margin: 8px 0 0 !important;
}

/* --- the arrow -----------------------------------------------------------
   left:0 is the panel's padding-box edge — the join.
   translate, not transform. A Design Options rule may set transform with
   !important, which would permanently beat arrow-btn's :active scale and kill
   the press feedback. Overriding it to `none` and using the individual
   property lets the two compose again.
   ------------------------------------------------------------------------- */
.text-overlap .w-btn-wrapper:has(.arrow-btn) {
    position: absolute !important;
    top: var(--to-arrow-y) !important;
    left: 0 !important;
    right: auto !important;
    width: auto !important;
    margin: 0 !important;
    transform: none !important;
    translate: -50% -50%;
    z-index: 3;
}

/* The CTA at the foot of the panel is also a .w-btn-wrapper, so it has to be
   put back into flow — the rule above would otherwise pull it to the join
   too. :not() on the arrow is the cheapest discriminator. */
.text-overlap .w-vwrapper > .w-btn-wrapper:not(:has(.arrow-btn)) {
    position: static !important;
    align-self: flex-start;
    margin: 16px 0 0 !important;
    translate: none;
}

/* --- the section ---------------------------------------------------------
   The section crops the bleed; the content wrapper has to let it out first.
   Without the second rule the panel is clipped at the content width and the
   bleed does nothing.
   clip, not hidden — hidden creates a scroll container.
   ------------------------------------------------------------------------- */
.l-section.text-overlap {
    overflow: clip;
}

.l-section.text-overlap > .l-section-h {
    overflow: visible;
}

/* --- laptops (901–1320) --------------------------------------------------
   Same layout, tighter. The fixed 260px inner padding left the copy in a
   narrow column once the panel shrank; it comes down with the overlap so the
   copy still clears the photo. */
@media (max-width: 1320px) {
    .text-overlap {
        --to-media-drop: 50px;
        --to-overlap: 140px;
        --to-panel-pad-block: 44px;
        --to-panel-pad-inner: 190px;
        --to-panel-pad-outer: 56px;
    }
}

/* --- tablets and phones --------------------------------------------------
   Stacked as one card: photo on top with rounded top corners, panel directly
   under it with rounded bottom corners, the arrow sitting on the join
   between them. The overlap, the stagger and the bleed all come off — none
   of them have anywhere to go in a single column.
   The column selector is repeated to match the desktop rules it is undoing.
   ------------------------------------------------------------------------- */
@media (max-width: 900px) {
    .text-overlap {
        --to-media-drop: 0px;
        --to-media-ratio: 4 / 3;
    }

    /* The row: block, no negative margins, its own gutter. See WHY IT RAN
       OFF THE SCREEN ON PHONES. */
    .text-overlap .g-cols.g-cols.g-cols.g-cols {
        display: block !important;
        box-sizing: border-box;
        width: auto;
        margin: 0 !important;
        padding-left: var(--to-gutter) !important;
        padding-right: var(--to-gutter) !important;
    }

    .text-overlap .g-cols.g-cols.g-cols.g-cols > .wpb_column:first-child,
    .text-overlap .g-cols.g-cols.g-cols.g-cols > .wpb_column:last-child {
        flex: none !important;
        width: 100% !important;
        margin-left: 0 !important;
        margin-right: 0 !important;
        margin-top: 0 !important;
    }

    /* The top padding clears the lower half of the arrow, which hangs down
       into the panel from the join. */
    .text-overlap .w-vwrapper.w-vwrapper {
        margin: 0 !important;
        padding: calc(var(--to-arrow-m) / 2 + 20px) var(--to-pad-m)
                 var(--to-pad-m) !important;
    }

    /* The wrapper sits on the panel's top edge, in from the left by the
       panel's own padding so it lines up with the copy. */
    .text-overlap .w-btn-wrapper:has(.arrow-btn) {
        top: 0 !important;
        left: var(--to-pad-m) !important;
        translate: 0 -50%;
    }

    /* The button itself, released from its Design Options positioning.
       It stays relative, not static: it is the containing block for its own
       glyph and ring. */
    .text-overlap .w-vwrapper .arrow-btn.arrow-btn.arrow-btn {
        --ab-size: var(--to-arrow-m);
        position: relative !important;
        top: auto !important;
        left: auto !important;
        right: auto !important;
        bottom: auto !important;
        transform: none !important;
    }
}

@media (max-width: 600px) {
    .text-overlap {
        --to-gutter: 24px;
        --to-pad-m: 24px;
        --to-arrow-m: 44px;
        --to-radius: 16px;
    }
}

/* --------------------------------------------------------------------------
   TEXT OVERLAP 1 — photo left, panel overlapping from the right
   The panel's right corners are square because it bleeds off the viewport;
   the photo's left corners are square because it runs to the content edge.
   Both round where they face each other.
   The radius goes on .w-image as well as .w-image-h: Design Options writes
   one onto .w-image, which clips, so it has to be overridden there too.
   -------------------------------------------------------------------------- */
.text-overlap-1 .w-image.w-image.w-image,
.text-overlap-1 .w-image .w-image-h {
    border-radius: 0 var(--to-radius) var(--to-radius) 0 !important;
}

.text-overlap-1 .w-vwrapper.w-vwrapper {
    border-radius: var(--to-radius) 0 0 var(--to-radius) !important;
}

@media (max-width: 900px) {
    .text-overlap-1 .w-image.w-image.w-image,
    .text-overlap-1 .w-image .w-image-h {
        border-radius: var(--to-radius) var(--to-radius) 0 0 !important;
    }

    .text-overlap-1 .w-vwrapper.w-vwrapper {
        border-radius: 0 0 var(--to-radius) var(--to-radius) !important;
    }
}

/* --------------------------------------------------------------------------
   FUTURE VARIATIONS
   A mirrored version — photo right, panel overlapping from the left and
   bleeding off the LEFT edge — needs the column order flipped and both
   margins moved to the other side:

     .text-overlap-2 .g-cols.g-cols.g-cols.g-cols > .wpb_column:first-child {
         order: 2;
         margin-left: 0 !important;
     }
     .text-overlap-2 .g-cols.g-cols.g-cols.g-cols > .wpb_column:last-child {
         order: 1;
         margin-left: calc(50% - 50vw) !important;
         margin-right: calc(-1 * var(--to-overlap)) !important;
     }

   Note that --to-panel-pad-inner then applies to the RIGHT side, so the
   padding shorthand in the base rule needs its inner/outer values swapped for
   that variation. The mobile stack needs nothing extra — below 900px every
   variation becomes the same photo-over-panel card. Keep the order rules
   inside a (min-width: 901px) query so the photo still leads on phones.
   -------------------------------------------------------------------------- */

/* --------------------------------------------------------------------------
   5.15 - FULL-BLEED IMAGE
   Class on the Section. The image escapes the content wrapper and runs the
   full width of the viewport.
   -------------------------------------------------------------------------- */
/* --------------------------------------------------------------------------
   FULL-BLEED IMAGE
   Class goes on the IMAGE element, not the section.
   The image escapes the content wrapper with 50% - 50vw — the distance from
   its own edge out to the viewport's, which works from inside a centred
   container without needing to know its width.
   -------------------------------------------------------------------------- */
.w-image.full-bleed-image {
    display: block;
    width: 100vw !important;
    max-width: none !important;
    margin-inline: calc(50% - 50vw) !important;
}

.full-bleed-image .w-image-h {
    display: block;
    width: 100%;
}

.full-bleed-image img {
    display: block;
    width: 100% !important;
    height: auto;
    max-width: none !important;
}

/* Impreza caps content at --site-content-width on .l-section-h and adds
   padding on the column wrappers — all of which crop the bleed. :has() lets
   the image reach back up to them.
   clip, not hidden — hidden creates a scroll container, which pins any
   scroll-driven animation inside it at 0%. */
.l-section:has(.full-bleed-image) {
    overflow: clip;
}

.l-section:has(.full-bleed-image) > .l-section-h,
.vc_column-inner:has(.full-bleed-image),
.wpb_wrapper:has(.full-bleed-image) {
    overflow: visible;
    padding-inline: 0 !important;
}

/* ==========================================================================
   16.0 - TEAM CARD — the Grid Layout for the team Post List
   A portrait with the name and role beneath it. Hovering the card fades a
   scrim over the photo and slides the bio up over it; a long bio scrolls
   inside the photo's box rather than making the card taller.
   --------------------------------------------------------------------------
   GRID LAYOUT
   Vertical Wrapper              -> tm-media
      Post Image                 -> tm-photo
      Post Content               -> tm-bio
   Horizontal Wrapper            -> tm-meta          <-- NOT tm-media
      Post Title                 -> tm-name
      LinkedIn icon              -> tm-linkedin
   Testimonial Fields: Job Title -> tm-role
   --------------------------------------------------------------------------
   THE NAME ROW IS NOT A CARD
   The two wrappers sit next to each other in the layout editor and the class
   names are one letter apart, so this is easy to get wrong — and when it is
   wrong the symptom looks nothing like a class typo. A name row carrying
   tm-media inherits the 3/4 ratio and the clip, becomes a second portrait
   box, and the 1300px LinkedIn logo inside it fills the whole thing.
   The card rule is therefore written as .tm-media:has(.tm-photo) — only a
   wrapper that actually contains the portrait is treated as one. The meta
   rule accepts .tm-media:not(:has(.tm-photo)) alongside .tm-meta, so a row
   that still carries the old class lays out correctly rather than silently
   losing its styling.
   --------------------------------------------------------------------------
   WHERE THE VARIABLES LIVE
   On the GRID ITEM, not on .tm-media. The name row, the icon and the role
   are siblings of the portrait, not children of it, so a variable declared
   on .tm-media never reaches them — anything set there applies to the photo
   and the bio and to nothing else. The grid item is the nearest ancestor all
   four share.
   Every var() below still carries a fallback, so the block degrades to
   sensible values rather than to nothing if :has() is ever unavailable.
   --------------------------------------------------------------------------
   THE BIO IS ONE PARAGRAPH, NOT THREE
   The content field currently outputs a single <p> with <br> tags between
   the three blocks of copy. That is why a paragraph margin appeared to do
   nothing however far its specificity was raised — there is only ever one
   paragraph, and its margin sits below the whole thing.
   The .tm-bio br rule below fakes the gap instead. It exists only for that
   markup: split the copy into three real paragraphs in the editor and it
   becomes redundant and should be deleted, since a stray <br> inside a
   paragraph would then get an unwanted gap. Same workaround, same reasoning,
   as the one on .split-band .band-panel in 5.2.
   --------------------------------------------------------------------------
   TYPE IS SET HERE, NOT INHERITED
   The name is an h2 and would otherwise inherit --h2-font-family — the
   display face, not the body one. It has to be told which family to use, on
   the element and again on its anchor (post_title carries
   color_link_inherit, so the anchor takes its own styling).
   ========================================================================== */
.w-grid-item:has(.tm-media) {
    --tm-ratio: 3 / 4;          /* the portrait's shape                     */
    --tm-radius: 14px;
    --tm-scrim: rgb(0 0 0 / .72);
    --tm-bio-pad: 30px;
    /* --- type ------------------------------------------------------------
       The bio, the name and the role are sized as a set. Raising one alone
       will break the relationship the design has between them.
       At this bio size a long biography will overflow and scroll inside the
       card — that is the intended behaviour, and the scrollbar is styled
       below. Drop --tm-bio-size before touching --tm-bio-pad if you would
       rather it fit: the padding is what keeps the first line clear of the
       rounded corner. */
    --tm-bio-size: 20px;
    --tm-bio-line: 1.45;
    --tm-bio-gap: .3em;         /* between blocks of copy, in bio font size */
    --tm-name-size: 26px;
    --tm-role-size: 24px;
    --tm-icon: 34px;            /* the LinkedIn glyph — see the note below  */
    --tm-speed: 420ms;
    --tm-ease: cubic-bezier(.22, .68, .3, 1);
}
/* --- the card ------------------------------------------------------------
   clip, not hidden — hidden creates a scroll container, which pins any
   scroll-driven animation inside it at 0%. The bio has its own scroll
   container below; that one is deliberate.
   ------------------------------------------------------------------------- */
.tm-media:has(.tm-photo) {
    position: relative;
    display: block;
    aspect-ratio: var(--tm-ratio, 3 / 4);
    overflow: clip;
    border-radius: var(--tm-radius, 14px);
    /* The wrapper carries a gap from the editor. Both children are out of
       flow, so a gap here would do nothing but confuse. */
    gap: 0;
    isolation: isolate;
	border: var(--color-white) 1px solid;
}
/* --- the photograph ------------------------------------------------------
   Three repeats to clear Impreza's margin on .w-post-elm — on an inset:0 box
   a bottom margin is subtracted from the height rather than pushing anything
   around, which would leave a strip along the bottom. The same repeats also
   clear the negative margins that .stretched brings with it.
   ------------------------------------------------------------------------- */
.tm-photo.tm-photo.tm-photo {
    position: absolute;
    inset: 0;
    z-index: 0;
    width: auto;
    height: auto;
    margin: 0;
    padding: 0;
    aspect-ratio: auto;
}
.tm-photo :is(a, .w-post-elm-h) {
    display: block;
    width: 100%;
    height: 100%;
}
.tm-photo img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: center top;
}
/* --- the bio -------------------------------------------------------------
   Over the photo, hidden until hover. The scrim is the bio's own background
   rather than a separate element, so the Grid Layout stays free of empty
   blocks and the two fade as one.
   overflow-y:auto is the one place in this file a scroll container is wanted:
   a long bio scrolls inside the card instead of stretching it.
   --------------------------------------------------------------------------
   SCROLL CHAINING IS LEFT ON.
   This element previously carried overscroll-behavior: contain, which stops
   a scroll gesture inside the bio from ever reaching the page. That reads as
   the page being stuck: the pointer sits over an open card, the bio hits its
   last line, and nothing else moves until you steer the cursor off it.
   The default `auto` is what we want instead — the browser latches the
   scroll to the bio until it reaches an end, then hands the rest to the
   page. Cards whose bio is short enough not to overflow have no end to
   reach, so they pass the gesture straight through rather than swallowing
   it, which is the behaviour you want on a row of cards of unequal length.
   Do NOT reinstate `contain` here. The place it belongs is a modal or a
   fixed panel that stays put while you read it; this is neither.
   ------------------------------------------------------------------------- */
.tm-bio.tm-bio.tm-bio {
    position: absolute;
    inset: 0;
    z-index: 1;
    margin: 0;
    padding: var(--tm-bio-pad, 30px);
    background: var(--tm-scrim, rgb(0 0 0 / .72));
    color: #fff;
    font-family: var(--font-family, inherit);
    font-size: var(--tm-bio-size, 25px);
    font-weight: 400;
    line-height: var(--tm-bio-line, 1.45);
    overflow-y: auto;
    /* Horizontal chaining stays contained. The team list is a carousel, and
       a sideways trackpad gesture over an open bio should not drag the
       carousel's track with it. Only the vertical axis chains. */
    overscroll-behavior-x: contain;
    overscroll-behavior-y: auto;
    opacity: 0;
    /* Visibility waits for the fade going out and switches at once coming
       back, so the fade is visible in both directions. Without it the bio
       would still be scrollable and focusable while invisible. */
    visibility: hidden;
    transition:
        opacity var(--tm-speed, 420ms) var(--tm-ease, ease),
        visibility 0s linear var(--tm-speed, 420ms);
}
/* The repeated class clears Impreza's own post-content rules, which load
   after this file and would otherwise tie and win on order. */
.tm-bio.tm-bio.tm-bio :is(p, div, span) {
    color: inherit;
    font-family: inherit;
    font-size: inherit;
    line-height: inherit;
}
.tm-bio.tm-bio.tm-bio :is(p, div) {
    margin: 0 0 var(--tm-bio-gap, .8em);
}
.tm-bio.tm-bio.tm-bio :is(p, div):last-child {
    margin-bottom: 0;
}
/* The line-break workaround — see the header. A <br> is an inline element
   with no box of its own, so it cannot take a margin as it stands; turning
   it into a block with empty content gives it one. Delete this rule once the
   copy is entered as three separate paragraphs. */
.tm-bio.tm-bio.tm-bio br {
    display: block;
    content: "";
    margin-bottom: var(--tm-bio-gap, .8em);
}
/* A thin scrollbar rather than the platform default, which is heavy over a
   photograph. Firefox uses the standard properties; WebKit needs its own. */
.tm-bio {
    scrollbar-width: thin;
    scrollbar-color: rgb(255 255 255 / .35) transparent;
}
.tm-bio::-webkit-scrollbar {
    width: 4px;
}
.tm-bio::-webkit-scrollbar-thumb {
    background: rgb(255 255 255 / .35);
    border-radius: 999px;
}
.tm-bio::-webkit-scrollbar-track {
    background: transparent;
}
/* --- the hover -----------------------------------------------------------
   Keyed off the whole card, so pointing anywhere on it opens the bio.
   .no-touch is what Impreza puts on <html> for non-touch devices. Without it,
   tapping a card on a tablet leaves it stuck open until you tap elsewhere.
   :focus-within keeps it reachable by keyboard — and because the bio is a
   scroll container, tabbing into it holds it open while you read.
   ------------------------------------------------------------------------- */
.no-touch .w-grid-item:hover .tm-bio.tm-bio.tm-bio,
.w-grid-item:focus-within .tm-bio.tm-bio.tm-bio {
    opacity: 1;
    visibility: visible;
    transition-delay: 0s, 0s;
}
/* --- the name row --------------------------------------------------------
   The name on the left, the LinkedIn icon pushed to the right. Repeated class
   because .w-hwrapper carries its own display and gap from the editor; the
   :not() branch is the same weight, so a row still carrying tm-media lands
   here too.
   ------------------------------------------------------------------------- */
.tm-meta.tm-meta,
.tm-media:not(:has(.tm-photo)) {
    display: flex;
    flex-direction: row;
    flex-wrap: nowrap;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    width: 100%;
    margin-top: 1.1rem;
}
.tm-name.tm-name {
    margin: 0;
    min-width: 0;
    font-family: var(--font-family, inherit);
    font-size: var(--tm-name-size, 24px);
    font-weight: 500;
    line-height: 1.25;
    letter-spacing: 0;
    color: #fff;
}
.tm-name.tm-name a {
    color: inherit;
    font-family: inherit;
    font-size: inherit;
    font-weight: inherit;
    line-height: inherit;
    text-decoration: none;
}
/* --- the LinkedIn icon ---------------------------------------------------
   THE WIDTH IS LOAD-BEARING. flex:none means the item takes its INTRINSIC
   width, and the uploaded logo is 1300px square — so without a width here it
   sizes to 1300px, shoves the name out of the row, and (inside a clipped
   card) fills the whole box. Impreza's max-width:100% on images does not save
   it, because the flex base size is settled before that applies.
   Set --tm-icon on the grid item to resize; everything below follows it.
   ------------------------------------------------------------------------- */
.tm-linkedin.tm-linkedin {
    flex: none;
    width: var(--tm-icon, 34px);
    height: auto;
    max-width: none;
    margin: 0;
    padding: 0;
    line-height: 0;
}
.tm-linkedin :is(a, .w-image-h, .w-post-elm-h) {
    display: block;
    width: 100%;
    height: auto;
}
.tm-linkedin :is(img, svg) {
    display: block;
    width: 100%;
    height: auto;
    max-width: none;
    margin: 0;
    object-fit: contain;
}
.tm-linkedin i {
    display: block;
    font-size: var(--tm-icon, 34px);
    line-height: 1;
}
/* --- the role ------------------------------------------------------------ */
.tm-role.tm-role {
	margin-top: -5px;
    margin: 0;
    font-family: var(--font-family, inherit);
    font-size: var(--tm-role-size, 24px);
    font-weight: 400;
    line-height: 1.3;
    color: var(--color-blue, #00bfff);
}
/* --- touch ---------------------------------------------------------------
   No hover, so the bio would never be reachable. Shown permanently instead —
   the scrim keeps it legible and it still scrolls.
   ------------------------------------------------------------------------- */
@media (hover: none) {
    .tm-bio.tm-bio.tm-bio {
        opacity: 1;
        visibility: visible;
    }
}
/* --- responsive ----------------------------------------------------------
   The card narrows at each step while the copy does not, so the type comes
   down with it to keep the same proportion of text to card.
   ------------------------------------------------------------------------- */
@media (max-width: 1320px) {
    .w-grid-item:has(.tm-media) {
        --tm-bio-size: 21px;
        --tm-name-size: 23px;
        --tm-role-size: 21px;
        --tm-icon: 30px;
    }
}
@media (max-width: 600px) {
    .w-grid-item:has(.tm-media) {
        --tm-bio-pad: 24px;
        --tm-bio-size: 18px;
        --tm-name-size: 20px;
        --tm-role-size: 18px;
        --tm-icon: 26px;
    }
}
/* --- reduced motion ------------------------------------------------------ */
@media (prefers-reduced-motion: reduce) {
    .tm-bio.tm-bio.tm-bio {
        transition-duration: 1ms;
    }
}

/* ==========================================================================
   17.0 - NEWS SECTION
   ========================================================================== */
/* --------------------------------------------------------------------------
   17.1 - NEWS FILTERS
   Class "news-filters" goes on the Vertical Wrapper holding both elements:
   the List Search and the List Filter.
   --------------------------------------------------------------------------
   WHY THE PILL ROW USES !important
   Impreza lays the filter out differently per state (desktop / mobile) and
   per layout option, and writes some of it inline. The pill row is forced
   onto every wrapper between the item and its values so that whichever one
   the element is actually using gets caught.
   --------------------------------------------------------------------------
   THE "ANY" VALUE
   With the filter set to Radio buttons, Impreza adds an "Any" value. The
   element should be set to Checkboxes, which has no "Any". A rule below
   hides it as a fallback.
   --------------------------------------------------------------------------
   TABLETS AND PHONES
   Below 600px Impreza switches the filter to state_mobile. In that state
   the list becomes a fixed, full-screen panel with its own background, and
   an opener button replaces it. This section keeps the pills in the page
   instead: the opener is hidden and the panel is put back into normal flow.
   Without that reset the panel covers the whole viewport, hero included,
   with the pills floating at the top of it.
   From 900px down the pills sit side by side as a compact pair, and the
   search bar stays on one row.
   -------------------------------------------------------------------------- */

.news-filters {
    --nf-blue: var(--color-blue, #00bfff);
    --nf-ink: #fff;

    /* --- the search bar --------------------------------------------------- */
    --nf-search-w: 670px;
    --nf-search-h: 48px;
    --nf-search-bg: #fff;
    --nf-search-text: 1rem;
    --nf-icon-size: 28px;        /* the magnifier                          */
    --nf-icon-x: 22px;           /* its distance in from the left edge     */
    --nf-btn-w: 158px;           /* the "Search" button                    */
    --nf-btn-gap: 6px;           /* clearance from the pill's right edge   */
    --nf-btn-pad: 28px;
    --nf-btn-text: 1rem;

    /* --- the pills -------------------------------------------------------- */
    --nf-pill-w: 320px;          /* minimum width, so both pills match     */
    --nf-pill-max: none;         /* maximum width, used from 900px down    */
    --nf-pill-pad: 11px 14px 11px 26px;
    --nf-pill-border: 2px;
    --nf-pill-text: 1rem;
    --nf-pill-inner-gap: 40px;   /* between the label and the +            */
    --nf-gap: 30px;              /* between Blogs and News                 */
    --nf-plus: 32px;             /* the circled + on the right             */
    --nf-plus-glyph: 19px;       /* the + drawn inside it                  */
    --nf-filter-top: 28px;       /* space between the search and the pills */

    --nf-speed: .25s;

    /* Theme input variables, overridden at the source. */
    --inputs-background: transparent;
    --inputs-focus-background: transparent;
    --inputs-border-color: transparent;
    --inputs-focus-border-color: transparent;
    --inputs-border-width: 0px;
    --inputs-border-radius: 999px;
    --inputs-text-color: #111;
    --inputs-focus-text-color: #111;
    --inputs-height: var(--nf-search-h);
    --inputs-padding: 0px;
}

/* ==========================================================================
   ALIGNMENT
   Both elements inherit auto margins from their align_* class, which is
   what pushed the search bar and the pills off the column's left edge.
   Zeroed here so the two share one left edge.
   Repeated classes rather than !important. Impreza's align rules are in a
   stylesheet, not inline, so equal weight plus one extra class clears them.
   ========================================================================== */
.news-filters .w-search.w-search,
.news-filters .w-filter.w-filter,
.news-filters .w-filter-list.w-filter-list {
    width: 100%;
    max-width: none;
    margin-inline: 0;
    padding-inline: 0;
}

/* ==========================================================================
   THE SEARCH BAR
   The form is the white pill. The magnifier is a background image on the
   form rather than an icon element, because the element's only icon lives
   inside the submit button, and that button is turned into the "Search"
   text label instead.
   ========================================================================== */
.news-filters .w-search.for_list > form {
    display: flex;
    flex-wrap: nowrap;
    align-items: center;
    gap: 10px;
    width: 100%;
    max-width: var(--nf-search-w);
    margin-inline: 0;
    margin-block: 0;
    padding: 5px 5px 5px calc(var(--nf-icon-x) * 2 + var(--nf-icon-size));
    background-color: var(--nf-search-bg);
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2300bfff' stroke-width='2' stroke-linecap='round'%3E%3Ccircle cx='10.5' cy='10.5' r='7.5'/%3E%3Cpath d='M21 21l-5-5'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: var(--nf-icon-x) center;
    background-size: var(--nf-icon-size);
    border: 0;
    border-radius: 999px;
}

.news-filters .w-search .w-form-row-field {
    flex: 1;
    min-width: 0;
    margin: 0;
}

/* Repeated class to clear .us-field-style_1 input, which is (0,2,0). */
.news-filters .w-search.w-search input[type="text"] {
    width: 100%;
    height: var(--nf-search-h);
    margin: 0;
    padding: 0;
    background: transparent;
    border: 0;
    border-radius: 0;
    box-shadow: none;
    color: #111;
    font-size: var(--nf-search-text);
    line-height: var(--nf-search-h);
}

.news-filters .w-search.w-search input[type="text"]:focus {
    background: transparent;
    box-shadow: none;
    outline: 0;
}

.news-filters .w-search input::placeholder {
    color: #8a8a8a;
    opacity: 1;
}

/* --- the submit button ---------------------------------------------------
   The clearance from the pill's right edge is a margin on the BUTTON, not
   padding on the form. As a flex child with its own min-width, the button
   sits against whatever edge the form's padding leaves it, so form padding
   moves the edge and the button follows it. A margin on the button itself
   is the only thing that separates the two.
   The element gives no way to set button text, so the label is a
   pseudo-element and the theme's magnifier glyph inside it is hidden. CSS
   content is not translatable and cannot be selected by the user. If this
   site ever goes multilingual, this is the line to revisit.
   Three repeats to clear .w-search-form-btn plus the theme's own
   .no-touch .us-btn-style_*:hover chain.
   ------------------------------------------------------------------------- */
.news-filters .w-search-form-btn.w-search-form-btn.w-search-form-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: none;
    width: auto;
    min-width: var(--nf-btn-w);
    height: var(--nf-search-h);
    margin-right: var(--nf-btn-gap);
    padding: 0 var(--nf-btn-pad);
    background: transparent;
    border: 1px solid var(--nf-blue);
    border-radius: 999px;
    box-shadow: none;
    color: #111;
    font-size: var(--nf-btn-text);
    font-weight: 400;
    line-height: 1;
    transition:
        background-color var(--nf-speed) ease,
        color var(--nf-speed) ease;
}

.news-filters .w-search-form-btn i {
    display: none;
}

.news-filters .w-search-form-btn::after {
    content: "Search";
}

.no-touch .news-filters .w-search-form-btn.w-search-form-btn.w-search-form-btn:hover {
    background: var(--nf-blue);
    color: #000;
}

/* The reset "x", which appears once there is text in the field. */
.news-filters .w-search-reset {
    flex: none;
    margin: 0 2px 0 0;
    color: #777;
}

/* ==========================================================================
   THE FILTER
   Each VALUE is a pill. The group's own chrome (title, reset link, border)
   comes off, and the values become a left-aligned row.
   ========================================================================== */
.news-filters .w-filter {
    margin-top: var(--nf-filter-top);
}

/* Scaffolding for a multi-group filter. With one group shown as pills
   there is nothing left for these to label, and the "Filters" heading and
   "Reset" link were the two stray bits of text floating over the design.
   The panel and closer belong to the mobile pop-up, which isn't used. */
.news-filters .w-filter-list-title,
.news-filters .w-filter-item-title,
.news-filters .w-filter-item-reset,
.news-filters .w-filter-list-panel,
.news-filters .w-filter-list-closer {
    display: none;
}

/* --- the pill row --------------------------------------------------------
   See WHY THE PILL ROW USES !important in the header.
   ------------------------------------------------------------------------- */
.news-filters .w-filter-item,
.news-filters .w-filter-item-content,
.news-filters .w-filter-item-content > *,
.news-filters .w-filter-item-values {
    display: flex !important;
    flex-direction: row !important;
    flex-wrap: wrap !important;
    justify-content: flex-start !important;
    align-items: center !important;
    gap: var(--nf-gap) !important;
    width: 100% !important;
    max-width: none !important;
    margin-inline: 0 !important;
    padding-inline: 0 !important;
    border: 0 !important;
    background: none !important;
}

/* Fallback only. The real fix is switching the element to checkboxes.
   See THE "ANY" VALUE in the header. */
.news-filters .w-filter-item-value[data-value="*"] {
    display: none !important;
}

/* --- the pill ------------------------------------------------------------
   The LABEL is the pill, not the wrapper. Impreza renders each value as
   .w-filter-item-value > label > input + .w-filter-item-value-label, so the
   label is the only element containing both the input and the text. Border
   the wrapper instead and the clickable area ends up smaller than the pill.
   The wrapper is flex: 0 0 auto on desktop so the pills size to their
   content rather than stretching to fill the row. space-between plus a
   min-width on the label pins the + to the right edge at a consistent
   width whatever the term name is.
   ------------------------------------------------------------------------- */
.news-filters .w-filter-item-value {
    flex: 0 0 auto !important;
    width: auto !important;
    max-width: var(--nf-pill-max) !important;
    margin: 0 !important;
    padding: 0 !important;
    border: 0 !important;
    background: none !important;
}

.news-filters .w-filter-item-value label {
    box-sizing: border-box;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--nf-pill-inner-gap);
    min-width: var(--nf-pill-w);
    margin: 0;
    padding: var(--nf-pill-pad);
    border: var(--nf-pill-border) solid var(--nf-ink);
    border-radius: 999px;
    color: var(--nf-ink);
    font-size: var(--nf-pill-text);
    font-weight: 400;
    line-height: 1.2;
    cursor: pointer;
    transition:
        border-color var(--nf-speed) ease,
        color var(--nf-speed) ease;
}

/* Hidden but NOT display:none. It stays focusable and readable by
   assistive tech, and the pill can still react to :checked. display:none
   removes it from the accessibility tree and breaks the keyboard path
   through the filter entirely. */
.news-filters .w-filter-item-value input {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: 0;
    padding: 0;
    opacity: 0;
    pointer-events: none;
}

.news-filters .w-filter-item-value-label {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* --- the circled + -------------------------------------------------------
   Two glyphs rather than one recoloured by a mask, because the stroke
   inverts between states: blue on transparent, black on blue.
   The ring tracks --nf-pill-border, so thickening the pill outline
   thickens both together.
   ------------------------------------------------------------------------- */
.news-filters .w-filter-item-value label::after {
    content: "";
    box-sizing: border-box;
    flex: none;
    width: var(--nf-plus);
    height: var(--nf-plus);
    border: var(--nf-pill-border) solid var(--nf-blue);
    border-radius: 50%;
    background-color: transparent;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' stroke='%2300bfff' stroke-width='2' stroke-linecap='round'%3E%3Cpath d='M12 6v12M6 12h12'/%3E%3C/svg%3E");
    background-size: var(--nf-plus-glyph);
    background-position: center;
    background-repeat: no-repeat;
    transition:
        transform .3s ease,
        background-color var(--nf-speed) ease;
}

/* --- selected ------------------------------------------------------------
   The + turns 45deg into an x and fills solid.
   :has(input:checked) fires immediately on click; Impreza's own .active
   only lands after its AJAX round trip. Both are listed so the pill
   responds instantly AND is correct on first paint, where the checked
   state comes from the URL.
   ------------------------------------------------------------------------- */
.news-filters .w-filter-item-value:has(input:checked) label,
.news-filters .w-filter-item-value.active label {
    border-color: var(--nf-blue);
    color: var(--nf-blue);
}

.news-filters .w-filter-item-value:has(input:checked) label::after,
.news-filters .w-filter-item-value.active label::after {
    transform: rotate(45deg);
    background-color: var(--nf-blue);
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' stroke='%23000' stroke-width='2' stroke-linecap='round'%3E%3Cpath d='M12 6v12M6 12h12'/%3E%3C/svg%3E");
}

/* --- hover and focus -----------------------------------------------------
   .no-touch is what Impreza puts on <html> for non-touch devices. Without
   it, tapping a pill on a tablet leaves it stuck in its hover state.
   The focus ring is drawn on the label because the input itself is 1px and
   invisible.
   ------------------------------------------------------------------------- */
.no-touch .news-filters .w-filter-item-value:not(:has(input:checked)) label:hover {
    border-color: var(--nf-blue);
}

.news-filters .w-filter-item-value:has(input:focus-visible) label {
    outline: 2px solid var(--nf-blue);
    outline-offset: 3px;
}

/* ==========================================================================
   TABLETS AND PHONES (900px and below)
   Everything steps down through the tokens. The search bar stays one row,
   and the two pills share a row at up to 260px each, instead of stacking
   full width.
   ========================================================================== */
@media (max-width: 900px) {
    .news-filters {
        --nf-search-w: 100%;
        --nf-search-h: 44px;
        --nf-search-text: 16px;     /* 16px or more, or iOS zooms on focus */
        --nf-icon-size: 22px;
        --nf-icon-x: 16px;
        --nf-btn-w: 0px;
        --nf-btn-gap: 0px;
        --nf-btn-pad: 22px;
        --nf-btn-text: 15px;
        --nf-pill-w: 0px;
        --nf-pill-max: 260px;
        --nf-pill-pad: 9px 10px 9px 20px;
        --nf-pill-border: 1.5px;
        --nf-pill-text: 16px;
        --nf-pill-inner-gap: 12px;
        --nf-gap: 12px;
        --nf-plus: 26px;
        --nf-plus-glyph: 15px;
        --nf-filter-top: 16px;
    }

    .news-filters .w-search.for_list > form {
        gap: 8px;
        padding: 4px 4px 4px calc(var(--nf-icon-x) * 2 + var(--nf-icon-size) - 4px);
    }

    /* The pills share the row equally. flex-basis 0 with min-width 0 lets
       them shrink together, so they never wrap onto a second line. */
    .news-filters .w-filter-item-value {
        flex: 1 1 0 !important;
        min-width: 0;
    }

    .news-filters .w-filter-item-value label {
        width: 100%;
    }
}

/* ==========================================================================
   PHONES (600px and below)
   ========================================================================== */
@media (max-width: 600px) {
    .news-filters {
        --nf-search-h: 40px;
        --nf-icon-size: 20px;
        --nf-icon-x: 14px;
        --nf-btn-pad: 16px;
        --nf-btn-text: 14px;
        --nf-pill-max: none;
        --nf-pill-pad: 8px 8px 8px 16px;
        --nf-pill-text: 15px;
        --nf-pill-inner-gap: 8px;
        --nf-gap: 10px;
        --nf-plus: 24px;
        --nf-plus-glyph: 14px;
    }

    /* --- the mobile panel, put back into the page ------------------------
       See TABLETS AND PHONES in the header. Impreza's state_mobile rules
       turn the list into a fixed full-screen panel. Every property that
       does that is reset here. The repeated classes clear its
       .w-filter.state_mobile .w-filter-list rules, including the open
       state. */
    .news-filters .w-filter.w-filter.state_mobile .w-filter-list.w-filter-list {
        position: static !important;
        inset: auto;
        z-index: auto;
        display: block !important;
        width: 100%;
        height: auto;
        min-height: 0;
        max-height: none;
        margin: 0;
        padding: 0;
        overflow: visible;
        background: none;
        box-shadow: none;
        transform: none;
        opacity: 1;
        visibility: visible;
    }

    .news-filters .w-filter.w-filter .w-filter-opener {
        display: none !important;
    }
}

/* --- reduced motion ------------------------------------------------------ */
@media (prefers-reduced-motion: reduce) {
    .news-filters .w-search-form-btn,
    .news-filters .w-filter-item-value label,
    .news-filters .w-filter-item-value label::after {
        transition-duration: 1ms;
    }
}

/* ==========================================================================
   17.2  NEWS HERO — the post template's top band
   Photograph right, dark panel over its left edge, blue arrow sitting on the
   panel's bottom-right corner. No JS.
   --------------------------------------------------------------------------
   EDITOR SETUP
   Horizontal Wrapper  -> news-hero            (gap 0, valign Middle)
      Vertical Wrapper -> hero-panel
         Post Date     -> hero-date
         Post Title    -> hero-title
         Button        -> hero-arrow arrow-btn-down
      Post Image       -> hero-media           (UNTICK "stretched")
   --------------------------------------------------------------------------
   WHY THE PANEL SELECTORS ARE SO LONG
   The panel is a .w-vwrapper, and Impreza writes width, align-self and gap
   onto that element from the editor's own options — as .w-vwrapper rules in
   a stylesheet that loads after this file, and in some cases as inline
   styles from Design Options.
   Left at (0,2,0) the panel keeps its content-sized width, which is what put
   its left edge halfway across the row instead of on the content edge. Four
   repeats plus !important on the three sizing properties is what makes
   flex: 1 1 0 actually take.
   The !important is confined to those three declarations deliberately —
   everything else here wins on specificity alone, and an !important on the
   background or padding would be fighting nothing.
   --------------------------------------------------------------------------
   THE PANEL IS SHORTER THAN THE PHOTO
   The photo sets the band's height and the panel is centred against it,
   leaving a strip of image visible above and below. So the panel gets no
   height of its own — align-self does the work, and the arrow's position is
   then measured from the panel's box rather than the row's.
   Same reasoning as the feature band in 5.3, mirrored: there the panel was
   the taller element, here it is the shorter one.
   ========================================================================== */
.news-hero {
    /* --- the photograph --------------------------------------------------- */
    --nh-media-w: 55%;
    --nh-media-ratio: 3 / 2;
    --nh-media-radius: 0px;

    /* --- the panel -------------------------------------------------------- */
    --nh-overlap: 0px;           /* how far the panel rides over the photo.
                                    0 butts them edge to edge, as the design
                                    has it. Raise to overlap.                */
    --nh-panel-bg: rgb(51 51 51 / .92);
    --nh-panel-pad: 44px 56px 52px;
    --nh-panel-gap: 14px;

    /* --- type ------------------------------------------------------------- */
    --nh-date-size: 17px;
    --nh-date-ink: var(--color-blue, #00bfff);
    --nh-title-size: 44px;
    --nh-title-weight: 100;      /* the theme's h2 is 300, but the Grid
                                    Layout may set its own — pinned here     */
    --nh-title-measure: 14ch;    /* wraps "Our latest machine acquisition"
                                    onto two lines, as the design shows      */

    /* --- the arrow -------------------------------------------------------- */
    --nh-arrow-size: 64px;
    --nh-arrow-x: 120px;         /* in from the panel's right edge           */
    --nh-arrow-y: 0px;           /* down from its bottom edge; 0 centres the
                                    button ON the edge                       */

    position: relative;          /* the arrow anchors to this                */
    display: flex;
    flex-wrap: nowrap;
    align-items: center;
    gap: 0;
    width: 100%;
}

/* Impreza nests wrappers between the element and its blocks. None should
   claim a width or become the containing block the arrow anchors to. */
.news-hero :is(.vc_column-inner, .wpb_wrapper) {
    position: static;
    min-width: 0;
}

/* ==========================================================================
   THE PANEL
   ========================================================================== */
.news-hero .hero-panel.hero-panel.hero-panel.hero-panel {
    order: 1;
    position: relative;
    z-index: 2;
    flex: 1 1 0 !important;
    width: auto !important;
    max-width: none !important;
    min-width: 0;
    align-self: center;
    /* The overlap comes out of the panel's TRAILING edge, because the panel
       is first in flow and the photo follows it. On the split band in 5.2 it
       was the leading edge, since the order there is reversed. */
    margin: 0 calc(-1 * var(--nh-overlap)) 0 0;
    gap: var(--nh-panel-gap);
    padding: var(--nh-panel-pad);
    background: var(--nh-panel-bg);
}

/* The gap sets the rhythm, so the date and title drop the margins they
   inherit from the theme's heading and post-element rules. */
.news-hero .hero-panel > * {
    max-width: none;
    margin: 0;
}

/* --- type ----------------------------------------------------------------
   The title is an h2 and would otherwise take --h2-font-size (35px) and
   whatever weight the Grid Layout set on it — which is what made it render
   bold and on one line. Both are pinned here, and the measure is what puts
   it over two lines rather than the font size.
   The colour and weight go on the anchor too: post_title carries
   color_link_inherit, so the <a> takes its own styling and would otherwise
   ignore anything set on the parent.
   ------------------------------------------------------------------------- */
.news-hero .hero-date,
.news-hero .hero-date :is(a, span, time) {
    font-size: var(--nh-date-size);
    font-weight: 400;
    line-height: 1.2;
    color: var(--nh-date-ink);
    text-decoration: none;
}

.news-hero .hero-title,
.news-hero .hero-title :is(a, span) {
    display: block;
    max-width: var(--nh-title-measure);
    font-size: var(--nh-title-size);
    font-weight: var(--nh-title-weight);
    line-height: 1.15;
    letter-spacing: 0;
    color: #fff;
    text-decoration: none;
}

/* ==========================================================================
   THE PHOTOGRAPH
   Three repeats of the class to clear Impreza's own margin on .w-post-elm,
   and the negative inline margins that the "stretched" option adds. Better
   to untick stretched in the editor — this is the safety net.
   ========================================================================== */
.news-hero .hero-media.hero-media.hero-media {
    order: 2;
    flex: 0 0 var(--nh-media-w);
    width: var(--nh-media-w);
    max-width: none;
    min-width: 0;
    margin: 0;
    padding: 0;
    border-radius: var(--nh-media-radius);
    /* clip, not hidden — hidden creates a scroll container, which pins any
       scroll-driven animation inside it at 0%. */
    overflow: clip;
}

.news-hero .hero-media :is(a, .w-post-elm-h) {
    display: block;
    width: 100%;
}

/* A fixed crop, so a portrait photo can't double the height of the band. */
.news-hero .hero-media img {
    display: block;
    width: 100%;
    height: auto;
    aspect-ratio: var(--nh-media-ratio);
    object-fit: cover;
}

/* ==========================================================================
   THE ARROW
   Anchored to the panel's bottom-right corner. right / bottom are measured
   against the panel's PADDING box, so the offsets ignore the padding and
   the translate then centres the button ON the corner rather than inside it.
   translate, not transform — the base arrow-btn uses transform for its
   :active scale and the two would overwrite each other.
   Everything else about the button — glyph, ring, hover, press — comes from
   3.0; only the size is set here.
   ========================================================================== */
.news-hero .hero-panel .w-btn-wrapper:has(.hero-arrow) {
    position: absolute;
    right: var(--nh-arrow-x);
    bottom: var(--nh-arrow-y);
    left: auto;
    top: auto;
    width: auto;
    max-width: none;
    margin: 0;
    translate: 50% 50%;
    z-index: 3;
}

/* Repeated class to clear the arrow-btn size variants at (0,2,0). */
.news-hero .hero-arrow.hero-arrow.hero-arrow {
    --ab-size: var(--nh-arrow-size);
}

/* ==========================================================================
   THE SECTION
   The panel runs to the content edge on the left and the photo to the
   content edge on the right, so neither bleeds — no overflow rules needed
   here, unlike the split band in 5.2.
   Set --nh-media-w above 55% and the panel narrows to match; the row always
   totals 100%.
   ========================================================================== */

/* --- laptops ------------------------------------------------------------- */
@media (max-width: 1320px) {
    .news-hero {
        --nh-panel-pad: 36px 40px 44px;
        --nh-title-size: 34px;
        --nh-title-measure: 13ch;
        --nh-arrow-x: 80px;
    }
}

/* --- mobile --------------------------------------------------------------
   Stack, with the panel tucked under the photo. The arrow returns to normal
   flow — on a stacked panel there is no corner for it to straddle, and a
   half-off-the-edge button on a phone is a tap target hanging in space.
   The measure comes off too: at 100% width the panel can wrap the title on
   its own.
   ------------------------------------------------------------------------- */
@media (max-width: 900px) {
    .news-hero {
        --nh-overlap: 0px;
        --nh-panel-pad: 28px 24px;
        --nh-title-size: 28px;
        --nh-title-measure: none;
        --nh-arrow-size: 44px;
        display: block;
    }
    .news-hero .hero-media.hero-media.hero-media,
    .news-hero .hero-panel.hero-panel.hero-panel.hero-panel {
        width: 100% !important;
        max-width: none !important;
        margin: 0;
    }
    .news-hero .hero-panel.hero-panel.hero-panel.hero-panel {
        margin-top: -32px;
    }
    .news-hero .hero-panel .w-btn-wrapper:has(.hero-arrow) {
        position: static;
        translate: none;
        margin: 16px 0 0;
    }
}



/* ==========================================================================
   WHY CARDS — HOVER PHOTO
   REPLACES the why-cards CSS from earlier today (the nth-child background
   images, and the wrapper / Image overlay version after it). Delete those.
   Pairs with the WHY CARDS JS snippet, which moves each Image element's
   picture into its card as .why-photo and takes the builder wrappers out,
   so 20.4 in the stylesheet matches the cards again.
   ========================================================================== */

.why-cards{
    background-color: var(--color-blue);
    padding: 20px;
    min-width: 350px;
    min-height: 350px;
    border-radius: 20px;
}

.why-cards.w-iconbox{
    display: flex;
    flex-direction: column;
}

/* The photo covers the whole card on hover, number and copy included, so
   nothing that 20.4 draws on the card can sit over it or hide it. */
.why-cards.has-photo{
    position: relative;
}

.why-cards .why-photo{
    position: absolute;
    inset: 0;
    z-index: 5;
    border-radius: inherit;
    overflow: hidden;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.8s ease-in-out;
}

.why-cards .why-photo img{
    display: block;
    width: 100%;
    height: 100%;
    max-width: none;
    object-fit: cover;
}

.why-cards.has-photo:hover .why-photo{
    opacity: 1;
}

/* Switch off the old hover photos set in CSS (20.4.6 and the nth-child
   rules), on the card, everything inside it and their pseudo-elements, so
   only the builder photo fades in. !important because some of those were
   written that way. Only background images go; the blue and the numbers
   stay. */
.careers-why .why-cards-row .why-cards.has-photo.has-photo.has-photo:is(:hover, :not(:hover)),
.careers-why .why-cards-row .why-cards.has-photo.has-photo.has-photo:is(:hover, :not(:hover))::before,
.careers-why .why-cards-row .why-cards.has-photo.has-photo.has-photo:is(:hover, :not(:hover))::after,
.careers-why .why-cards-row .why-cards.has-photo.has-photo.has-photo:is(:hover, :not(:hover)) :not(.why-photo):not(.why-photo *),
.careers-why .why-cards-row .why-cards.has-photo.has-photo.has-photo:is(:hover, :not(:hover)) :not(.why-photo):not(.why-photo *)::before,
.careers-why .why-cards-row .why-cards.has-photo.has-photo.has-photo:is(:hover, :not(:hover)) :not(.why-photo):not(.why-photo *)::after{
    background-image: none !important;
}

.why-cards.has-photo:hover .w-iconbox-icon,
.why-cards.has-photo:hover .w-iconbox-title{
    display: none;
}

/* Until the script has run, keep the builder's Image elements out of the
   layout so nothing flashes under the cards. Not in the Live Builder or the
   WPBakery editor, where you need to see them to pick the photos. */
body:not(.usb_preview):not(.vc_editor) .why-cards-row > .w-vwrapper > .w-image{
    display: none;
}

.why-cards-row{
    transform: translateY(-200px);
}

/* ==========================================================================
   17.3  NEWS POST GALLERY
   NEW SECTION. Add after 17.2 (News hero). Nothing else in the file changes.
   --------------------------------------------------------------------------
   The gallery on a news post, between the intro text and the body copy. It
   fills the width of the text column and lays its photos out by how many
   there are, so there is never a gap at the end of a row:

     1      one wide panorama
     2      side by side
     3      two side by side, one wide underneath
     4      two by two
     5+     rows of three; a single left over runs wide, a pair left over
            shares the last row

   Below 901px it is always rows of two, with the same rule for the one left
   over. Every tile is cropped to the same shape, so portrait and landscape
   uploads still line up.
   --------------------------------------------------------------------------
   PAIRS WITH the NEWS POST GALLERY JS snippet. The gallery is an Impreza Post
   Carousel, and Owl lays carousels out in script, which no stylesheet can
   argue with. The snippet takes Owl down and marks the list .npg-grid; this
   section does the rest. If the gallery is ever swapped for a Post List set
   to Grid, the snippet marks that list instead and nothing here changes.
   While it works the snippet puts .npg-js on <html>, and the carousel is held
   out of sight so it doesn't flash. If anything fails the class comes off and
   the carousel shows as before.
   --------------------------------------------------------------------------
   EDITOR SETUP (unchanged)
   Post Carousel, images from the gallery field   -> news-post-gallery
   The photos go in the post's gallery field, not in the intro text box. An
   image pasted into the text box is part of the text, and none of this
   reaches it.
   --------------------------------------------------------------------------
   HOW THE LAYOUTS ARE PICKED
   A six-column grid. Rows of two are tiles spanning 3, rows of three are
   tiles spanning 2, a wide tile spans all 6. Which applies is read off the
   count with :nth-child, so there is no maths in the script:
     last-child:nth-child(odd)      the one left over in rows of two
     :has(> :nth-child(5))          five or more, so rows of three
     last-child:nth-child(3n+1)     the one left over in rows of three
     nth-child(3n+1):nth-last-child(2) + nth-child(3n+2):last-child
                                    the pair left over in rows of three
   ========================================================================== */
.news-post-gallery {
    --npg-gap:      20px;
    --npg-radius:   20px;          /* matches the inline images in posts    */
    --npg-tile:     4 / 3;         /* every ordinary tile                   */
    --npg-single:   21 / 9;        /* one photo on its own                  */
    --npg-wide-2:   2 / 1;         /* the one left over, rows of two        */
    --npg-wide-3:   3 / 1;         /* the one left over, rows of three      */
    --npg-zoom:     1.04;          /* hover                                 */
    --npg-speed:    .6s;
    --npg-ease:     cubic-bezier(.22, .68, .3, 1);
    margin-bottom: 40px;
}

/* A post with no gallery photos shows nothing, rather than an empty band. */
.news-post-gallery.no_results,
.news-post-gallery.npg-empty {
    display: none;
}

/* Held out of sight while the snippet takes Owl down, so the carousel never
   flashes. Visibility rather than display, so Owl can still measure itself
   while it initialises. */
.npg-js .news-post-gallery .owl-carousel {
    visibility: hidden;
}

/* --- the grid ------------------------------------------------------------
   Three repeats to clear anything Impreza still aims at its grid list. */
.news-post-gallery .npg-grid.npg-grid.npg-grid {
    display: grid;
    grid-template-columns: repeat(6, minmax(0, 1fr));
    gap: var(--npg-gap);
    width: 100%;
    margin: 0;
    padding: 0;
    transform: none;
}

/* --- a tile --------------------------------------------------------------
   The TILE carries the shape, and the photo is pinned to fill it.
   Impreza's wrapper inside the tile is taken out of flow, so the tile has no
   content of its own and its aspect-ratio is the only thing setting its
   height. Left in flow, the ratio spacer Impreza puts in the image element
   (the carousel's 2/3 portrait setting) would stretch every tile to that
   shape instead. min-height:0 for the same reason: an aspect-ratio box
   otherwise refuses to be shorter than its content.
   Everything inside that wrapper is static, so the photo pins to it.
   Repeated class to clear Impreza's own item padding, which it uses to make
   the gap on its grids.
   clip, not hidden — hidden creates a scroll container. */
.news-post-gallery .npg-grid > .w-grid-item.w-grid-item {
    position: relative;
    grid-column: span 3;
    aspect-ratio: var(--npg-tile);
    width: auto;
    max-width: none;
    min-width: 0;
    height: auto;
    min-height: 0;
    margin: 0;
    padding: 0;
    border-radius: var(--npg-radius);
    overflow: clip;
    background: rgb(255 255 255 / .06);  /* while the photo loads */
}

.news-post-gallery .npg-grid .w-grid-item-h.w-grid-item-h {
    position: absolute;
    inset: 0;
    margin: 0;
    padding: 0;
}

/* !important because Design Options writes position inline on post elements,
   and an inline position:relative on the image wrapper would become the
   photo's frame instead of the tile. It's the one !important here, and it
   only ever says "don't be a frame". */
.news-post-gallery .npg-grid .w-grid-item-h *:not(img) {
    position: static !important;
}

.news-post-gallery .npg-grid .w-grid-item-h img {
    position: absolute;
    inset: 0;
    display: block;
    width: 100%;
    height: 100%;
    max-width: none;
    aspect-ratio: auto;
    object-fit: cover;
    object-position: center;
    border-radius: 0;
    scale: 1;
    transition: scale var(--npg-speed) var(--npg-ease);
}

/* A slow push in on hover, the same feel as img-zoom (2.6). */
.no-touch .news-post-gallery .npg-grid > .w-grid-item:hover img {
    scale: var(--npg-zoom);
}

/* --- rows of two (all widths up to four photos, and always below 901px) ---- */

/* The one left over runs the full width. */
.news-post-gallery .npg-grid > .w-grid-item:last-child:nth-child(odd) {
    grid-column: 1 / -1;
    aspect-ratio: var(--npg-wide-2);
}

/* A photo on its own gets the wider, shorter panorama. After the rule above,
   which also matches it. */
.news-post-gallery .npg-grid > .w-grid-item:first-child:last-child {
    aspect-ratio: var(--npg-single);
}

/* --- rows of three: five or more photos, 901px and up ---------------------
   The second selector in the first rule undoes the rows-of-two "one left
   over" rule, which is weightier than a plain tile and would otherwise still
   stretch the fifth photo full width. The two rules after it come later at
   the same weight, so they win where they apply. */
@media (min-width: 901px) {
    .news-post-gallery .npg-grid:has(> :nth-child(5)) > .w-grid-item.w-grid-item,
    .news-post-gallery .npg-grid:has(> :nth-child(5)) > .w-grid-item:last-child:nth-child(odd) {
        grid-column: span 2;
        aspect-ratio: var(--npg-tile);
    }

    /* One left over: full width. */
    .news-post-gallery .npg-grid:has(> :nth-child(5)) > .w-grid-item:last-child:nth-child(3n+1) {
        grid-column: 1 / -1;
        aspect-ratio: var(--npg-wide-3);
    }

    /* Two left over: they share the row. */
    .news-post-gallery .npg-grid:has(> :nth-child(5)) > .w-grid-item:nth-child(3n+1):nth-last-child(2),
    .news-post-gallery .npg-grid:has(> :nth-child(5)) > .w-grid-item:nth-child(3n+2):last-child {
        grid-column: span 3;
        aspect-ratio: var(--npg-tile);
    }
}

/* --- laptops (1320 and below) --------------------------------------------- */
@media (max-width: 1320px) {
    .news-post-gallery {
        --npg-gap: 16px;
    }
}

/* --- tablets (900 and below) ----------------------------------------------
   Rows of two whatever the count — three across gets too small here. */
@media (max-width: 900px) {
    .news-post-gallery {
        --npg-gap: 14px;
        --npg-radius: 16px;
        margin-bottom: 30px;
    }
}

/* --- phones (600 and below) -----------------------------------------------
   Still two across, which keeps a long gallery from becoming a long scroll.
   The panoramas get a little taller so the photo isn't a thin strip. */
@media (max-width: 600px) {
    .news-post-gallery {
        --npg-gap: 10px;
        --npg-radius: 12px;
        --npg-single: 16 / 9;
        --npg-wide-2: 16 / 9;
        margin-bottom: 24px;
    }
}

/* --- reduced motion ------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
    .news-post-gallery .npg-grid .w-grid-item-h img {
        transition: none;
    }

    .no-touch .news-post-gallery .npg-grid > .w-grid-item:hover img {
        scale: 1;
    }
}

/* ==========================================================================
   18.0  MOBILE OPTIMISATION
   Appended last on purpose. Several rules here beat earlier ones on ORDER
   rather than specificity — the utilities in 1.1 and the responsive blocks
   inside 5.4 / 5.7 are the same selectors at the same weight, so this file
   position is load-bearing. Anything added after this section needs to know
   that.
   Design Options rules (.us_custom_*) live in a stylesheet that loads AFTER
   this one and are written !important, so those are matched with a repeated
   class — (0,2,0) plus !important clears (0,1,0) plus !important regardless
   of order.
   --------------------------------------------------------------------------
     18.1  Global guards
     18.2  Text size utilities
     18.3  Hero
     18.4  Sector cards
     18.5  Copy panel over photo
     18.6  Capabilities row
     18.7  Testimonials
     18.8  Footer
   ========================================================================== */


/* --------------------------------------------------------------------------
   18.1  GLOBAL GUARDS
   The woosh entrances start 60vw off-screen. On desktop the sections they sit
   in are wide enough that nothing notices; on a 390px phone that is 234px of
   overhang and a horizontal scrollbar for the length of the animation.
   clip, not hidden — hidden on .l-main would make it a scroll container and
   pin every scroll-driven exit in 2.4 at 0%.
   -------------------------------------------------------------------------- */
@media (max-width: 900px) {
    .l-main {
        overflow-x: clip;
        overflow-y: visible;
    }

    /* clip on one axis with visible on the other is the one legal
       combination — it is why this doesn't become a scroll container. */
    [class*="heading-in-woosh"] {
        --hi-dist: 45vw;
        --hi-move: 800ms;
    }
}

/* Belt and braces for the hero specifically, where the section has no clip of
   its own. Harmless where one is already set. */
.l-section:has([class*="heading-in-woosh"]) {
    overflow: clip;
}


/* --------------------------------------------------------------------------
   18.2  TEXT SIZE UTILITIES
   1.1 sets these in fixed px with !important, so nothing in the theme's own
   responsive type scale can touch them — .xxl-text stays 90px on a phone,
   which is what puts "TURNING VISION INTO REALITY" over four lines in the
   footer.
   Same selectors, same weight, later in the file: these win on order.
   -------------------------------------------------------------------------- */
@media (max-width: 900px) {
    .xs-text   { font-size: 14px !important; }
    .s-text    { font-size: 18px !important; }
    .m-text    { font-size: 28px !important; }
    .l-text    { font-size: 32px !important; }
    .xl-text   { font-size: 48px !important; }
    .xxl-text  { font-size: 56px !important; }
    .xxxl-text { font-size: 96px !important; }
}

@media (max-width: 600px) {
    .xs-text   { font-size: 13px !important; }
    .s-text    { font-size: 16px !important; }
    .m-text    { font-size: 24px !important; }
    .l-text    { font-size: 26px !important; }
    .xl-text   { font-size: 34px !important; }
    .xxl-text  { font-size: 38px !important; }
    .xxxl-text { font-size: 56px !important; }
}


/* --------------------------------------------------------------------------
   18.3  HERO — "SECTOR / OVERVIEW"
   Two H1s stacked. The first takes the theme's --h1-font-size, which drops to
   32px on mobile; the second carries a Design Options font-size of 54px that
   does NOT drop. So on a phone the subtitle renders larger than the title.
   Both are pinned here so the pair scales together.
   The selector is long because it has to clear the Design Options !important:
   four classes plus an element beats one class whatever the load order.
   -------------------------------------------------------------------------- */
@media (max-width: 900px) {
    .l-section.full_height .w-vwrapper h1.w-text,
    .l-section.full_height .w-vwrapper h1.w-text .w-text-h {
        font-size: 44px !important;
        line-height: 1.1;
    }
}

@media (max-width: 600px) {
    .l-section.full_height .w-vwrapper h1.w-text,
    .l-section.full_height .w-vwrapper h1.w-text .w-text-h {
        font-size: 32px !important;
    }
}


/* --------------------------------------------------------------------------
   18.4  SECTOR CARDS
   Five cards at 3/3.6 in a single column is roughly one viewport height each
   — six screens of scrolling before the next section starts.
   The ratio is the lever, not the column count: Impreza writes
   #us_post_list_xxxx { --columns: 1 !important } into the page as an ID rule,
   which no class selector can outrank. If you want two columns on a phone,
   change it in the Post List element's responsive settings rather than here.
   Landscape cards also suit the layout better — title top-left, pill
   bottom-right, with the scrim's gradient still covering the title.
   Type comes up a step because the card is now full-bleed rather than a fifth
   of the row; 13px reads as a caption at that width.
   -------------------------------------------------------------------------- */
@media (max-width: 900px) {
    .sector-cards .w-grid-item {
        --card-ratio: 3 / 3.2;
        --card-pad: 18px;
    }
}

@media (max-width: 600px) {
    .sector-cards .w-grid-item {
        --card-ratio: 16 / 10;
        --card-pad: 20px;
    }

    .sector-cards .card-title {
        padding-right: 34px;
        font-size: 16px;
        line-height: 22px;
    }

    .sector-cards .card-teaser {
        font-size: 15px;
    }

    .sector-cards .card-cta {
        font-size: 14px;
        padding: .6em 1.4em;
    }

    /* The toggle sits on the title's line box, so it grows with it. */
    .sector-cards .card-x {
        width: 22px;
        height: 22px;
    }

    .sector-cards .card-x::before,
    .sector-cards .card-x::after {
        width: 11px;
    }
}

/* --------------------------------------------------------------------------
   18.6  CAPABILITIES ROW
   5.4 drops to one column at 600px, which turns five cards into five
   full-width blocks with an icon, two lines of copy and a lot of air. Two
   columns holds together down to about 420px, below which the titles
   ("Multiple Axis CNC Milling") wrap to three lines and it stops being worth
   it.
   These are the same selectors as 5.4's own 600px block, winning on order.
   -------------------------------------------------------------------------- */
@media (max-width: 600px) {
    .capabilities-row {
        --cap-columns: 2;
        --cap-gap: 16px;
        --cap-pad: 18px;
        --cap-icon: 56px;
        --cap-icon-gap: 20px;
        --cap-title-size: 18px;
        --cap-desc-size: 14px;
        --cap-desc-gap: 16px;
        --cap-arrow: 40px;
        --cap-min-height: 0;
        --cap-radius: 14px;
    }
}

@media (max-width: 420px) {
    .capabilities-row {
        --cap-columns: 1;
    }
}


/* --------------------------------------------------------------------------
   18.7  TESTIMONIALS
   The carousel already handles itself (one card plus a peek below 900). The
   only problem is the heading column and the track sitting flush against each
   other once the two columns stack, and the arrow having nothing between it
   and the next section.
   -------------------------------------------------------------------------- */
@media (max-width: 900px) {
    .testimonial-cards {
        margin-top: 24px;
    }

    .tc-next.tc-next.tc-next {
        margin-top: 1.2rem;
        margin-bottom: .5rem;
    }
}


/* --------------------------------------------------------------------------
   18.8  FOOTER
   Two nested cards at 50px padding each, so the inner copy starts 100px in
   from a 390px viewport. Both are Design Options boxes, hence the repeated
   class and the !important.
   -------------------------------------------------------------------------- */
@media (max-width: 900px) {
    .us_custom_42f65206.us_custom_42f65206 {
        padding: 30px !important;
    }

    .us_custom_b65ba543.us_custom_b65ba543 {
        padding: 30px !important;
    }
}

@media (max-width: 600px) {
    .us_custom_42f65206.us_custom_42f65206 {
        padding: 20px !important;
        border-radius: 14px !important;
    }

    .us_custom_b65ba543.us_custom_b65ba543 {
        padding: 20px !important;
        border-radius: 14px !important;
    }

    /* The two link columns are a .w-hwrapper with no stack option set, so at
       this width they compress rather than wrap. Half each is enough for the
       longest item ("Quality & Approval") over two lines. */
    .l-footer .w-hwrapper > .w-vwrapper {
        flex: 1 1 0;
        min-width: 0;
    }

    /* Full-width CTA — a centred pill on a narrow column reads as an
       afterthought, and it is the only action in the footer. */
    .us_custom_5c4d1344.us_custom_5c4d1344 {
        width: 100% !important;
        justify-content: center;
    }
}

/* --------------------------------------------------------------------------
   18.5  SECTOR OVERVIEW — INTRO BAND
   Dark copy panel sitting over a background photo, with a blue arrow
   straddling its left edge.
   --------------------------------------------------------------------------
   EDITOR SETUP
   Section                             (background photo)
      Separator                        (the spacer above the panel)
      Vertical Wrapper -> sector-overview-intro-band     <-- THE CLASS IS HERE
         Button                        (the arrow — no class needed)
         Text (H5)                     (the blue standfirst)
         Text block                    (the body copy)
   The class is on the PANEL, not the Section. The arrow is the only button
   inside the panel, so it is matched as a descendant. The separator and the
   section sit ABOVE the panel in the tree, so those two rules reach back up
   with :has().
   --------------------------------------------------------------------------
   THE !important IS FIGHTING DESIGN OPTIONS, NOTHING ELSE
   Impreza writes those as .us_custom_xxxxxxx { ... !important } in a
   stylesheet that loads AFTER this file, so order alone loses. The class is
   repeated to reach (0,2,0), which clears .us_custom_* at (0,1,0) whatever
   the load order. Clear Width / Padding / Position from Design Options on the
   panel and the arrow — on every breakpoint tab, Impreza stores them
   per-breakpoint — and every !important here becomes redundant.
   --------------------------------------------------------------------------
   THE ARROW MUST STAY POSITIONED
   The arrow is the <a> itself and it is the containing block for its own
   glyph (::before, inset:0) and ring (::after, negative inset). `static`
   hands both to the nearest positioned ancestor — the panel — so the glyph
   stretches across the whole panel and the ring draws around its border.
   `relative` releases the absolute placement while keeping the anchor. Same
   guard as .arrow-group .arrow-btn in 3.0.
   -------------------------------------------------------------------------- */

/* --- the panel -----------------------------------------------------------
   box-sizing is stated explicitly: width:100% with content-box padding is
   exactly how a box ends up wider than its parent, and the padding arrives
   with !important from a rule this file doesn't own.
   min-width:0 stops a long unbroken string in the copy pushing the panel past
   its parent, which a flex or grid child otherwise does.
   position:relative because it anchors the arrow — z-index stays auto, since
   giving it one makes the panel a stacking context and buries the arrow
   behind it.
   ------------------------------------------------------------------------- */
.sector-overview-intro-band.sector-overview-intro-band {
    --ib-max-width:   1200px;
    --ib-pad-block:   100px;
    --ib-pad-inline:  100px;
    --ib-radius:      30px;
    --ib-arrow-y:     80px;
    box-sizing: border-box;
    position: relative !important;
    width: 100% !important;
    max-width: var(--ib-max-width) !important;
    min-width: 0;
    margin-block: 0 !important;
    margin-inline: auto !important;         /* centred below desktop */
    padding: var(--ib-pad-block) var(--ib-pad-inline) !important;
    border-radius: var(--ib-radius) !important;
}

/* --- desktop only: pushed left and dropped down ------------------------- */
@media (min-width: 2285px) {
    .sector-overview-intro-band.sector-overview-intro-band {
        --ib-shift: 0;                    /* negative pulls it further left  */
        --ib-drop:  250px;                  /* positive pushes it further down */
        margin-block-start: var(--ib-drop) !important;
        margin-inline-start: var(--ib-shift) !important;
        margin-inline-end: auto !important;
    }
}

@media (min-width: 2085px) and (max-width: 2284px) {
    .sector-overview-intro-band.sector-overview-intro-band {
        --ib-shift: -200px;
		--ib-drop:  250px;                  /* positive pushes it further down */
        margin-block-start: var(--ib-drop) !important;
        margin-inline-start: var(--ib-shift) !important;
        margin-inline-end: auto !important;
    }
}

@media (min-width: 1880px) and (max-width: 2085px) {
    .sector-overview-intro-band.sector-overview-intro-band {
        --ib-shift: -100px;
		--ib-drop:  250px;                  /* positive pushes it further down */
        margin-block-start: var(--ib-drop) !important;
        margin-inline-start: var(--ib-shift) !important;
        margin-inline-end: auto !important;
    }
}

/* --- small screens: tighter padding so the copy has room ----------------- */
@media (max-width: 900px) {
    .sector-overview-intro-band.sector-overview-intro-band {
        --ib-pad-block:  48px;
        --ib-pad-inline: 28px;
        --ib-radius:     20px;
    }
}

@media (max-width: 600px) {
    .sector-overview-intro-band.sector-overview-intro-band {
        --ib-pad-block:  36px;
        --ib-pad-inline: 22px;
    }
}

/* Impreza's column wrappers must not claim a width or become the containing
   block — either leaves the arrow anchored to a wrapper instead of the panel.
   :has() so this reaches the wrappers ABOVE the panel, which is where they
   sit now the class has moved down a level. */
:is(.vc_column-inner, .wpb_wrapper):has(> .sector-overview-intro-band) {
    position: static;
    min-width: 0;
}

/* --- the arrow -----------------------------------------------------------
   Centred on the panel's left edge. left:0 is the padding box, so the panel's
   own padding is ignored and the button sits on the visible edge.
   translate, not transform — the base arrow-btn uses transform for its
   :active scale and the two would overwrite each other.
   ------------------------------------------------------------------------- */
.sector-overview-intro-band .w-btn-wrapper:has(.arrow-btn) {
    position: absolute;
    top: var(--ib-arrow-y);
    left: 0;
    right: auto;
    width: auto;
    max-width: none;
    margin: 0;
    translate: -50% -50%;
    z-index: 3;
}

.sector-overview-intro-band .arrow-btn.arrow-btn.arrow-btn {
    position: relative !important;
    left: auto !important;
    top: auto !important;
    right: auto !important;
    bottom: auto !important;
    transform: none !important;
}

/* --- laptops ------------------------------------------------------------- */
@media (max-width: 1320px) {
    .sector-overview-intro-band.sector-overview-intro-band {
        --ib-pad-block: 60px;
        --ib-pad-inline: 60px;
        --ib-arrow-y: 60px;
    }
}

/* --- mobile --------------------------------------------------------------
   The arrow returns to normal flow. Once the panel runs to the content edge
   there is no inset left for a button centred on that edge to occupy — half
   of it would land in the section's gutter or off-screen.
   ------------------------------------------------------------------------- */
@media (max-width: 900px) {
    .sector-overview-intro-band.sector-overview-intro-band {
        --ib-pad-block: 32px;
        --ib-pad-inline: 24px;
        --ib-radius: 16px;
    }

    .sector-overview-intro-band .w-btn-wrapper:has(.arrow-btn) {
        position: static;
        translate: none;
        margin: 0 0 12px;
    }

    .sector-overview-intro-band .arrow-btn.arrow-btn.arrow-btn {
        --ab-size: 44px;
    }

    /* The section's background is `contain`, so on a narrow viewport the photo
       becomes a short band across the top and the 20vw spacer is clearing
       nothing. Halved rather than removed.
       !important because the height is an inline style from the editor. */
    .l-section:has(.sector-overview-intro-band) .w-separator.size_custom {
        height: 10vw !important;
    }
}

@media (max-width: 600px) {
    .sector-overview-intro-band.sector-overview-intro-band {
        --ib-pad-block: 26px;
        --ib-pad-inline: 20px;
    }
}

/* --- the section ---------------------------------------------------------
   Reaching up from the panel. A safety net, not the fix: if anything still
   overhangs, something between the section and the panel is setting a width —
   check that column's Design Options before leaving this in, because clipping
   hides the symptom rather than removing the cause.
   clip, not hidden — hidden makes it a scroll container, which pins any
   scroll-driven animation inside at 0%.
   ------------------------------------------------------------------------- */
.l-section:has(.sector-overview-intro-band) {
    overflow: clip;
}

/* --------------------------------------------------------------------------
   18.9  HOME HERO
   Two H1s, then the copy panel and its arrow.
   The H1 sizing is already handled by 18.3 — this section is only the 200px
   top margin the vwrapper carries from Design Options, which on a phone
   pushes the headline most of the way down the viewport before it starts.
   --------------------------------------------------------------------------
   EDITOR SETUP
   Section -> home-hero
   :has(h1) picks the headline wrapper rather than the arrow-group below it,
   which is also a .w-vwrapper. Repeated class plus the descendant gives
   (0,3,0), which clears the Design Options rule at (0,1,0) !important.
   -------------------------------------------------------------------------- */
@media (max-width: 900px) {
    .home-hero .w-vwrapper.w-vwrapper:has(h1) {
        margin-top: 60px !important;
    }

    /* The panel and button return to flow via 3.5's own mobile block; only
       the button's size needs bringing down. 64px centred under a full-width
       panel reads as an orphan. */
    .home-hero .arrow-btn.arrow-btn.arrow-btn {
        --ab-size: 44px;
    }

    /* The panel carries bottom/right padding from Design Options that was
       there to clear the absolutely positioned button. In flow there is
       nothing to clear. */
    .home-hero .arrow-group.arrow-group {
        padding: 0 !important;
    }
}

@media (max-width: 600px) {
    .home-hero .w-vwrapper.w-vwrapper:has(h1) {
        margin-top: 40px !important;
    }
}


/* --------------------------------------------------------------------------
   18.10  TEXT FILL — the fixed-width copy block
   The "How we make it happen" paragraph carries a Design Options width of
   700px, written !important. On a 390px viewport that is 310px of overhang,
   and the sentences run off the right edge mid-word.
   Repeated class reaches (0,2,0), which clears .us_custom_* at (0,1,0)
   whatever the load order. Clear the Width field on that Text block — on
   every breakpoint tab — and this becomes redundant.
   Scoped to .text-fill rather than to every .wpb_text_column, so it only
   touches blocks that actually carry a fixed width from this design.
   -------------------------------------------------------------------------- */
@media (max-width: 900px) {
    .text-fill.text-fill,
    [class*="text-fill"][class*="text-fill"] {
        box-sizing: border-box;
        width: 100% !important;
        max-width: 100% !important;
        min-width: 0;
    }
}


/* --------------------------------------------------------------------------
   18.11  DIRECTION SWITCHER — the multi-box panel on mobile
   5.6's mobile block returns .dir-panel to static flow, but the multi-box
   variant is matched by a LONGER selector — .dir-panel:has(.w-iconbox ~
   .w-iconbox) at (0,2,0) — which keeps its position:absolute, its fixed
   top of 105px and its 645px height. So the Values panel stays pinned over
   the three words instead of stacking under them, which is the overlap in
   the screenshot.
   The same applies to the single-box variant, whose contents are each
   absolutely positioned against a 420px-tall box.
   These selectors repeat .dir-panel to outrank both.
   -------------------------------------------------------------------------- */
@media (max-width: 900px) {
    /* --- multi-box: back into flow, spacing from the gap not from a height */
    .dir-panel.dir-panel:has(.w-iconbox ~ .w-iconbox) {
        position: static;
        top: auto;
        height: auto;
        margin-top: 30px;
        justify-content: flex-start;
        gap: 2rem;
    }

    .dir-panel.dir-panel:has(.w-iconbox ~ .w-iconbox) .w-iconbox {
        margin: 0 !important;
    }

    /* The standfirst was lifted out of flow into the space above the panel,
       which only existed because the panel was absolutely positioned. */
    .dir-panel.dir-panel:has(.w-iconbox ~ .w-iconbox) > .w-text,
    .dir-panel .dir-panel-title {
        position: static;
        margin: 0 0 1.2rem;
        text-align: left;
    }

    /* --- single-box: the icon, heading and copy are each absolute against
       a 420px box. Stacked in flow they need none of that. */
    .dir-panel.dir-panel:has(.w-iconbox):not(:has(.w-iconbox ~ .w-iconbox)) .w-iconbox {
        min-height: 0;
        margin-top: 30px !important;
    }

    .dir-panel.dir-panel:has(.w-iconbox):not(:has(.w-iconbox ~ .w-iconbox)) .w-iconbox-meta {
        display: block;
    }

    .dir-panel.dir-panel:has(.w-iconbox):not(:has(.w-iconbox ~ .w-iconbox)) :is(
        .w-iconbox-icon,
        .w-iconbox-title,
        .w-iconbox-text
    ) {
        position: static;
        transform: none;
        width: auto;
        max-width: 100%;
        margin: 0 auto 1rem !important;
    }

    /* The two-column icon-box grid becomes a stack: at this width a fixed
       110px icon track leaves the description in a 12ch gutter. */
    .dir-panel .w-iconbox {
        --dir-icon: 64px;
        grid-template-columns: var(--dir-icon) minmax(0, 1fr) !important;
        gap: 1.2rem !important;
    }

    .dir-panel {
        --dir-measure: none;
    }
}

@media (max-width: 600px) {
    .dir-panel .w-iconbox {
        --dir-icon: 52px;
    }

    .dir-panel .w-iconbox-title {
        font-size: 17px;
    }

    .dir-panel .w-iconbox-text,
    .dir-panel .w-iconbox-text p {
        font-size: 15px;
    }
}


/* --------------------------------------------------------------------------
   18.12  CAPABILITY CAROUSEL
   The slide's meta block is a three-column grid with the arrow in its own
   track, pulled up 38px so the arrow and title straddle the image's bottom
   edge. That reads on a wide slide; at 390px the arrow eats a third of the
   row and the title wraps behind it.
   Stacked instead: arrow on its own line, then title, copy and button full
   width. The overlap goes with it — there is no longer a column for the
   arrow to sit beside.
   Repeated class because 5.5 sets the grid at (0,2,0).
   -------------------------------------------------------------------------- */
@media (max-width: 900px) {
    .cap-carousel {
        --cap-overlap: 0px;
        --cap-arrow-size: 52px;
        --cap-arrow-x: 0px;
        --cap-arrow-y: 0px;
        --cap-radius: 12px;
    }

    .cap-carousel .w-hwrapper.w-hwrapper {
        display: flex;
        flex-direction: column;
        align-items: flex-start;
        gap: .8rem;
        margin-top: 1rem;
    }

    /* grid-area is inert once the wrapper is flex, but cleared so nothing is
       left half-applied if this is ever switched back. */
    .cap-carousel :is(.cap-arrow, .cap-title, .cap-text, .w-btn-wrapper) {
        grid-area: auto;
        align-self: auto;
        width: 100%;
    }

    .cap-carousel .cap-arrow {
        flex: none;
        width: var(--cap-arrow-size);
        translate: none;
    }

    .cap-carousel .cap-title {
        margin: 0;
        font-size: 22px;
    }

    .cap-carousel .cap-text {
        font-size: 15px;
    }
}


/* --------------------------------------------------------------------------
   18.13  MEDIA STAGE
   5.1 already narrows the frame on mobile. The title is the remaining
   problem: it inherits --h2-font-size and sits over the video's top-left
   corner, where at 28px it runs to three lines and covers most of the frame.
   -------------------------------------------------------------------------- */
@media (max-width: 600px) {
    .media-stage {
        --ms-title-x: 1rem;
        --ms-title-y: 1rem;
    }

    .media-stage .media-title,
    .media-stage .media-title .w-text-h {
        font-size: 20px !important;
        line-height: 1.15;
    }
}

/* --------------------------------------------------------------------------
   18.14  HERO STAGE — hold the panel still, keep the arrow's turn
   --------------------------------------------------------------------------
   EDITOR SETUP
   Vertical Wrapper -> hero-stage arrow-group nw reveal
      Text block    -> arrow-panel
      Button                          (no class needed)
   --------------------------------------------------------------------------
   THE `nw` CLASS DOES TWO UNRELATED THINGS
     --ab-hover   where the ARROW turns to      (-135deg)  <- untouched
     --ap-dx/dy   where the PANEL travels to    (-1, -1)   <- zeroed here
   They are separate variables, so pinning the panel leaves the arrow's
   swing exactly as it was. Overriding the direction class itself would take
   the turn with it; this does not.
   Both axes go to 0: dy was lifting the panel into the headline, dx was
   sliding it left. With both at zero the translate resolves to 0 0 and the
   panel sits where it is laid out.
   Repeated class to match .arrow-group.nw.nw in 3.5, which is (0,2,0).
   -------------------------------------------------------------------------- */
.hero-stage.hero-stage {
    --ap-dx: 0;
    --ap-dy: 0;
}

/* --- mobile --------------------------------------------------------------
   3.5's own mobile block already returns the panel and the button to normal
   flow below 900px and forces the panel visible — there is no hover on
   touch, so a reveal-on-hover panel would otherwise be unreachable.
   What it does NOT do is stop the `reveal` transition running: the panel is
   visible, but a pointer landing on it still animates opacity and transform
   for 360ms. On a phone that reads as the copy flickering when you scroll
   with a finger over it.
   Zeroing the durations rather than removing the transition keeps the
   declaration intact if this is ever revisited.
   ------------------------------------------------------------------------- */
@media (max-width: 900px) {
    .hero-stage.arrow-group.reveal .arrow-panel,
    .hero-stage.arrow-group.reveal:has(:is(.arrow-btn, .arrow-panel):is(:hover, :focus-visible)) .arrow-panel {
        opacity: 1;
        visibility: visible;
        transform: none;
        transition: none;
    }
}


/* --------------------------------------------------------------------------
   18.15  MEDIA STAGE — the toggle on mobile
   The button is centred ON the frame's bottom-right corner: `right` is
   measured to that corner and `translate: 50% 50%` pushes half the button
   back out past it. On desktop that half sits in the 72vw gutter and reads
   as intentional overhang.
   On mobile 5.1 widens the frame to calc(100vw - 3rem), so the same half
   now lands in the page's own gutter — or past it, which is the button
   clipped at the viewport edge.
   Pulled fully inside the frame instead: the translate goes, and the offsets
   become a real inset from the corner rather than a distance to it.
   --------------------------------------------------------------------------
   The wrapper selector has to match 5.1's own — .w-btn-wrapper:has(.media-toggle)
   at (0,2,0) — so this is written with the class repeated to reach (0,3,0)
   rather than relying on source order, which the media query alone would not
   guarantee if anything is appended after this file.
   -------------------------------------------------------------------------- */
@media (max-width: 900px) {
    .media-stage.media-stage {
        --ms-btn-x: 16px;      /* inset from the frame's right edge  */
        --ms-btn-y: 16px;      /* inset from its bottom edge         */
    }

    .media-stage.media-stage .w-btn-wrapper:has(.media-toggle) {
        right: calc((100% - var(--ms-w)) / 2 + var(--ms-btn-x));
        bottom: var(--ms-btn-y);
        translate: none;
    }

    .media-stage .media-toggle.media-toggle.media-toggle {
        --ab-size: 44px;
    }

    /* The 45° turn and the swell were sized against a 64px square sitting
       clear of the frame. Inside it, at 44px, the diamond's corners overhang
       the rounded frame edge. The ring still blooms, so hover is still
       answered. */
    .media-stage.media-stage {
        --ms-btn-turn: 0deg;
        --ms-btn-scale: 1;
    }
}

/* ==========================================================================
   19.0  CAPABILITIES OVERVIEW — MOBILE
   Seven reusable classes plus two class-free rules. Each is written to be
   safe anywhere on the site, so the same names can go on the other templates
   as they come up.
   --------------------------------------------------------------------------
     19.1  section gutters   no class — every section
     19.2  hero margin       no class — found via .full_height
     19.3  copy-panel        any fixed-width dark panel over a photo
     19.4  panel-arrow       any arrow placed absolutely by Design Options
     19.5  stack-row         any Horizontal Wrapper that must stack
     19.6  fluid-media       any Image given a fixed px width, height or ratio
     19.7  flush-on-mobile   any wrapper carrying large inset padding
     19.8  split-band        making 5.2's own mobile stack actually apply
     19.9  media-first       flip a two-column row so the image leads
   --------------------------------------------------------------------------
   ONE GUTTER VALUE THROUGHOUT
   28px at 900px, 24px at 600px. Every rule below that pads anything uses
   those two numbers, so a panel, a bare wrapper and a lone arrow all share
   one optical edge regardless of which of them a given section happens to
   contain. Change them in one place and they drift; change them in all
   places or none.
   --------------------------------------------------------------------------
   EVERY !important HERE IS FIGHTING DESIGN OPTIONS, NOTHING ELSE
   Impreza writes those as .us_custom_xxxxxxx { ... !important } in a
   stylesheet that loads AFTER this file, so order alone loses. Each class is
   repeated to clear (0,1,0). Clear the corresponding fields in the editor —
   on every breakpoint tab, Impreza stores them per-breakpoint — and the
   !important becomes redundant.
   ========================================================================== */


/* --------------------------------------------------------------------------
   19.1  SECTION GUTTERS
   Impreza sets --padding-inline on .l-section per breakpoint: 2.5rem down to
   900px, then 1.5rem at 600px. Those are rem against the ROOT font size, not
   this site's 30px --font-size, so 1.5rem resolves to 24px. On a 390px phone
   that reads as the copy running into the screen edge.
   --------------------------------------------------------------------------
   THE VARIABLE, NOT A PADDING DECLARATION
   --padding-inline is what Impreza's own rules read, so overriding it reaches
   every section without this file needing to know which ones exist. Setting
   `padding` here instead would be outranked by the theme's own rule and would
   have to be restated per breakpoint.
   --------------------------------------------------------------------------
   IT DOES NOT REACH A width_full SECTION
   Those set --padding-inline to 0 by design, which is the whole point of the
   option. That is why 19.7 and 19.10 pad their own elements rather than
   relying on this — several sections on this page are width_full.
   --------------------------------------------------------------------------
   WATCH THE FULL-BLEED COMPONENTS
   full-bleed-image, feature-band-alt, text-overlap and split-band escape the
   content wrapper with 50% - 50vw, measured from their own edge outward. A
   wider gutter moves that starting edge, so the bleed still reaches the
   viewport correctly — but the CONTENT inside shifts in by the same amount.
   Usually what you want; worth a scroll-through after applying.
   -------------------------------------------------------------------------- */
@media (max-width: 600px) {
    .l-section {
        --padding-inline: 24px;
    }
}


/* --------------------------------------------------------------------------
   19.2  HERO — the 200px top margin
   --------------------------------------------------------------------------
   NO CLASS NEEDED. The hero is the only section carrying `full_height`, and
   18.3 already identifies it that way for the H1 sizing — so the margin hangs
   off the same selector rather than a class that has to be placed by hand.
   :has(h1) picks the wrapper holding the two H1s specifically, in case
   another vwrapper is added to the section later.
   Repeated class plus the ancestors reaches (0,4,0), clearing the Design
   Options rule at (0,1,0) !important.
   -------------------------------------------------------------------------- */
@media (max-width: 900px) {
    .l-section.full_height .w-vwrapper.w-vwrapper:has(h1) {
        margin-top: 60px !important;
    }
}

@media (max-width: 600px) {
    .l-section.full_height .w-vwrapper.w-vwrapper:has(h1) {
        margin-top: 40px !important;
    }
}

/* --------------------------------------------------------------------------
   19.3  copy-panel
   Both band panels are 800px wide with 100px of inline padding. On a 390px
   viewport that is 410px of overhang before the padding is counted.
   --------------------------------------------------------------------------
   THREE THINGS HAVE TO COME OFF TOGETHER
     width        800px -> 100%
     margin       `margin-left: auto` on one, `100px` on the other. Both
                  measure against a width the panel no longer has.
     box-shadow   the Multi-Axis panel uses `250px 0 0 0` as a fake bleed to
                  the right. A shadow cannot produce a scrollbar — browsers
                  do not count painted overflow — but at full width it paints
                  a 250px slab past the panel's edge, which reads as a
                  rendering fault rather than a bleed.
   box-sizing is stated explicitly: width:100% with content-box padding is
   exactly how a box ends up wider than its parent, and the padding arrives
   with !important from a rule this file doesn't own.
   position:relative because the panel anchors its arrow — z-index stays
   auto, since giving it one makes the panel a stacking context and buries
   the arrow behind it.
   --------------------------------------------------------------------------
   MULTI-AXIS: BREAKPOINTS
   1730 -> 1321   LAPTOP: side by side, images overlap the panel
                    row         72px padding left, 40px right
                    panel       fills its column + 160px under the images,
                                capped at 800px + 160px
                    copy        right padding grows by the same 160px, so
                                text never runs under the photos
                    images      fluid, fill their column, drawn above the
                                panel
   1600 -> 1321   panel padding also condenses: 100px at 1600 -> 60px at
                  1320, so it meets the 1320 rule below without a step
   1320 -> 901    TABLET: stacked, panel on top, images below
                    row         72px left (arrow clearance), 40px right
                    images      wide image on top, pair side by side
   900  -> 0      MOBILE: stacked, arrow in flow (19.4)
                    row         28px / 24px gutter, matching 19.1
                    images      all three stacked, full width, 4 / 3
   --------------------------------------------------------------------------
   LAPTOP OVERLAP — THE PANEL EXTENDS, NOT A SHADOW
   The Design Options 250px box-shadow draws the panel's rounded right edge
   as a seam once the panel is held to its column, and a pseudo-element
   replacement showed a lighter strip over the semi-transparent panel.
   Instead the panel itself is made wider than its column by
   --ma-overlap and pulled back with an equal negative right margin, so it
   runs under the image column as one surface with no seam. The shadow
   stays off in this range.
     --ma-overlap   how far the grey runs under the images (160px)
     --ma-pad       the panel's padding; set here rather than in a padding
                    shorthand so the condense rule can change it without
                    wiping out the extra right padding
   The image column gets position:relative + z-index so the photos paint
   above the panel. The panel itself still has no z-index, so the arrow is
   unaffected.
   --------------------------------------------------------------------------
   THE NEGATIVE ROW MARGIN
   Impreza pulls .g-cols outwards with a negative inline margin to cancel
   the columns' own padding. Stacked, that column padding is zeroed, so the
   pull is no longer cancelled and the whole row slid off the left edge.
   margin-inline:0 on the row removes it; the row's own padding then sets
   the gutter.
   --------------------------------------------------------------------------
   WHY THE LEFT GUTTER IS 72px
   The arrow straddles the panel's left edge, overhanging it by half its
   64px width. 72px = 32px overhang + 40px clearance. If the arrow size
   changes, use (arrow width / 2) + 40px. Below 900 the arrow is in flow
   (19.4), so the plain mobile gutter is enough.
   --------------------------------------------------------------------------
   FLUID IMAGES — STRUCTURE-INDEPENDENT
   Design Options gives the images fixed px sizes (810 x 250 on top,
   400 x 400 below). Every .w-image in the image column is released, and
   every element in that column is capped at 100%.
   The pair is found by CONTENT, not class: any element whose direct
   children include two .w-image.
     above 900   single 81 / 25, pair 1 / 1 in a row
     900 down    all 4 / 3, stacked
   MOBILE PAIR: the theme turns the pair's wrapper into a column below
   600px. With flex-basis 0 in a column each image's height resolves to 0,
   which is what collapsed them. Below 900 the pair is set to a column
   explicitly, with flex:0 0 auto so each image keeps its natural height.
   ID-scoped, so these outrank 19.6 fluid-media's 16 / 10.
   --------------------------------------------------------------------------
   IMAGE COLUMN is the row's LAST column, COPY COLUMN the FIRST. If the
   order is ever swapped in the editor, swap :last-child / :first-child.
   --------------------------------------------------------------------------
   STACK ORDER is source order (copy, then images). If this row also carries
   `media-first`, 19.9 flips it at 900px only. Add the `order` rules from
   19.9 to the stack block if you want images first at every stacked width.
   -------------------------------------------------------------------------- */
.copy-panel.copy-panel {
    box-sizing: border-box;
    position: relative !important;
    min-width: 0;
}

/* --- Multi-Axis: fluid images ------------------------------------------- */
@media (max-width: 1730px) {
    #multi-axis-cnc .g-cols.g-cols {
        box-sizing: border-box;
        max-width: 100%;
    }

    #multi-axis-cnc .g-cols > .wpb_column:last-child,
    #multi-axis-cnc .g-cols > .wpb_column:last-child * {
        min-width: 0;
        max-width: 100%;
        box-sizing: border-box;
    }

    #multi-axis-cnc .g-cols > .wpb_column:last-child .w-image {
        width: 100% !important;
        max-width: 100% !important;
        height: auto !important;
        max-height: none !important;
        min-height: 0 !important;
        aspect-ratio: auto !important;
        flex-shrink: 1 !important;
    }

    #multi-axis-cnc .g-cols > .wpb_column:last-child .w-image .w-image-h {
        display: block;
        width: 100%;
        height: auto;
        border-radius: inherit;
        overflow: clip;
    }

    #multi-axis-cnc .g-cols > .wpb_column:last-child .w-image img {
        display: block;
        width: 100%;
        height: auto;
        max-width: 100%;
        aspect-ratio: 81 / 25;
        object-fit: cover;
    }

    /* the pair: whatever holds two images side by side */
    #multi-axis-cnc .g-cols > .wpb_column:last-child :has(> .w-image ~ .w-image) {
        display: flex !important;
        flex-direction: row !important;
        flex-wrap: nowrap !important;
        width: 100% !important;
    }

    #multi-axis-cnc .g-cols > .wpb_column:last-child :has(> .w-image ~ .w-image) > .w-image {
        flex: 1 1 0 !important;
        width: auto !important;
    }

    #multi-axis-cnc .g-cols > .wpb_column:last-child :has(> .w-image ~ .w-image) > .w-image img {
        aspect-ratio: 1 / 1;
    }
}

/* --- Multi-Axis: laptop, images overlap the panel ------------------------ */
@media (min-width: 1321px) and (max-width: 1730px) {
    #multi-axis-cnc {
        --ma-overlap: 160px;
        --ma-pad: 100px;
    }

    #multi-axis-cnc .g-cols.g-cols {
        padding-left: 72px !important;   /* arrow overhang + 40px */
        padding-right: 40px !important;
    }

    #multi-axis-cnc .g-cols > .wpb_column:first-child {
        min-width: 0;
    }

    /* images paint above the extended panel */
    #multi-axis-cnc .g-cols > .wpb_column:last-child {
        position: relative;
        z-index: 1;
    }

    #multi-axis-cnc .g-cols > .wpb_column:last-child > .vc_column-inner {
        padding-left: 0 !important;
    }

    #multi-axis-cnc .copy-panel.copy-panel {
        width: calc(100% + var(--ma-overlap)) !important;
        max-width: calc(800px + var(--ma-overlap)) !important;
        margin-left: auto !important;
        margin-right: calc(-1 * var(--ma-overlap)) !important;
        padding: var(--ma-pad)
                 calc(var(--ma-pad) + var(--ma-overlap))
                 var(--ma-pad)
                 var(--ma-pad) !important;
        box-shadow: none !important;
    }
}

/* --- Multi-Axis: condense padding --------------------------------------- */
@media (min-width: 1321px) and (max-width: 1600px) {
    #multi-axis-cnc {
        --ma-pad: clamp(60px, calc(14.2857vw - 128.57px), 100px);
    }
}

/* --- Multi-Axis: stack (tablet + mobile) --------------------------------- */
@media (max-width: 1320px) {
    #multi-axis-cnc .g-cols.g-cols {
        display: flex !important;
        flex-direction: column;
        row-gap: 32px;
        margin-inline: 0 !important;
    }

    #multi-axis-cnc .g-cols.g-cols > .wpb_column {
        width: 100% !important;
        max-width: 100% !important;
        flex: 0 0 auto !important;
        min-width: 0;
        margin: 0 !important;
    }

    #multi-axis-cnc .g-cols.g-cols > .wpb_column > .vc_column-inner {
        padding-inline: 0 !important;
    }
}

/* --- Multi-Axis: tablet -------------------------------------------------- */
@media (min-width: 901px) and (max-width: 1320px) {
    #multi-axis-cnc .g-cols.g-cols {
        padding-left: 72px !important;   /* arrow overhang + 40px */
        padding-right: 40px !important;
    }

    #multi-axis-cnc .copy-panel.copy-panel {
        max-width: none !important;
        margin: 0 !important;
        box-shadow: none !important;
    }
}

/* --- Multi-Axis: mobile -------------------------------------------------- */
@media (max-width: 900px) {
    #multi-axis-cnc .g-cols.g-cols {
        padding-inline: 28px !important;
    }

    /* pair stacks, each image keeps its own height */
    #multi-axis-cnc .g-cols > .wpb_column:last-child :has(> .w-image ~ .w-image) {
        flex-direction: column !important;
    }

    #multi-axis-cnc .g-cols > .wpb_column:last-child :has(> .w-image ~ .w-image) > .w-image {
        flex: 0 0 auto !important;
        width: 100% !important;
    }

    /* one shape for all three */
    #multi-axis-cnc .g-cols > .wpb_column:last-child .w-image img,
    #multi-axis-cnc .g-cols > .wpb_column:last-child :has(> .w-image ~ .w-image) > .w-image img {
        aspect-ratio: 4 / 3;
    }
}

@media (max-width: 600px) {
    #multi-axis-cnc .g-cols.g-cols {
        padding-inline: 24px !important;
    }
}

/* --- all copy-panels ----------------------------------------------------- */
@media (max-width: 1320px) {
    .copy-panel.copy-panel {
        width: 100% !important;
        max-width: 900px !important;
        padding: 60px !important;
    }
}

@media (max-width: 900px) {
    .copy-panel.copy-panel {
        width: 100% !important;
        max-width: 100% !important;
        margin: 0 !important;
        padding: 32px 28px !important;
        border-radius: 16px !important;
        box-shadow: none !important;
    }
}

@media (max-width: 600px) {
    .copy-panel.copy-panel {
        padding: 28px 24px !important;
    }
}

/* --------------------------------------------------------------------------
   19.4  panel-arrow
   --------------------------------------------------------------------------
   THE CLASS GOES ON THE <a>, NOT ON A WRAPPER
   Design Options writes `position: absolute` onto the button itself, so the
   button — not .w-btn-wrapper — is what has to be released. That matters
   because the button is the containing block for its own glyph (::before,
   inset:0) and ring (::after, negative inset). Setting it to `static` hands
   both to the nearest positioned ancestor, which is the panel: the glyph
   stretches across the whole panel and the ring draws around its border.
   `relative` releases the absolute placement while keeping the anchor.
   The offsets are cleared explicitly because they are still declared with
   !important and would apply to a relative box as a nudge.
   `transform: none` removes the translateX(-50%), and clearing it also
   restores the button's own :active press — .arrow-btn:active uses
   transform: scale(.94), which an !important transform would outrank.
   Three repeats plus !important clears both .us_custom_* and 3.0's own
   .arrow-btn.arrow-btn.arrow-btn chain whatever the load order.
   -------------------------------------------------------------------------- */
@media (max-width: 900px) {
    .panel-arrow.panel-arrow.panel-arrow {
        position: relative !important;
        left: auto !important;
        top: auto !important;
        right: auto !important;
        bottom: auto !important;
        transform: none !important;
        translate: none;
        margin: 0 !important;
        --ab-size: 44px;
    }

    /* The wrapper carries the vertical spacing now the button is in flow. */
    .w-btn-wrapper:has(.panel-arrow) {
        position: static;
        translate: none;
        margin: 0 0 12px;
    }

    /* --- the gutter, ONLY where the arrow has no padded parent -----------
       Inside a copy-panel or a band-panel the arrow already inherits that
       panel's 28px, and adding more would double it. The CNC Turning arrow
       is the exception: it sits in the IMAGE column, in a bare wrapper with
       no padding, so in flow it lands hard against the screen edge while the
       copy beside it is 28px in.
       `:not(.copy-panel *)` reads as "not a descendant of a copy-panel".
       Both exclusions are needed — an arrow can be in either — and both are
       cheap, since they are only evaluated for elements the :has() already
       matched.
       Padding rather than margin: the wrapper is a flex child in some of
       these layouts, where a margin would be collapsed or overridden by the
       parent's alignment. Padding always applies.
       Add another :not() if a new padded panel class ever holds an arrow.
       The failure is visible rather than silent — 56px instead of 28px — so
       it is easy to spot. */
    .w-btn-wrapper:has(.panel-arrow):not(.copy-panel *):not(.band-panel *) {
        padding-inline: 28px;
    }
}

@media (max-width: 600px) {
    .w-btn-wrapper:has(.panel-arrow):not(.copy-panel *):not(.band-panel *) {
        padding-inline: 24px;
    }
}


/* --------------------------------------------------------------------------
   19.5  stack-row
   Impreza's own `stack_on_mobiles` only fires at 600px, and these rows break
   well before that — the intro row puts a 16/9 image, a button and three
   paragraphs on one line.
   Repeated class to clear .w-hwrapper's own flex rules at (0,1,0).
   The gap variable is reused rather than a margin, so the row keeps whatever
   spacing was set in the editor.
   -------------------------------------------------------------------------- */
@media (max-width: 900px) {
    .stack-row.stack-row {
        display: flex;
        flex-direction: column;
        align-items: stretch;
        row-gap: var(--hwrapper-gap, 1.2rem);
    }

    .stack-row.stack-row > * {
        width: 100%;
        max-width: 100%;
        min-width: 0;
        margin: 0;
    }
}


/* --------------------------------------------------------------------------
   19.6  fluid-media
   --------------------------------------------------------------------------
   TWO THINGS COME FROM DESIGN OPTIONS, NOT ONE
     height          400px / 250px
     aspect-ratio    1 / 1 and 16:9, set on the .w-image WRAPPER
   Clearing the height alone shrinks nothing: the ratio still holds the box
   open — roughly 570px tall at full width — while the <img> inside renders
   at its own natural height and leaves the remainder as background. That gap
   is the ratio, not a margin.
   So the ratio moves to the <img>, where object-fit has something to crop
   against and the wrapper sizes to whatever the image turns out to be.
   Change 16 / 10 below to 1 / 1 if you want the squares to stay square — the
   gap goes either way, since the fix is moving the ratio off the wrapper
   rather than the value itself.
   -------------------------------------------------------------------------- */
@media (max-width: 900px) {
    .fluid-media.fluid-media {
        width: 100% !important;
        max-width: 100% !important;
        height: auto !important;
        max-height: none !important;
        min-height: 0 !important;
        aspect-ratio: auto !important;
        min-width: 0;
        margin-inline: 0 !important;
        border-radius: 16px !important;
    }

    .fluid-media .w-image-h {
        display: block;
        width: 100%;
        height: auto;
        aspect-ratio: auto;
        border-radius: inherit;
        /* clip, not hidden — hidden creates a scroll container, which pins
           any scroll-driven animation inside it at 0%. */
        overflow: clip;
    }

    .fluid-media img {
        display: block;
        width: 100%;
        height: auto;
        max-width: 100%;
        aspect-ratio: 16 / 10;
        object-fit: cover;
    }
}


/* --------------------------------------------------------------------------
   19.7  flush-on-mobile
   The CNC Turning copy sits 80px in from its column, which reads as an inset
   against the photo beside it. Once the two columns stack there is nothing
   to inset from and 80px is a large bite out of an already narrow measure.
   --------------------------------------------------------------------------
   IT DOES NOT GO TO ZERO — 19.1'S GUTTER IS NOT AVAILABLE HERE
   The obvious version zeroes the padding and lets the section's own
   --padding-inline provide the spacing. That works in a normal section, but
   the CNC Turning section is `width_full`, which sets --padding-inline to 0.
   With nothing on either side the copy runs to the screen edge.
   So this reduces the padding to the shared gutter rather than removing it.
   If this class ever goes in a NORMAL section it will double up — 24px from
   the section plus 28px here. Scope it with
   `.l-section:not(.width_full) .flush-on-mobile { padding-inline: 0 }` if
   that comes up.
   Inline only; block padding is left alone, since it is usually doing
   something the width has no bearing on.
   -------------------------------------------------------------------------- */
@media (max-width: 900px) {
    .flush-on-mobile.flush-on-mobile {
        padding-inline: 28px !important;
        margin-inline: 0 !important;
        min-width: 0;
    }
}

@media (max-width: 600px) {
    .flush-on-mobile.flush-on-mobile {
        padding-inline: 24px !important;
    }
}


/* --------------------------------------------------------------------------
   19.8  SPLIT BAND — make 5.2's mobile stack actually apply
   5.2 already stacks this band at 900px with `display: block`, but that rule
   is (0,1,0) on .split-band and the band is a .w-hwrapper, which Impreza
   gives its own display:flex at the same weight in a stylesheet that loads
   later. So the theme wins, the band stays side by side, and the copy ends
   up in a 12ch column.
   Repeated class takes it to (0,2,0). Order alone is not enough, because
   .w-hwrapper is not a selector this file controls the position of.
   --------------------------------------------------------------------------
   IMAGE ABOVE, COPY BELOW is already the source order — .band-media comes
   first — so no `order` is needed here, unlike 19.9.
   The panel's -32px pull from 5.2 stays: it tucks the copy under the photo's
   rounded corner, which is what makes the two read as one object rather than
   two stacked boxes.
   -------------------------------------------------------------------------- */
@media (max-width: 900px) {
    .split-band.split-band {
        display: block;
    }

    .split-band.split-band .band-panel.band-panel {
        padding: 32px 28px !important;
    }

    .split-band.split-band .band-media,
    .split-band.split-band .band-media .w-image-h {
        width: 100%;
        max-width: 100%;
    }
}

@media (max-width: 600px) {
    .split-band.split-band .band-panel.band-panel {
        padding: 28px 24px !important;
    }
}

/* ---------------------------------------------------------------
   SPLIT BAND (INSET) — square photo
   The panel is shorter than the photo again, so it sits centred
   on the photo's right edge as before. The photo is cropped by
   object-fit, so nothing is stretched.
--------------------------------------------------------------- */
.split-band.band-inset .media-first {
    align-items: center;
}

.split-band.band-inset .band-media {
    aspect-ratio: 1 / 1;
    height: auto !important;     /* beats the Height set in Design Options */
    align-self: center;
}

.split-band.band-inset .band-media .w-image-h,
.split-band.band-inset .band-media img {
    width: 100%;
    height: 100% !important;
    object-fit: cover;
    object-position: 40% center; /* keeps him in frame as the sides crop */
}

/* --------------------------------------------------------------------------
   19.9  media-first
   Flips a two-column row so the IMAGE column comes first once stacked.
   --------------------------------------------------------------------------
   EDITOR SETUP
   The class goes on the ROW (.g-cols) — not the section, not a column.
   --------------------------------------------------------------------------
   The CNC Turning row is copy-then-image in source order, which is right on
   desktop: the copy sits left of the photo. Stacked, that puts three
   paragraphs and a button above the image, so the reader scrolls past all
   the text before seeing what it is about.
   `order` rather than reordering in the editor, because it applies only
   inside the media query and leaves the desktop arrangement untouched.
   It needs the row to be a flex container — .g-cols.via_flex already is, but
   `display: flex` is restated because the theme switches some rows to block
   at this breakpoint, and order is inert on a block container.
   The vc_col percentages survive the switch to a column direction and would
   otherwise hold each column at its desktop share, hence the width reset.
   -------------------------------------------------------------------------- */
@media (max-width: 900px) {
    .media-first.media-first {
        display: flex !important;
        flex-direction: column;
    }

    .media-first.media-first > .wpb_column:first-child { order: 2; }
    .media-first.media-first > .wpb_column:last-child  { order: 1; }

    .media-first.media-first > .wpb_column {
        width: 100% !important;
        max-width: 100% !important;
        min-width: 0;
        margin: 0 0 24px !important;
    }

    .media-first.media-first > .wpb_column:last-child {
        margin-bottom: 24px !important;
    }
}

/* --- no internal scroll --------------------------------------------------
   Impreza caps dropdowns to the viewport and sets overflow-y:auto, possibly
   inline from its JS, hence the !important. Desktop only: the mobile menu
   still needs to scroll. Transforms drive the dropdown_height reveal, not
   overflow, so the open animation is unaffected. */
@media (min-width: 901px) {
    .ush_menu_1 .w-nav-list:not(.level_1):has(.mega-top),
    .ush_menu_1 .w-nav-list:not(.level_1):has(.mega-top) > .w-nav-item {
        max-height: none !important;
        overflow: visible !important;
    }

    /* Spacing in px, not rem. 1rem is 30px here, which is what made the
       panel tall enough to hit the cap. */
    .mega-panel,
    .w-nav-list:not(.level_1):has(.mega-top) {
        --mm-panel-pad: 36px 44px 24px;
    }

    .mega-top,
    .mega-policies {
        --mm-gap: 40px;
        --mm-link-gap: 16px;
        --mm-policy-gap: 32px;
        --mm-policy-pad: 20px;
    }
}

/* Short laptop screens: tighten a step further so the panel always clears
   the bottom of the viewport. */
@media (min-width: 901px) and (max-height: 760px) {
    .mega-panel,
    .w-nav-list:not(.level_1):has(.mega-top) {
        --mm-panel-pad: 24px 36px 18px;
    }

    .mega-top,
    .mega-policies {
        --mm-link-gap: 12px;
        --mm-policy-pad: 14px;
        --mm-link-size: 15px;
    }
}
/* ==========================================================================
   19.10  MULTI AXIS TURNING — FLUID LAYOUT
   Append to the END of the site stylesheet (after 19.9 and the mega menu
   block). Section id: multi-axis-turning.
   --------------------------------------------------------------------------
   WHY IT OVERLAPPED
   Design Options give every piece of this section a fixed size:
     copy panel   width 800px, margin-left 100px, plus a 250px box-shadow
                  that paints the grey further right       (us_custom_157112e3)
     main image   810 x 550                                (us_custom_bc506d22)
     two squares  400 x 400 each                           (us_custom_44ad4bbd)
   The columns shrink with the window but none of those do, so the photos
   ended up over the TEXT. The two columns also stacked at different widths
   (vc_col-md-6 and vc_col-sm-6), so between 768 and 900px the photos sat in
   a half-width column on their own.
   --------------------------------------------------------------------------
   WHAT THIS DOES
   The panel stays in its own column. The photos are pulled LEFT by
   --mat-overlap, so they sit over the right-hand strip of the panel's grey.
   The panel's right padding is that same --mat-overlap plus --mat-breathe,
   so the strip they cover never has text in it, at any width.
   1201px and up   side by side. The whole composition is capped at
                   --mat-max and centred, so on very wide screens it keeps
                   the proportions of the design rather than stretching.
   1200px and down stacked. The photos sit below the panel and rise up over
                   its bottom edge instead.
   600px and down  tighter padding and a smaller overlap.
   The photos keep their proportions at every width (810:550 and squares).
   --------------------------------------------------------------------------
   WEIGHT
   The ID gives (1,x,x), which clears the theme's column widths and 19.0
   without !important. Design Options write width/height/margin/padding/
   box-shadow with !important, so those properties need it here too — and
   only those. Nothing here touches translate, so the column-snap entrance
   still runs.
   ========================================================================== */

#multi-axis-turning {
    --mat-max: 2020px;                            /* widest the pair gets    */
    --mat-arrow: 64px;                            /* the panel arrow's size  */
    --mat-indent: calc(var(--mat-arrow) / 2);     /* room for the half of it
                                                     that hangs off the panel */
    --mat-overlap: clamp(48px, 6vw, 150px);       /* how far the photos sit
                                                     over the grey            */
    --mat-breathe: clamp(24px, 2.5vw, 50px);      /* text to the photos      */
    --mat-row-gap: clamp(24px, 4vw, 48px);        /* stacked only            */
    --mat-tile-gap: 0.3rem;                       /* between the photos      */
    --mat-edge: clamp(20px, 4vw, 80px);           /* photos to the right edge */
}

/* --- the row: a grid instead of the theme's percentage columns ---------- */
#multi-axis-turning > .l-section-h > .g-cols {
    display: grid;
    grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr);
    column-gap: 0;
    row-gap: var(--mat-row-gap);
    align-items: center;
    max-width: var(--mat-max);
    margin: 0 auto;
}

#multi-axis-turning > .l-section-h > .g-cols > .wpb_column {
    position: relative;
    width: auto;
    min-width: 0;
    margin: 0;
}

/* Text column underneath, photos on top of it. */
#multi-axis-turning > .l-section-h > .g-cols > .wpb_column:first-child { z-index: 1; }
#multi-axis-turning > .l-section-h > .g-cols > .wpb_column:last-child  { z-index: 2; }

#multi-axis-turning > .l-section-h > .g-cols > .wpb_column > .vc_column-inner {
    padding-left: 0;
    padding-right: 0;
}

/* Breathing room between the photos and the right edge of the screen. */
#multi-axis-turning > .l-section-h > .g-cols > .wpb_column:last-child > .vc_column-inner {
    padding-right: var(--mat-edge);
}

/* --- the copy panel ------------------------------------------------------
   Fills its own column, no further. The right padding keeps the text out
   of the strip the photos cover.
   ------------------------------------------------------------------------- */
#multi-axis-turning .copy-panel {
    box-sizing: border-box;
    width: auto !important;
    max-width: none;
    margin-left: clamp(var(--mat-indent), 5vw, 100px) !important;
    margin-right: 0 !important;
    padding:
        30px
        calc(var(--mat-overlap) + var(--mat-breathe))
        50px
        clamp(56px, 6vw, 100px) !important;
    box-shadow: none !important;
}

/* --- the photos ----------------------------------------------------------
   Pulled left by --mat-overlap and widened by the same amount, so the left
   edge moves onto the grey while the right edge stays put.
   ------------------------------------------------------------------------- */
#multi-axis-turning .wpb_column:last-child .w-vwrapper {
    width: calc(100% + var(--mat-overlap));
    max-width: 810px;
    margin-left: calc(-1 * var(--mat-overlap));
}

#multi-axis-turning .fluid-media {
    width: 100% !important;
    height: auto !important;
    max-width: 100%;
}

#multi-axis-turning .us_custom_bc506d22 {
    aspect-ratio: 810 / 550 !important;
}

#multi-axis-turning .us_custom_44ad4bbd {
    aspect-ratio: 1 / 1 !important;
}

#multi-axis-turning .fluid-media .w-image-h,
#multi-axis-turning .fluid-media img {
    display: block;
    width: 100%;
    height: 100%;
}

#multi-axis-turning .fluid-media img {
    object-fit: cover;
}

/* The two squares, always side by side, splitting the main photo's width. */
#multi-axis-turning .stack-row {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--mat-tile-gap);
    width: 100%;
}

#multi-axis-turning .stack-row > * {
    margin: 0;
}

/* --- 1200px and down: one column -----------------------------------------
   The overlap turns vertical. The panel gets --mat-overlap of extra space
   below its button, and the photos are pulled up into it. They are also
   inset from the panel's sides so the grey frames them.
   ------------------------------------------------------------------------- */
@media (max-width: 1200px) {
    #multi-axis-turning {
        --mat-overlap: clamp(40px, 8vw, 100px);
        --mat-inset: clamp(16px, 4vw, 60px);
    }

    #multi-axis-turning > .l-section-h > .g-cols {
        grid-template-columns: minmax(0, 1fr);
    }

    #multi-axis-turning .copy-panel {
        margin-left: var(--mat-indent) !important;
        padding:
            30px
            clamp(30px, 5vw, 60px)
            calc(50px + var(--mat-overlap))
            clamp(56px, 7vw, 100px) !important;
    }

    #multi-axis-turning .wpb_column:last-child .w-vwrapper {
        max-width: none;
        width: calc(100% - var(--mat-indent) - var(--mat-inset));
        margin-top: calc(-1 * (var(--mat-row-gap) + var(--mat-overlap)));
        margin-left: calc(var(--mat-indent) + var(--mat-inset));
    }

    /* Same inset on the right, so the photos sit centred on the panel. */
    #multi-axis-turning > .l-section-h > .g-cols > .wpb_column:last-child > .vc_column-inner {
        padding-right: var(--mat-inset);
    }
}

/* --- 600px and down: tighter panel --------------------------------------- */
@media (max-width: 600px) {
    #multi-axis-turning {
        --mat-overlap: 40px;
        --mat-inset: 16px;
    }

    #multi-axis-turning .copy-panel {
        padding: 24px 20px calc(32px + var(--mat-overlap)) 48px !important;
    }
}

/* ==========================================================================
   20.0  CAREERS PAGE
   Replaces the whole of the previous 20.0 section. Append to the END of the
   site stylesheet (after 19.9).
   --------------------------------------------------------------------------
   CONTENTS
     20.1  Tokens and shared type
       20.1.1  Tokens
       20.1.2  Section rhythm
       20.1.3  Section headings
     20.2  Hero
     20.3  Intro
     20.4  Why cards
       20.4.1  The lift maths
       20.4.2  The section
       20.4.3  The row
       20.4.4  The card
       20.4.5  Number and copy
       20.4.6  Hover photo
       20.4.7  Swipe strip (1200px and below)
     20.5  Why CTA — arrow and hover panel
       20.5.1  Position
       20.5.2  The arrow
       20.5.3  The panel
       20.5.4  The reveal
       20.5.5  Touch and mobile
     20.6  Story cards — employee stories AND apprenticeships
       20.6.1  Section settings
       20.6.2  The row
       20.6.3  The card
       20.6.4  Photo and shade
       20.6.5  Role, arrow and name
       20.6.6  Bio
       20.6.7  Open state
       20.6.8  Carousel (900px and below)
       20.6.9  Carousel controls
     20.7  Current vacancies (Post List)
     20.8  Testimonials
     20.9  Supplier band
     20.10 White button size variants (fix)
     20.11 Reduced motion
     20.12 Footer at tablet size (site-wide)
   --------------------------------------------------------------------------
   PAIRS WITH the STORY CARDS JS snippet (tap-to-open on touch screens).
   Mouse and keyboard work without it; phones need it, otherwise the bio is
   shown permanently as a fallback.
   ========================================================================== */


/* ==========================================================================
   20.1  TOKENS AND SHARED TYPE
   ========================================================================== */

/* --------------------------------------------------------------------------
   20.1.1  TOKENS
   -------------------------------------------------------------------------- */
.careers-hero,
.careers-sec,
.careers-why {
    --c-blue: var(--color-blue, #00bfff);
    --c-ink: #fff;
    --c-ink-soft: rgb(255 255 255 / .8);
    --c-panel: var(--color-dark-dark-grey, #333);
    /* The face for everything set LIGHT (300) on this page: section titles,
       leads, story names, the testimonial heading.
       Atkinson Hyperlegible Next appears to be in your Adobe Fonts kit in
       Bold only — every 300-weight line set in it was rendering bold. Open
       Sans is loaded as a variable font covering 300–800, so it can
       genuinely go light. Once Atkinson Light is added to the kit, change
       this one line to var(--h2-font-family) and the whole page follows. */
    --c-face-light: var(--font-family, inherit);
    --c-radius: 16px;
    --sec-pad: clamp(56px, 7vw, 140px);
    --c-speed: 420ms;
    --c-ease: cubic-bezier(.22, .68, .3, 1);
}

/* --------------------------------------------------------------------------
   20.1.2  SECTION RHYTHM
   Every careers section uses height="auto" in the editor, so Impreza adds no
   padding of its own and --sec-pad is the only thing setting the rhythm.
   -------------------------------------------------------------------------- */
.l-section.careers-sec.careers-sec > .l-section-h {
    padding-top: var(--sec-pad);
    padding-bottom: var(--sec-pad);
}

/* Anchors from the Careers mega menu land below the sticky header. */
.careers-sec[id],
.careers-why[id] {
    scroll-margin-top: var(--header-sticky-height, 70px);
}

/* --------------------------------------------------------------------------
   20.1.3  SECTION HEADINGS
   -------------------------------------------------------------------------- */
.careers-sec .sec-title.sec-title {
    margin: 0 0 clamp(14px, 1.4vw, 26px);
    font-family: var(--c-face-light, inherit);
    font-size: clamp(28px, 2.4vw, 46px);
    font-weight: 300;
    line-height: 1.15;
    letter-spacing: 0;
    color: var(--c-ink);
}

.careers-sec .sec-lead.sec-lead {
    max-width: 30em;
    margin: 0 0 clamp(32px, 4vw, 72px);
    font-family: var(--c-face-light, inherit);
    font-size: clamp(20px, 1.9vw, 38px);
    font-weight: 300;
    line-height: 1.3;
    color: var(--c-blue);
    text-wrap: pretty;
}

.careers-sec :is(.sec-title, .sec-lead) :is(.w-text-h, .w-text-value) {
    color: inherit;
}


/* ==========================================================================
   20.2  HERO
   Both lines sized as a pair. Five classes clear 18.3's (0,4,1) mobile rule,
   which would otherwise set the two lines to the same size below 900px.
   ========================================================================== */
.l-section.careers-hero.careers-hero .w-vwrapper .hero-title,
.l-section.careers-hero.careers-hero .w-vwrapper .hero-title .w-text-h {
    margin: 0;
    font-size: clamp(32px, 5.4vw, 96px) !important;
    line-height: 1.05;
    letter-spacing: .02em;
    text-wrap: balance;
}

.l-section.careers-hero.careers-hero .w-vwrapper .hero-sub,
.l-section.careers-hero.careers-hero .w-vwrapper .hero-sub .w-text-h {
    margin: 0;
    font-family: var(--h1-font-family, inherit);
    font-size: clamp(22px, 3.2vw, 56px) !important;
    font-weight: 700;
    line-height: 1.1;
    letter-spacing: .02em;
    text-wrap: balance;
}


/* ==========================================================================
   20.3  INTRO
   The bottom padding makes room for the top half of the why cards, which
   ride up out of the next section. --why-lift is shared with 20.4.
   ========================================================================== */
.l-section.careers-intro.careers-intro > .l-section-h {
    padding-bottom: calc(var(--why-lift) + clamp(40px, 4vw, 72px));
}

.careers-intro .careers-lead.careers-lead,
.careers-intro .careers-sub.careers-sub {
    width: 100%;
    margin: 0;
}

.careers-intro .careers-lead.careers-lead {
    max-width: 1080px;
    margin-bottom: clamp(36px, 5vw, 96px);
}

.careers-intro .careers-sub.careers-sub {
    max-width: 660px;
}

.careers-intro .careers-lead :is(p, h2) {
    margin: 0;
    font-family: var(--c-face-light, inherit);
    font-size: clamp(22px, 2.1vw, 40px);
    font-weight: 300;
    line-height: 1.3;
    color: var(--c-blue);
    text-wrap: pretty;
}

.careers-intro .careers-sub :is(p, h2) {
    margin: 0;
    font-family: var(--c-face-light, inherit);
    font-size: clamp(20px, 1.7vw, 32px);
    font-weight: 300;
    line-height: 1.3;
    color: var(--c-ink);
}


/* ==========================================================================
   20.4  WHY CARDS
   Five numbered blue cards straddling the join between the black intro and
   the photograph.
   ========================================================================== */

/* --------------------------------------------------------------------------
   20.4.1  THE LIFT MATHS
   The row is pulled up by exactly half a card, worked out from the same
   three numbers that size the cards:
       card width  = (row width − gaps) / --why-cols
       card height = card width / --why-ratio
       --why-lift  = card height / 2
   Declared on both sections so the intro's bottom padding always matches.
   -------------------------------------------------------------------------- */
.careers-intro,
.careers-why {
    --why-cols: 5;
    --why-gap: 24px;
    --why-ratio: 1;
    --why-lift: calc(
        (min(100vw - 2 * var(--padding-inline, 2.5rem), var(--site-content-width, 1600px))
            - (var(--why-cols) - 1) * var(--why-gap))
        / var(--why-cols) / var(--why-ratio) / 2
    );
}

/* --------------------------------------------------------------------------
   20.4.2  THE SECTION
   No min-height any more: the section is exactly as tall as the cards, the
   drop to the arrow (20.5) and the padding below it, so the arrow always
   lands the same distance up from the bottom of the photograph.
   z-index lets the raised cards and the hover panel paint over the sections
   either side.
   -------------------------------------------------------------------------- */
.l-section.careers-why.careers-why {
    position: relative;
    z-index: 1;
    overflow: visible;
}

.l-section.careers-why.careers-why > .l-section-h {
    padding-top: 0;
    padding-bottom: clamp(72px, 10vw, 190px);
}

/* --------------------------------------------------------------------------
   20.4.3  THE ROW
   The counter-reset that used to sit here is gone. The numbers are now set
   per card in 20.4.4, see the note there.
   -------------------------------------------------------------------------- */
.careers-why .why-cards-row.why-cards-row {
    position: relative;
    z-index: 2;
    display: flex;
    flex-wrap: nowrap;
    justify-content: center;
    align-items: stretch;
    gap: var(--why-gap);
    width: 100%;
    margin: calc(-1 * var(--why-lift)) 0 0;
    padding: 0;
    translate: none;
}

/* --------------------------------------------------------------------------
   20.4.4  THE CARD
   container-type makes the card the unit of measurement for its own type
   (20.4.5): the number and the copy are sized as a share of the card's
   width, so they fill it the same way on a 300px desktop card and a 230px
   laptop one.
   aspect-ratio is a floor, not a cage — a card whose copy runs long grows
   rather than clipping.
   --------------------------------------------------------------------------
   WHY THE NUMBERS ARE NOT A CSS COUNTER
   They used to be counter(why), reset on the row and incremented per card.
   WebKit (Safari, and every browser on iOS) gives a container style
   containment, which walls CSS counters off at the card's edge, so every
   card started a fresh count and showed 0. Chrome dropped that behaviour,
   which is why it only went wrong on phones.
   Each card now gets its number from its position as a custom property.
   Custom properties inherit normally and containment doesn't touch them.
   Nine are covered; a tenth card needs a tenth line.
   -------------------------------------------------------------------------- */
.careers-why .why-cards-row.why-cards-row > .why-cards.w-iconbox {
    --why-img: url("https://www.hec-precision.co.uk/wp-content/uploads/HEC-Photos-202658-2-scaled.jpg");
    --why-num: "";
    position: relative;
    isolation: isolate;
    container-type: inline-size;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: space-between;
    flex: 0 0 calc((100% - (var(--why-cols) - 1) * var(--why-gap)) / var(--why-cols));
    min-width: 0;
    max-width: none;
    /* auto, not a length: the old WHY CARDS block set min-height:350px,
       which overrode the square on any card narrower than 350px. auto puts
       the floor back to "just enough for the copy". */
    min-height: auto;
    max-height: none;
    aspect-ratio: var(--why-ratio);
    margin: 0;
    padding: clamp(18px, 1.5vw, 28px);
    background: var(--c-blue);
    border-radius: var(--c-radius);
    box-shadow: 0 24px 48px -24px rgb(0 0 0 / .7);
    overflow: clip;
    color: var(--c-ink);
    text-align: center;
}

.careers-why .why-cards-row.why-cards-row > .why-cards:nth-child(1) { --why-num: "1"; }
.careers-why .why-cards-row.why-cards-row > .why-cards:nth-child(2) { --why-num: "2"; }
.careers-why .why-cards-row.why-cards-row > .why-cards:nth-child(3) { --why-num: "3"; }
.careers-why .why-cards-row.why-cards-row > .why-cards:nth-child(4) { --why-num: "4"; }
.careers-why .why-cards-row.why-cards-row > .why-cards:nth-child(5) { --why-num: "5"; }
.careers-why .why-cards-row.why-cards-row > .why-cards:nth-child(6) { --why-num: "6"; }
.careers-why .why-cards-row.why-cards-row > .why-cards:nth-child(7) { --why-num: "7"; }
.careers-why .why-cards-row.why-cards-row > .why-cards:nth-child(8) { --why-num: "8"; }
.careers-why .why-cards-row.why-cards-row > .why-cards:nth-child(9) { --why-num: "9"; }


.careers-why .why-cards-row.why-cards-row > .why-cards.w-iconbox:nth-child(1) {
    --why-img: url("https://www.hec-precision.co.uk/wp-content/uploads/Box_1_5axis.jpg");
}
.careers-why .why-cards-row.why-cards-row > .why-cards.w-iconbox:nth-child(2) {
    --why-img: url("https://www.hec-precision.co.uk/wp-content/uploads/Box_2_B30A1970-scaled.jpg");
}
.careers-why .why-cards-row.why-cards-row > .why-cards.w-iconbox:nth-child(3) {
    --why-img: url("https://www.hec-precision.co.uk/wp-content/uploads/Box_3_HEC-Photos-202665-scaled.jpg");
}
.careers-why .why-cards-row.why-cards-row > .why-cards.w-iconbox:nth-child(4) {
    --why-img: url("https://www.hec-precision.co.uk/wp-content/uploads/Box_4_HEC-Photos-202630-scaled.jpg");
}
.careers-why .why-cards-row.why-cards-row > .why-cards.w-iconbox:nth-child(5) {
    --why-img: url("https://www.hec-precision.co.uk/wp-content/uploads/Box_5_HEC-Photos-202614-scaled.jpg");
}




.careers-why .why-cards .w-iconbox-icon {
    display: none;
}

/* --------------------------------------------------------------------------
   20.4.5  NUMBER AND COPY
   cqi is 1% of the card's width. The copy is 9.5% of it — roughly half as
   big again as before, which is what fills the empty middle of the card.
   Raise or lower that one number to taste; the clamp stops it running away
   on very wide or very narrow cards.
   Each font-size is written twice: the first is the fallback for browsers
   without container units, which ignore the second.
   The number is read from --why-num, set per card in 20.4.4.
   -------------------------------------------------------------------------- */
.careers-why .why-cards.why-cards::before {
    content: var(--why-num);
    position: relative;
    z-index: 1;
    display: block;
    flex: none;
    font-family: var(--h1-font-family, inherit);
    font-size: clamp(52px, 5.2vw, 100px);
    font-size: clamp(48px, 27cqi, 110px);
    font-weight: 300;
    line-height: .9;
    color: transparent;
    -webkit-text-fill-color: transparent;
    -webkit-text-stroke: 1.5px var(--c-ink);
    transition: opacity var(--c-speed) ease;
}

.careers-why .why-cards .w-iconbox-meta {
    position: relative;
    z-index: 1;
    width: 100%;
    margin: 0;
    padding: 0;
    transition: opacity var(--c-speed) ease;
}

.careers-why .why-cards .w-iconbox-title.w-iconbox-title {
    margin: 0;
    font-family: var(--font-family, inherit);
    font-size: clamp(16px, 1.6vw, 26px);
    font-size: clamp(16px, 9.5cqi, 30px);
    font-weight: 500;
    line-height: 1.25;
    color: var(--c-ink);
    text-wrap: balance;
	color: var(--color-grey);
}

/* --------------------------------------------------------------------------
   20.4.6  HOVER PHOTO
   Change the two opacity:0 values at the end to .15 to keep the copy
   readable over the photo instead of hiding it.
   -------------------------------------------------------------------------- */
.careers-why .why-cards.why-cards::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 0;
    background: var(--why-img) center / cover no-repeat;
    opacity: 0;
    scale: 1.06;
    transition:
        opacity var(--c-speed) ease,
        scale 800ms var(--c-ease);
    pointer-events: none;
}

@media (hover: hover) {
    .no-touch .careers-why .why-cards.why-cards:hover::after {
        opacity: 1;
        scale: 1;
    }

    .no-touch .careers-why .why-cards.why-cards:hover::before,
    .no-touch .careers-why .why-cards.why-cards:hover .w-iconbox-meta {
        opacity: 0;
    }
}

/* --------------------------------------------------------------------------
   20.4.7  CAROUSEL (1200px AND BELOW)
   REPLACES the previous swipe strip. Pairs with the WHY CARDS JS snippet,
   which adds the arrows, the counter and .is-current.
   Same approach as the story cards (20.6.8): the track bleeds to both
   screen edges and is padded by half the space left around one card, so
   the first and last cards can sit dead centre.
   The card width is now a set value rather than a share of the row, so the
   lift into the intro section is worked out from that instead.
   -------------------------------------------------------------------------- */
.careers-why .why-nav {
    display: none;
}

@media (max-width: 1200px) {
    .careers-intro,
    .careers-why {
        --why-card-w: min(40vw, 360px);
        --why-gap: 16px;
        --why-ratio: 1.15;
        --why-lift: calc(var(--why-card-w) / var(--why-ratio) / 2);
    }

    .careers-why .why-cards-row.why-cards-row {
        justify-content: flex-start;
        width: auto;
        margin-left: calc(-1 * var(--padding-inline, 24px));
        margin-right: calc(-1 * var(--padding-inline, 24px));
        padding: 0 calc((100% + 2 * var(--padding-inline, 24px) - var(--why-card-w)) / 2) 28px;
        overflow-x: auto;
        overscroll-behavior-x: contain;
        scroll-snap-type: x mandatory;
        scrollbar-width: none;
        overflow-anchor: none;
    }

    .careers-why .why-cards-row::-webkit-scrollbar {
        display: none;
    }

    .careers-why .why-cards-row.why-cards-row > .why-cards.w-iconbox {
        flex: 0 0 var(--why-card-w);
        scroll-snap-align: center;
        scroll-snap-stop: always;   /* one card per swipe */
        transition:
            opacity var(--c-speed) ease,
            scale var(--c-speed) var(--c-ease);
    }

    /* Only once the JS has marked the track, so without it nothing dims. */
    .careers-why .why-cards-row.is-carousel > .why-cards.w-iconbox:not(.is-current) {
        opacity: .4;
        scale: .94;
    }

    /* --- controls --------------------------------------------------------- */
    .careers-why .why-nav {
        position: relative;
        z-index: 2;
        display: flex;
        align-items: center;
        justify-content: center;
        gap: 20px;
        margin-top: 0;
    }

    .careers-why .why-nav .arrow-btn.arrow-btn.arrow-btn {
        --ab-size: 48px;
    }

    .careers-why .why-nav .arrow-btn.arrow-btn.arrow-btn:disabled {
        opacity: .3;
        cursor: default;
        pointer-events: none;
    }

    /* Sits on the photograph, so a soft shadow keeps it legible. */
    .careers-why .why-count {
        min-width: 3.5em;
        font-family: var(--font-family, inherit);
        font-size: 15px;
        font-variant-numeric: tabular-nums;
        text-align: center;
        color: #fff;
        text-shadow: 0 1px 6px rgb(0 0 0 / .6);
    }
}

@media (max-width: 900px) {
    .careers-intro,
    .careers-why {
        --why-card-w: min(56vw, 340px);
    }
}

@media (max-width: 600px) {
    .careers-intro,
    .careers-why {
        --why-card-w: min(76vw, 320px);
        --why-gap: 12px;
        --why-ratio: 1.1;
        --c-radius: 14px;
    }
}

@media (prefers-reduced-motion: reduce) {
    .careers-why .why-cards-row > .why-cards {
        transition-duration: 1ms;
    }
}

/* ==========================================================================
   20.5  WHY CTA — ARROW AND HOVER PANEL
   The blue arrow sits low on the photograph; hovering it slides a dark
   panel out to its right with the copy and a "Have a question?" button.
   --------------------------------------------------------------------------
   EDITOR SETUP (inside the careers-why column, after the cards)
   Horizontal Wrapper       -> why-cta
      Button (style 5)      -> why-cta-arrow
      Vertical Wrapper      -> why-cta-panel
         Text block         -> why-cta-text
         Button (style 6)   -> white-button why-cta-btn
   --------------------------------------------------------------------------
   WHY IT IS IN FLOW NOW
   The first version positioned the arrow absolutely against the section. On
   the live page something between the section and the button is also
   positioned, so the arrow anchored to the column instead and landed on
   top of card 4. In normal flow there is no containing block to go wrong:
   the arrow simply sits --cta-drop below the cards, and the section's
   bottom padding (20.4.2) sets how much photo shows beneath it.
   ========================================================================== */

/* --------------------------------------------------------------------------
   20.5.1  POSITION
   --cta-x   how far across the arrow sits. The max()/min() pair stops the
             open panel running past the right edge on narrower screens —
             the arrow slides left as far as it needs to, and no further.
   --cta-drop  gap between the bottom of the cards and the top of the arrow.
   -------------------------------------------------------------------------- */
.careers-why .why-cta.why-cta {
    --cta-arrow: clamp(52px, 4.4vw, 72px);
    /* Clearance between the arrow and the panel. It has to clear the
       arrow's hover ring, which sits 8px outside the button — at the old
       12–20px the ring was all but touching the panel. */
    --cta-gap: clamp(26px, 2.2vw, 40px);
    --cta-w: clamp(360px, 30vw, 520px);
    --cta-x: 52%;
    --cta-drop: clamp(160px, 22vw, 440px);
    position: relative;
    z-index: 3;
    display: flex;
    flex-wrap: nowrap;
    align-items: flex-start;
    gap: 0;
    width: fit-content;
    margin: var(--cta-drop) 0 0
        max(0px, min(var(--cta-x), 100% - var(--cta-arrow) - var(--cta-gap) - var(--cta-w)));
    padding: 0;
}

.careers-why .why-cta.why-cta > * {
    margin: 0;
}

/* --------------------------------------------------------------------------
   20.5.2  THE ARROW
   An arrow-btn from 3.0 with a thinner, darker glyph to match the design.
   Five classes clear 3.3's own (0,4,0) chains.
   -------------------------------------------------------------------------- */
.careers-why .why-cta .w-btn-wrapper:has(.why-cta-arrow) {
    flex: none;
    margin: 0;
}

.careers-why .why-cta-arrow.why-cta-arrow.why-cta-arrow.why-cta-arrow {
    --ab-size: var(--cta-arrow);
    --ab-ink: #222;
    --ab-radius: 18%;
    --ab-glyph-size: 64%;
    --ab-glyph: url("https://www.hec-precision.co.uk/wp-content/uploads/ARROW-RIGHT-PLAIN.svg");
}

/* --------------------------------------------------------------------------
   20.5.3  THE PANEL
   Absolutely positioned against the CTA wrapper, top-aligned with the arrow
   and one gap to its right. Out of flow, so it can hang past the bottom of
   the photograph into the next section, as in the design.
   Hidden with visibility as well as opacity, so an invisible panel can't
   catch the pointer and open itself.
   -------------------------------------------------------------------------- */
.careers-why .why-cta .why-cta-panel.why-cta-panel {
    /* Vertical nudge against the arrow's top edge. Negative moves it up.
       Only used by the hover pop-out (above 1200px); the in-flow layout in
       20.5.5 ignores it. */
    --cta-panel-y: -10px;
    position: absolute;
    top: var(--cta-panel-y);
    left: calc(100% + var(--cta-gap));
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: clamp(24px, 2.4vw, 44px);
    width: var(--cta-w);
    margin: 0;
    padding: clamp(28px, 2.6vw, 48px);
    background: var(--c-panel);
    border-radius: 20px;
    box-shadow: 0 30px 60px -30px rgb(0 0 0 / .85);
    opacity: 0;
    visibility: hidden;
    translate: -14px 0;
    pointer-events: none;
    transition:
        opacity 220ms ease,
        translate var(--c-speed) var(--c-ease),
        visibility 0s linear var(--c-speed);
}

.careers-why .why-cta-panel.why-cta-panel > * {
    margin: 0;
}

/* Invisible bridge across the gap, so moving from the arrow to the panel
   doesn't close it on the way. */
.careers-why .why-cta-panel.why-cta-panel::before {
    content: "";
    position: absolute;
    top: 0;
    bottom: 0;
    right: 100%;
    width: calc(var(--cta-gap) + 2px);
}

.careers-why .why-cta-text p {
    margin: 0 0 .9em;
    font-family: var(--font-family, inherit);
    font-size: clamp(16px, 1.2vw, 22px);
    font-weight: 400;
    line-height: 1.45;
    color: var(--c-ink);
}

.careers-why .why-cta-text p:last-child {
    margin-bottom: 0;
}

.careers-why .why-cta-text strong {
    font-weight: 700;
}

/* White outline, blue label, fills blue on hover (the hover comes from 1.5).
   The !important is Impreza's color:#fff !important on the button style. */
.white-button.white-button.white-button.white-button.why-cta-btn {
    --wb-pad-y: .8em;
    --wb-pad-x: 1.8em;
    --wb-pad-x-hover: 2.6em;
    font-size: clamp(16px, 1.3vw, 22px);
    color: var(--c-blue, #00bfff) !important;
}

/* --------------------------------------------------------------------------
   20.5.4  THE REVEAL
   :hover on the WRAPPER, so the panel stays open while the pointer is on
   it — it is a child of the wrapper, even though it sits outside its box.
   :focus-within opens it for keyboard users tabbing to the arrow.
   -------------------------------------------------------------------------- */
@media (hover: hover) and (min-width: 1201px) {
    .careers-why .why-cta:hover .why-cta-panel.why-cta-panel {
        opacity: 1;
        visibility: visible;
        translate: none;
        pointer-events: auto;
        transition:
            opacity 260ms ease 40ms,
            translate var(--c-speed) var(--c-ease),
            visibility 0s;
    }

    /* The arrow keeps its hover ring while the pointer is on the panel, so
       the two read as one object. */
    .no-touch .careers-why .why-cta:hover .why-cta-arrow.arrow-btn.arrow-btn.arrow-btn::after {
        opacity: 1;
        transform: scale(1);
    }
}

.careers-why .why-cta:focus-within .why-cta-panel.why-cta-panel {
    opacity: 1;
    visibility: visible;
    translate: none;
    pointer-events: auto;
    transition:
        opacity 260ms ease,
        translate var(--c-speed) var(--c-ease),
        visibility 0s;
}

/* --------------------------------------------------------------------------
   20.5.5  TABLET, TOUCH AND MOBILE
   At 1200px and below the panel is simply shown, in flow, beside the arrow,
   so it sits on the photograph. As a hover pop-out it hangs off the bottom
   of the photo, and on anything narrower than a laptop there isn't enough
   gap before the next section — it landed on the Employee stories lead.
   Touch screens get this layout at every width, since they can't hover.
   Raise 1200px to push the in-flow layout further up the size range.
   -------------------------------------------------------------------------- */
@media (max-width: 1200px), (hover: none) {
    .careers-why .why-cta .why-cta-panel.why-cta-panel {
        position: static;
        flex: 0 1 var(--cta-w);
        min-width: 0;
        width: auto;
        opacity: 1;
        visibility: visible;
        translate: none;
        pointer-events: auto;
    }

    .careers-why .why-cta-panel.why-cta-panel::before {
        content: none;
    }

    .careers-why .why-cta.why-cta {
        gap: var(--cta-gap);
    }
}

/* More photo between the cards and the panel. At the old 18vw the panel
   landed almost on the cards and the photograph all but disappeared. */
@media (max-width: 900px) {
    .careers-why .why-cta.why-cta {
        --cta-drop: clamp(150px, 34vw, 280px);
        --cta-w: 460px;
        margin-left: 0;
    }

    .l-section.careers-why.careers-why > .l-section-h {
        padding-bottom: clamp(48px, 8vw, 72px);
    }
}

@media (max-width: 600px) {
    .careers-why .why-cta.why-cta {
        --cta-arrow: 44px;
        --cta-gap: 16px;
    }

    .careers-why .why-cta .why-cta-panel.why-cta-panel {
        gap: 22px;
        padding: 22px;
        border-radius: var(--c-radius);
    }
}


/* ==========================================================================
   20.6  STORY CARDS — EMPLOYEE STORIES AND APPRENTICESHIPS
   One component, two sections. Portrait photo with a dark band across its
   foot holding the role and name, and a blue arrow sitting on the band's
   top edge. Hover (or tap) dims the whole photo, the band and arrow fade,
   and the bio grows in underneath the name, pushing it up the card.
   --------------------------------------------------------------------------
   EDITOR SETUP
   Section                  -> careers-sec careers-stories  (or careers-appr)
      Horizontal Wrapper    -> story-row
         Vertical Wrapper   -> story-card        (one per person)
            Image           -> story-media
            Text (P)        -> story-role
            Text (H3)       -> story-name
            Text block      -> story-bio
   The order inside the card matters only for reading order; the layout is
   placed by grid area, not by position.
   --------------------------------------------------------------------------
   HOW THE OVERLAY IS LAID OUT
   The photo is pinned behind everything, filling the card. On top of it the
   card is a four-row grid: empty space, role, name, bio. Row 1 takes
   whatever height is left, so as the bio opens from nothing the role and
   name are pushed up the card with it. No extra wrapper needed — WordPress
   can't nest a Vertical Wrapper inside another.
   The arrow is drawn by CSS on the role, so it needs nothing in the editor.
   ========================================================================== */

/* --------------------------------------------------------------------------
   20.6.1  SECTION SETTINGS
   The only differences between the two sections.
     --story-cols    cards per row on desktop
     --story-ratio   card shape, width / height
     --story-name    name size, as a share of the card's width
     --story-card-w  card width in the tablet / mobile carousel
   -------------------------------------------------------------------------- */
.careers-stories {
    --story-cols: 3;
    --story-ratio: 5 / 8;
    --story-name: 9.5cqi;
    --story-card-w: min(74vw, 400px);
}

.careers-appr {
    --story-cols: 2;
    --story-ratio: 15 / 16;
    --story-name: 7.4cqi;
    --story-card-w: min(84vw, 560px);
}

/* --------------------------------------------------------------------------
   20.6.2  THE ROW
   align-items:start, so an opening card that grows (a long bio on a small
   card) grows alone rather than stretching its neighbours with it.
   -------------------------------------------------------------------------- */
.careers-sec .story-row.story-row {
    display: grid;
    grid-template-columns: repeat(var(--story-cols, 3), minmax(0, 1fr));
    align-items: start;
    gap: clamp(16px, 1.6vw, 32px);
    width: 100%;
    margin: 0;
    padding: 0;
}

.careers-sec .story-row.story-row > * {
    margin: 0;
}

/* --------------------------------------------------------------------------
   20.6.3  THE CARD
   --so is the open state as a number, 0 or 1. Every fade in the card reads
   it, so opening a card is one variable changing (20.6.7) rather than a
   rule per layer. The fades still animate — each layer transitions its own
   opacity as the number underneath it changes.
   The spacing variables are in cqi — 1% of the card's width — so the card
   keeps its proportions from a 260px phone card to an 800px desktop one.
   --------------------------------------------------------------------------
   THE CARD NEVER CHANGES HEIGHT
   min-height:0 makes the aspect-ratio a fixed shape rather than a floor.
   Without it, a bio too long for the card made the card grow on hover —
   the row grew, everything below moved down, and the browser shifted the
   scroll position to compensate, which read as the page scrolling. It only
   happened on the first card of each row because those carry the long bios.
   The bio's row is minmax(0, max-content): it takes as much room as its
   copy needs, up to whatever is left once the role and name are placed.
   Past that it scrolls inside the card (20.6.6).
   --------------------------------------------------------------------------
   overflow-anchor: none — THE PAGE-JUMP FIX
   When anything on a page changes, the browser picks the first visible
   element as a scroll "anchor" and moves the page to hold it still. Opening
   a card pushes its role and name up the card; if the anchor was inside
   the card, the whole page scrolled to follow the name. The first card's
   text comes first in the page, so it was nearly always the one chosen —
   which is why only card one did it, and why it was worst on a phone, where
   the card fills most of the screen. This takes the cards out of the
   running; the browser anchors on something that isn't moving instead.
   -------------------------------------------------------------------------- */
.careers-sec .story-card.story-card {
    --so: 0;
    --sx: clamp(18px, 7cqi, 48px);          /* inset from the card's sides   */
    --sy: clamp(14px, 5cqi, 32px);          /* band padding, top and bottom */
    --sa: clamp(40px, 15cqi, 64px);         /* arrow size                    */
    position: relative;
    isolation: isolate;
    container-type: inline-size;
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: minmax(0, 1fr) auto auto minmax(0, max-content);
    gap: 0;
    min-width: 0;
    min-height: 0;
    aspect-ratio: var(--story-ratio, 5 / 8);
    margin: 0;
    padding: 0;
    border: 1px solid rgb(255 255 255 / .16);
    border-radius: 18px;
    background: #222;
    overflow: clip;
    color: var(--c-ink);
    cursor: pointer;
    overflow-anchor: none;
}

.careers-sec .story-card.story-card > * {
    margin: 0;
}

.careers-sec .story-card:focus-visible {
    outline: 2px solid var(--c-blue);
    outline-offset: 4px;
}

/* --------------------------------------------------------------------------
   20.6.4  PHOTO AND SHADE
   --------------------------------------------------------------------------
   THE PHOTO
   Taken out of the grid altogether and pinned to all four edges of the card,
   so it fills the background whatever shape the upload is. The previous
   version placed it in the grid and relied on the <img> being absolutely
   positioned inside Impreza's image wrapper; on the live page something in
   the theme won that fight, and the photo drew at its own square shape with
   the card's dark background showing underneath.
   The !important declarations are there to win that fight outright. Also
   check the Image element's own "Aspect Ratio" setting is left on Original:
   a ratio set there adds sizing of its own to the wrapper.
   -------------------------------------------------------------------------- */
.careers-sec .story-card .story-media.story-media {
    position: absolute !important;
    inset: 0;
    z-index: 0;
    width: 100% !important;
    height: 100% !important;
    max-width: none;
    margin: 0;
}

.careers-sec .story-card .story-media .w-image-h {
    position: absolute !important;
    inset: 0;
    display: block;
    width: 100% !important;
    height: 100% !important;
    aspect-ratio: auto !important;
}

.careers-sec .story-card .story-media img {
    position: absolute !important;
    inset: 0;
    display: block;
    width: 100% !important;
    height: 100% !important;
    max-width: none !important;
    max-height: none !important;
    aspect-ratio: auto !important;
    object-fit: cover;
    object-position: center 22%;
    scale: calc(1 + var(--so) * .04);
    transition: scale 800ms var(--c-ease);
}

/* --------------------------------------------------------------------------
   THE SHADE
   One translucent grey layer does both jobs. At rest it is the band behind
   the role and name: it covers rows 2 to the bottom of the card, so it
   always reaches the foot and grows with the bio.
   On open, a box-shadow of the same colour spreads out from it until it
   covers the whole photo, so the grey visibly rises up the card rather than
   fading in on the spot. A box-shadow is only drawn outside its box, so
   band and shadow never overlap — the grey is one even tint top to bottom.
   The card's overflow:clip crops the spread at its edges.
   The spread is written twice: in vh as a fallback, then in cqi so it
   scales with the card instead of the screen.
   --story-shade is the one colour to change: raise the last number for a
   darker band, lower it to show more of the photo through it.
   -------------------------------------------------------------------------- */
.careers-sec .story-card.story-card {
    --story-shade: rgb(45 45 45 / .72);
}

.careers-sec .story-card.story-card::before {
    content: "";
    grid-area: 2 / 1 / -1 / -1;
    z-index: 1;
    background: var(--story-shade);
    box-shadow: 0 0 0 calc(var(--so) * 150vh) var(--story-shade);
    box-shadow: 0 0 0 calc(var(--so) * 170cqi) var(--story-shade);
    transition: box-shadow 640ms cubic-bezier(.45, 0, .2, 1);
    pointer-events: none;
}

/* The old full-card shade is no longer needed. */
.careers-sec .story-card.story-card::after {
    content: none;
}

/* --------------------------------------------------------------------------
   20.6.5  ROLE, ARROW AND NAME
   The arrow hangs off the role's top edge, which is also the band's top
   edge, and translate centres it on that line. The role reserves room on
   the right so a long job title wraps before it reaches the arrow.
   -------------------------------------------------------------------------- */
.careers-sec .story-card .story-role.story-role {
    grid-area: 2 / 1;
    position: relative;
    z-index: 2;
    padding: var(--sy) calc(var(--sx) + var(--sa) + 12px) 0 var(--sx);
    font-family: var(--font-family, inherit);
    font-size: clamp(14px, 4.3cqi, 19px);
    font-weight: 700;
    line-height: 1.25;
    color: var(--c-blue);
}

.careers-sec .story-card .story-role.story-role::after {
    content: "";
    position: absolute;
    top: 0;
    right: var(--sx);
    width: var(--sa);
    aspect-ratio: 1;
    border-radius: 20%;
    background:
        url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='%23111'%20stroke-width='1.5'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cpath%20d='M19%2012H5'/%3E%3Cpath%20d='M11%206l-6%206%206%206'/%3E%3C/svg%3E")
            center / 48% no-repeat,
        var(--c-blue);
    translate: 0 -50%;
    opacity: calc(1 - var(--so));
    scale: calc(1 - var(--so) * .15);
    transition:
        opacity 260ms ease,
        scale var(--c-speed) var(--c-ease);
}

.careers-sec .story-card .story-name.story-name {
    grid-area: 3 / 1;
    position: relative;
    z-index: 2;
    padding: .12em var(--sx) var(--sy);
    font-family: var(--c-face-light, inherit);
    font-size: clamp(24px, 6vw, 44px);
    font-size: clamp(24px, var(--story-name, 9.5cqi), 52px);
    font-weight: 100;
    line-height: 1.1;
    letter-spacing: 0;
    color: var(--c-ink);
}

.careers-sec .story-card :is(.story-role, .story-name) :is(.w-text-h, .w-text-value) {
    color: inherit;
    font-weight: inherit;
}

/* --------------------------------------------------------------------------
   20.6.6  BIO
   The 0fr-to-1fr trick: the text block is a one-row grid whose row animates
   from nothing to its natural height, so the bio grows in without anyone
   having to know how long it is. The padding lives on the inner wrapper so
   it collapses with it.
   -------------------------------------------------------------------------- */
.careers-sec .story-card .story-bio.story-bio {
    grid-area: 4 / 1;
    position: relative;
    z-index: 2;
    display: grid;
    grid-template-rows: 0fr;
    opacity: var(--so);
    transition:
        grid-template-rows 560ms var(--c-ease),
        opacity 320ms ease;
}

/* Side padding only. Bottom padding here left a dark strip under the band
   when closed: a box can never be shorter than its own padding, so 0fr
   couldn't collapse it. The space below the bio is the last paragraph's
   margin instead, which sits inside the clipped box and folds away with it. */
.careers-sec .story-card .story-bio > .wpb_wrapper {
    min-height: 0;
    overflow-x: hidden;
    overflow-y: auto;
    /* Vertical scroll chains to the page once the bio reaches its end;
       sideways stays put so a swipe in the mobile strip moves the strip. */
    overscroll-behavior-x: contain;
    padding: 0 var(--sx);
    /* Scrollbar hidden: it would otherwise flash on every card while the
       bio animates open. Wheel, trackpad and touch all still scroll it. */
    scrollbar-width: none;
}

.careers-sec .story-card .story-bio > .wpb_wrapper::-webkit-scrollbar {
    display: none;
}

.careers-sec .story-card .story-bio p {
    margin: 0 0 .9em;
    font-family: var(--font-family, inherit);
    font-size: clamp(14px, 3.9cqi, 17px);
    font-weight: 400;
    line-height: 1.5;
    color: rgb(255 255 255 / .92);
}

.careers-sec .story-card .story-bio p:first-child {
    margin-top: clamp(10px, 3.5cqi, 22px);
}

.careers-sec .story-card .story-bio p:last-child {
    margin-bottom: clamp(22px, 8cqi, 56px);
}

/* --------------------------------------------------------------------------
   20.6.7  OPEN STATE
   Three ways in, one result:
     hover          mouse devices
     .is-open       added by the STORY CARDS snippet on tap
     :focus-visible keyboard — the snippet makes each card focusable
   And a fallback: on a touch screen with the snippet missing, every card is
   shown open, so the bios are never unreachable.
   -------------------------------------------------------------------------- */
.careers-sec .story-card.story-card:is(.is-open, :focus-visible) {
    --so: 1;
}

.careers-sec .story-card:is(.is-open, :focus-visible) .story-bio.story-bio {
    grid-template-rows: 1fr;
}

@media (hover: hover) {
    .no-touch .careers-sec .story-card.story-card:hover {
        --so: 1;
    }

    .no-touch .careers-sec .story-card:hover .story-bio.story-bio {
        grid-template-rows: 1fr;
    }
}

@media (hover: none) {
    html:not(.story-js) .careers-sec .story-card.story-card {
        --so: 1;
    }

    html:not(.story-js) .careers-sec .story-card .story-bio.story-bio {
        grid-template-rows: 1fr;
    }
}

/* --------------------------------------------------------------------------
   20.6.8  CAROUSEL (900px AND BELOW)
   One card centred, the neighbours peeking in at either side, dimmed. Swipe
   still works — it is a real scroll track with snap points — and the arrows
   in 20.6.9 step through it one card at a time.
   --------------------------------------------------------------------------
   CENTRING THE FIRST AND LAST CARDS
   A snap point can only centre a card if there is room either side of it,
   so the track is padded by half the space left over around one card:
       (track width − card width) / 2
   The track bleeds out to both screen edges (the negative margins), so its
   width is the column plus both gutters — which is what the calc adds back.
   width:auto is load-bearing: with the desktop width:100% still in place,
   the negative margins would shift the track instead of widening it.
   --------------------------------------------------------------------------
   The dimming only applies once the JS has marked the track .is-carousel,
   so without the script every card stays at full strength.
   -------------------------------------------------------------------------- */
@media (max-width: 900px) {
    .careers-sec .story-row.story-row {
        display: flex;
        align-items: flex-start;
        gap: 14px;
        width: auto;
        margin-left: calc(-1 * var(--padding-inline, 24px));
        margin-right: calc(-1 * var(--padding-inline, 24px));
        padding: 0 calc((100% + 2 * var(--padding-inline, 24px) - var(--story-card-w)) / 2);
        overflow-x: auto;
        overscroll-behavior-x: contain;
        scroll-snap-type: x mandatory;
        scrollbar-width: none;
        overflow-anchor: none;
    }

    .careers-sec .story-row::-webkit-scrollbar {
        display: none;
    }

    .careers-sec .story-row.story-row > .story-card {
        flex: 0 0 var(--story-card-w);
        scroll-snap-align: center;
        scroll-snap-stop: always;   /* one card per swipe, never skip two */
        transition:
            opacity var(--c-speed) ease,
            scale var(--c-speed) var(--c-ease);
    }

    .careers-sec .story-row.is-carousel > .story-card:not(.is-current) {
        opacity: .4;
        scale: .94;
    }
}

@media (max-width: 600px) {
    .careers-stories {
        --story-card-w: min(78vw, 400px);
    }

    .careers-appr {
        --story-card-w: min(86vw, 560px);
    }

    .careers-sec .story-row.story-row {
        gap: 10px;
    }

    .careers-sec .story-card.story-card {
        border-radius: var(--c-radius);
    }
}

/* --------------------------------------------------------------------------
   20.6.9  CAROUSEL CONTROLS
   Built by the STORY CARDS snippet and placed straight after each track:
       [ ← ]   2 / 3   [ → ]
   The two buttons are arrow-btn from 3.0, so they match every other arrow
   on the site. Hidden above 900px, where all the cards are on screen.
   -------------------------------------------------------------------------- */
.careers-sec .story-nav {
    display: none;
}

@media (max-width: 900px) {
    .careers-sec .story-nav {
        display: flex;
        align-items: center;
        justify-content: center;
        gap: 20px;
        margin-top: 24px;
    }

    .careers-sec .story-nav .arrow-btn.arrow-btn.arrow-btn {
        --ab-size: 48px;
    }

    .careers-sec .story-nav .arrow-btn.arrow-btn.arrow-btn:disabled {
        opacity: .3;
        cursor: default;
        pointer-events: none;
    }

    .careers-sec .story-count {
        min-width: 3.5em;
        font-family: var(--font-family, inherit);
        font-size: 15px;
        font-variant-numeric: tabular-nums;
        text-align: center;
        color: var(--c-ink-soft);
    }
}

/* ==========================================================================
   20.7  CURRENT VACANCIES — POST LIST
   The vacancies Post List (Grid Layout 1938), styled to match the static
   cards it replaced: blue outline, blue title, soft copy, small white
   "Apply now" pill pinned to the foot of the card.
   --------------------------------------------------------------------------
   MARKUP (per vacancy)
   .w-grid-item > .w-grid-item-h > .w-vwrapper
       h2.post_title > a            the job title
       .post_custom_field           the description (hero_description)
       a.w-btn.white-button         Apply now, with an arrow icon
   --------------------------------------------------------------------------
   WHY grid-template-columns IS SET HERE AND NOT --columns
   Impreza writes #us_post_list_xxxx { --columns: 2 !important } into the
   page for tablets, as an ID rule — no class selector can outrank it. So
   the column count is set on the track itself instead, which the ID rule
   doesn't touch. The Post List's own column settings are ignored on this
   page as a result; change the counts below.
   --------------------------------------------------------------------------
   THE !important ON THE COLOURS
   Grid Layout element colours are written by Impreza as
   .layout_xxxx .usg_... { color: ... !important }. Equal weight plus
   !important is the only way past them. Clear the colours in the Grid
   Layout editor and these can come off.
   ========================================================================== */
.careers-vac.careers-vac .w-grid.type_grid .w-grid-list {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    align-items: stretch;
    gap: clamp(16px, 1.4vw, 24px);
    width: 100%;
    margin: 0;
}

.careers-vac .w-grid .w-grid-item {
    width: auto;
    max-width: none;
    min-width: 0;
    margin: 0;
    padding: 0;
}

/* --- the card ------------------------------------------------------------- */
.careers-vac .w-grid .w-grid-item-h {
    display: flex;
    flex-direction: column;
    height: 100%;
    min-height: clamp(300px, 23vw, 400px);
    padding: clamp(22px, 1.8vw, 32px);
    border: 1px solid var(--c-blue);
    border-radius: var(--c-radius);
    background: rgb(255 255 255 / .02);
}

/* The vwrapper fills the card, so the button can be pushed to its foot. */
.careers-vac .w-grid .w-grid-item-h > .w-vwrapper.w-vwrapper {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    flex: 1 1 auto;
    gap: 0;
    width: 100%;
    margin: 0;
}

.careers-vac .w-grid .w-grid-item-h > .w-vwrapper > * {
    margin: 0;
}

/* --- title ---------------------------------------------------------------- */
.careers-vac .w-grid .post_title.post_title {
    margin: 0 0 14px;
    font-size: clamp(18px, 1.25vw, 22px);
    font-weight: 700;
    line-height: 1.25;
    letter-spacing: 0;
    color: var(--c-blue) !important;
    text-wrap: balance;
}

.careers-vac .w-grid .post_title a {
    color: inherit !important;
    text-decoration: none;
}

.careers-vac .w-grid .post_title a:hover,
.careers-vac .w-grid .post_title a:focus-visible {
    text-decoration: underline;
    text-underline-offset: .18em;
}

/* --- description -----------------------------------------------------------
   Clamped to five lines so a long description can't make one card taller
   than the rest of its row. The full text is on the vacancy page. Raise or
   lower the number to taste; delete the three clamp lines to show it all.
   -------------------------------------------------------------------------- */
.careers-vac .w-grid .post_custom_field.post_custom_field {
    margin: 0 0 24px;
    font-family: var(--font-family, inherit);
    font-size: clamp(14px, .95vw, 16px);
    font-weight: 400;
    line-height: 1.55;
    color: var(--c-ink-soft) !important;
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 5;
    overflow: hidden;
}

.careers-vac .w-grid .post_custom_field .w-post-elm-value {
    color: inherit;
}

/* --- Apply now -------------------------------------------------------------
   The white pill from 1.5 at a smaller size, pinned to the card's foot.
   Six classes clear 1.5's four-deep chain.
   -------------------------------------------------------------------------- */
.careers-vac .w-grid-item .white-button.white-button.white-button.white-button {
    --wb-pad-y: .55em;
    --wb-pad-x: 1.2em;
    --wb-pad-x-hover: 1.8em;
    gap: .6em;
    margin-top: auto;
    align-self: flex-start;
    font-size: 14px;
}

.careers-vac .w-grid-item .white-button i {
    font-size: .85em;
    line-height: 1;
    transition: translate var(--c-speed) var(--c-ease);
}

.no-touch .careers-vac .w-grid-item .white-button:hover i {
    translate: 3px 0;
}

/* --- load more -------------------------------------------------------------
   Only appears when there are more vacancies than the Post List shows per
   page. Set its button to Style 6 in the Post List's Pagination settings
   and it becomes the same small white pill as the old "See more" button.
   -------------------------------------------------------------------------- */
.careers-vac .w-grid .g-loadmore {
    display: flex;
    justify-content: center;
    margin-top: clamp(28px, 3vw, 52px);
}

.careers-vac .w-grid .g-loadmore.hidden {
    display: none;
}

.careers-vac .g-loadmore .white-button.white-button.white-button.white-button {
    --wb-ink: var(--color-blue, #00bfff);
    --wb-pad-y: .55em;
    --wb-pad-x: 1.4em;
    --wb-pad-x-hover: 2.2em;
    font-size: 14px;
    color: var(--wb-ink) !important;
}

/* --- responsive ------------------------------------------------------------ */
@media (max-width: 1100px) {
    .careers-vac.careers-vac .w-grid.type_grid .w-grid-list {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    /* The 300px floor was sized for four across. Two across it left each
       card half empty; paired cards still match, since grid items stretch
       to the taller one. */
    .careers-vac .w-grid .w-grid-item-h {
        min-height: 0;
    }

    .careers-vac .w-grid .post_custom_field.post_custom_field {
        margin-bottom: 28px;
    }
}

@media (max-width: 600px) {
    .careers-vac.careers-vac .w-grid.type_grid .w-grid-list {
        grid-template-columns: minmax(0, 1fr);
    }
}


/* ==========================================================================
   20.8  TESTIMONIALS
   Heading column left, the 5.11 carousel right, bleeding off the right edge
   so the third card is cut by the screen as in the design. Only
   --tc-visible and --tc-peek change; everything else is 5.11 untouched.
   ========================================================================== */
.careers-testi {
    --testi-bleed: calc(
        (100vw - min(100vw - 2 * var(--padding-inline, 2.5rem), var(--site-content-width, 1600px))) / 2
    );
}

.l-section.careers-testi.careers-testi {
    overflow: clip;
}

.l-section.careers-testi.careers-testi > .l-section-h {
    overflow: visible;
}

/* --------------------------------------------------------------------------
   THE ROW AND ITS TWO COLUMNS
   Found by what they CONTAIN rather than by class: the row is whichever set
   of columns holds the carousel, the heading column is the one that
   doesn't. The first version keyed off testi-row / testi-head, and on the
   live page the row was never stacking at tablet size — the heading was
   squeezed into a quarter-width column, one word per line. This works
   whether the row came from the supplied shortcode or was copied from the
   homepage.
   -------------------------------------------------------------------------- */
.careers-testi .g-cols:has(.testimonial-cards) {
    align-items: flex-start;
}

.careers-testi .g-cols:has(.testimonial-cards) > .wpb_column:not(:has(.testimonial-cards)) :is(p, h2, h3).w-text:first-child {
    margin: 0 0 clamp(8px, .8vw, 14px);
    font-family: var(--c-face-light, inherit);
    font-size: clamp(20px, 1.7vw, 32px);
    font-weight: 400;
    line-height: 1.2;
    color: var(--c-blue);
}

.careers-testi .g-cols:has(.testimonial-cards) > .wpb_column:not(:has(.testimonial-cards)) :is(h2, h3).w-text:not(:first-child) {
    max-width: 11em;
    margin: 0;
    font-family: var(--c-face-light, inherit);
    font-size: clamp(26px, 2.5vw, 50px);
    font-weight: 300;
    line-height: 1.2;
    color: var(--c-ink);
    text-wrap: balance;
}

.careers-testi .g-cols:has(.testimonial-cards) > .wpb_column:not(:has(.testimonial-cards)) :is(.w-text-h, .w-text-value) {
    color: inherit;
    font-weight: inherit;
}

.careers-testi .testimonial-cards.testimonial-cards.testimonial-cards {
    --tc-visible: 2.6;
    --tc-peek: 0px;
    margin-right: calc(-1 * var(--testi-bleed));
}

/* --------------------------------------------------------------------------
   THE ARROW
   Centred on the page as in the design. Flex rather than text-align, so it
   centres whether Impreza has made the wrapper block or inline-block, and
   whichever column it was dropped into.
   -------------------------------------------------------------------------- */
.careers-testi .w-btn-wrapper.w-btn-wrapper:has(.tc-next) {
    display: flex;
    justify-content: center;
    width: 100%;
    margin: clamp(8px, 1.5vw, 24px) 0 0;
}

@media (max-width: 1320px) {
    .careers-testi .testimonial-cards.testimonial-cards.testimonial-cards {
        --tc-visible: 2.25;
    }
}

/* Stacked: heading above, carousel full width below. The column selectors
   are long so they clear Impreza's own stacking rule at (0,5,0). */
@media (max-width: 1100px) {
    .careers-testi .g-cols.g-cols:has(.testimonial-cards) {
        display: flex;
        flex-direction: column;
        flex-wrap: nowrap;
    }

    .careers-testi .g-cols.g-cols:has(.testimonial-cards) > .wpb_column.wpb_column {
        width: 100%;
        max-width: 100%;
        margin: 0;
    }

    .careers-testi .g-cols.g-cols:has(.testimonial-cards) > .wpb_column.wpb_column:not(:has(.testimonial-cards)) {
        margin-bottom: clamp(20px, 3vw, 32px);
    }

    .careers-testi .g-cols:has(.testimonial-cards) > .wpb_column:not(:has(.testimonial-cards)) :is(h2, h3).w-text:not(:first-child) {
        max-width: 18em;
    }

    .careers-testi .testimonial-cards.testimonial-cards.testimonial-cards {
        --tc-visible: 2.2;
    }
}

@media (max-width: 900px) {
    .careers-testi .testimonial-cards.testimonial-cards.testimonial-cards {
        --tc-visible: 1.6;
        --tc-gap: 1rem;
    }
}

@media (max-width: 600px) {
    .careers-testi .testimonial-cards.testimonial-cards.testimonial-cards {
        --tc-visible: 1.15;
    }
}


/* ==========================================================================
   20.9  SUPPLIER BAND
   The band itself is 5.12; only the spacing is set here.
   ========================================================================== */
.l-section.careers-supplier.careers-supplier > .l-section-h {
    padding-top: 0;
}


/* ==========================================================================
   20.10  WHITE BUTTON SIZE VARIANTS — FIX
   The -sm, -lg and -right variants in 1.5 are (0,2,0) against the base's
   (0,4,0), so they never took effect. Five repeats, so they finally win.
   ========================================================================== */
.white-button-sm.white-button-sm.white-button-sm.white-button-sm.white-button-sm {
    --wb-pad-y: .5em;
    --wb-pad-x: 1.15em;
    --wb-pad-x-hover: 1.9em;
    font-size: 14px;
}

.white-button-lg.white-button-lg.white-button-lg.white-button-lg.white-button-lg {
    --wb-pad-y: .85em;
    --wb-pad-x: 2em;
    --wb-pad-x-hover: 3.2em;
    font-size: 18px;
}

.white-button-right.white-button-right.white-button-right.white-button-right.white-button-right {
    display: flex;
    margin-left: auto;
    margin-right: 0;
}

.white-button.white-button.white-button.white-button.vac-apply {
    --wb-pad-y: .55em;
    --wb-pad-x: 1.2em;
    --wb-pad-x-hover: 1.8em;
    font-size: 14px;
}


/* ==========================================================================
   20.11  REDUCED MOTION
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
    .careers-why .why-cards::before,
    .careers-why .why-cards::after,
    .careers-why .why-cards .w-iconbox-meta,
    .careers-why .why-cta .why-cta-panel,
    .careers-sec .story-card::before,
    .careers-sec .story-card img,
    .careers-sec .story-card .story-role::after,
    .careers-sec .story-card .story-bio,
    .careers-sec .story-row > .story-card {
        transition-duration: 1ms;
    }
}


/* ==========================================================================
   20.12  FOOTER AT TABLET SIZE (SITE-WIDE)
   This is the global footer, so it fixes every page — move it into 18.8 if
   you'd rather keep footer rules together.
   Between 601 and 900px the three footer columns were still side by side
   at 25 / 50 / 25%, so the address wrapped a word per line, the phone number
   broke in two, and the link columns were crushed together. Reflowed as:
       [ logo + address ]  [ links ]
       [       Let's talk        ]
   Below 601px Impreza's own stacking takes over and this doesn't apply.
   The selectors are long to clear Impreza's stacking rule at (0,5,0).
   ========================================================================== */
@media (min-width: 601px) and (max-width: 900px) {
    .l-footer .g-cols.wpb_row.wpb_row {
        display: flex;
        flex-wrap: wrap;
        row-gap: 32px;
    }

    .l-footer .g-cols.wpb_row.wpb_row > .wpb_column.wpb_column {
        width: 50%;
        max-width: 50%;
        margin: 0;
    }

    /* The Let's talk column: full width, on its own row, last. */
    .l-footer .g-cols.wpb_row.wpb_row > .wpb_column.wpb_column:nth-child(2) {
        order: 3;
        width: 100%;
        max-width: 100%;
    }

    .l-footer .g-cols.wpb_row.wpb_row > .wpb_column.wpb_column:nth-child(3) {
        order: 2;
    }

    /* The two link lists share the right-hand column evenly. */
    .l-footer .g-cols.wpb_row.wpb_row .w-hwrapper > .w-vwrapper {
        flex: 1 1 0;
        min-width: 0;
    }
}

/* ==========================================================================
   21.0  VACANCY PAGE — single job post template
   Append to the END of the site stylesheet (after 20.12).
   --------------------------------------------------------------------------
   CONTENTS
     21.1  Tokens and section rhythm
     21.2  Layout — role panel and sidebar
     21.3  Role panel
     21.4  Apply card (Forminator)
     21.5  Other vacancies
     21.6  Header between laptop and tablet (site-wide)
     21.7  Reduced motion
   --------------------------------------------------------------------------
   EDITOR SETUP (Vacancy Template, post 1930)
   Row (the one after the hero)            -> job-post
      Column 2/3                           -> job-main
         Text "Position"                   -> l-text job-kicker
         Post Title                        (no class)
         Custom field hero_description     (no class — found by field name)
         Text "The opportunity:" etc.      -> l-text job-subhead (every heading)
         Custom fields / Text blocks       (no class)
      Column 1/3                           -> job-side
         Text block                        -> job-apply
            content:   <h2>Apply now</h2>
                       [forminator_form id="1949"]
                       …small print paragraphs after it
         Post List (Grid Layout 1951)      -> job-others
   The separators in the left column are hidden — spacing is set here, so
   the rhythm is the same on every vacancy however the fields are filled.
   --------------------------------------------------------------------------
   BREAKPOINTS
     above 1024   panel and sidebar side by side
     601–1024     stacked; names share a row in the form, vacancies 2 across
     600 and down single column throughout
   --------------------------------------------------------------------------
   WHY SOME RULES CARRY !important
   Two sources this file can't outrank on specificity alone:
     - Design Options (.us_custom_*) — written !important. The headings'
       60px margin and 300 weight, the l-text size, and the Post List's
       border and padding all come from there.
     - Forminator's per-form stylesheet (style-1949.css), scoped with the
       form's ID. An ID beats any number of classes, so the visual
       properties it may set on fields and buttons have to be !important.
   Layout properties neither of them touches are left without.
   ========================================================================== */


/* ==========================================================================
   21.1  TOKENS AND SECTION RHYTHM
   ========================================================================== */
.job-post {
    --job-blue: var(--color-blue, #00bfff);
    --job-ink: #fff;
    --job-ink-soft: rgb(255 255 255 / .9);
    --job-panel: var(--color-dark-dark-grey, #333);
    /* Open Sans goes to 300; Atkinson is only in the kit in Bold (see 20.1.1). */
    --job-face-light: var(--font-family, inherit);
    --job-radius: 20px;
    --job-gap: clamp(16px, 1.6vw, 28px);
    --job-sec-pad: clamp(44px, 6.5vw, 120px);
    --job-pad: clamp(24px, 3.2vw, 60px);
    --job-speed: 320ms;
    --job-ease: cubic-bezier(.22, .68, .3, 1);
}

/* Beats Impreza's .l-section.height_medium > .l-section-h padding. */
.l-section.job-post.job-post > .l-section-h {
    padding-top: var(--job-sec-pad);
    padding-bottom: var(--job-sec-pad);
}

@media (max-width: 600px) {
    .job-post {
        --job-radius: 14px;
        --job-pad: 22px;
    }
}


/* ==========================================================================
   21.2  LAYOUT — ROLE PANEL AND SIDEBAR
   Grid rather than Impreza's 2/3 + 1/3 flex columns, so the sidebar has a
   floor (300px) and the gap is one number instead of two sets of column
   padding. Four repeats clear .g-cols.stacking_default.via_flex > div
   (0,4,1), which would otherwise put the 1.5rem stacking margins back
   below 768px.
   ========================================================================== */
.job-post .g-cols.g-cols.g-cols.g-cols {
    display: grid;
    grid-template-columns: minmax(0, 2fr) minmax(300px, 1fr);
    align-items: start;
    gap: var(--job-gap);
    margin: 0;
}

.job-post .g-cols.g-cols.g-cols.g-cols > .wpb_column {
    width: auto;
    max-width: none;
    min-width: 0;
    margin: 0;
}

/* (0,5,0) clears .g-cols.via_flex.type_default > div > .vc_column-inner. */
.job-post .g-cols.g-cols > .wpb_column > .vc_column-inner {
    padding: 0;
}

/* The sidebar's two cards, stacked with the same gap as the columns. */
.job-post .job-side > .vc_column-inner > .wpb_wrapper {
    display: flex;
    flex-direction: column;
    gap: var(--job-gap);
}

.job-post .job-side > .vc_column-inner > .wpb_wrapper > * {
    margin: 0;
}

@media (max-width: 1024px) {
    .job-post .g-cols.g-cols.g-cols.g-cols {
        grid-template-columns: minmax(0, 1fr);
    }
}


/* ==========================================================================
   21.3  ROLE PANEL
   ========================================================================== */
.job-post .g-cols .job-main.job-main > .vc_column-inner {
    padding: var(--job-pad);
    background: var(--job-panel);
    border-radius: var(--job-radius);
    color: var(--job-ink);
}

.job-post .job-main .w-separator {
    display: none;
}

/* --- "Position" ------------------------------------------------------------
   !important against l-text (1.1, 18.2) and the Design Options margin-left
   and weight. Remove l-text and clear Design Options on these blocks and
   the !importants can come off. */
.job-post .job-main .job-kicker.job-kicker {
    margin: 0 0 .4em !important;
    font-family: var(--font-family, inherit);
    font-size: clamp(14px, 1.15vw, 22px) !important;
    font-weight: 700 !important;
    line-height: 1.2;
    color: var(--job-blue);
}

/* --- the job title -------------------------------------------------------- */
.job-post .job-main .post_title.post_title {
    margin: 0 0 clamp(20px, 2.4vw, 44px);
    font-family: var(--job-face-light);
    font-size: clamp(28px, 3.1vw, 60px);
    font-weight: 300;
    line-height: 1.1;
    letter-spacing: 0;
    color: var(--job-ink);
    text-wrap: balance;
}

/* --- the blue lead (hero_description) ------------------------------------- */
.job-post .job-main .post_custom_field.hero_description {
    margin: 0 0 clamp(8px, 1.5vw, 28px);
    font-family: var(--job-face-light);
    font-size: clamp(20px, 2.2vw, 42px);
    font-weight: 300;
    line-height: 1.3;
    color: var(--job-blue);
    text-wrap: pretty;
}

/* --- sub-headings --------------------------------------------------------- */
.job-post .job-main .job-subhead.job-subhead {
    margin: clamp(28px, 3.2vw, 60px) 0 .6em !important;
    font-family: var(--font-family, inherit);
    font-size: clamp(18px, 1.6vw, 30px) !important;
    font-weight: 700 !important;
    line-height: 1.25;
    color: var(--job-blue);
}

.job-post .job-main :is(.job-kicker, .job-subhead) :is(p, h2, h3, h4, span) {
    margin: 0;
    font: inherit;
    color: inherit;
}

/* --- body copy -------------------------------------------------------------
   Every custom field except the lead, and the About us text block. */
.job-post .job-main :is(.post_custom_field:not(.hero_description), .wpb_text_column:not(.job-kicker, .job-subhead)) {
    margin: 0;
    font-family: var(--font-family, inherit);
    font-size: clamp(15px, 1.15vw, 21px);
    font-weight: 400;
    line-height: 1.55;
    color: var(--job-ink-soft);
}

.job-post .job-main :is(.post_custom_field, .wpb_text_column) :is(.w-post-elm-value, .wpb_wrapper) {
    color: inherit;
}

/* A plain textarea field arrives as raw text, so its line breaks would be
   lost. Only applied when the field holds no markup of its own — a rich
   text field keeps normal whitespace handling. */
.job-post .job-main .post_custom_field.type_text .w-post-elm-value:not(:has(p, ul, ol, br)) {
    white-space: pre-line;
}

.job-post .job-main :is(.post_custom_field, .wpb_text_column) p {
    margin: 0 0 .9em;
}

.job-post .job-main :is(.post_custom_field, .wpb_text_column) :is(p, ul, ol):last-child {
    margin-bottom: 0;
}

/* Headings typed into a rich text field match the sub-headings. */
.job-post .job-main :is(.post_custom_field, .wpb_text_column:not(.job-kicker, .job-subhead)) :is(h2, h3, h4) {
    margin: 1.4em 0 .5em;
    font-family: var(--font-family, inherit);
    font-size: clamp(18px, 1.6vw, 30px);
    font-weight: 700;
    line-height: 1.25;
    color: var(--job-blue);
}

.job-post .job-main :is(.post_custom_field, .wpb_text_column) a {
    color: var(--job-blue);
    text-decoration: underline;
    text-underline-offset: .18em;
}

/* --- bullet lists --------------------------------------------------------- */
.job-post .job-main :is(.post_custom_field, .wpb_text_column) ul {
    margin: 0 0 .9em;
    padding: 0;
    list-style: none;
}

.job-post .job-main :is(.post_custom_field, .wpb_text_column) ul li {
    position: relative;
    margin: 0 0 .7em;
    padding-left: 1em;
}

.job-post .job-main :is(.post_custom_field, .wpb_text_column) ul li::before {
    content: "";
    position: absolute;
    left: 0;
    top: .62em;
    width: .34em;
    height: .34em;
    border-radius: 50%;
    background: var(--job-blue);
}

/* --- empty fields ----------------------------------------------------------
   A vacancy with a field left blank loses the field AND its heading, so
   there is never a heading with nothing under it. Needs each heading to
   sit directly before its field, as it does in the template. */
.job-post .job-main .post_custom_field:has(> .w-post-elm-value:empty) {
    display: none;
}

.job-post .job-main .job-subhead:has(+ .post_custom_field > .w-post-elm-value:empty) {
    display: none;
}


/* ==========================================================================
   21.4  APPLY CARD (FORMINATOR)
   ========================================================================== */
.job-post .job-side .job-apply.job-apply {
    --ja-ink: #151515;
    --ja-field-h: clamp(48px, 3.4vw, 64px);
    --ja-field-size: clamp(15px, 1vw, 19px);
    --ja-text: clamp(14px, .92vw, 17px);
    --ja-box: clamp(26px, 1.8vw, 34px);
    --ja-tick: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='%23000'%20stroke-width='3'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cpath%20d='M5%2012.5l4.5%204.5L19%207.5'/%3E%3C/svg%3E");
    --ja-arrow: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2034%2020'%20fill='none'%20stroke='%23000'%20stroke-width='1.8'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cpath%20d='M1%2010h31'/%3E%3Cpath%20d='M23.5%201.5%2032%2010l-8.5%208.5'/%3E%3C/svg%3E");
    /* Impreza's input variables, overridden at the source so any theme
       input rule that still wins resolves to the design. */
    --inputs-background: #fff;
    --inputs-focus-background: #fff;
    --inputs-border-width: 0px;
    --inputs-border-color: transparent;
    --inputs-focus-border-color: transparent;
    --inputs-text-color: var(--ja-ink);
    --inputs-focus-text-color: var(--ja-ink);
    --inputs-border-radius: 8px;
    --inputs-height: var(--ja-field-h);
    margin: 0;
    padding: clamp(22px, 2.4vw, 44px);
    background: var(--job-blue);
    border-radius: var(--job-radius);
    color: var(--ja-ink);
}

/* --- the heading and the small print around the form ---------------------- */
.job-post .job-apply > .wpb_wrapper > :is(h2, h3) {
    margin: 0 0 .7em;
    font-family: var(--job-face-light);
    font-size: clamp(28px, 2.6vw, 52px);
    font-weight: 300;
    line-height: 1.1;
    text-align: center;
    color: var(--ja-ink);
}

.job-post .job-apply > .wpb_wrapper > p {
    margin: 1.6em 0 0;
    font-size: var(--ja-text);
    font-weight: 400;
    line-height: 1.5;
    color: var(--ja-ink);
}

.job-post .job-apply > .wpb_wrapper > p + p {
    margin-top: .9em;
}

/* wpautop can leave an empty paragraph either side of the shortcode. */
.job-post .job-apply > .wpb_wrapper > p:empty {
    display: none;
}

/* --- the form as a grid ----------------------------------------------------
   One column by default; the name rows share a row at tablet width
   (bottom of this section). Hidden inputs are display:none natively, so
   they never become grid items. */
.job-apply .forminator-ui.forminator-custom-form[data-design] {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: 12px;
    margin: 0 !important;
    padding: 0 !important;
    background: none !important;
    border: 0 !important;
}

.job-apply .forminator-ui.forminator-custom-form[data-design] > * {
    grid-column: 1 / -1;
    min-width: 0;
}

.job-apply .forminator-ui.forminator-custom-form[data-design] .forminator-row {
    display: block !important;
    margin: 0 !important;
    padding: 0 !important;
}

.job-apply .forminator-ui.forminator-custom-form[data-design] .forminator-col {
    flex: none !important;
    width: 100% !important;
    max-width: 100% !important;
    margin: 0 !important;
    padding: 0 !important;
}

.job-apply .forminator-ui.forminator-custom-form[data-design] .forminator-field {
    position: relative;
    margin: 0 !important;
}

/* --- text fields ---------------------------------------------------------- */
.job-apply .forminator-ui.forminator-custom-form[data-design] :is(input.forminator-input, select, textarea) {
    width: 100%;
    height: var(--ja-field-h) !important;
    margin: 0 !important;
    padding: 0 1em !important;
    background: #fff !important;
    border: 0 !important;
    border-radius: 8px !important;
    box-shadow: none !important;
    color: var(--ja-ink) !important;
    font-family: var(--font-family, inherit) !important;
    font-size: var(--ja-field-size) !important;
    font-weight: 400 !important;
    line-height: 1.2 !important;
    transition: box-shadow var(--job-speed) ease;
}

.job-apply .forminator-ui.forminator-custom-form[data-design] textarea {
    height: auto !important;
    min-height: 8em;
    padding: .8em 1em !important;
}

.job-apply .forminator-ui.forminator-custom-form[data-design] :is(input, textarea)::placeholder {
    color: #3a3a3a;
    opacity: 1;
}

.job-apply .forminator-ui.forminator-custom-form[data-design] :is(input.forminator-input, select, textarea):focus {
    outline: 0;
    box-shadow: 0 0 0 3px var(--ja-ink) !important;
}

/* --- labels ----------------------------------------------------------------
   The design shows the field name INSIDE the box, which is a placeholder.
   Set a placeholder on each field in Forminator and its label is hidden
   visually — still read out by screen readers. A field with no placeholder
   keeps a small label above it, so nothing is ever left unlabelled. */
.job-apply .forminator-ui.forminator-custom-form[data-design] .forminator-label {
    display: block;
    margin: 0 0 6px !important;
    font-family: var(--font-family, inherit) !important;
    font-size: var(--ja-text) !important;
    font-weight: 600 !important;
    line-height: 1.3;
    color: var(--ja-ink) !important;
}

.job-apply .forminator-ui.forminator-custom-form[data-design] .forminator-field:has(:is(input, textarea)[placeholder]:not([placeholder=""])) > .forminator-label {
    position: absolute !important;
    width: 1px;
    height: 1px;
    margin: -1px !important;
    padding: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

/* --- consent ---------------------------------------------------------------
   Box left, "Tick to signify consent" beside it, the privacy text full
   width underneath. The checkbox wrapper is dissolved so its two children
   can be placed in the field's grid alongside the label. */
.job-apply .forminator-ui.forminator-custom-form[data-design] .forminator-field-consent .forminator-field {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    grid-template-areas:
        "box  label"
        "desc desc";
    align-items: center;
    column-gap: 14px;
    row-gap: 18px;
    margin-top: 6px !important;
}

.job-apply .forminator-custom-form .forminator-field-consent .forminator-checkbox__wrapper.forminator-checkbox__wrapper {
    display: contents;
}

.job-apply .forminator-ui.forminator-custom-form[data-design] .forminator-field-consent .forminator-label {
    grid-area: label;
    margin: 0 !important;
    font-weight: 400 !important;
}

/* The asterisk reads as "(required)", as in the design. */
.job-apply .forminator-ui.forminator-custom-form[data-design] .forminator-field-consent .forminator-required {
    font-size: 0;
    color: inherit !important;
}

.job-apply .forminator-ui.forminator-custom-form[data-design] .forminator-field-consent .forminator-required::after {
    content: "(required)";
    font-size: var(--ja-text);
}

.job-apply .forminator-ui.forminator-custom-form[data-design] .forminator-checkbox {
    grid-area: box;
    position: relative;
    display: block !important;
    width: var(--ja-box);
    height: var(--ja-box);
    margin: 0 !important;
    padding: 0 !important;
    cursor: pointer;
}

/* The real input is laid over the box — invisible but clickable and
   focusable, which is what keeps the keyboard path intact. */
.job-apply .forminator-ui.forminator-custom-form[data-design] .forminator-checkbox input {
    position: absolute;
    inset: 0;
    z-index: 1;
    width: 100%;
    height: 100%;
    margin: 0;
    opacity: 0;
    cursor: pointer;
}

.job-apply .forminator-ui.forminator-custom-form[data-design] .forminator-checkbox .forminator-checkbox-box {
    position: relative !important;
    display: block !important;
    width: var(--ja-box) !important;
    height: var(--ja-box) !important;
    margin: 0 !important;
    background: #fff !important;
    border: 0 !important;
    border-radius: 6px !important;
    box-shadow: none !important;
}

.job-apply .forminator-ui.forminator-custom-form[data-design] .forminator-checkbox .forminator-checkbox-box::before {
    content: "" !important;
    position: absolute !important;
    inset: 18% !important;
    width: auto !important;
    height: auto !important;
    margin: 0 !important;
    border: 0 !important;
    font-size: 0 !important;
    background-color: var(--ja-ink) !important;
    -webkit-mask: var(--ja-tick) center / contain no-repeat;
    mask: var(--ja-tick) center / contain no-repeat;
    opacity: 0 !important;
    transform: scale(.6);
    transition: opacity 180ms ease, transform 260ms var(--job-ease);
}

.job-apply .forminator-ui.forminator-custom-form[data-design] .forminator-checkbox input:checked + .forminator-checkbox-box::before {
    opacity: 1 !important;
    transform: none;
}

.job-apply .forminator-ui.forminator-custom-form[data-design] .forminator-checkbox input:focus-visible + .forminator-checkbox-box {
    outline: 3px solid var(--ja-ink);
    outline-offset: 2px;
}

.job-apply .forminator-ui.forminator-custom-form[data-design] .forminator-field-consent .forminator-checkbox__label {
    grid-area: desc;
    margin: 0;
    font-family: var(--font-family, inherit) !important;
    font-size: var(--ja-text) !important;
    font-weight: 400 !important;
    line-height: 1.5 !important;
    color: var(--ja-ink) !important;
}

.job-apply .forminator-ui.forminator-custom-form[data-design] .forminator-field-consent .forminator-checkbox__label p {
    margin: 0;
    font: inherit;
    color: inherit;
}

/* The consent copy is one paragraph split with <br>s; this turns each
   break into a paragraph gap. Delete if the copy is ever entered as real
   paragraphs. */
.job-apply .forminator-ui.forminator-custom-form[data-design] .forminator-field-consent .forminator-checkbox__label br {
    display: block;
    content: "";
    margin-bottom: .9em;
}

/* --- Apply now ------------------------------------------------------------ */
.job-apply .forminator-ui.forminator-custom-form[data-design] .forminator-row-last {
    margin-top: 14px !important;
}

.job-apply .forminator-ui.forminator-custom-form[data-design] .forminator-row-last .forminator-field {
    display: flex;
    justify-content: center;
}

.job-apply .forminator-ui.forminator-custom-form[data-design] .forminator-button-submit {
    display: inline-flex !important;
    align-items: center;
    justify-content: center;
    gap: .7em;
    width: auto !important;
    min-width: 0 !important;
    height: auto !important;
    margin: 0 !important;
    padding: .75em 1.6em !important;
    background: #fff !important;
    border: 1px solid #fff !important;
    border-radius: 999px !important;
    box-shadow: none !important;
    color: var(--ja-ink) !important;
    font-family: var(--font-family, inherit) !important;
    font-size: clamp(15px, 1.05vw, 20px) !important;
    font-weight: 500 !important;
    line-height: 1.2 !important;
    letter-spacing: 0 !important;
    text-transform: none !important;
    cursor: pointer;
    transition:
        padding var(--job-speed) var(--job-ease),
        background-color var(--job-speed) ease,
        border-color var(--job-speed) ease,
        color var(--job-speed) ease;
}

.job-apply .forminator-ui.forminator-custom-form[data-design] .forminator-button-submit::after {
    content: "";
    flex: none;
    width: 1.5em;
    height: .9em;
    background-color: currentColor;
    -webkit-mask: var(--ja-arrow) center / contain no-repeat;
    mask: var(--ja-arrow) center / contain no-repeat;
    transition: translate var(--job-speed) var(--job-ease);
}

.no-touch .job-apply .forminator-ui.forminator-custom-form[data-design] .forminator-button-submit:hover,
.job-apply .forminator-ui.forminator-custom-form[data-design] .forminator-button-submit:focus-visible {
    padding-left: 2.1em !important;
    padding-right: 2.1em !important;
    background: var(--ja-ink) !important;
    border-color: var(--ja-ink) !important;
    color: #fff !important;
}

.job-apply .forminator-ui.forminator-custom-form[data-design] .forminator-button-submit:focus-visible {
    outline: 3px solid #fff;
    outline-offset: 3px;
}

.no-touch .job-apply .forminator-ui.forminator-custom-form[data-design] .forminator-button-submit:hover::after {
    translate: 4px 0;
}

/* --- messages --------------------------------------------------------------
   Red on this blue fails contrast, so errors sit on a white chip. */
.job-apply .forminator-ui.forminator-custom-form[data-design] .forminator-response-message:is(:empty, [aria-hidden="true"]) {
    display: none !important;
}

.job-apply .forminator-ui.forminator-custom-form[data-design] .forminator-response-message {
    margin: 0 0 6px !important;
    padding: 14px 16px !important;
    background: #fff !important;
    border: 0 !important;
    border-radius: 8px !important;
    color: var(--ja-ink) !important;
    font-size: var(--ja-text) !important;
    line-height: 1.45;
}

.job-apply .forminator-ui.forminator-custom-form[data-design] .forminator-error-message {
    display: inline-block;
    margin: 6px 0 0 !important;
    padding: .3em .65em !important;
    background: #fff !important;
    border-radius: 4px !important;
    color: #9b1c1c !important;
    font-size: 13px !important;
    font-weight: 600 !important;
}

.job-apply .forminator-ui.forminator-custom-form[data-design] .forminator-has_error :is(input.forminator-input, select, textarea) {
    box-shadow: inset 0 0 0 2px #9b1c1c !important;
}

/* The "Edit form" link only shows to logged-in admins. */
.job-apply .forminator-edit-module {
    margin-top: 12px;
    font-size: 12px;
    text-align: center;
}

.job-apply .forminator-edit-module a {
    color: var(--ja-ink);
}

/* --- tablet: first and last name share a row ------------------------------ */
@media (min-width: 601px) and (max-width: 1024px) {
    .job-apply .forminator-ui.forminator-custom-form[data-design] {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    .job-apply .forminator-ui.forminator-custom-form[data-design] > .forminator-row:has(.forminator-field-name) {
        grid-column: auto;
    }
}

@media (max-width: 600px) {
    .job-post .job-side .job-apply.job-apply {
        padding: 22px;
    }
}


/* ==========================================================================
   21.5  OTHER VACANCIES
   A black card with a white outline; each vacancy is a full-width row with
   the arrow pushed to the right.
   --------------------------------------------------------------------------
   The Post List IS the card. Its Design Options border, radius and padding
   are overridden here so the card scales with the rest of the page.
   --------------------------------------------------------------------------
   THE HEADING
   There is no heading block in the template, so "Other vacancies" is drawn
   with ::before. Screen readers read generated text, but not as a heading —
   if that matters, add a Text block above the Post List and delete the
   ::before rule.
   --------------------------------------------------------------------------
   THE ROWS
   The Grid Layout's white-button, restyled almost entirely through its own
   variables (1.5) — no border, no fill, no pill, and the hover turns the
   text blue instead of filling. Seven classes clear 1.5's (0,4,0) base and
   (0,5,0) hover.
   ========================================================================== */
.job-post .job-side .w-grid.job-others.job-others {
    --jo-arrow: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2034%2020'%20fill='none'%20stroke='%23000'%20stroke-width='1.6'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cpath%20d='M1%2010h31'/%3E%3Cpath%20d='M23.5%201.5%2032%2010l-8.5%208.5'/%3E%3C/svg%3E");
    margin: 0;
    padding: clamp(22px, 2.2vw, 40px) !important;
    background: #000;
    border: 2px solid #fff !important;
    border-radius: var(--job-radius) !important;
}

.job-post .job-side .w-grid.job-others.job-others::before {
    content: "Other vacancies";
    display: block;
    margin: 0 0 clamp(14px, 1.4vw, 24px);
    font-family: var(--job-face-light);
    font-size: clamp(22px, 2vw, 42px);
    font-weight: 300;
    line-height: 1.15;
    text-align: center;
    color: var(--job-blue);
}

/* Replaces the Post List's 4-column grid (and the ID rule that sets
   --columns per breakpoint, which no class can outrank). */
.job-post .job-others.job-others.type_grid .w-grid-list {
    display: flex;
    flex-direction: column;
    gap: clamp(6px, .8vw, 14px);
    margin: 0;
}

.job-post .job-others .w-grid-item {
    width: auto;
    max-width: none;
    margin: 0;
    padding: 0;
}

.job-post .job-others .w-grid-item .white-button.white-button.white-button.white-button.white-button {
    --wb-ink: #fff;
    --wb-bg: transparent;
    --wb-bg-hover: transparent;
    --wb-ink-hover: var(--job-blue);
    --wb-border: 0px;
    --wb-radius: 0;
    --wb-pad-y: .35em;
    --wb-pad-x: 0;
    --wb-pad-x-hover: 0;
    justify-content: space-between;
    gap: 1em;
    width: 100%;
    font-family: var(--font-family, inherit);
    font-size: clamp(16px, 1.5vw, 30px);
    font-weight: 700;
    line-height: 1.2;
    text-align: left;
    white-space: normal;
}

.job-post .job-others .w-grid-item .white-button .w-btn-label {
    flex: 1 1 auto;
    min-width: 0;
    white-space: normal;
}

/* A thin drawn arrow in place of the Font Awesome one. font-size:0 hides
   the icon glyph; the mask draws the new one at a fixed size. */
.job-post .job-others .w-grid-item .white-button i {
    display: block;
    flex: none;
    width: clamp(22px, 1.8vw, 34px);
    height: clamp(13px, 1.05vw, 20px);
    font-size: 0 !important;
    line-height: 0;
    background-color: currentColor;
    -webkit-mask: var(--jo-arrow) center / contain no-repeat;
    mask: var(--jo-arrow) center / contain no-repeat;
    transition: translate var(--job-speed) var(--job-ease);
}

.no-touch .job-post .job-others .w-grid-item .white-button:hover i,
.job-post .job-others .w-grid-item .white-button:focus-visible i {
    translate: 6px 0;
}

/* Two across once the card is full width. */
@media (min-width: 601px) and (max-width: 1024px) {
    .job-post .job-others.job-others.type_grid .w-grid-list {
        display: grid;
        grid-template-columns: repeat(2, minmax(0, 1fr));
        column-gap: 32px;
    }
}


/* ==========================================================================
   21.6  HEADER BETWEEN LAPTOP AND TABLET (SITE-WIDE)
   The menu stays in its desktop layout down to 901px, and at 18px with a
   14px item gap the row runs out of room below roughly 1150px. Tightened
   in two steps; the header CTA drops out at the narrowest end — "Let's
   talk" in the footer and the page's own CTAs cover it.
   901 has to stay the floor: 4.1's mega menu is scoped to 901 and up.
   ========================================================================== */
@media (min-width: 901px) and (max-width: 1200px) {
    .ush_menu_1.ush_menu_1.type_desktop {
        --menu-items-gap: 8px;
    }

    .ush_menu_1.ush_menu_1 .w-nav-title,
    .ush_menu_1.ush_menu_1 .w-nav-arrow {
        font-size: 15px;
        white-space: nowrap;
    }

    .l-header .ush_image_1.ush_image_1 {
        height: 64px !important;
    }

    .l-header.sticky .ush_image_1.ush_image_1 {
        height: 50px !important;
    }

    .l-header .ush_btn_1.white-button.white-button.white-button.white-button {
        --wb-pad-x: 1.1em;
        --wb-pad-x-hover: 1.6em;
        font-size: 14px;
    }
}

@media (min-width: 901px) and (max-width: 1040px) {
    .l-header .ush_btn_1.white-button.white-button.white-button.white-button {
        display: none;
    }
}


/* ==========================================================================
   21.7  REDUCED MOTION
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
    .job-apply .forminator-custom-form :is(input.forminator-input, select, textarea),
    .job-apply .forminator-custom-form .forminator-checkbox-box::before,
    .job-apply .forminator-custom-form .forminator-button-submit,
    .job-apply .forminator-custom-form .forminator-button-submit::after,
    .job-post .job-others .white-button i {
        transition-duration: 1ms;
    }
}

/* ==========================================================================
   22.0  CONTACT PAGE
   Append to the END of the site stylesheet (after 21.7).
   --------------------------------------------------------------------------
   CONTENTS
     22.1  Tokens
     22.2  Hero section
     22.3  Layout — intro and form card
     22.4  Intro column
     22.5  Form card (Forminator)
     22.6  Map
     22.7  Reduced motion
   --------------------------------------------------------------------------
   PAIRS WITH the CONTACT FORM LABELS JS snippet, which copies each field's
   label into the box as its placeholder. Without it the labels sit above
   the fields instead, so the form is still fully usable.
   --------------------------------------------------------------------------
   EDITOR SETUP
   Row                                    -> contact-hero
      Column 1/2                          -> contact-intro
         Horizontal Wrapper               -> contact-head
            Text "Let's Talk"             -> contact-title
            Button (style 5)              -> contact-arrow   (links to #contact-form)
         Text block (blue)                -> contact-lead
         Text block                       -> contact-copy
         Icon Box (phone)                 -> contact-line
         Icon Box (email)                 -> contact-line
         Text block                       -> contact-copy contact-note
      Column 1/2                          -> contact-side
         Text block   id contact-form     -> contact-form
            content:  <h2>Tell us a bit about what you need.</h2>
                      [forminator_form id="981"]
   Row (full width)                       -> contact-map
      Google Maps                         (no class — found by its iframe)
   Row                                    -> careers-sec careers-testi   (20.8)
   Row                                    -> careers-sec careers-supplier (20.9)
   --------------------------------------------------------------------------
   BREAKPOINTS
     above 1024   intro and form side by side
     601–1024     stacked; the arrow turns to point down at the form;
                  form fields stay in pairs
     600 and down fields single column, everything a step smaller
   --------------------------------------------------------------------------
   WHY THE FORM RULES CARRY !important
   Same as 21.4: Forminator's per-form stylesheet (style-981.css) is scoped
   with the form's ID, and an ID beats any number of classes.
   --------------------------------------------------------------------------
   THE HERO'S TOP PADDING IS LEFT TO IMPREZA
   The header is fixed, and Impreza adds its height to the first section's
   top padding. Only the bottom padding is set here — overriding the top
   would mean re-doing that header clearance at every breakpoint.
   ========================================================================== */


/* ==========================================================================
   22.1  TOKENS
   ========================================================================== */
.contact-hero,
.contact-map {
    --ct-blue: var(--color-blue, #00bfff);
    --ct-ink: #fff;
    --ct-ink-soft: rgb(255 255 255 / .9);
    --ct-dark: #151515;
    /* Open Sans goes to 300; Atkinson is only in the kit in Bold (see 20.1.1). */
    --ct-face-light: var(--font-family, inherit);
    --ct-radius: 20px;
    --ct-gap: clamp(14px, 1.4vw, 24px);
    --ct-card-pad: clamp(22px, 2.4vw, 40px);
    --ct-arrow: clamp(52px, 4.4vw, 72px);
    --ct-speed: 320ms;
    --ct-ease: cubic-bezier(.22, .68, .3, 1);
    --ct-arrow-glyph: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2064%2064'%3E%3Cg%20fill='none'%20stroke='%23000'%20stroke-width='3'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cpath%20d='M16%2032h32'/%3E%3Cpath%20d='M36%2020%2048%2032%2036%2044'/%3E%3C/g%3E%3C/svg%3E");
    --ct-line-arrow: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2034%2020'%20fill='none'%20stroke='%23000'%20stroke-width='1.8'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cpath%20d='M1%2010h31'/%3E%3Cpath%20d='M23.5%201.5%2032%2010l-8.5%208.5'/%3E%3C/svg%3E");
    --ct-tick: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='%23000'%20stroke-width='3'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cpath%20d='M5%2012.5l4.5%204.5L19%207.5'/%3E%3C/svg%3E");
}

@media (max-width: 600px) {
    .contact-hero,
    .contact-map {
        --ct-radius: 14px;
        --ct-card-pad: 20px;
        --ct-arrow: 44px;
    }
}


/* ==========================================================================
   22.2  HERO SECTION
   The photograph is the row's Design Options background image. This lays
   a scrim over it — darker on the left, where the copy sits on the photo
   rather than on the blue card. If no image is set the section is black
   and the scrim does nothing.
   ========================================================================== */
.l-section.contact-hero.contact-hero {
    position: relative;
    isolation: isolate;
}

.l-section.contact-hero.contact-hero::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 1;
    background: linear-gradient(90deg,
        rgb(0 0 0 / .72) 0%,
        rgb(0 0 0 / .45) 45%,
        rgb(0 0 0 / .25) 100%);
    pointer-events: none;
}

.l-section.contact-hero.contact-hero > .l-section-h {
    position: relative;
    z-index: 2;
    padding-bottom: clamp(40px, 4.5vw, 72px);
}

/* Stacked, the copy runs across the whole photo, so the scrim evens out. */
@media (max-width: 1024px) {
    .l-section.contact-hero.contact-hero::before {
        background: linear-gradient(180deg,
            rgb(0 0 0 / .7) 0%,
            rgb(0 0 0 / .55) 100%);
    }
}


/* ==========================================================================
   22.3  LAYOUT — INTRO AND FORM CARD
   Grid rather than Impreza's 1/2 + 1/2 columns: the design gives the card
   the larger share, and the gap is one number. Four repeats clear
   .g-cols.stacking_default.via_flex > div (0,4,1).
   ========================================================================== */
.contact-hero .g-cols.g-cols.g-cols.g-cols {
    display: grid;
    grid-template-columns: minmax(0, .72fr) minmax(0, 1fr);
    align-items: start;
    gap: clamp(32px, 5vw, 56px) var(--ct-gap);
    margin: 0;
}

.contact-hero .g-cols.g-cols.g-cols.g-cols > .wpb_column {
    width: auto;
    max-width: none;
    min-width: 0;
    margin: 0;
}

.contact-hero .g-cols.g-cols > .wpb_column > .vc_column-inner {
    padding: 0;
}

@media (max-width: 1024px) {
    .contact-hero .g-cols.g-cols.g-cols.g-cols {
        grid-template-columns: minmax(0, 1fr);
    }
}


/* ==========================================================================
   22.4  INTRO COLUMN
   ========================================================================== */

/* --- the heading row: "Let's talk" left, arrow right ----------------------
   The arrow sits at the column's right edge, pointing at the card beside
   it. Stacked, it turns to point down at the form below. */
.contact-hero .contact-head.contact-head {
    display: flex;
    flex-wrap: nowrap;
    justify-content: space-between;
    align-items: center;
    gap: 16px;
    width: 100%;
    margin: clamp(8px, 1vw, 18px) 0 clamp(24px, 2.6vw, 48px);
}

.contact-hero .contact-head.contact-head > * {
    margin: 0;
}

.contact-hero .contact-title,
.contact-hero .contact-title .w-text-h {
    margin: 0;
    font-family: var(--ct-face-light);
    font-size: clamp(32px, 3.2vw, 62px);
    font-weight: 300;
    line-height: 1.1;
    letter-spacing: 0;
    color: var(--ct-ink);
}

.contact-hero .contact-head .w-btn-wrapper {
    flex: none;
    margin: 0;
}

.contact-hero .contact-arrow.contact-arrow.contact-arrow {
    --ab-size: var(--ct-arrow);
    --ab-ink: #222;
    --ab-radius: 18%;
    --ab-glyph-size: 64%;
    --ab-glyph: var(--ct-arrow-glyph);
}

/* The copy stops short of the arrow's column, so the two never collide. */
.contact-intro > .vc_column-inner > .wpb_wrapper > :not(.contact-head) {
    max-width: calc(100% - var(--ct-arrow) - 16px);
}

/* --- the blue lead -------------------------------------------------------- */
.contact-hero .contact-lead.contact-lead {
    margin: 0 0 clamp(22px, 2.2vw, 40px);
    font-family: var(--ct-face-light);
    font-size: clamp(18px, 1.55vw, 30px);
    font-weight: 300;
    line-height: 1.35;
    color: var(--ct-blue);
    text-wrap: pretty;
}

.contact-hero .contact-lead :is(p, span) {
    margin: 0;
    font: inherit;
    color: inherit;
}

/* --- body copy ------------------------------------------------------------ */
.contact-hero .contact-copy.contact-copy {
    margin: 0 0 clamp(24px, 2.4vw, 44px);
    font-family: var(--font-family, inherit);
    font-size: clamp(15px, 1.05vw, 19px);
    font-weight: 400;
    line-height: 1.5;
    color: var(--ct-ink-soft);
}

.contact-hero .contact-copy p {
    margin: 0;
    font: inherit;
    color: inherit;
}

.contact-hero .contact-note.contact-note {
    margin: clamp(24px, 2.4vw, 44px) 0 0;
}

/* --- phone and email -------------------------------------------------------
   Outline icon in blue, a fixed-width column so the two lines of text
   start at the same point, then the number or address in the headline
   face. The whole row is pinned to the column's left edge, in line with
   the copy above and below it.
   The Icon Box arrives with Impreza's centred alignment, which centres the
   row and puts auto margins on the icon — hence the !importants on
   justify-content, text-align and the margins.
   The icons are the Font Awesome solids chosen in the editor, switched to
   the light (outline) cut by weight — the site loads fa-light-300, so no
   editor change is needed.
   With a link set, Impreza wraps the icon in a.w-iconbox-link, so that
   wrapper is the flex item rather than the icon itself. Both are covered. */
.contact-hero .w-iconbox.contact-line.contact-line {
    display: flex;
    flex-direction: row;
    justify-content: flex-start !important;
    align-items: center;
    gap: .7em;
    width: 100%;
    margin: 0 0 .5em !important;
    padding: 0;
    font-size: clamp(18px, 1.5vw, 30px);
    text-align: left !important;
}

.contact-hero .w-iconbox.contact-line.contact-line + .w-iconbox.contact-line {
    margin-top: 0 !important;
}

/* The last line hands the spacing to the note below it. */
.contact-hero .w-iconbox.contact-line.contact-line:not(:has(+ .contact-line)) {
    margin-bottom: 0 !important;
}

.contact-hero .contact-line > .w-iconbox-link {
    flex: none;
    display: flex;
    margin: 0 !important;
    padding: 0;
    color: inherit;
    text-decoration: none;
}

.contact-hero .contact-line .w-iconbox-icon {
    flex: none;
    display: flex;
    justify-content: center;
    align-items: center;
    width: 1.2em;
    height: auto;
    margin: 0 !important;
    padding: 0;
    font-size: 1.1em !important;
    line-height: 1;
    color: var(--ct-blue);
    background: none;
    border: 0;
}

.contact-hero .contact-line .w-iconbox-icon i {
    font-size: inherit;
    font-weight: 300 !important;
    line-height: 1;
    color: inherit;
}

.contact-hero .contact-line .w-iconbox-meta {
    flex: 0 1 auto;
    min-width: 0;
    margin: 0 !important;
    padding: 0 !important;
    text-align: left !important;
}

.contact-hero .contact-line .w-iconbox-title.w-iconbox-title {
    margin: 0 !important;
    padding: 0;
    font-family: var(--h1-font-family, inherit);
    font-size: inherit !important;
    font-weight: 400;
    line-height: 1.25;
    letter-spacing: .01em;
    text-align: left;
    color: var(--ct-ink);
    overflow-wrap: anywhere;
}

.contact-hero .contact-line .w-iconbox-title a {
    color: inherit;
    text-decoration: none;
    transition: color var(--ct-speed) ease;
}

.no-touch .contact-hero .contact-line .w-iconbox-title a:hover,
.contact-hero .contact-line .w-iconbox-title a:focus-visible {
    color: var(--ct-blue);
}

.contact-hero .contact-line a:focus-visible {
    outline: 2px solid var(--ct-blue);
    outline-offset: 4px;
}

/* --- stacked ---------------------------------------------------------------
   The column is full width, so the copy is capped at a readable measure
   instead, and the arrow points down at the form. */
@media (max-width: 1024px) {
    .contact-intro > .vc_column-inner > .wpb_wrapper {
        max-width: 680px;
    }

    .contact-intro > .vc_column-inner > .wpb_wrapper > :not(.contact-head) {
        max-width: none;
    }

    .contact-hero .contact-arrow.contact-arrow.contact-arrow {
        --ab-rest: 90deg;
    }
}


/* ==========================================================================
   22.5  FORM CARD (FORMINATOR)
   Fields sit in pairs where the form puts them in the same Forminator row
   (First / Last, Company / Email), and each field fills its share. Below
   600px every field takes the full width.
   ========================================================================== */
.contact-hero .contact-side .contact-form.contact-form {
    --cf-ink: var(--ct-dark);
    --cf-field-h: clamp(48px, 3.4vw, 64px);
    --cf-field-size: clamp(15px, 1vw, 19px);
    --cf-text: clamp(14px, .92vw, 17px);
    --cf-box: clamp(26px, 1.8vw, 34px);
    --cf-gap: 12px;
    /* The focus state: a light grey edge with a soft white halo round it.
       Visible against the blue without shouting. */
    --cf-focus:
        inset 0 0 0 1.5px #c3c9d0,
        0 0 0 4px rgb(255 255 255 / .55);
    /* Impreza's input variables, overridden at the source. */
    --inputs-background: #fff;
    --inputs-focus-background: #fff;
    --inputs-border-width: 0px;
    --inputs-border-color: transparent;
    --inputs-focus-border-color: transparent;
    --inputs-text-color: var(--cf-ink);
    --inputs-focus-text-color: var(--cf-ink);
    --inputs-border-radius: 8px;
    --inputs-height: var(--cf-field-h);
    margin: 0;
    padding: var(--ct-card-pad);
    background: var(--ct-blue);
    border-radius: var(--ct-radius);
    color: var(--cf-ink);
    scroll-margin-top: calc(var(--header-sticky-height, 70px) + 16px);
}

/* --- the heading ---------------------------------------------------------- */
.contact-hero .contact-form > .wpb_wrapper > :is(h2, h3) {
    margin: 0 0 .6em;
    font-family: var(--ct-face-light);
    font-size: clamp(26px, 2.5vw, 50px);
    font-weight: 100;
    line-height: 1.1;
    letter-spacing: 0;
    text-align: center;
    color: var(--cf-ink);
    text-wrap: balance;
}

.contact-hero .contact-form > .wpb_wrapper > p {
    margin: 1.4em 0 0;
    font-size: var(--cf-text);
    line-height: 1.5;
    color: var(--cf-ink);
}

/* wpautop can leave an empty paragraph either side of the shortcode. */
.contact-hero .contact-form > .wpb_wrapper > p:empty {
    display: none;
}

/* --- the form and its rows ------------------------------------------------ */
.contact-form .forminator-ui.forminator-custom-form[data-design] {
    display: flex;
    flex-direction: column;
    gap: var(--cf-gap);
    margin: 0 !important;
    padding: 0 !important;
    background: none !important;
    border: 0 !important;
}

.contact-form .forminator-ui.forminator-custom-form[data-design] .forminator-row {
    display: flex !important;
    flex-wrap: nowrap;
    gap: var(--cf-gap);
    margin: 0 !important;
    padding: 0 !important;
}

.contact-form .forminator-ui.forminator-custom-form[data-design] .forminator-col {
    flex: 1 1 0 !important;
    width: auto !important;
    max-width: none !important;
    min-width: 0;
    margin: 0 !important;
    padding: 0 !important;
}

.contact-form .forminator-ui.forminator-custom-form[data-design] .forminator-field {
    position: relative;
    margin: 0 !important;
}

/* --- text fields ---------------------------------------------------------- */
.contact-form .forminator-ui.forminator-custom-form[data-design] :is(input.forminator-input, select, textarea) {
    width: 100%;
    height: var(--cf-field-h) !important;
    margin: 0 !important;
    padding: 0 1em !important;
    background: #fff !important;
    border: 0 !important;
    border-radius: 8px !important;
    box-shadow: none !important;
    color: var(--cf-ink) !important;
    font-family: var(--font-family, inherit) !important;
    font-size: var(--cf-field-size) !important;
    font-weight: 100 !important;
    line-height: 1.2 !important;
    transition: box-shadow var(--ct-speed) ease;
}

/* --- the message box -------------------------------------------------------
   textarea[name] rather than a bare textarea. The rule above lists
   input.forminator-input inside :is(), and :is() takes the weight of its
   heaviest argument — so it outranked a plain textarea selector and kept
   the message box at field height with no top padding. [name] brings this
   level with it, and coming later in the file, it wins. */
.contact-form .forminator-ui.forminator-custom-form[data-design] textarea[name] {
    height: auto !important;
    min-height: clamp(180px, 15vw, 280px) !important;
    padding: 1em 1em !important;
    line-height: 1.45 !important;
    resize: vertical;
}

/* The placeholder IS the label now, so it is set in the same ink as the
   design's field names rather than the usual faded grey. */
.contact-form .forminator-ui.forminator-custom-form[data-design] :is(input, textarea)::placeholder {
    color: var(--cf-ink);
    opacity: 1;
}

.contact-form .forminator-ui.forminator-custom-form[data-design] :is(input.forminator-input, select, textarea):focus {
    outline: 0;
    box-shadow: var(--cf-focus) !important;
}

/* --- labels ----------------------------------------------------------------
   The field names sit INSIDE the boxes. The JS snippet copies each label
   into its field's placeholder; once a field has one, its label is hidden
   visually — still read out by screen readers. If the script doesn't run,
   the labels simply stay above the fields. */
.contact-form .forminator-ui.forminator-custom-form[data-design] .forminator-label {
    display: block;
    margin: 0 0 6px !important;
    font-family: var(--font-family, inherit) !important;
    font-size: var(--cf-text) !important;
    font-weight: 100 !important;
    line-height: 1.3;
    color: var(--cf-ink) !important;
}

.contact-form .forminator-ui.forminator-custom-form[data-design] .forminator-field:has(:is(input, textarea)[placeholder]:not([placeholder=""])) > .forminator-label {
    position: absolute !important;
    width: 1px;
    height: 1px;
    margin: -1px !important;
    padding: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

/* --- the character counter ------------------------------------------------
   The "0 / 180" under the message box. Hidden only — the limit itself is
   still enforced. Turn the limit off in the field's settings in Forminator
   if you don't want one at all. */
.contact-form .forminator-ui.forminator-custom-form[data-design] :is(.forminator-description:has([data-limit]), [data-limit]) {
    display: none !important;
}

/* --- consent ---------------------------------------------------------------
   Box left, "Tick to signify consent" beside it, the privacy line full
   width underneath. */
.contact-form .forminator-ui.forminator-custom-form[data-design] .forminator-field-consent .forminator-field {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    grid-template-areas:
        "box  label"
        "desc desc";
    align-items: center;
    column-gap: 14px;
    row-gap: clamp(18px, 2vw, 32px);
    margin-top: 10px !important;
}

.contact-form .forminator-custom-form .forminator-field-consent .forminator-checkbox__wrapper.forminator-checkbox__wrapper {
    display: contents;
}

.contact-form .forminator-ui.forminator-custom-form[data-design] .forminator-field-consent .forminator-label {
    grid-area: label;
    margin: 0 !important;
    font-weight: 100 !important;
}

.contact-form .forminator-ui.forminator-custom-form[data-design] .forminator-field-consent .forminator-required {
    font-size: 0;
    color: inherit !important;
}

.contact-form .forminator-ui.forminator-custom-form[data-design] .forminator-field-consent .forminator-required::after {
    content: "(required)";
    font-size: var(--cf-text);
}

.contact-form .forminator-ui.forminator-custom-form[data-design] .forminator-checkbox {
    grid-area: box;
    position: relative;
    display: block !important;
    width: var(--cf-box);
    height: var(--cf-box);
    margin: 0 !important;
    padding: 0 !important;
    cursor: pointer;
}

.contact-form .forminator-ui.forminator-custom-form[data-design] .forminator-checkbox input {
    position: absolute;
    inset: 0;
    z-index: 1;
    width: 100%;
    height: 100%;
    margin: 0;
    opacity: 0;
    cursor: pointer;
}

.contact-form .forminator-ui.forminator-custom-form[data-design] .forminator-checkbox .forminator-checkbox-box {
    position: relative !important;
    display: block !important;
    width: var(--cf-box) !important;
    height: var(--cf-box) !important;
    margin: 0 !important;
    background: #fff !important;
    border: 0 !important;
    border-radius: 6px !important;
    box-shadow: none !important;
    transition: box-shadow var(--ct-speed) ease;
}

.contact-form .forminator-ui.forminator-custom-form[data-design] .forminator-checkbox .forminator-checkbox-box::before {
    content: "" !important;
    position: absolute !important;
    inset: 18% !important;
    width: auto !important;
    height: auto !important;
    margin: 0 !important;
    border: 0 !important;
    font-size: 0 !important;
    background-color: var(--cf-ink) !important;
    -webkit-mask: var(--ct-tick) center / contain no-repeat;
    mask: var(--ct-tick) center / contain no-repeat;
    opacity: 0 !important;
    transform: scale(.6);
    transition: opacity 180ms ease, transform 260ms var(--ct-ease);
}

.contact-form .forminator-ui.forminator-custom-form[data-design] .forminator-checkbox input:checked + .forminator-checkbox-box::before {
    opacity: 1 !important;
    transform: none;
}

.contact-form .forminator-ui.forminator-custom-form[data-design] .forminator-checkbox input:focus-visible + .forminator-checkbox-box {
    outline: 0;
    box-shadow: var(--cf-focus) !important;
}

.contact-form .forminator-ui.forminator-custom-form[data-design] .forminator-field-consent .forminator-checkbox__label {
    grid-area: desc;
    margin: 0;
    font-family: var(--font-family, inherit) !important;
    font-size: var(--cf-text) !important;
    font-weight: 100 !important;
    line-height: 1.5 !important;
    color: var(--cf-ink) !important;
}

.contact-form .forminator-ui.forminator-custom-form[data-design] .forminator-field-consent .forminator-checkbox__label p {
    margin: 0;
    font: inherit;
    color: inherit;
}

.contact-form .forminator-ui.forminator-custom-form[data-design] .forminator-field-consent .forminator-checkbox__label br {
    display: block;
    content: "";
    margin-bottom: .9em;
}

/* --- Submit form ---------------------------------------------------------- */
.contact-form .forminator-ui.forminator-custom-form[data-design] .forminator-row-last {
    margin-top: clamp(10px, 1.4vw, 24px) !important;
}

.contact-form .forminator-ui.forminator-custom-form[data-design] .forminator-row-last .forminator-field {
    display: flex;
    justify-content: center;
}

.contact-form .forminator-ui.forminator-custom-form[data-design] .forminator-button-submit {
    display: inline-flex !important;
    align-items: center;
    justify-content: center;
    gap: .7em;
    width: auto !important;
    min-width: 0 !important;
    height: auto !important;
    margin: 0 !important;
    padding: .75em 1.6em !important;
    background: #fff !important;
    border: 1px solid #fff !important;
    border-radius: 999px !important;
    box-shadow: none !important;
    color: var(--cf-ink) !important;
    font-family: var(--font-family, inherit) !important;
    font-size: clamp(15px, 1.05vw, 20px) !important;
    font-weight: 100 !important;
    line-height: 1.2 !important;
    letter-spacing: 0 !important;
    text-transform: none !important;
    cursor: pointer;
    transition:
        padding var(--ct-speed) var(--ct-ease),
        background-color var(--ct-speed) ease,
        border-color var(--ct-speed) ease,
        color var(--ct-speed) ease;
}

.contact-form .forminator-ui.forminator-custom-form[data-design] .forminator-button-submit::after {
    content: "";
    flex: none;
    width: 1.5em;
    height: .9em;
    background-color: currentColor;
    -webkit-mask: var(--ct-line-arrow) center / contain no-repeat;
    mask: var(--ct-line-arrow) center / contain no-repeat;
    transition: translate var(--ct-speed) var(--ct-ease);
}

.no-touch .contact-form .forminator-ui.forminator-custom-form[data-design] .forminator-button-submit:hover,
.contact-form .forminator-ui.forminator-custom-form[data-design] .forminator-button-submit:focus-visible {
    padding-left: 2.1em !important;
    padding-right: 2.1em !important;
    background: var(--cf-ink) !important;
    border-color: var(--cf-ink) !important;
    color: #fff !important;
}

.contact-form .forminator-ui.forminator-custom-form[data-design] .forminator-button-submit:focus-visible {
    outline: 3px solid #fff;
    outline-offset: 3px;
}

.no-touch .contact-form .forminator-ui.forminator-custom-form[data-design] .forminator-button-submit:hover::after {
    translate: 4px 0;
}

/* --- messages --------------------------------------------------------------
   Red on this blue fails contrast, so errors sit on a white chip. */
.contact-form .forminator-ui.forminator-custom-form[data-design] .forminator-response-message:is(:empty, [aria-hidden="true"]) {
    display: none !important;
}

.contact-form .forminator-ui.forminator-custom-form[data-design] .forminator-response-message {
    margin: 0 0 6px !important;
    padding: 14px 16px !important;
    background: #fff !important;
    border: 0 !important;
    border-radius: 8px !important;
    color: var(--cf-ink) !important;
    font-size: var(--cf-text) !important;
    line-height: 1.45;
}

.contact-form .forminator-ui.forminator-custom-form[data-design] .forminator-error-message {
    display: inline-block;
    margin: 6px 0 0 !important;
    padding: .3em .65em !important;
    background: #fff !important;
    border-radius: 4px !important;
    color: #9b1c1c !important;
    font-size: 13px !important;
    font-weight: 100 !important;
}

.contact-form .forminator-ui.forminator-custom-form[data-design] .forminator-has_error :is(input.forminator-input, select, textarea) {
    box-shadow: inset 0 0 0 2px #9b1c1c !important;
}

.contact-form .forminator-edit-module {
    margin-top: 12px;
    font-size: 12px;
    text-align: center;
}

.contact-form .forminator-edit-module a {
    color: var(--cf-ink);
}

/* --- phones: one field per row -------------------------------------------- */
@media (max-width: 600px) {
    .contact-form .forminator-ui.forminator-custom-form[data-design] .forminator-row {
        flex-direction: column;
    }
}


/* ==========================================================================
   22.6  MAP
   Edge to edge, no gaps above or below, at a fixed shape that scales with
   the viewport.
   --------------------------------------------------------------------------
   The Google Maps element writes a fixed-size iframe inside one or more
   wrappers, and may use a padding-bottom ratio box or an absolutely
   positioned iframe depending on version. Every wrapper that contains the
   iframe is flattened, and the iframe is put back in flow at a set height,
   so it works whichever markup the element produces.
   --------------------------------------------------------------------------
   Change the height with --map-h.
   ========================================================================== */
.contact-map {
    --map-h: clamp(320px, 40vw, 640px);
}

.l-section.contact-map.contact-map > .l-section-h {
    max-width: none;
    padding: 0;
}

.contact-map .g-cols.g-cols.g-cols {
    display: block;
    margin: 0;
}

.contact-map .g-cols.g-cols.g-cols > .wpb_column {
    width: 100%;
    max-width: none;
    margin: 0;
}

.contact-map .g-cols.g-cols > .wpb_column > .vc_column-inner {
    padding: 0;
}

.contact-map .vc_column-inner :is(div, figure):has(iframe) {
    position: static !important;
    width: 100% !important;
    max-width: none !important;
    height: auto !important;
    margin: 0 !important;
    padding: 0 !important;
    border: 0 !important;
}

.contact-map iframe {
    position: relative !important;
    inset: auto !important;
    display: block;
    width: 100% !important;
    max-width: none !important;
    height: var(--map-h) !important;
    margin: 0;
    border: 0;
}

/* The element's optional title. */
.contact-map .wpb_heading {
    display: none;
}

@media (max-width: 900px) {
    .contact-map {
        --map-h: clamp(300px, 62vw, 460px);
    }
}


/* ==========================================================================
   22.7  REDUCED MOTION
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
    .contact-form .forminator-custom-form :is(input.forminator-input, select, textarea),
    .contact-form .forminator-custom-form .forminator-checkbox-box,
    .contact-form .forminator-custom-form .forminator-checkbox-box::before,
    .contact-form .forminator-custom-form .forminator-button-submit,
    .contact-form .forminator-custom-form .forminator-button-submit::after,
    .contact-hero .contact-line .w-iconbox-title a {
        transition-duration: 1ms;
    }
}

/* ==========================================================================
   23.0  ABOUT PAGE
   REPLACES the previous 23.0 block entirely. Append to the END of the site
   stylesheet (after 22.7).
   --------------------------------------------------------------------------
   CONTENTS
     23.1  Tokens and section rhythm
     23.2  Hero
     23.3  Intro
     23.4  Credentials (the four icon boxes)
     23.5  (removed: Our direction is back on 5.6 / 18.11)
     23.6  Meet the team: photo and blue band
     23.7  Team strip (1024px and below)
       23.7.1  Which list shows where
       23.7.2  The strip
       23.7.3  The card
       23.7.4  Photo and shade
       23.7.5  Role, arrow, name and LinkedIn
       23.7.6  Bio
       23.7.7  Open state
       23.7.8  Controls
     23.8  A little history
     23.9  Reduced motion
   --------------------------------------------------------------------------
   PAIRS WITH the TEAM STRIP JS snippet (23.7). It replaces the TEAM CAROUSEL
   snippet from the last round, which should be deleted.
   The supplier band carries the careers classes, so 20.9 styles it.
   Testimonials are back to how they were, so 5.11 styles them as before.
   --------------------------------------------------------------------------
   BREAKPOINTS
     above 1320   untouched: the desktop build as it stands
     1025-1320    hero pair rescaled, history padding eased, team 4 across
     1024 and down credentials 2x2, and the team list switches from the Owl
                  carousel to the story-card strip
     900 and down history stacks
     600 and down phone type and gutters
   --------------------------------------------------------------------------
   PREFIX NOTE
   Tokens here are --abt-* and --tm-*, never --ab-*. The arrow buttons in 3.0
   own --ab-size, --ab-blue and the rest, and those are inherited, so an
   --ab- token on a section would silently restyle every arrow inside it.
   ========================================================================== */


/* ==========================================================================
   23.1  TOKENS AND SECTION RHYTHM
   Every row with about-sec gets the same padding from 1024px down, which
   closes up the black gaps between sections. Above 1024px Impreza's own
   height_medium padding is left alone.
   The gutter is only used by the two full-width rows (team and history).
   A width_full section has no inline padding of its own, so those rows pad
   their contents with this instead, to line up with the rest of the page.
   ========================================================================== */
.about-sec {
    --abt-blue: var(--color-blue, #00bfff);
    --abt-ink: #fff;
    --abt-rule: var(--color-grey, #636363);
    --abt-gutter: clamp(24px, 5vw, 40px);
    --abt-pad: clamp(48px, 7vw, 88px);
    --abt-speed: 420ms;
    --abt-ease: cubic-bezier(.22, .68, .3, 1);
}

@media (max-width: 1024px) {
    .l-section.about-sec.about-sec > .l-section-h {
        padding-top: var(--abt-pad);
        padding-bottom: var(--abt-pad);
    }
}


/* ==========================================================================
   23.2  HERO
   The two lines are sized as a pair, the same way as the careers hero (20.2).
   The clamps top out at exactly 90px and 54px, so a wide desktop screen is
   unchanged. Five classes clear 18.3's (0,4,1) mobile hero rule.
   ========================================================================== */
.l-section.about-hero.about-hero .w-vwrapper .hero-title,
.l-section.about-hero.about-hero .w-vwrapper .hero-title .w-text-h {
    margin: 0;
    font-size: clamp(32px, 5vw, 90px) !important;
    line-height: 1.05;
    text-wrap: balance;
}

.l-section.about-hero.about-hero .w-vwrapper .hero-sub,
.l-section.about-hero.about-hero .w-vwrapper .hero-sub .w-text-h {
    margin: 0;
    font-family: var(--h1-font-family, inherit);
    font-size: clamp(22px, 3vw, 54px) !important;
    font-weight: 700;
    line-height: 1.1;
    letter-spacing: .02em;
    text-wrap: balance;
}


/* ==========================================================================
   23.3  INTRO
   The blue lead's column carries a 60px left margin from Design Options.
   From 1024px down that is what pushed the lead in from the left edge, out
   of line with the copy under it. It is cleared from the column and from
   its inner wrapper, so it goes whichever of the two Impreza wrote it to,
   and the lead is forced left-aligned.
   ========================================================================== */
@media (max-width: 1024px) {
    .about-intro .about-intro-lead.about-intro-lead,
    .about-intro .about-intro-lead.about-intro-lead > .vc_column-inner {
        margin-left: 0 !important;
    }

    .about-intro .about-lead,
    .about-intro .about-lead h2 {
        text-align: left;
    }

    .about-intro .about-lead h2 {
        margin: 0;
        font-size: 48px;
		font-weight: 300;
        line-height: 1.25;
    }

    .about-intro .about-body {
        max-width: 62ch;
        font-size: 24px;
        line-height: 1.6;
		font-weight: 400;
    }

    .about-intro .about-body p {
        margin: 0 0 1em;
    }

    .about-intro .about-body p:last-child {
        margin-bottom: 0;
    }
}


/* ==========================================================================
   23.4  CREDENTIALS
   The four icon boxes. Four across on laptops and up, 2x2 from 1024px down.
   The grey dividers are drawn here rather than in Design Options (they came
   out of the shortcode last round) so that they can turn into a cross in the
   2x2 layout. The desktop rule draws the identical 3px line.
   Four repeats of .g-cols clear Impreza's stacking rule at (0,4,1).
   ========================================================================== */
.about-stats .about-stat:not(:last-child) > .vc_column-inner {
    border-right: 3px solid var(--abt-rule);
}

@media (max-width: 1024px) {
    .about-stats .g-cols.g-cols.g-cols.g-cols {
        display: grid;
        grid-template-columns: repeat(2, minmax(0, 1fr));
        gap: 0;
        margin: 0;
    }

    .about-stats .g-cols.g-cols.g-cols.g-cols > .wpb_column {
        width: auto;
        max-width: none;
        min-width: 0;
        margin: 0;
    }

    .about-stats .g-cols.g-cols > .about-stat > .vc_column-inner {
        height: 100%;
        padding: clamp(22px, 4vw, 36px) clamp(12px, 3vw, 28px);
        border: 0;
    }

    .about-stats .g-cols.g-cols > .about-stat:nth-child(odd) > .vc_column-inner {
        border-right: 2px solid var(--abt-rule);
    }

    .about-stats .g-cols.g-cols > .about-stat:nth-child(-n+2) > .vc_column-inner {
        border-bottom: 2px solid var(--abt-rule);
    }

    .about-stats .about-stat-box.w-iconbox {
        margin: 0;
    }

    /* size="6rem" is written inline on the icon, hence the !important. */
    .about-stats .about-stat-box .w-iconbox-icon {
        margin: 0 auto .7rem;
        font-size: clamp(52px, 8vw, 72px) !important;
    }

    .about-stats .about-stat-box .w-iconbox-icon img {
        width: 1em;
        height: 1em;
        object-fit: contain;
    }

    .about-stats .about-stat-box .w-iconbox-title {
        margin: 0 0 .45em;
        font-size: clamp(16px, 2.4vw, 22px);
        line-height: 1.2;
        text-wrap: balance;
    }

    .about-stats .about-stat-box .w-iconbox-text,
    .about-stats .about-stat-box .w-iconbox-text p {
        margin: 0;
        font-size: clamp(13px, 1.8vw, 16px);
        line-height: 1.45;
    }
}


/* ==========================================================================
   23.6  MEET THE TEAM: PHOTO AND BLUE BAND
   --------------------------------------------------------------------------
   THE CARDS NO LONGER SIT ON THE TITLE
   The desktop carousel is pulled 200px up into the blue band by Design
   Options. From 1024px down that carousel is hidden and the strip (23.7)
   takes its place. The strip has no negative margin, so it sits below the
   band, and the title and the "Careers at HEC" button are left clear.
   The band's "huge" separator only existed to make room for that overlap,
   so from 1024px down it shrinks to ordinary padding.
   Between 1025px and 1320px the desktop carousel and its 200px overlap are
   still in play. The same separator is made taller there so the cards stop
   short of the button.
   ========================================================================== */
@media (min-width: 1025px) and (max-width: 1320px) {
    .about-team .team-band .w-separator.size_huge {
        height: 240px;
    }
}

@media (max-width: 1320px) {
    /* xxxl-text is 180px down to 901px, and "dedicated" at 180px bold is
       wider than a 1000px screen. About 145px at 1320, 43px on a phone. */
    .about-team .team-band .team-band-title.team-band-title {
        font-size: clamp(38px, 11vw, 150px) !important;
        line-height: 1.02;
        text-wrap: balance;
    }
}

@media (max-width: 1024px) {
    .l-section.about-team.about-team > .l-section-h {
        padding-bottom: 0;
    }

    /* 60px from Design Options, on a row with no gutter of its own. */
    .about-team .team-kicker.team-kicker {
        margin: 0 var(--abt-gutter) 16px !important;
    }

    .about-team .team-band.team-band {
        padding-top: clamp(28px, 5vw, 48px);
    }

    .about-team .team-band .w-separator.size_huge {
        height: clamp(32px, 6vw, 56px);
    }

    .l-section.about-team-list.about-team-list > .l-section-h {
        padding-top: clamp(36px, 6vw, 56px);
        padding-bottom: clamp(48px, 7vw, 88px);
    }
}


/* ==========================================================================
   23.7  TEAM STRIP (1024px AND BELOW)
   The careers story cards (20.6), rebuilt for the team list: one card
   centred, the neighbours peeking in dimmed, [ ← ] 1 / 5 [ → ] underneath,
   and the bio hidden until the card is tapped.
   --------------------------------------------------------------------------
   WHY THERE ARE TWO LISTS
   The desktop list is an Owl carousel (5 across, autoplay, loop), and Owl
   decides its own geometry in JavaScript. The story-card behaviour needs a
   plain scroll-snap row that the browser controls. The two can't be the same
   element, so the row now holds both:
     team-desktop   the Post Carousel, shown above 1024px
     team-strip     a Post List of the same employees, shown at 1024 and below
   Both use Grid Layout 1784, so an edit to the layout shows up in both.
   --------------------------------------------------------------------------
   THE CARD IS BUILT FROM THE EXISTING GRID LAYOUT
   Layout 1784 is tm-media (photo + bio), tm-meta (name + LinkedIn) and
   tm-role, styled by 16.0. Here the wrappers around them are dissolved with
   display:contents, so the photo, role, name row and bio all become children
   of the card and can be placed on the same four-row grid the story cards
   use. Nothing needs changing in the Grid Layout editor.
   ========================================================================== */

/* --------------------------------------------------------------------------
   23.7.1  WHICH LIST SHOWS WHERE
   Repeated classes because Impreza's own .w-grid rules set display at equal
   weight.
   -------------------------------------------------------------------------- */
.team-strip.team-strip,
.team-nav {
    display: none;
}

@media (max-width: 1024px) {
    .team-desktop.team-desktop.team-desktop {
        display: none;
    }

    .team-strip.team-strip {
        --tm-card-w: min(44vw, 400px);
        --tm-ratio: 5 / 8;
        --tm-blue: var(--color-blue, #00bfff);
        --tm-shade: rgb(45 45 45 / .72);
        --tm-speed: 420ms;
        --tm-ease: cubic-bezier(.22, .68, .3, 1);
        display: block;
    }

    /* The strip bleeds out to both screen edges. overflow-x only, so the
       section still lets anything above or below it show. */
    .l-section:has(.team-strip) {
        overflow-x: clip;
    }
}

@media (max-width: 900px) {
    .team-strip.team-strip {
        --tm-card-w: min(58vw, 400px);
    }
}

@media (max-width: 600px) {
    .team-strip.team-strip {
        --tm-card-w: min(78vw, 400px);
    }
}

@media (max-width: 1024px) {

    /* ----------------------------------------------------------------------
       23.7.2  THE STRIP
       Same centring as 20.6.8. The row reaches from screen edge to screen
       edge, and its inline padding is half the space left around one card,
       so the first and last cards can sit dead centre.
       Three repeats of .team-strip give (0,4,0), clearing Impreza's
       .w-grid.type_grid .w-grid-list at (0,3,0), the rule that makes this a
       grid.
       ---------------------------------------------------------------------- */
    .team-strip.team-strip.team-strip .w-grid-list {
        display: flex;
        flex-wrap: nowrap;
        align-items: flex-start;
        gap: 14px;
        grid-template-columns: none;
        width: auto;
        margin: 0 calc(50% - 50vw);
        padding: 8px calc((100vw - var(--tm-card-w)) / 2);
        overflow-x: auto;
        overscroll-behavior-x: contain;
        scroll-snap-type: x mandatory;
        scrollbar-width: none;
        overflow-anchor: none;
    }

    .team-strip .w-grid-list::-webkit-scrollbar {
        display: none;
    }

    .team-strip.team-strip.team-strip .w-grid-item {
        --so: 0;
        flex: 0 0 var(--tm-card-w);
        width: auto;
        max-width: none;
        min-width: 0;
        margin: 0;
        padding: 0;
        scroll-snap-align: center;
        scroll-snap-stop: always;
        outline: none;
        transition:
            opacity var(--tm-speed) ease,
            scale var(--tm-speed) var(--tm-ease);
    }

    /* Only once the JS has marked the row, so nothing dims without it. */
    .team-strip .w-grid-list.is-carousel > .w-grid-item:not(.is-current) {
        opacity: .4;
        scale: .94;
    }

    /* ----------------------------------------------------------------------
       23.7.3  THE CARD
       The card is .w-grid-item-h. Four rows, as in 20.6.3: empty space,
       role, name, bio. Row 1 takes what is left, so as the bio opens the
       role and name are pushed up the card.
       min-height:0 fixes the shape. A long bio scrolls inside the card
       rather than making it taller, which is what stops the page jumping.
       ---------------------------------------------------------------------- */
    .team-strip.team-strip .w-grid-item-h {
        --sx: clamp(18px, 7cqi, 40px);   /* inset from the sides   */
        --sy: clamp(14px, 5cqi, 28px);   /* band padding           */
        --sa: clamp(40px, 15cqi, 60px);  /* arrow size             */
        position: relative;
        isolation: isolate;
        container-type: inline-size;
        display: grid;
        grid-template-columns: minmax(0, 1fr);
        grid-template-rows: minmax(0, 1fr) auto auto minmax(0, max-content);
        aspect-ratio: var(--tm-ratio);
        height: auto;
        min-height: 0;
        padding: 0;
        border: 1px solid rgb(255 255 255 / .16);
        border-radius: 18px;
        background: #222;
        overflow: clip;
        overflow-anchor: none;
        color: #fff;
        cursor: pointer;
    }

    .team-strip .w-grid-item:focus-visible .w-grid-item-h {
        outline: 2px solid var(--tm-blue);
        outline-offset: 3px;
    }

    /* Dissolve the layout's wrappers so their contents join the card's
       grid, EXCEPT the one holding the name, which stays as the name row.
       --------------------------------------------------------------------
       WHY THIS IS FOUND BY CONTENT, NOT BY CLASS
       The last version kept the name row by its class, tm-meta. On the live
       layout the name row still carries the old tm-media class (the mix-up
       16.0 warns about), so it was dissolved along with the photo wrapper.
       The name then fell into the empty top row, behind the photo, and the
       LinkedIn icon made an extra row under the grid. That extra row is
       what the grey band stopped short of: -1 in grid-area means the last
       row declared, not the last row that exists.
       Every wrapper that doesn't directly hold the name is dissolved,
       whatever its class. */
    .team-strip .w-grid-item-h :is(.w-vwrapper, .w-hwrapper):not(:has(> .tm-name)) {
        display: contents;
    }

    /* ----------------------------------------------------------------------
       23.7.4  PHOTO AND SHADE
       16.0 already pins the photo to all four edges. With tm-media dissolved,
       the edges it pins to are now the card's.
       The shade is the story cards' (20.6.4). It is the band behind the role
       and name at rest, and spreads up over the whole photo when the card
       opens.
       ---------------------------------------------------------------------- */
    .team-strip .tm-photo img {
        object-position: center 22%;
        scale: calc(1 + var(--so) * .04);
        transition: scale 800ms var(--tm-ease);
    }

    .team-strip.team-strip .w-grid-item-h::before {
        content: "";
        grid-area: 2 / 1 / -1 / -1;
        z-index: 1;
        background: var(--tm-shade);
        box-shadow: 0 0 0 calc(var(--so) * 150vh) var(--tm-shade);
        box-shadow: 0 0 0 calc(var(--so) * 170cqi) var(--tm-shade);
        transition: box-shadow 640ms cubic-bezier(.45, 0, .2, 1);
        pointer-events: none;
    }

    /* ----------------------------------------------------------------------
       23.7.5  ROLE, ARROW, NAME AND LINKEDIN
       Placed by grid area, so the layout's element order doesn't matter.
       The arrow is drawn on the role, sitting on the band's top edge, and
       fades as the card opens.
       ---------------------------------------------------------------------- */
    .team-strip .tm-role.tm-role.tm-role {
        grid-area: 2 / 1;
        position: relative;
        z-index: 2;
        margin: 0;
        padding: var(--sy) calc(var(--sx) + var(--sa) + 12px) 0 var(--sx);
        font-family: var(--font-family, inherit);
        font-size: clamp(14px, 4.3cqi, 19px);
        font-weight: 700;
        line-height: 1.25;
        color: var(--tm-blue);
    }

    .team-strip .tm-role.tm-role.tm-role::after {
        content: "";
        position: absolute;
        top: 0;
        right: var(--sx);
        width: var(--sa);
        aspect-ratio: 1;
        border-radius: 20%;
        background:
            url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='%23111'%20stroke-width='1.5'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cpath%20d='M19%2012H5'/%3E%3Cpath%20d='M11%206l-6%206%206%206'/%3E%3C/svg%3E")
                center / 48% no-repeat,
            var(--tm-blue);
        translate: 0 -50%;
        opacity: calc(1 - var(--so));
        scale: calc(1 - var(--so) * .15);
        transition:
            opacity 260ms ease,
            scale var(--tm-speed) var(--tm-ease);
    }

    /* The name row, whichever class it carries (see 23.7.3). */
    .team-strip.team-strip .w-grid-item-h :is(.w-hwrapper, .w-vwrapper):has(> .tm-name) {
        display: flex;
        flex-direction: row;
        flex-wrap: nowrap;
        justify-content: space-between;
        grid-area: 3 / 1;
        position: relative;
        z-index: 2;
        align-items: center;
        gap: 12px;
        width: auto;
        margin: 0;
        padding: .12em var(--sx) var(--sy);
    }

    .team-strip .tm-name.tm-name.tm-name {
        font-family: var(--font-family, inherit);
        font-size: clamp(24px, 9.5cqi, 48px);
        font-weight: 300;
        line-height: 1.1;
        color: #fff;
    }

    .team-strip .tm-linkedin.tm-linkedin.tm-linkedin {
        width: clamp(22px, 7cqi, 30px);
    }

    /* ----------------------------------------------------------------------
       23.7.6  BIO
       16.0 lays the bio over the whole photo. Here it becomes the card's
       bottom row instead, closed at zero height and opened by --so.
       max-height rather than the 0fr trick in 20.6.6, because Post Content
       outputs its paragraphs directly with no single wrapper to collapse.
       The bio is its own scroll box, and 120cqi is more than the card's
       height, so the grid, not max-height, decides how much of it fits.
       Seven classes: 16.0's hover rule is (0,6,0) and would otherwise set
       the bio to fully visible regardless of --so.
       ---------------------------------------------------------------------- */
    .team-strip.team-strip.team-strip .w-grid-item .tm-bio.tm-bio.tm-bio {
        grid-area: 4 / 1;
        position: relative;
        inset: auto;
        z-index: 2;
        min-height: 0;
        max-height: calc(var(--so) * 120cqi);
        margin: 0;
        padding: 0 var(--sx);
        background: none;
        overflow-x: hidden;
        overflow-y: auto;
        overscroll-behavior-x: contain;
        scrollbar-width: none;
        font-size: clamp(14px, 3.9cqi, 17px);
        line-height: 1.5;
        color: rgb(255 255 255 / .92);
        opacity: var(--so);
        visibility: visible;
        transition:
            max-height 560ms var(--tm-ease),
            opacity 320ms ease;
    }

    .team-strip .tm-bio::-webkit-scrollbar {
        display: none;
    }

    .team-strip.team-strip .tm-bio.tm-bio.tm-bio p:first-child {
        margin-top: clamp(10px, 3.5cqi, 20px);
    }

    .team-strip.team-strip .tm-bio.tm-bio.tm-bio :is(p, div):last-child {
        margin-bottom: clamp(20px, 8cqi, 44px);
    }

    /* ----------------------------------------------------------------------
       23.7.7  OPEN STATE
       Same three ways in as the story cards:
         .is-open        tapped, added by the TEAM STRIP snippet
         :focus-visible  keyboard; the snippet makes each card focusable
         hover           mouse only
       On a touch screen with the snippet missing, every card is shown open,
       so the bios are never unreachable.
       ---------------------------------------------------------------------- */
    .team-strip.team-strip.team-strip .w-grid-item.is-open,
    .team-strip.team-strip.team-strip .w-grid-item:focus-visible {
        --so: 1;
    }

    @media (hover: hover) {
        .no-touch .team-strip.team-strip.team-strip .w-grid-item:hover {
            --so: 1;
        }
    }

    @media (hover: none) {
        html:not(.team-js) .team-strip.team-strip.team-strip .w-grid-item {
            --so: 1;
        }
    }

    /* ----------------------------------------------------------------------
       23.7.8  CONTROLS
       Built by the TEAM STRIP snippet and placed straight after the list,
       the same as the story cards' (20.6.9).
       ---------------------------------------------------------------------- */
    .team-nav {
        display: flex;
        align-items: center;
        justify-content: center;
        gap: 20px;
        margin-top: 24px;
    }

    .team-nav .arrow-btn.arrow-btn.arrow-btn {
        --ab-size: 48px;
    }

    .team-nav .arrow-btn.arrow-btn.arrow-btn:disabled {
        opacity: .3;
        cursor: default;
        pointer-events: none;
    }

    .team-count {
        min-width: 3.5em;
        font-family: var(--font-family, inherit);
        font-size: 15px;
        font-variant-numeric: tabular-nums;
        text-align: center;
        color: rgb(255 255 255 / .8);
    }
}


/* ==========================================================================
   23.8  A LITTLE HISTORY
   The dark panel carries copy-panel and its arrow carries panel-arrow, so
   19.3 and 19.4 do most of the work. This section handles three things:
     - the heading block. Its 60px margin and 80px padding (Design Options)
       squeezed "A little history" and the line under it into the middle of
       the screen. Both headings are now pinned left, flush with the panel's
       edge below.
     - stacking the two columns from 900px rather than Impreza's 768px
     - a gutter, because the row is full width and 19.3 zeroes the panel's
       margins
   ========================================================================== */
@media (max-width: 1320px) {
    .about-history .history-head.history-head {
        align-items: flex-start;
        margin-left: 40px !important;
        padding: 48px !important;
        text-align: left;
    }

    .about-history .history-head .w-text {
        width: 100%;
        text-align: left !important;
    }
}

@media (max-width: 900px) {
    .about-history .g-cols.g-cols.g-cols.g-cols {
        display: block;
    }

    .about-history .g-cols.g-cols.g-cols.g-cols > .wpb_column {
        width: 100%;
        max-width: none;
        margin: 0;
    }

    .about-history .g-cols.g-cols > .wpb_column > .vc_column-inner {
        padding-left: var(--abt-gutter);
        padding-right: var(--abt-gutter);
    }

    .about-history .history-head.history-head {
        width: 100%;
        max-width: none;
        margin: 0 !important;
        padding: 0 0 24px !important;
    }

    .about-history .history-head h2 {
        margin: 0 0 .4em;
    }

    .about-history .history-head h2:last-child {
        margin-bottom: 0;
    }

    .about-history .history-panel h2 {
        margin: 0 0 .8em;
        font-size: clamp(20px, 4.4vw, 26px);
        line-height: 1.3;
    }

    .about-history .history-panel .wpb_text_column {
        margin: 0 0 1.4rem;
    }

    .about-history .history-panel .wpb_text_column p {
        margin: 0 0 1em;
        font-size: clamp(15px, 2vw, 17px);
        line-height: 1.6;
    }

    .about-history .history-panel .wpb_text_column p:last-child {
        margin-bottom: 0;
    }
}


/* ==========================================================================
   23.9  REDUCED MOTION
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
    .team-strip .w-grid-item,
    .team-strip .w-grid-item-h::before,
    .team-strip .tm-photo img,
    .team-strip .tm-role::after,
    .team-strip .tm-bio {
        transition-duration: 1ms;
    }
}

/* ==========================================================================
   24.0  SECTOR PAGE
   Append to the END of the site stylesheet (after 23.9).
   --------------------------------------------------------------------------
   CONTENTS
     24.1  Hero badge
   ========================================================================== */

/* --------------------------------------------------------------------------
   24.1  HERO BADGE
   The coloured square in the sector hero, holding the outlined sector name
   and the standfirst.
   --------------------------------------------------------------------------
   NO CLASS NEEDED
   It is found as the wrapper that directly holds .hero-standfirst. That
   class only appears in this hero, so every sector page picks this up with
   no editor changes.
   --------------------------------------------------------------------------
   WHY IT RAN OFF THE SCREEN
   Design Options fixes the box at 500 x 500px, written !important. Below
   about 580px there is not 500px of room inside the gutters, so the box
   overhung the right edge and took the end of the standfirst with it.
   The width now caps at 500px and otherwise fills the column. aspect-ratio
   with height:auto keeps it square as a floor rather than a cage: a long
   sector name ("Commercial Engineering") grows the box instead of spilling
   out of it.
   The background colour is left with Design Options, so each sector keeps
   its own.
   --------------------------------------------------------------------------
   SPECIFICITY
   Six classes, (0,6,0), clear three !important rules:
     .us_custom_*                                    the 500px box   (0,1,0)
     19.2  .l-section.full_height .w-vwrapper...:has(h1)  60px margin (0,4,1)
     18.3  sizes the H1 and is left alone; it already takes the name down
           to 44px at tablet and 32px on phones, which fits the box.
   -------------------------------------------------------------------------- */
.l-section.full_height .w-vwrapper.w-vwrapper.w-vwrapper:has(> .hero-standfirst) {
    --hb-size: 500px;
    --hb-pad-mobile: 24px;
    box-sizing: border-box;
    width: min(var(--hb-size), 100%) !important;
    max-width: 100%;
    min-width: 0;
    height: auto !important;
    min-height: 0;
    aspect-ratio: 1 !important;
}

/* Neither line may push the box wider than itself. overflow-wrap only
   breaks a word that cannot fit on a line of its own, so normal copy wraps
   between words as usual. */
.l-section.full_height .w-vwrapper.w-vwrapper:has(> .hero-standfirst) > :is(.hero-title, .hero-standfirst) {
    max-width: 100%;
    margin: 0;
    overflow-wrap: break-word;
}

.l-section.full_height .w-vwrapper.w-vwrapper:has(> .hero-standfirst) > .hero-standfirst {
    line-height: 1.25;
    text-wrap: balance;
}

/* --- tablets and phones --------------------------------------------------
   19.2 adds a 60px (then 40px) top margin to the hero's H1 wrapper, which
   is this box. The section already centres it vertically, so the margin
   only pushed it off centre. */
@media (max-width: 900px) {
    .l-section.full_height .w-vwrapper.w-vwrapper.w-vwrapper:has(> .hero-standfirst) {
        margin-top: 0 !important;
    }
}

@media (max-width: 600px) {
    .l-section.full_height .w-vwrapper.w-vwrapper.w-vwrapper:has(> .hero-standfirst) {
        padding: var(--hb-pad-mobile) !important;
    }
}

/* ==========================================================================
   25.0  CAPABILITIES OVERVIEW — MOBILE FIXES
   Append to the END of the stylesheet (after 24.1). Three unrelated problems
   that all surface below 900px.
   --------------------------------------------------------------------------
   CONTENTS
     25.1  Split band arrow, corrected for 19.8's padding override
     25.2  Multi-Axis image column, stacked at tablet
     25.3  CNC Turning, image flush to the section's foot
   --------------------------------------------------------------------------
   FILE POSITION IS LOAD-BEARING
   Every rule here is undoing something declared earlier — 19.6 and 19.8 in
   particular. Several are ties on specificity that win on order alone, so
   nothing may be inserted between this section and the end of the file that
   reuses these selectors.
   ========================================================================== */


/* --------------------------------------------------------------------------
   25.1  SPLIT BAND ARROW — corrected for 19.8's padding override
   --------------------------------------------------------------------------
   5.2's mobile block sets a large padding-top on the panel specifically so
   the arrow — which is out of flow and can't push anything down itself — has
   somewhere to sit. 19.8 then replaces the panel's padding wholesale with
   `32px 28px !important`, which wipes that allowance, and the arrow lands on
   top of the standfirst.
   19.8 also moves the inline padding from 24px to 28px, which
   --sb-arrow-m-x in 5.2 doesn't know about, so the arrow sits 4px off the
   copy's left edge as well. Both values are restated below against 19.8's
   actual numbers.
   --------------------------------------------------------------------------
   :not(.band-inset) KEEPS THIS OFF THE INSET VARIANT, which puts its arrow on
   the horizontal seam between photo and panel instead and has its own
   treatment in 5.2.1. Without the exclusion this would drag it back down into
   the panel.
   --------------------------------------------------------------------------
   Six repeats on the padding rule. 19.8's is (0,4,0) plus !important; a tie
   would lose on order, since 19.8 loads first — so this has to clear it
   outright rather than match it.
   -------------------------------------------------------------------------- */
@media (max-width: 900px) {
    .split-band:not(.band-inset) {
        /* The panel's ACTUAL inline padding on mobile, set by 19.8. Change it
           there and here together, or the arrow drifts off the copy's edge. */
        --sb-pad-inline-m: 28px;
        /* Panel's top edge to the top of the arrow. */
        --sb-arrow-m-top: 12px;
        /* Bottom of the arrow to the standfirst. */
        --sb-arrow-clear: 18px;
        /* Arrow's CENTRE, in from the panel's left edge. */
        --sb-arrow-m-x: calc(var(--sb-pad-inline-m) + var(--sb-arrow-size) / 2);
    }

    .split-band.split-band.split-band:not(.band-inset) .band-panel.band-panel {
        padding-top: calc(
            var(--sb-arrow-m-top) + var(--sb-arrow-size) + var(--sb-arrow-clear)
        ) !important;
    }

    .split-band:not(.band-inset) .band-panel .w-btn-wrapper:has(.band-arrow) {
        top: calc(var(--sb-arrow-m-top) + var(--sb-arrow-size) / 2);
        left: var(--sb-arrow-m-x);
        right: auto;
        bottom: auto;
        translate: -50% -50%;
    }
}


/* --------------------------------------------------------------------------
   25.2  MULTI-AXIS IMAGE COLUMN — stacked at tablet
   --------------------------------------------------------------------------
   THIS IS A MARKUP PROBLEM, NOT A CSS ONE
   The row mixes breakpoints: the copy column is vc_col-md-6, which only
   resolves to 50% above 901px, while the image column is vc_col-sm-6, which
   is 50% from 601px up. So between 601 and 900 the first column goes full
   width and the second stays at half — and the images inside it inherit that
   half. stack-row then stacks them correctly, at half the width they should
   be.
   The right fix is in the editor: put both columns on the same breakpoint.
   Once that's done this block is redundant and should be deleted.
   --------------------------------------------------------------------------
   (0,3,0) against .vc_col-sm-6 at (0,1,0). The margin gives the stacked
   columns the gap the flex row was providing.
   -------------------------------------------------------------------------- */
@media (max-width: 900px) {
    #multi-axis-cnc .g-cols.g-cols > .wpb_column {
        width: 100%;
        max-width: 100%;
        min-width: 0;
        margin: 0 0 24px;
    }

    #multi-axis-cnc .g-cols.g-cols > .wpb_column:last-child {
        margin-bottom: 0;
    }
}


/* --------------------------------------------------------------------------
   25.3  CNC TURNING — image flush to the section's foot
   --------------------------------------------------------------------------
   The dark surface under the image is the SECTION's background
   (us_custom_c8b8285f), not the image wrapper's — so once the columns stack,
   the section's own bottom padding renders as a band of dark below the photo.
   Zeroing it lets the image meet the section edge, and the bottom corners are
   squared so it does that cleanly rather than showing two rounded notches.
   The radius carries !important to clear 19.6's, which is (0,2,0) !important.
   --------------------------------------------------------------------------
   IF A STRIP IS STILL THERE after this, it's a leftover column margin rather
   than section padding — the two look identical on screen. Check the image
   column's Design Options before adding anything else here.
   -------------------------------------------------------------------------- */
@media (max-width: 900px) {
    .l-section#cnc-turning > .l-section-h {
        padding-bottom: 0;
    }

    #cnc-turning .fluid-media.fluid-media.fluid-media {
        border-radius: 16px 16px 0 0 !important;
    }
}
/* ==========================================================================
   25.4  CERTIFICATIONS & APPROVALS
   REPLACES the previous 25.4 entirely.
   Pairs with the CERTIFICATIONS & APPROVALS JS snippet.

   The logo row runs in one of two ways, and THIS FILE decides which:

     AUTO    1025px and up. Logos side by side, no arrows. The row moves on
             by one logo every few seconds, round and round.
                 1025 to 1320 (laptop)    two across
                 1321 and up  (desktop)   three across
             White logos, blue on hover. It waits while the pointer is over
             the row.

     SWIPE   1024px and below. One logo centred and blue, its neighbours
             dimmed, with  [ ← ]  1 / 4  [ → ]  underneath.

   The JS never looks at the screen width. It reads two custom properties
   off the row: --cert-auto (1 = run itself) and --cert-cols (how many
   across). Change the breakpoints in 25.4.1 and nothing else needs to know.

   Visitors who have asked for reduced motion get SWIPE at every width, so
   nothing moves by itself for them. That is why the SWIPE numbers below
   still have a 1025px-and-up row.

   Delete any earlier .logo-swap / .logo-white / .logo-blue rules first.
   The rules below also neutralise the usual suspects (absolute positioning,
   transforms, the 75% sizing from the editor), but it's cleaner with one
   source of truth.
   ========================================================================== */

/* --------------------------------------------------------------------------
   25.4.1  THE NUMBERS
   Every percentage here is a share of the ROW's width, not of one logo's
   slot. (Percentage padding on a flex item always measures the container.)

   SWIPE
       --cert-w     one logo slot. Smaller = more neighbours in view.
       --cert-pad   clear space either side of the logo, inside its slot.
                    The logo's own width is --cert-w minus twice this.
                      slot    pad    logo     in view
       600 and below   62%    10%    42%      one, neighbours just peeking
       601 to 1024     38%    10%    18%      one, a third of each neighbour
       1025 and up     26%    4.5%   17%      (reduced motion only)

   AUTO
       --cert-auto  1 switches it on.
       --cert-cols  how many logos across. Each slot is an equal share of
                    the row, and the logo fills the middle 60% of its slot.
   -------------------------------------------------------------------------- */
#cert-approve {
    --cert-h: clamp(90px, 8vw, 140px);   /* height of each logo box        */
    --cert-gap: 16px;                    /* between slots                  */
    --cert-gutter: 0px;                  /* either side of heading and row */

    --cert-w: 62%;                       /* phones                         */
    --cert-pad: 10%;

    --cert-auto: 0;
    --cert-cols: 3;
}

@media (min-width: 601px) {
    #cert-approve {
        --cert-w: 38%;                   /* tablets: neighbours peek in more */
    }
}

/* Laptop: the row runs itself, two across. */
@media (min-width: 1025px) {
    #cert-approve {
        --cert-gap: 30px;
        --cert-gutter: clamp(20px, 5vw, 100px);

        --cert-w: 26%;
        --cert-pad: 4.5%;

        --cert-auto: 1;
        --cert-cols: 2;
    }
}

/* Desktop: three across. */
@media (min-width: 1321px) {
    #cert-approve {
        --cert-cols: 3;
    }
}

/* --------------------------------------------------------------------------
   25.4.2  THE SECTION
   -------------------------------------------------------------------------- */

/* While the script swaps Owl out, hide Owl so it doesn't flash. The class
   is removed on success and on failure, so the logos always end up visible. */
html.cert-js #cert-approve .owl-carousel {
    visibility: hidden;
}

/* The section is width_full, so it has no inline padding of its own. The
   gutter goes on the heading (and, in AUTO, on the row) rather than on the
   whole section, which leaves the SWIPE row free to run to the screen
   edges. Zero below 1025px, so this does nothing there. */
#cert-approve .wpb_text_column {
    padding-inline: var(--cert-gutter);
}

/* A carousel can't carry padding on one side only. */
#cert-approve .w-content-carousel {
    padding-left: 0 !important;
}

/* --------------------------------------------------------------------------
   25.4.3  ONE LOGO: white and blue stacked in the same box
   The vertical padding is a share of the box's own height. It used to be
   6%, which is 6% of the row's WIDTH: 23px on a phone, 115px on a 1920px
   row, inside a 140px box. The grid track is pinned to the box as well
   (minmax(0, 1fr)), so a tall logo is scaled to fit rather than pushing
   out of the bottom.
   -------------------------------------------------------------------------- */
#cert-approve .cert-item {
    display: grid !important;       /* overrides the vwrapper's flex column */
    grid-template: "logo" minmax(0, 1fr) / minmax(0, 1fr);
    place-items: center;
    gap: 0 !important;
    height: var(--cert-h);
    padding: calc(var(--cert-h) * 0.12) var(--cert-pad);
    margin: 0 !important;
    box-sizing: border-box;
    transition: filter 0.35s ease, scale 0.35s ease;
}

#cert-approve .cert-item > .w-image {
    grid-area: logo;
    position: relative !important;
    inset: auto !important;
    transform: none !important;
    width: 100% !important;         /* beats the editor's 75% */
    height: 100% !important;
    margin: 0 !important;
    transition: opacity 0.3s ease;
}

#cert-approve .cert-item .w-image-h {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: 100%;
}

#cert-approve .cert-item img {
    display: block;
    width: 100% !important;
    height: 100% !important;
    object-fit: contain;
}

/* White by default, blue on hover. */
#cert-approve .cert-item .logo-white { opacity: 1; }
#cert-approve .cert-item .logo-blue  { opacity: 0; }

@media (hover: hover) {
    #cert-approve .cert-item:hover .logo-white { opacity: 0; }
    #cert-approve .cert-item:hover .logo-blue  { opacity: 1; }
}

/* --------------------------------------------------------------------------
   25.4.4  THE ROW, SWIPE
   This is the row as the script first builds it. AUTO (25.4.5) is layered
   on top by the .is-auto class.
   -------------------------------------------------------------------------- */
#cert-approve .cert-row {
    display: flex;
    gap: var(--cert-gap);
    align-items: center;
    padding-block: 12px;            /* breathing room, nothing clips */
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scroll-snap-type: x mandatory;
    scrollbar-width: none;          /* a mouse would otherwise get a bar */
    -webkit-overflow-scrolling: touch;
}

#cert-approve .cert-row::-webkit-scrollbar {
    display: none;
}

/* Spacers either side, so the first and last logo can sit centred.
   (Pseudo-elements rather than padding: some browsers drop the end
   padding of a scrolling flex row.) */
#cert-approve .cert-row::before,
#cert-approve .cert-row::after {
    content: "";
    flex: 0 0 calc((100% - var(--cert-w)) / 2 - var(--cert-gap));
}

#cert-approve .cert-row > .cert-item {
    flex: 0 0 var(--cert-w);
    scroll-snap-align: center;
}

/* Neighbours dim back; the centred logo shows in blue. .is-carousel is only
   on the row while it is a SWIPE row that scrolls, so a lone logo keeps the
   plain hover swap, and so does AUTO.

   The dim is filter: opacity() and the shrink is the individual `scale`
   property, NOT `opacity` and `transform`. Three of the four logos carry an
   Impreza entrance animation (us_animate_this), and once that has played it
   keeps hold of the logo's opacity and transform, so plain ones here were
   ignored and those logos stayed full size at full white. An animation only
   holds the properties in its own keyframes; filter and scale are not among
   them. */
#cert-approve .cert-row.is-carousel > .cert-item:not(.is-current) {
    filter: opacity(0.35);
    scale: 0.88;
    cursor: pointer;
}

#cert-approve .cert-row.is-carousel > .is-current .logo-white { opacity: 0; }
#cert-approve .cert-row.is-carousel > .is-current .logo-blue  { opacity: 1; }

/* With a mouse, a dimmed neighbour lifts as well as turning blue, so it
   reads as something to click. Clicking it brings it to the centre. */
@media (hover: hover) {
    #cert-approve .cert-row.is-carousel > .cert-item:not(.is-current):hover {
        filter: opacity(0.8);
    }
}

/* --------------------------------------------------------------------------
   25.4.5  THE ROW, AUTO
   The script adds .is-auto where --cert-auto is 1, and .is-looping while
   there are logos out of view and the row is actually moving.

   overflow-x: hidden, not clip. The script moves the row by scrolling it,
   and a clipped box can't be scrolled at all; hidden still can be, just
   not by the visitor. (Rule 1 at the top of this file is about scroll
   timelines. Nothing in this row uses one.)

   Snap is off: the script places the row itself, and with snap on, the
   jump back to the start of the loop is re-snapped and twitches.
   -------------------------------------------------------------------------- */
#cert-approve .cert-row.is-auto {
    margin-inline: var(--cert-gutter);  /* lines up with the heading */
    overflow-x: hidden;
    scroll-snap-type: none;
}

/* No centring spacers: the first logo starts at the row's left edge. */
#cert-approve .cert-row.is-auto::before,
#cert-approve .cert-row.is-auto::after {
    content: none;
}

/* Equal shares of the row, less the gaps between them. The logo fills the
   middle 60% of its slot: 20% of a slot each side, and a slot is one
   --cert-cols'th of the row. */
#cert-approve .cert-row.is-auto > .cert-item {
    flex-basis: calc((100% - (var(--cert-cols) - 1) * var(--cert-gap)) / var(--cert-cols));
    padding-inline: calc(20% / var(--cert-cols));
}

/* Every logo fits, so nothing moves. Sit them in the middle. (Only when
   it isn't looping: centring a row that overflows pushes its first logo
   off the left where it can't be scrolled back to.) */
#cert-approve .cert-row.is-auto:not(.is-looping) {
    justify-content: center;
}

/* --------------------------------------------------------------------------
   25.4.6  NAV:  [ ← ]  1 / 4  [ → ]
   SWIPE only. The script hides it in AUTO, and when there is nothing to
   scroll.
   -------------------------------------------------------------------------- */
.cert-nav {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 1.5rem;
    margin-top: 1.5rem;
}

.cert-nav[hidden] {
    display: none !important;
}

.cert-count {
    min-width: 4ch;
    text-align: center;
    font-size: 1rem;
    font-variant-numeric: tabular-nums;
    color: var(--color-white);
    opacity: 0.8;
}

.cert-nav .arrow-btn:disabled {
    opacity: 0.35;
    cursor: default;
    pointer-events: none;
}

@media (prefers-reduced-motion: reduce) {
    #cert-approve .cert-item,
    #cert-approve .cert-item > .w-image {
        transition: none;
    }
}

/* ==========================================================================
   5.13.1  ACCORDION — images at one set height
   Paste at the very end of the stylesheet. DELETE the earlier
   "PLANT LIST — accordion images at one set height" block if it is in there;
   this replaces it.
   --------------------------------------------------------------------------
   WHY THE IMAGES WERE THE WRONG SIZE
   5.13 already sizes these images, in two ways:
     two or three images   height: var(--hec-media-height), which is 30rem.
                           1rem is 30px on this site, so every image sat in a
                           box 900px tall and the picture floated in the
                           middle of it. That is the gap above and below the
                           height gauges.
     one image             height: auto at the full width of the column, so a
                           tall picture (the Mitutoyo projector, the Pioneer
                           CMM) came out 900 to 1300px high.
   --------------------------------------------------------------------------
   WHAT THIS DOES
   Every image gets the same height, --hec-img-h. The width follows the
   picture's own shape, nothing is cropped, and a set of two or three sits
   side by side in the middle of the column. A set too wide for the column
   shrinks to fit, still in proportion.
   --hec-img-h is the one number to change: smallest, scales with the
   screen, largest. Written in px, not rem, because 1rem is 30px here.
   --------------------------------------------------------------------------
   WEIGHT
   5.13's one-image rule is (0,4,0), so anything lighter loses to it however
   late it sits in the file. Each class is written twice here, (0,6,0),
   which clears it and the 600px rule without !important.
   ========================================================================== */
.hec-accordion.hec-accordion {
    --hec-img-h: clamp(200px, 22vw, 340px);
}

.hec-accordion.hec-accordion .hec-acc__media.hec-acc__media > .hec-acc__img.hec-acc__img {
    flex: 0 1 auto;
    width: auto;
    min-width: 0;
    max-width: 100%;
    height: var(--hec-img-h);
    max-height: none;
    object-fit: contain;
    object-position: center;
}

/* NEWS POST CAROUSEL: image shape and corners */

.news-post-gallery {
    --nc-ratio: 2 / 3;      /* width / height of each image */
    --nc-radius: 20px;
}

.news-post-gallery .w-post-elm.post_image {
    aspect-ratio: var(--nc-ratio);
    border-radius: var(--nc-radius);
    overflow: hidden;
}

/* The image may be wrapped in a link to the post. */
.news-post-gallery .w-post-elm.post_image a {
    display: block;
    height: 100%;
}

/* Fill the frame and crop, rather than stretch. */
.news-post-gallery .w-post-elm.post_image img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
}


.vacancy-h3-h4-headings h3, .vacancy-h3-h4-headings h3 *, .vacancy-h3-h4-headings h4, .vacancy-h3-h4-headings h4 * {
	color: var(--color-blue) !important;
}

/* ===== Careers – laptop / vertical monitor (1001–1320px) ===== */
@media (min-width: 1001px) and (max-width: 1320px) {

	/* 1. Stack "Current opportunities" heading above the vacancy cards */
	#current-opportunity .g-cols.vc_row {
		grid-template-columns: 100%;
		--cols: 1;
	}

	/* 3. Blog/news grid: 2 columns instead of 3 */
	.w-grid.post-layout {
		--columns: 2 !important;
	}
}

/* 2. Job card labels: size to the text, never overlap the value.
      Applied at all sizes, since it can happen any time the card is narrow */
#current-opportunity .layout_2340 .usg_text_1,
#current-opportunity .layout_2340 .usg_text_2 {
	width: auto !important;
	min-width: 7em;
	flex: 0 0 auto;
	padding-right: 0.5rem;
}

/* ==========================================================================
   26.0  SUPPLIER BAND — BANNER ONLY
   SUPERSEDES 5.12 and 20.9. Paste at the very END of the stylesheet (renumber
   if 26 is taken). Once it's live and checked, 5.12 and 20.9 can be deleted.
   --------------------------------------------------------------------------
   WHAT CHANGED
   The band is now just the client's own banner artwork. No logo slot, no
   overlay. They design the whole thing, logo included.
     Laptop / desktop / tablet   full content width, 1600 x 300 at full size
     Phone (600px and below)     full content width x 200px, mobile artwork
   --------------------------------------------------------------------------
   WHY THE DESKTOP BAND SCALES RATHER THAN STAYING 300px HIGH
   An advert has the client's logo and wording in it, so it must never be
   cropped. A fixed 300px height on an 810px-wide tablet would show only the
   middle half of a 1600px banner. Instead the band keeps the 1600:300 shape,
   so it is exactly 300px high at full width and shrinks in proportion below
   that. The whole banner always shows.
   The phone band is a fixed 200px as asked, so the mobile artwork is drawn
   to the typical phone shape (700 x 400, see the note at the end). Its edges
   can lose a little on unusually narrow or wide phones.
   --------------------------------------------------------------------------
   EDITOR
   Remove the "advert_client_logo" custom field from the advert Grid Layout,
   and from the advert field group so editors aren't asked for one. The rule
   below hides it anyway, so nothing breaks in the meantime.
   --------------------------------------------------------------------------
   Repeated classes, not !important, as everywhere else in this file.
   ========================================================================== */

/* --- tokens ------------------------------------------------------------- */
.supplier-adverts.supplier-adverts.supplier-adverts {
    --sb-ratio: 1600 / 300;     /* desktop artwork shape                     */
    --sb-max-h: 300px;          /* never taller than this                    */
    --sb-mobile-h: 200px;       /* phone band height                         */
    --sb-radius: 20px;          /* matches the footer information box        */
    --sb-bleed: 0px;            /* see 26.0 note on width, below             */
    --sb-bg: var(--color-dark-dark-grey, #333);   /* shows while it loads    */
}

/* --- width ---------------------------------------------------------------
   The band fills the content width, which tops out at --site-content-width
   (1600px), the same container the footer box sits in.
   The adverts sit in a section nested inside another section, and a nested
   section adds its own side padding on top of its parent's. That would inset
   the band a second time, so it is taken off here. A nested section with no
   background gains nothing from the padding.
   IF THE FOOTER BOX STILL STICKS OUT PAST THE BANNER at full width, measure
   the difference on one side and put it in --sb-bleed (e.g. 22px). The
   banner then reaches out by that much each side.
   ------------------------------------------------------------------------- */
.l-section .l-section:has(.supplier-adverts) {
    --padding-inline: 0px;
    padding-left: 0;
    padding-right: 0;
}

.supplier-adverts.supplier-adverts.supplier-adverts,
.supplier-adverts.supplier-adverts.supplier-adverts .w-grid-list,
.supplier-adverts.supplier-adverts.supplier-adverts .w-grid-item,
.supplier-adverts.supplier-adverts.supplier-adverts .w-grid-item-h {
    width: auto;
    max-width: none;
    margin: 0;
    padding: 0;
    background: none;
}

.supplier-adverts.supplier-adverts.supplier-adverts {
    margin-left: calc(-1 * var(--sb-bleed));
    margin-right: calc(-1 * var(--sb-bleed));
}

/* --- the band ------------------------------------------------------------
   height: auto is what lets aspect-ratio work. Any fixed height left over
   from 5.12 (the old 225px) would switch it off.
   ------------------------------------------------------------------------- */
.supplier-adverts.supplier-adverts.supplier-adverts .supplier-band {
    position: relative;
    display: block;
    width: 100%;
    max-width: none;
    height: auto;
    min-height: 0;
    max-height: var(--sb-max-h);
    aspect-ratio: var(--sb-ratio);
    margin: 0;
    padding: 0;
    border-radius: var(--sb-radius);
    background: var(--sb-bg);
    overflow: clip;
}

/* Each image fills the band. cover rather than contain, so there are never
   bars down the sides; at the desktop shape it is an exact fit anyway. */
.supplier-adverts.supplier-adverts.supplier-adverts .supplier-band > .w-post-elm {
    position: absolute;
    inset: 0;
    width: auto;
    height: auto;
    margin: 0;
    padding: 0;
}

.supplier-adverts.supplier-adverts.supplier-adverts .supplier-band :is(.sb-bg, .sb-bg-mobile) img {
    display: block;
    width: 100%;
    height: 100%;
    max-width: none;
    margin: 0;
    object-fit: cover;
    object-position: center;
    border-radius: 0;
}

/* --- no logo ------------------------------------------------------------ */
.supplier-adverts.supplier-adverts.supplier-adverts .sb-logo {
    display: none;
}

/* --- which artwork -------------------------------------------------------
   Desktop artwork above 600px, mobile artwork at 600px and below.
   If an advert has no mobile artwork (Impreza outputs a .g-placeholder image
   for an empty field), the desktop artwork stays on, cropped to the middle,
   rather than showing a blank band.
   ------------------------------------------------------------------------- */

.supplier-adverts.supplier-adverts.supplier-adverts .sb-bg {
    display: block;
}

.supplier-adverts.supplier-adverts.supplier-adverts .sb-bg-mobile {
    display: none;
}

@media (max-width: 600px) {
    .supplier-adverts.supplier-adverts.supplier-adverts .supplier-band {
        aspect-ratio: auto;
        height: var(--sb-mobile-h);
        max-height: none;
    }

    .supplier-adverts.supplier-adverts.supplier-adverts
        .supplier-band:has(.sb-bg-mobile img:not(.g-placeholder)) .sb-bg {
        display: none;
    }

    .supplier-adverts.supplier-adverts.supplier-adverts
        .supplier-band:has(.sb-bg-mobile img:not(.g-placeholder)) .sb-bg-mobile {
        display: block;
    }
}

/* ==========================================================================
   25.0  PLACEHOLDER LINKS — default cursor where a link goes nowhere
   --------------------------------------------------------------------------
   Any <a> with no href, an empty href, a bare "#" or a javascript: href
   shows the normal arrow instead of the hand. Real anchors (#page-top,
   #cert-approve) keep the hand, and <button>s (carousel arrows) are untouched.

   Left alone on purpose, because their "#" links open things:
     .l-header             mega menu parents, mobile menu toggle, search
     .w-popup-trigger      Impreza popups
     .cmplz-cookiebanner   cookie banner "Manage options" etc.

   Weight: the general rule is (0,2,1), which clears Impreza's .w-btn.
   3.3 sets the arrow button's cursor at (0,3,0), so it gets its own line.
   ========================================================================== */

a:is(:not([href]), [href=""], [href="#"], [href^="javascript:"]):not(.l-header *, .w-popup-trigger, .cmplz-cookiebanner *) {
    cursor: default !important;
}