/* ============================================================================
   PEF — site stylesheet.

   ONE FILE, deliberately. This was seven (tokens, base, fonts, buttons,
   header, surfaces, transparent-header), which was seven render-blocking
   requests for 20KB of CSS. They were split because they began life as
   separate Elementor Custom Code snippets; as theme files there is no reason
   for the split, and their load order was load-bearing, which a single file
   makes structural rather than something functions.php has to enforce.

   Enqueued at priority 999 so it lands AFTER Elementor's generated CSS.
   That is not optional. Elementor emits its global classes as
   `.elementor .foo{...}` — specificity (0,2,0), the same as most rules here —
   and equal specificity is broken by source order. Load this first and the
   is-hidden-mobile repair, the coloured-surface heading ink and every header
   override silently invert.

   Paired with pef-behaviour.js (footer-loaded) and the Elementor Variables
   panel, which owns the palette, spacing, type scale, radii and button
   padding. See section 1 for what is NOT in the panel and why.

   CONTENTS
     1  Tokens .................. the remainder that cannot be an Elementor variable
     2  Metric-matched fallbacks  @font-face, to stop the nav reflowing on load
     3  Header shell ............ sticky, elevation, logo, mobile-hide repair
     4  Mega menu — shared ...... titles, hub items, chevron
     5  Mega menu — desktop ..... >=1200: two columns + feature image
     6  Mega menu — compact ..... <=1199: full-screen panel, accordion rows
     7  Footer .................. link and social hover, mobile accordion
     8  Buttons ................. the remainder; the system lives in Elementor
     9  Coloured surfaces ....... heading ink on a coloured band
     10 Transparent header ...... driven by Page Settings -> Header
     11 Reduced motion .......... one block, everything the site animates
   ========================================================================= */


/* ============================================================================
   1. TOKENS
   ----------------------------------------------------------------------------
   MOST TOKENS LIVE IN ELEMENTOR, not here. Site Settings -> Variables holds
   the palette, the spacing steps, the flat type scale, the radii, border
   width, button padding and the font families. Elementor emits them as
   :root{--label:value} into the kit CSS and the global classes reference them
   by id, so renaming a variable updates every class that uses it.

   DO NOT REDEFINE AN ELEMENTOR VARIABLE HERE. This file is enqueued long
   after the kit CSS, so anything restated here silently overrides the
   Variables panel and makes it inert. That has now happened twice: first with
   42 tokens on the original pass, then with four type-scale steps
   (--text-display-lg/md, --text-editorial-lg/md) that survived the cleanup
   because their values happened to match. Nothing looked wrong; editing them
   in Elementor simply did nothing.

   WHAT REMAINS BELOW, and why each one cannot be an Elementor variable:
     - Anything that changes at a breakpoint. Elementor emits :root once, with
       no media queries, so a value that ramps across viewports has to live in
       CSS: --gutter-page, --display-xl-ramp, --pef-hdr-h.
     - Unitless ratios (line-height, tracking, font-weight). The size variable
       type expects a unit.
     - Multi-part values: easing curves, the crest radius geometry, shorthand
       rules, the chevron artwork.
     - ch-based measures.
     - Compositions of other tokens (the approved pairs).
   ========================================================================= */
:root{

  /* -- Breakpoint-dependent --------------------------------------------
     Page gutter. ONE formula, previously retyped into eight rules — the
     header bar, the footer's three bands, the mega-menu panel, the mobile
     toggle, the mobile panel and the section wrapper. Everything on the page
     aligns to the logo because they all resolve to this.
       >=1025px : 51 -> 100 across 1025 -> 1440
       <=1024px : 20 ->  51 across  390 -> 1024  (see the media query below) */
  --gutter-page:clamp(51px, calc(51px + 49 * (100vw - 1025px) / 415), 100px);

  /* Hero display type, per Figma: 96 / 68 / 44. Named --display-xl-ramp, not
     --text-display-xl: the Elementor variable `text-display-xl` points AT
     this one, and a variable whose value referenced its own name would be
     self-referential and therefore invalid. This is the only step in the type
     scale needing two ramps, which is why it cannot live in the panel. */
  --display-xl-ramp:clamp(68px, calc(68px + 28 * (100vw - 1025px) / 415), 96px);

  /* Header height. THE single source of truth for it. Read by header-bar's
     own min-height (set on the global class as var(--pef-hdr-h)), by the
     mobile toggle and panel, and by --section-pad-top-hero, so the bar and
     everything that has to clear it cannot drift apart.
     pef-behaviour.js used to measure the bar and publish a second property,
     --pef-header-h. It agreed with this token at every breakpoint on every
     test, so it was two names for one number and has been removed. */
  --pef-hdr-h:106px;


  /* -- Fluid type that is not breakpoint-switched but is still a clamp ----
     (--text-display-lg/md and --text-editorial-lg/md are NOT here. They are
     Elementor variables; see the warning above.) */


  /* -- Unitless ratios -------------------------------------------------- */
  --display-lh:0.78;   --display-tracking:0em;
  --editorial-lh:0.95; --editorial-tracking:-0.02em;
  --body-lh:1.2;       --body-lh-long:1.5;
  --ui-lh:0.9;         --ui-tracking:0.02em;
  --ui-tracking-sm:0.06em;  /* 13px eyebrows carry more tracking than 15px UI */

  --weight-body:400; --weight-body-strong:700; --weight-display:800;

  /* -- Measures --------------------------------------------------------- */
  --measure:62ch;
  --measure-narrow:44ch;

  /* -- Shape geometry -- derived from the logo crest: a square whose lower
     half is a half-circle. Only correct on a square frame. --------------- */
  --crest:0 0 50% 50% / 0 0 100% 100%;
  --crest-up:50% 50% 0 0 / 100% 100% 0 0;
  --smile:0 0 9999px 9999px;
  --arch:9999px 9999px 0 0;
  --rule:1px solid var(--border-hairline);
  --shadow-none:none;   /* the brand builds depth with flat colour, never shadow */

  /* -- Artwork ---------------------------------------------------------
     The design-system chevron (11 x 5.5), drawn as a mask so it takes
     currentColor. Used by the mega-menu dropdown icon and the footer
     accordion; it was previously typed out four times (each site needs both
     the -webkit- and standard property). viewBox is cropped to the artwork —
     with the full 0 0 24 24 box, `contain` leaves ~44% of the width empty and
     the glyph renders about half size. */
  --icon-chevron:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='5.25 8.25 13.5 7.5'%3E%3Cpath d='M6 9l6 6 6-6' fill='none' stroke='%23000' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");

  /* The CTA arrow, drawn rather than typed: Aptos Narrow Bold has no U+2197. */
  /* Card links point east: they go to another page on this site. */
  --icon-arrow-e:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M2.5 8h11M9 3.5 13.5 8 9 12.5' fill='none' stroke='%23000' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");

  --icon-arrow-ne:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='1.5 1.5 9 9'%3E%3Cpath d='M2.6 9.4 9.4 2.6M4.3 2.6h5.1v5.1' fill='none' stroke='%23000' stroke-width='2.1' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");

  /* -- Motion -- brisk, never bouncy. Colours change, geometry does not. -- */
  --ease-out:cubic-bezier(0.22,0.61,0.36,1);
  --ease-expo:cubic-bezier(.16,1,.3,1);   /* the reveal/slide curve used site-wide */
  --dur-fast:120ms;   /* hover, colour swaps */
  --dur-base:220ms;   /* reveals, menu open */
  --dur-slow:420ms;
  --hover-lift:none;
  --press-scale:0.98;

  /* -- Approved pairs -- two colours per execution, every pair reversible.
     Compositions of the Elementor colour variables, not new values. Figma:
     "Every pair measures 2.9:1 to 3.4:1: display type only, never body copy."
     The homepage hero is primary reversed — lime ground, green display. */
  --pair-primary-bg:var(--pef-lime);      --pair-primary-fg:var(--pef-green);
  --pair-secondary-a-bg:var(--pef-lilac); --pair-secondary-a-fg:var(--pef-orange);
  --pair-secondary-b-bg:var(--pef-blue);  --pair-secondary-b-fg:var(--pef-lilac);
  --pair-tertiary-bg:var(--pef-lime);     --pair-tertiary-fg:var(--pef-blue);
  --pair-restricted-bg:var(--pef-black);  --pair-restricted-fg:var(--pef-white);
}

/* Below the desktop breakpoint the gutter ramps 20 -> 51 across 390 -> 1024,
   and the hero display type ramps 44 -> 68 over the same span. Both switch at
   1024, Elementor's tablet breakpoint, where the global classes switch too. */
@media (max-width:1024px){
  :root{
    --gutter-page:clamp(20px, calc(20px + 31 * (100vw - 390px) / 634), 51px);
    --display-xl-ramp:clamp(44px, calc(44px + 24 * (100vw - 390px) / 634), 68px);
  }
}

/* The header bar is shorter on mobile only. */
@media (max-width:767px){
  :root{--pef-hdr-h:64px;}
}


/* ============================================================================
   2. METRIC-MATCHED FALLBACKS
   ----------------------------------------------------------------------------
   To stop the nav reflowing when Adobe Fonts lands.

   The problem: font-family and font-size never change during load — both are
   already "aptos-narrow" at 15px. What changes is which font is drawn. Until
   the Typekit file arrives the browser uses plain sans-serif, which is 22%
   WIDER than Aptos Narrow (measured: 624px vs 512px for the same string),
   because Aptos Narrow is condensed and the fallback is not. Every nav label
   then snaps narrower at once, which reads as the type changing size and cost
   0.058 of layout shift.

   The fix: wrap the local fallback in an @font-face and scale it with
   size-adjust so it occupies almost exactly the same width as the real face.
   The percentages are measured, not guessed — real width / Arial width at the
   weights each family is actually used at:
     aptos-narrow 700 : 511.7 / 624.0 = 82%
     aptos 400        : 569.0 / 632.2 = 90%
   A separate 700 face is declared so bold text maps to real Arial Bold rather
   than a synthesised bold, which would be wider again and undo the match.

   These faces used to be slotted in by a second stylesheet that restated
   font-family on six selectors purely to append the fallback. The full stack
   is now written into the original declaration in each case, so there is one
   place per element rather than two, and no ordering requirement between them.
   ANY NEW RULE THAT NAMES A FONT MUST NAME THE FALLBACK TOO.
   ========================================================================= */
@font-face{
  font-family:"aptos-narrow-fb";
  src:local("Arial"),local("Helvetica Neue"),local("Liberation Sans");
  size-adjust:82%;
  font-weight:400;
  font-style:normal;
}
@font-face{
  font-family:"aptos-narrow-fb";
  src:local("Arial Bold"),local("Arial-BoldMT"),local("Helvetica Neue Bold"),local("Liberation Sans Bold");
  size-adjust:82%;
  font-weight:700;
  font-style:normal;
}
@font-face{
  font-family:"aptos-fb";
  src:local("Arial"),local("Helvetica Neue"),local("Liberation Sans");
  size-adjust:90%;
  font-weight:400;
  font-style:normal;
}
@font-face{
  font-family:"aptos-fb";
  src:local("Arial Bold"),local("Arial-BoldMT"),local("Helvetica Neue Bold"),local("Liberation Sans Bold");
  size-adjust:90%;
  font-weight:700;
  font-style:normal;
}


/* ============================================================================
   3. HEADER SHELL
   ========================================================================= */
.elementor-location-header{position:sticky;top:0;z-index:100;}

/* Figma NavBar: Scroll=Top carries no elevation; Scroll=Scrolled adds
   Elevation/Header (drop-shadow #31352D14, offset 0 1, radius 3). The
   header-bar global class applies the shadow at all times, so it is cleared
   at rest and reinstated once the is-scrolled hook fires.
   ONE rule for this. It was previously declared in three places — twice here
   under competing selectors and again in the transparent-header file — with
   two of the three carrying !important at each other. */
.elementor-location-header .header-bar{
  position:relative;
  box-shadow:none;
  transition:box-shadow .2s ease;
}
.elementor-location-header.is-scrolled .header-bar{
  box-shadow:0 1px 3px 0 rgba(49,53,45,.08);
}

/* The button treatments set `display:inline-flex` on .btn with no media
   query. That matches .elementor .is-hidden-mobile at equal specificity but
   lands later in source order, so it was defeating the mobile hide and the
   Apply button stayed in the bar. Utility class wins. */
@media (max-width:767px){
  .elementor .is-hidden-mobile{display:none !important;}
}

/* The logo is an inline SVG with a viewBox and no width attribute, so its
   min-content width is 0. As a shrinkable flex item any header overflow
   collapses it to nothing (which is exactly what the rule above caused). */
.elementor-location-header a.logo{flex-shrink:0;}


/* ============================================================================
   4. MEGA MENU — SHARED
   ----------------------------------------------------------------------------
   Two Elementor internals govern this widget:
   1. Never give .e-n-menu-content padding or a border. Elementor leaves that
      wrapper in flow when the panel is closed and hides only the inner
      container, so anything that gives it height becomes an invisible
      click-blocker across the page. It does take .e-active itself when open,
      so open-only styling is keyed off that and stays safe.
   2. Each panel container carries data-tab-index (set via the element's
      Attributes prop) — activateTab() filters on it, so without it the panel
      never receives .e-active and cannot open.
   The title rules need the .elementor-location-header .e-n-menu prefix to
   outrank the widget's own typography, which otherwise forces 16px/24px.
   ========================================================================= */
.elementor-location-header .e-n-menu .e-n-menu-title-text{font-family:"aptos-narrow","aptos-narrow-fb",sans-serif;font-weight:700;font-size:15px;line-height:.9;letter-spacing:.02em;text-transform:uppercase;color:#31352D;display:block;}

/* Mobile browsers paint a translucent tap flash over a control when it is
   touched, and Site Settings gives every <button> a 9999px radius, so it
   landed as a dark pill behind the MENU label and behind each chevron.
   Suppressed only on controls that already answer a tap in their own right —
   the toggle relabels itself MENU/CLOSE and slides the panel, the chevrons
   rotate and expand a row — so nothing is left with no feedback at all. Links
   and the CTA buttons deliberately keep theirs, since for them the tap flash
   is the only acknowledgement before the page changes. */
.e-n-menu-toggle,
.e-n-menu-dropdown-icon,
.footer-eyebrow{
  -webkit-tap-highlight-color:transparent;
}

/* Hub link items — Figma NavDropdown "Item" (4144:17):
   Label/Tag  = Aptos Narrow Bold, 15px (--text-ui-md), line-height .9, 0.3px tracking, uppercase
   Body/UI    = Aptos Regular,     14px (--text-body-sm), line-height 1.2, no tracking
   4px between the two, 12px padding each side of the row, and the divider is
   the full-strength charcoal hairline rather than a tint. Item height 58. */
.e-n-menu .mm-t{display:block;font-family:"aptos-narrow","aptos-narrow-fb",sans-serif;font-weight:700;font-size:15px;line-height:.9;letter-spacing:.02em;text-transform:uppercase;color:#31352D;}
.e-n-menu .mm-d{display:block;font-family:"aptos","aptos-fb",sans-serif;font-weight:400;font-size:14px;line-height:1.2;letter-spacing:0;color:#31352D;margin-block-start:4px;}
.mega-panel .elementor-icon-list-item{break-inside:avoid;}
.mega-panel .elementor-icon-list-item > a{display:block;padding-block:12px;border-block-end:1px solid #31352D;text-decoration:none;}
.mega-panel .elementor-icon-list-item > a:hover .mm-t{color:#14A14D;}

/* Elementor's caret icons swapped for the design-system chevron (11 x 5.5).
   Elementor sets an explicit height:24px on the button, which would drive the
   row past its 77px spec — height:auto lets the row keep its size, and the
   32/32 padding sits on the title link and the button rather than on the row
   so both are full-row-height touch targets. */
.e-n-menu-dropdown-icon svg{display:none;}
.elementor-location-header .e-n-menu .e-n-menu-dropdown-icon{
  background:none;border:0;cursor:pointer;padding:0;line-height:0;
  display:flex;align-items:center;justify-content:flex-end;
  height:auto;flex:0 0 auto;
}
.e-n-menu-dropdown-icon .e-n-menu-dropdown-icon-opened,
.e-n-menu-dropdown-icon .e-n-menu-dropdown-icon-closed{display:inline-flex;align-items:center;height:5.5px;}
.e-n-menu-dropdown-icon .e-n-menu-dropdown-icon-closed::after,
.e-n-menu-dropdown-icon .e-n-menu-dropdown-icon-opened::after{
  content:'';width:11px;height:5.5px;background-color:#31352D;
  -webkit-mask:var(--icon-chevron) center/contain no-repeat;
  mask:var(--icon-chevron) center/contain no-repeat;
  transition:transform .22s var(--ease-expo);
}
.e-n-menu-dropdown-icon .e-n-menu-dropdown-icon-opened::after{transform:rotate(180deg);}


/* ============================================================================
   5. MEGA MENU — DESKTOP (>=1200)
   ----------------------------------------------------------------------------
   Two link columns + crest-masked feature image.
   Figma NavDropdown: 1240 content = 884 columns + 56 gap + 300 feature.
   The crest mask is a square top with a pill bottom, so it is plain
   border-radius rather than an SVG mask.

   The panel's inner content tracks the site container, --container (1440 in
   Site Settings), centred inside the bar's gutter. Capping the panel at that
   width + both gutters and centring it reproduces the header and footer
   alignment at every viewport, and reads the kit variable so it follows if
   the site width is ever changed. Deliberately no 100vw: that includes the
   scrollbar, which would sit the menu a few px right of everything else.
   The white surface stays full-bleed by living on .e-n-menu-content.e-active,
   and the panel's own shadow is dropped so the capped panel does not read as
   a floating card over it — the brand rules allow no shadows anyway.

   VERTICAL: Elementor anchors the dropdown to the menu TITLE (top:100%),
   which leaves it floating inside the header bar and clipping the logo. It is
   pushed down by --pef-menu-drop, measured in script as the distance from the
   menu heading's bottom to the header bar's bottom. That distance is not a
   constant — 38.3px on a one-row nav, 23.5px where the nav wraps to two rows
   — hence measuring rather than hard-coding. The heading gets an invisible
   bridge across the gap so travelling from a hub label down to the panel
   keeps the pointer inside .e-n-menu; it only exists while a panel is open
   and only spans the nav labels, so it never covers the CTAs.

   THE MENU BREAKPOINT IS 1200 AND IS STATED IN THREE PLACES: this block, the
   <=1199 block below, and pef-behaviour.js. Media queries cannot read a
   custom property, so it cannot be tokenised — if it changes, change all three.
   ========================================================================= */
@media (min-width:1200px){
  /* Elementor puts a 5px margin-inline-start on the toggle, and the label sits
     in a title with 16px side padding, so the chevron drifted 13px from its
     own label — nearly half the distance to the NEXT label, which is why it
     read as unattached. Figma's desktop NavBar carries no chevron at all, so
     there is no spec gap to copy; 4px groups it with its label. */
  .elementor-location-header .e-n-menu .e-n-menu-dropdown-icon{
    margin-inline-start:0;
    padding-inline-start:4px;
  }

  /* Tighten the nav as the bar runs out of room, 1400 down to 1200.

     At 1440 the bar spends 619px on the menu: 384 of actual label, 75 of
     chevron, and 160 of padding — 16px either side of five titles. That
     padding is the cheapest thing to give back. Below 1400 it ramps 16 -> 8,
     freeing 80px, and the logo gap ramps 56 -> 32 for another 24px. Roughly
     104px of headroom by 1200, which is where the mobile menu takes over.

     Ramped rather than stepped so nothing jumps at a single width, and capped
     at the Figma values above 1400 so the design is untouched at full size. */
  .elementor-location-header .e-n-menu .e-n-menu-title{
    padding-inline:clamp(8px, calc(8px + 8 * (100vw - 1200px) / 200), 16px);
  }
  .elementor-location-header .nav-left{
    gap:clamp(32px, calc(32px + 24 * (100vw - 1200px) / 200), 56px);
  }

  .e-n-menu-content.e-active{
    top:calc(100% + var(--pef-menu-drop, 0px)) !important;
    background:#FFFFFF;
    border-block-start:1px solid rgba(49,53,45,.14);
  }
  .e-n-menu-heading{position:relative;}
  .e-n-menu-heading:has(.e-n-menu-content.e-active)::after{
    content:'';position:absolute;inset-inline:0;inset-block-start:100%;
    height:var(--pef-menu-drop, 0px);
  }
  /* Panel padding is owned here, not by the mega-panel global class: the
     class cannot express the gutter ramp (it would have to hard-code the
     desktop half of the clamp, which is then wrong below 1025). The class
     carries only what it can state honestly — surface, direction, width. */
  .elementor-location-header .e-n-menu .e-n-menu-content > .mega-panel{
    padding:var(--space-6) var(--gutter-page) var(--space-7) !important;
    max-width:calc(var(--container) + 200px);
    margin-inline:auto;
    box-shadow:none;
    background:transparent;
  }
  .mega-panel.e-active{display:flex !important;flex-direction:row !important;gap:56px;align-items:flex-start;}
  .mega-panel > .elementor-widget-icon-list{flex:1 1 auto;min-width:0;}
  .mega-panel .elementor-icon-list-items{columns:2;column-gap:56px;}
  .mega-panel > .e-image-base{
    flex:0 0 300px;width:300px;height:300px;object-fit:cover;
    border-radius:var(--smile);align-self:flex-start;
  }

  /* Open motion — a clip reveal, so the panel unrolls from under the header.
     Deliberately clip rather than fade: the surface is white over live page
     content, so fading it in lets the hero type ghost through it.
     NOTHING here transitions `display`. Elementor opens a panel by writing an
     inline `display: var(--display)`, and a transition on display turns that
     step into a discrete transition of its own: the panel sat at display:block
     for ~80ms on first open, laying the feature image out under the links
     before the flex rule took hold, so the image visibly jumped into place. */
  .mega-panel{
    --display:flex;
    transform:translateY(-6px);
    transition:transform .3s var(--ease-expo);
  }
  .mega-panel.e-active{transform:translateY(0);}
  .e-n-menu-content{
    clip-path:inset(0 0 100% 0);
    transition:clip-path .26s var(--ease-expo);
  }
  .e-n-menu-content.e-active{clip-path:inset(0 0 0 0);}
  .e-n-menu.pef-closing .e-n-menu-content.e-active{clip-path:inset(0 0 100% 0);}
  .e-n-menu.pef-closing .mega-panel.e-active{transform:translateY(-6px);}

  /* Staggered links, reading down the first column then the second, with the
     feature image joining early so the right-hand side is not left empty.
     --pef-li rather than --pef-i because custom properties inherit and the
     mobile rows already own --pef-i on an ancestor; reusing the name would
     hand every link in a hub the same delay.
     Opacity only, no transform — the panel itself already settles 6px, and
     moving the links as well compounds into two competing motions. */
  .mega-panel .elementor-icon-list-item,
  .mega-panel > .e-image-base{
    opacity:0;
    transition:opacity .22s ease-out;
  }
  .mega-panel.e-active .elementor-icon-list-item{
    opacity:1;
    transition-delay:calc(var(--pef-li,0) * 28ms);
  }
  .mega-panel.e-active > .e-image-base{opacity:1;transition-delay:80ms;}

  /* Each hub owns a separate wrapper, so moving between hubs is really a close
     plus an open. While a panel is already open the swap is made instant, so
     the surface stays put and only its contents change — the links have to be
     included or they would re-stagger on every hub the pointer passes over,
     and zeroing only the duration would leave them waiting out their delay
     before snapping in. */
  .e-n-menu.pef-swapping .e-n-menu-content,
  .e-n-menu.pef-swapping .mega-panel,
  .e-n-menu.pef-swapping .mega-panel .elementor-icon-list-item,
  .e-n-menu.pef-swapping .mega-panel > .e-image-base{
    transition-duration:0s !important;
    transition-delay:0s !important;
  }
}


/* ============================================================================
   6. MEGA MENU — COMPACT (<=1199)
   ----------------------------------------------------------------------------
   Full-screen panel, Figma MobileMenu 4079:65.
   ========================================================================= */
@media (max-width:1199px){
  /* Figma's mobile menu is links only — no feature image. */
  .mega-panel > .e-image-base{display:none;}

  /* Sentence-case body type for the labels, and the MENU/CLOSE toggle drawn
     in ::after content. */
  .e-n-menu .mega-panel .mm-t{font-family:"aptos","aptos-fb",sans-serif;font-weight:400;font-size:16px;line-height:1.5;letter-spacing:0;text-transform:none;color:#31352D;}
  .e-n-menu .mm-d{display:none;}

  .elementor-location-header .e-n-menu-toggle,
  .elementor-location-header .e-n-menu-toggle:hover,
  .elementor-location-header .e-n-menu-toggle:focus,
  .elementor-location-header .e-n-menu-toggle:active,
  .elementor-location-header .e-n-menu-toggle[aria-expanded="true"]{
    background:none !important;border:0;box-shadow:none;
  }
  /* The toggle sits inside the menu widget on the left of the bar, and every
     e-con ancestor is position:relative — so it is pinned with position:fixed
     against the sticky header rather than absolutely.
     inset-inline-end is var(--gutter-page), NOT a copy of the mobile half of
     that clamp. It used to be the copy, which meant that between 1025 and
     1199 — where the menu is compact but the gutter is still on its DESKTOP
     ramp — the toggle sat up to 20.5px inboard of the logo it was supposed to
     line up with. */
  .elementor-location-header .e-n-menu-toggle{
    display:flex;
    align-items:center;
    justify-content:flex-end;
    padding:0;cursor:pointer;
    position:fixed;
    inset-block-start:0;
    height:var(--pef-hdr-h);
    inset-inline-end:var(--gutter-page);
    z-index:101;
  }
  .elementor-location-header .e-n-menu-toggle .e-n-menu-toggle-icon{display:none;}
  /* MENU and CLOSE cross-fade in place.
     CLOSE is kept IN FLOW so the button is always exactly as wide as the
     longer of the two words, and MENU is absolutely positioned over it. Do not
     be tempted to put both in one grid cell instead: Elementor sets `display`
     on this button at equal specificity and loads after this file, so
     display:grid silently loses the cascade, the two words lay out side by
     side, the button doubles to 82px, MENU shifts left of its position and the
     box overlaps the Donate button and steals its taps. Flow-plus-absolute
     does not care what `display` ends up being. */
  .elementor-location-header .e-n-menu-toggle::before,
  .elementor-location-header .e-n-menu-toggle::after{
    color:#31352D;
    font-family:"aptos-narrow","aptos-narrow-fb",sans-serif;
    font-weight:700;font-size:15px;line-height:.9;letter-spacing:.02em;
    transition:opacity .18s ease;
  }
  .elementor-location-header .e-n-menu-toggle::before{content:'CLOSE';opacity:0;}
  .elementor-location-header .e-n-menu-toggle::after{
    content:'MENU';
    position:absolute;
    inset-inline-end:0;
    inset-block-start:50%;
    transform:translateY(-50%);
    opacity:1;
  }
  .elementor-location-header .e-n-menu-toggle[aria-expanded="true"]::before{opacity:1;}
  .elementor-location-header .e-n-menu-toggle[aria-expanded="true"]::after{opacity:0;}

  /* Closing holds aria-expanded true for the whole 300ms panel slide, so
     keying the label only off that attribute left the button reading CLOSE
     until the panel had gone and MENU did not finish returning for ~480ms
     after the tap. The closing class swaps the word back at the START of the
     exit, so the label and the panel move as one gesture. Four classes, so it
     outranks the aria-expanded rules above. */
  .elementor-location-header .e-n-menu.pef-menu-closing .e-n-menu-toggle::before{opacity:0;}
  .elementor-location-header .e-n-menu.pef-menu-closing .e-n-menu-toggle::after{opacity:1;}

  /* Donate stays in the bar at all times, so the bar keeps clear of the
     pinned toggle. */
  .elementor-location-header .header-nav{padding-inline-end:74px;}

  /* The full-screen panel.
     CRITICAL: this is what the panel looks like OPEN, but it cannot be applied
     only when open — display:flex !important would then override Elementor's
     hidden state and leave a full-screen white sheet over the whole site with
     the menu shut, swallowing every tap. So the box is always built, and
     open/closed is expressed with clip-path plus visibility and pointer-events,
     which is also what makes it animatable: there is no display toggle to
     fight. Closed it is fully clipped, invisible, inert and out of the
     accessibility tree. */
  .elementor-location-header .e-n-menu-wrapper{
    position:fixed !important;
    inset-block-start:var(--pef-hdr-h) !important;
    inset-inline:0 !important;
    inset-block-end:0 !important;
    width:auto !important;
    max-width:none !important;
    background:#FFFFFF !important;
    display:flex !important;
    flex-direction:column !important;
    overflow-y:auto;
    padding:0 var(--gutter-page) 12px;
    clip-path:inset(0 0 100% 0);
    visibility:hidden;
    pointer-events:none;
    transition:clip-path .3s var(--ease-expo), visibility 0s linear .3s;
  }
  .elementor-location-header .e-n-menu:has(.e-n-menu-toggle[aria-expanded="true"]) .e-n-menu-wrapper{
    clip-path:inset(0 0 0 0);
    visibility:visible;
    pointer-events:auto;
    transition:clip-path .3s var(--ease-expo), visibility 0s;
  }
  /* Closing is script-driven. aria-expanded flips the instant Elementor is
     told to close, which stops the :has() rule matching, so the panel would
     jump shut with nothing left to animate. */
  .elementor-location-header .e-n-menu.pef-menu-closing .e-n-menu-wrapper{
    clip-path:inset(0 0 100% 0) !important;
  }

  /* Staggered entrance. --pef-i is the row's index and --pef-ri its index
     counted from the bottom, both set in script so adding a sixth hub needs no
     CSS change. Rows come in top-down behind the panel reveal, and the Apply
     CTA lands last. The exit runs on --pef-ri so it unwinds from the bottom
     up, and is quicker than the entrance — leaving should feel decisive,
     arriving should feel unhurried. */
  .e-n-menu-item{
    opacity:0;
    transform:translateY(6px);
    transition:opacity .26s ease-out, transform .26s var(--ease-expo);
  }
  .elementor-location-header .e-n-menu:has(.e-n-menu-toggle[aria-expanded="true"]) .e-n-menu-item{
    opacity:1;transform:none;
    transition-delay:calc(var(--pef-i,0) * 45ms);
  }
  .elementor-location-header .e-n-menu.pef-menu-closing .e-n-menu-item{
    opacity:0 !important;transform:translateY(6px) !important;
    transition-duration:.18s !important;
    transition-delay:calc(var(--pef-ri,0) * 30ms) !important;
  }

  /* Figma pins both CTAs to the foot of the open menu because the 390 bar has
     no room for Apply. Donate is deliberately NOT relocated — it stays in the
     header bar so giving is reachable at every moment, menu open or shut — so
     only Apply moves down, and this reverses the is-hidden-mobile that hides
     it in the bar. The live node is moved rather than duplicated, so there is
     still exactly one Apply button for the client to edit. */
  .elementor-location-header .pef-cta-in-menu{
    display:flex !important;
    align-items:center;justify-content:center;
    margin-block-start:auto;
    margin-block-end:12px;
    width:100%;
    min-height:44px;
    box-sizing:border-box;
    opacity:0;
    transform:translateY(6px);
    transition:opacity .26s ease-out, transform .26s var(--ease-expo);
  }
  .elementor-location-header .e-n-menu:has(.e-n-menu-toggle[aria-expanded="true"]) .pef-cta-in-menu{
    opacity:1;transform:none;
    transition-delay:calc(var(--pef-n,5) * 45ms);
  }
  .elementor-location-header .e-n-menu.pef-menu-closing .pef-cta-in-menu{
    opacity:0 !important;transform:translateY(6px) !important;
    transition-duration:.18s !important;
    transition-delay:0ms !important;
  }

  /* Elementor ships full-viewport-width rows and a 16px inset on the title;
     both are overridden so rows align to the panel gutter. Figma: 32/32
     padding on a 77px row, solid hairline per row, none on the last. */
  .e-n-menu-heading{flex-direction:column;width:100%;align-items:stretch;flex:0 0 auto;}
  .e-n-menu-item{width:100% !important;max-width:100%;box-sizing:border-box;border-block-end:1px solid #31352D;}
  .e-n-menu-item:last-child{border-block-end:0;}
  .e-n-menu-title{display:flex;align-items:center;justify-content:space-between;width:100%;max-width:100%;box-sizing:border-box;padding:0 !important;border-block-end:0;}
  .e-n-menu-title-container{flex:1 1 auto;text-decoration:none;display:flex;align-items:center;padding:32px 0;}
  .elementor-location-header .e-n-menu .e-n-menu-dropdown-icon{padding:32px 0 32px 12px;min-width:44px;margin-inline-start:0;}

  /* Accordion expand. A row has no fixed height, so it is animated with the
     grid 0fr-to-1fr technique rather than max-height guesswork. The panel needs
     min-height:0 and overflow:hidden for the track to actually compress it.
     Collapsing is driven from script (pef-collapsing) because Elementor sets
     display:none the instant it closes. */
  .e-n-menu-content{
    display:grid !important;
    grid-template-rows:0fr;
    transition:grid-template-rows .28s var(--ease-expo);
  }
  .e-n-menu-content.e-active{grid-template-rows:1fr;}
  .e-n-menu-content.pef-collapsing{grid-template-rows:0fr;}
  .e-n-menu-content > .mega-panel{min-height:0;overflow:hidden;}

  /* Children: Body/Default 16px sentence case, indented 12px, 4px gap.
     Figma's 32px of breathing space under the children sits on the LIST, not
     the panel. On the panel it was outside the clipped box, so a collapsing
     row bottomed out at 32px and hung there until the script closed it — a
     visible snap at the end of every collapse, the same trap as the footer
     accordion's 18px. It needs the extra specificity and !important because
     Elementor's icon-list stylesheet resets the list's padding to 0 at equal
     weight and loads after this file. */
  .elementor .mega-panel{--display:flex;padding:0 0 0 12px !important;box-shadow:none !important;border-block-start:0 !important;transform:none;}
  .e-n-menu-content .mega-panel .elementor-icon-list-items{
    columns:auto;display:flex;flex-direction:column;gap:4px;
    padding-block-end:32px !important;
  }
  .mega-panel .elementor-icon-list-item{opacity:1;}
  .mega-panel .elementor-icon-list-item > a{border-block-end:0;padding:0;}
}


/* ============================================================================
   7. FOOTER
   ----------------------------------------------------------------------------
   Link and social hover, then the mobile accordion.

   Figma TextLink (4241:185) draws three states: Default, Hover and Focus.
   Hover is a colour swap PLUS an underline — var(--rule-thick) 2px, offset by
   var(--space-1) 4px. The Hover variant is 4px taller than Default in the
   file, which is that underline.

   Figma draws it green-on-white, swapping to charcoal. The footer is the
   inverse — white on green — so the swap goes to lime, the paired accent for
   that ground (4.33:1 on the green). The underline is what actually carries
   the state: white and lime are only 1.13:1 apart, so on colour alone the
   change would be easy to miss.

   Excludes .btn (the CTAs own their hover) and .e-svg-base (the footer logo,
   which must not gain an underline). Social icons are handled separately
   below since they have no text to underline.

   :focus-visible throughout, so keyboard users get the same affordance —
   WCAG 2.4.7. The ring is white rather than the usual blue, because
   --focus-ring #0081F3 measures 1.26:1 on this green and is invisible.
   ========================================================================= */
.elementor-location-footer a:not(.btn):not(.e-svg-base){
  transition:color var(--dur-fast) ease-out;
}
.elementor-location-footer a:not(.btn):not(.e-svg-base):hover,
.elementor-location-footer a:not(.btn):not(.e-svg-base):focus-visible{
  color:var(--pef-lime);
}

/* The rule is drawn as a pseudo-element rather than text-decoration, because
   text-decoration cannot be animated — it can only switch on. This wipes in
   from the left on the expo curve used elsewhere for reveals.

   It sits on the SPAN, not the anchor. Elementor's icon-list anchors are
   flex and stretch to the column (84px for "Impact"), while the span hugs the
   text (49px), so on the anchor the rule would overshoot past the word.

   Geometry still matches Figma TextLink: 2px thick (--rule-thick), 4px below
   the baseline box (--space-1). currentColor means it inherits the lime swap
   without restating the value. */
.elementor-location-footer a:not(.btn):not(.e-svg-base) .elementor-icon-list-text{
  position:relative;
}
.elementor-location-footer a:not(.btn):not(.e-svg-base) .elementor-icon-list-text::after{
  content:'';
  position:absolute;
  inset-inline:0;
  inset-block-end:-4px;
  height:2px;
  background-color:currentColor;
  transform:scaleX(0);
  transform-origin:left center;
  transition:transform .32s var(--ease-expo);
}
.elementor-location-footer a:not(.btn):not(.e-svg-base):hover .elementor-icon-list-text::after,
.elementor-location-footer a:not(.btn):not(.e-svg-base):focus-visible .elementor-icon-list-text::after{
  transform:scaleX(1);
}
/* Elementor wraps icon-list link text in a span, and the footer-link class
   colours it white, so the colour has to be set on the span as well as the
   anchor or only unwrapped links would change. */
.elementor-location-footer a:not(.btn):not(.e-svg-base):hover .elementor-icon-list-text,
.elementor-location-footer a:not(.btn):not(.e-svg-base):focus-visible .elementor-icon-list-text,
.elementor-location-footer a:not(.btn):not(.e-svg-base):hover .footer-link,
.elementor-location-footer a:not(.btn):not(.e-svg-base):focus-visible .footer-link{
  color:var(--pef-lime);
}
.elementor-location-footer a:not(.btn):focus-visible{
  outline:2px solid var(--pef-white);
  outline-offset:3px;
}

/* Social icons. The artwork carries fill="white" as a presentation attribute
   on its paths, which any CSS rule outranks. No text, so the colour swap is
   the whole signal. */
.elementor-location-footer a.social-icon svg,
.elementor-location-footer a.social-icon svg *{
  transition:fill var(--dur-fast) ease-out;
}
.elementor-location-footer a.social-icon:hover svg *,
.elementor-location-footer a.social-icon:focus-visible svg *{
  fill:var(--pef-lime);
}

/* ---- Footer accordion (mobile) ---- */
@media (max-width:767px){
  /* Social row sits under the brand block, per the Figma Layout=Accordion variant.
     margin-block-end 37 + the icon's own 11px margin = 48 above the accordion block,
     matching the 48 below it. */
  .footer-groups > .footer-group:last-child{order:1;margin-block-end:37px;}
  .footer-groups > .footer-group{order:2;}

  /* The accordion rows are a continuous list separated by hairlines, so the grid
     gap is removed and each row's own padding is the only spacing. */
  .elementor .footer-groups{gap:0;}
  .footer-groups > .footer-group:not(:last-child){
    border-block-end:1px solid rgba(255,255,255,.24);
    padding-block:18px;
    gap:0;
  }
  .footer-groups > .footer-group:not(:last-child) > .footer-eyebrow{
    position:relative;
    width:100%;
    cursor:pointer;
    padding-inline-end:30px;
    user-select:none;
  }
  .footer-groups > .footer-group:not(:last-child) > .footer-eyebrow::after{
    content:'';
    position:absolute;
    inset-inline-end:0;
    top:50%;
    width:14px;
    height:8px;
    margin-block-start:-4px;
    background-color:currentColor;
    transition:transform .22s var(--ease-expo);
    -webkit-mask:var(--icon-chevron) center/contain no-repeat;
    mask:var(--icon-chevron) center/contain no-repeat;
  }
  .footer-groups > .footer-group.is-open > .footer-eyebrow::after{transform:rotate(180deg);}

  /* The row collapses with the grid 0fr-to-1fr technique rather than a display
     toggle, so both directions animate. visibility is what actually keeps a
     closed row out of the tab order and the accessibility tree — a zero-height
     grid track still contains focusable links, which display:none used to
     handle for free. It is delayed on the way out so it only applies once the
     collapse has finished. */
  .footer-groups > .footer-group:not(:last-child) > .footer-links{
    display:grid !important;
    grid-template-rows:0fr;
    visibility:hidden;
    transition:grid-template-rows .28s var(--ease-expo), visibility 0s linear .28s;
  }
  .footer-groups > .footer-group.is-open > .footer-links{
    grid-template-rows:1fr;
    visibility:visible;
    transition:grid-template-rows .28s var(--ease-expo), visibility 0s;
  }
  .footer-groups > .footer-group:not(:last-child) > .footer-links > *{
    min-height:0;
    overflow:hidden;
  }
  /* The 18px breathing space goes on the list itself, INSIDE the clipped box.
     On the grid item it sat outside the clip and left every collapsed row 18px
     tall instead of closing flush. */
  .footer-groups > .footer-group:not(:last-child) > .footer-links .elementor-icon-list-items{
    padding-block-start:18px !important;
  }

  /* Links fade in one by one behind the row opening. --pef-fi is set in script.
     They fade out together rather than in reverse: a staggered exit competes
     with the collapse, which is already moving everything upward. */
  .footer-groups > .footer-group:not(:last-child) .elementor-icon-list-item{
    opacity:0;
    transition:opacity .2s ease-out;
  }
  .footer-groups > .footer-group.is-open .elementor-icon-list-item{
    opacity:1;
    transition-delay:calc(var(--pef-fi,0) * 40ms);
  }

  /* Utility block stacks and left-aligns on mobile.
     Needs .elementor to beat the global class at equal specificity. */
  .elementor .legal-stack{align-items:flex-start;}
  .elementor .legal-line{text-align:left;}
  .elementor .utility-row{gap:8px;}
}


/* ============================================================================
   8. BUTTONS
   ----------------------------------------------------------------------------
   The button system lives in Elementor, not here:

     VALUES   -> Elementor Variables  (--btn-pad-x, --btn-pad-y, --radius-pill,
                 --border-width, --text-ui-md, --font-ui, and the colours)
     RECIPES  -> Elementor Global Classes
                   `btn`            geometry + type, referencing the variables
                   `btn-primary`    colour pairing only, plus its hover state
                   `btn-outline`    "
                   `btn-secondary`  " (square, tighter side padding)
                   `btn-text`       "
                   `btn-outline-light` / `btn-accent`  on-dark pair

   Every button carries TWO classes: `btn` plus one variant. To change padding
   on all buttons, edit --btn-pad-x / --btn-pad-y in the Variables panel. To
   change one treatment's colour, edit that variant in the Class Manager.
   Nothing below restates any of that — if a value appears here as well as in
   a class, this file wins on source order and the Class Manager is lying.

   Class Manager ORDER matters: `btn` is ordered first, so the variants (which
   sit at the same (0,2,0) specificity) override it. Do not reorder it below
   the variants.

   WHAT REMAINS HERE, and why each one cannot be a class:
     1. the font fallback  — the `font-ui` variable names one family; the
                             metric-matched fallback has to follow it
     2. the CTA arrow      — a ::after pseudo-element, not a state
     3. the Ghost underline— likewise
     4. unclassed fallback — a :not() selector, not a state
     5. motion + press     — transition/transform are not style props, and
                             prefers-reduced-motion is not an Elementor breakpoint
     6. a few shorthands Elementor's schema has no prop for (white-space,
        text-decoration, cursor, box-sizing, outline)
   ========================================================================= */

/* --- 1 + 6. Font fallback, and the properties with no Elementor prop -----
   One rule covering every button, classed or not. This replaced a six-selector
   list that named each variant individually and had gone stale — `btn` and
   `btn-secondary` were both missing from it, so neither picked up the
   metric-matched fallback. */
.elementor .btn,
.elementor .e-button-base{
  font-family:"aptos-narrow","aptos-narrow-fb",sans-serif;
  box-sizing:border-box;
  text-decoration:none;
  white-space:nowrap;
  cursor:pointer;
}

/* --- 5. Motion ----------------------------------------------------------
   From the Figma component description: "Hover colour swap only. Geometry
   never moves (--hover-lift: none)." and "Active press. Same colours as Hover
   PLUS transform: scale(0.98)". Only the four animatable properties are
   listed — `all` would sweep in box-shadow and undo "no shadows". */
.elementor .btn{
  transition:background-color var(--dur-fast) ease-out,
             color var(--dur-fast) ease-out,
             border-color var(--dur-fast) ease-out,
             transform var(--dur-fast) ease-out;
}
.elementor .btn:active{transform:scale(var(--press-scale));}

/* --- 3. Ghost underline --------------------------------------------------
   Figma's TextLink (4241:185) hover is a colour swap PLUS a 2px rule offset
   4px — and Ghost is the button system's counterpart of that link, so it takes
   the same treatment. Same implementation as the footer links above: a
   pseudo-element that wipes in from the left, because text-decoration can
   only switch on, never animate.

   Ghost is the one variant where this is safe to hang off the anchor rather
   than an inner span: btn-text zeroes the padding and min-height it inherits
   from `btn`, and inline-flex hugs its content, so the box IS the text box.
   currentColor means the rule follows the swap to --text-link without
   restating it. No conflict with the arrow below — Ghost carries no arrow. */
.elementor .btn-text{
  position:relative;
}
.elementor .btn-text::after{
  content:'';
  position:absolute;
  inset-inline:0;
  inset-block-end:-4px;
  height:2px;
  background-color:currentColor;
  transform:scaleX(0);
  transform-origin:left center;
  transition:transform .32s var(--ease-expo);
}
.elementor .btn-text:hover::after,
.elementor .btn-text:focus-visible::after{
  transform:scaleX(1);
}

/* --- 2. CTA arrow ------------------------------------------------------- */
.elementor .btn-outline::after,
.elementor .btn-outline-light::after{
  content:'';display:inline-block;width:.62em;height:.62em;
  margin-inline-start:.34em;vertical-align:-.02em;
  background-color:currentColor;
  -webkit-mask:var(--icon-arrow-ne) center/contain no-repeat;
  mask:var(--icon-arrow-ne) center/contain no-repeat;
}

/* --- Disabled -----------------------------------------------------------
   Styled off aria-disabled because these are anchors, which never match
   :disabled. Elementor also offers an `e--disabled` CLASS state, which would
   move this into the Class Manager — but it requires the element to carry
   that class, which nothing does yet. The low contrast is deliberate and
   exempt under WCAG 1.4.3; the point is that a dead control must not look
   pressable. aria-disabled alone does not stop an anchor being followed —
   whoever marks one disabled must also remove href or intercept the click. */
.elementor .btn[aria-disabled="true"],
.elementor button.btn:disabled{
  background-color:var(--surface-disabled) !important;
  color:var(--text-disabled) !important;
  border-color:transparent !important;
  cursor:not-allowed;
  transform:none;
}

/* --- 4. Unclassed fallback ----------------------------------------------
   Elementor v4 atomic buttons ignore Site Settings > Buttons entirely — its
   rules compile to `.elementor-kit-7 button, .elementor-button` and an atomic
   button is an <a class="e-button-base">, so it matches none of them. Left to
   itself it takes `.elementor .e-button-base{background:#375EFB;padding:12px
   24px}` and comes out Elementor blue.

   So anything dropped on a page without the `btn` class still needs a sane
   default. It inherits the Inverted treatment. This is a safety net, not part
   of the system: the correct markup is always `btn` + a variant.

   `.card-link` is excluded because it is an atomic button element used as a
   LINK, not a button (Figma treats TextLink and Button as separate
   components). Without the exclusion it would inherit the charcoal pill.
   KEEP THIS CHAIN SHORT. An earlier version listed five variant names, went
   stale, and silently swallowed every class that was not added to it. Two
   names is the ceiling; anything more means the fallback is the wrong tool. */
.elementor .e-button-base:not(.btn):not(.card-link){
  display:inline-flex;align-items:center;justify-content:center;
  min-height:44px;
  background-color:var(--pef-charcoal);
  color:var(--pef-white);
  border:var(--border-width) solid var(--pef-charcoal);
  border-radius:var(--radius-pill);
  padding:var(--btn-pad-y) var(--btn-pad-x);
  font-weight:700;font-size:var(--text-ui-md);line-height:.9;letter-spacing:.02em;
  text-transform:uppercase;
}
.elementor .e-button-base:not(.btn):not(.card-link):hover{
  background-color:transparent;color:var(--pef-charcoal);
}


/* ============================================================================
   12. CARDS
   ----------------------------------------------------------------------------
   The card LAYOUTS live in Elementor: `card-shell`, `badge`, `card-link` and
   `card-media-crest` / `-square` / `-flat` are global classes built from the
   variables, and the five JetEngine listings assemble them from atomic
   elements bound to dynamic tags. Only what the atomic style schema cannot
   express is here.

   Figma: ScholarshipCard 4170:26, ProfileCard 4187:111/118, NewsCard 4261:191,
   ServiceCard 28:2. Every card is 392 wide, which is what CardGrid assumes.
   ========================================================================= */

/* Shape masks. border-radius with the slash syntax is a multi-part value and
   the size prop type holds one number, so the crest cannot be a class value.
   It is only correct on a square frame, which is why the flat variants are
   separate: ProfileCard Type=Organisation is 392x220 and takes no mask. */
.elementor .card-media-crest{border-radius:var(--crest);}
.elementor .card-media-square,
.elementor .card-media-flat{border-radius:var(--radius-none);}

/* Card link = `btn` + `btn-text` + this modifier.

   Figma models TextLink (4241:185) and Button (4234:171) as separate
   components, and the first pass here built a standalone class to match that.
   That was wrong in practice: the CODED Ghost variant already IS the TextLink
   treatment - same geometry reset, same 2px rule offset 4px, same wipe on the
   same curve. The standalone class restated twelve declarations that `btn`
   and `btn-text` already own, and while restating them set the type two steps
   too small (13px against a measured ~16px in the Figma card).

   As a modifier it is three declarations, and anything that changes about
   button padding or type now reaches the cards for free. The colour pair
   (green at rest, charcoal on hover) lives on the class in the Class Manager;
   only the arrow is here, because a pseudo-element is not a style prop.

   The arrow is ::before with order:1 rather than ::after. Pseudo-elements are
   flex items, so order puts it after the label - which leaves ::after free to
   go on carrying btn-text's underline instead of fighting it for the slot. */
.elementor .card-link::before{
  content:'';
  order:1;
  display:inline-block;flex:0 0 auto;
  width:.78em;height:.78em;
  margin-inline-start:.45em;
  background-color:currentColor;
  -webkit-mask:var(--icon-arrow-e) center/contain no-repeat;
  mask:var(--icon-arrow-e) center/contain no-repeat;
}

/* btn-text's rule spans the whole element. Pull its end in by the arrow's
   width so it stops at the last word, as Figma's TextLink hover does - drawn
   edge to edge it crosses the arrow and reads as a strikethrough.
   The card arrow points EAST; the CTA button's points north-east, which in
   this system means "leaves the site". They must not share a glyph. */
.elementor .card-link::after{inset-inline-end:calc(.78em + .45em);}

/* The badge is an inline pill drawn on a block paragraph, so it needs the
   width collapse that align-self alone does not give it in a grid cell. */
.elementor .badge{width:fit-content;}

/* Elementor Pro's `post-terms` tag renders each term as an <a>, and the kit
   colours every anchor green (.elementor-kit-7 a{color:#14A14D}). That beat
   the badge's own muted ink, so the pill came out green on sand and read as a
   BUTTON rather than a tag. The link is kept - it goes to the term archive,
   which is wanted once the level pages exist - it just inherits the pill. */
.elementor .badge a{color:inherit;text-decoration:none;}

/* Two properties the atomic style schema will not take, verified by reading
   the generated CSS rather than assuming the write succeeded:

   border-width on a CONTAINER is dropped. Elementor routes container borders
   through --border-*-width custom properties on .e-con, so `card-boxed` can
   state the colour and the style but not the hairline. Left unset, the border
   still paints, at the CSS initial width of `medium` - which is 3px, and looks
   like a mistake rather than a hairline.

   margin with an `auto` keyword is dropped too (the dimensions prop wants a
   size). Pushing the link to the bottom is what keeps a row of cards with
   different amounts of body copy aligned along their links. */
.elementor .card-boxed{border-width:1px;}
.elementor .card-link{margin-block-start:auto;}

/* --- Focus ---------------------------------------------------------------
   Elementor pairs its `hover` state with :focus-visible automatically, which
   covers the colour swap. The ring itself is drawn here because outline is
   not an Elementor style prop. outline rather than box-shadow: both sit
   outside the border box and neither eats the 44px hit area, but a shadow
   cannot leave a transparent gap without painting a ring colour behind it,
   and this ring must read on white, sand AND charcoal. outline-offset gives
   the gap for free on any ground, and follows border-radius.
   :focus-visible, so a mouse press leaves no ring, while every keyboard and
   assistive-tech focus still gets one — which is what WCAG 2.4.7 requires.
   outline is never set to none anywhere. */
.elementor .btn:focus-visible,
.elementor .e-button-base:not(.btn):not(.card-link):focus-visible{
  outline:2px solid var(--focus-ring);
  outline-offset:2px;
}


/* ============================================================================
   9. COLOURED SURFACES
   ----------------------------------------------------------------------------
   The kit sets an explicit `.elementor-kit-7 h1..h6 {color:#31352D}`. An
   explicit rule on the heading always beats inheriting the surface colour, so
   headings stayed dark on every coloured band — 2.58:1 on the green, a 1.4.3
   failure. The surface class owns the ink: let headings inherit it.

   The :not() matters. This selector is (0,2,1), which would also outrank a
   .elementor .color-* utility at (0,2,0). Excluding headings that carry an
   explicit colour class means the rule never matches them, so the utility
   applies instead of merely losing on specificity.
   ========================================================================= */
.elementor :is(.bg-white,.bg-shell,.bg-lime,.bg-lilac,.bg-green,.bg-blue,.bg-black)
  :is(h1,h2,h3,h4,h5,h6):not([class*="color-"]){color:inherit;}

/* btn-outline-light carries min-width:280px because it was built for the
   footer CTA stack, where buttons are full-width blocks. In the hero the
   actions sit in an inline row, so let them size to their label. */
.elementor .hero-actions .btn-outline-light{min-width:0;}


/* ============================================================================
   10. TRANSPARENT HEADER
   ----------------------------------------------------------------------------
   Transparent until scrolled. Not in Figma — both NavBar variants (Scroll=Top,
   Scroll=Scrolled) are --surface-page #ffffff and differ only by
   Elevation/Header. If this stays, it wants a NavBar Scroll=Transparent
   variant in the file.

   Driven by Elementor Page Settings -> Header -> Header Style
   (inc-header-style.php), which emits on <body>:
     .pef-header-transparent + .pef-header-ink-light   (dark hero, white nav)
     .pef-header-transparent + .pef-header-ink-dark    (pale hero, dark nav)

   TWO HALVES, ON DIFFERENT ELEMENTS, AND ONLY ONE IS AUTOMATIC.

   1. The header is pulled out of the way by its own height, so whatever
      follows runs up underneath it. Acting on the header itself needs no
      knowledge of the page structure.
   2. The first section has to give that height back as top padding, or its
      content sits under the navigation. That is the `section-under-header`
      global class, which sets padding-block-start to var(--section-pad-top-hero)
      — the section rhythm plus the header height — and the author applies it
      to the hero.

   Step 2 used to be automatic, matched with .e-con:not(.e-con .e-con). It kept
   selecting the wrong element in the Elementor editor, which wraps the
   document in extra helper elements, and produced a band of white above the
   first container. Three attempts at a smarter selector all failed the same
   way. A class needs no structural guessing and is visible in the Class
   Manager, so an author can see why the hero has the padding it has.

   TRADE-OFF: forget the class on a transparent-header page and the hero's
   content sits under the navigation. Page Settings and the class have to be
   used together.
   ========================================================================= */
body.pef-header-transparent .elementor-location-header{
  margin-block-end:calc(-1 * var(--pef-hdr-h));
}

/* --- Bar background --------------------------------------------------- */
body.pef-header-transparent .elementor-location-header .header-bar{
  background-color:transparent !important;
  transition:background-color .25s ease, box-shadow .2s ease;
}
body.pef-header-transparent .elementor-location-header.is-scrolled .header-bar,
body.pef-header-transparent .elementor-location-header:has([aria-expanded="true"]) .header-bar{
  background-color:#FFFFFF !important;
}

/* --- Inverted ink, light mode only, and only while truly transparent -----
   i.e. at the top of the page AND with no menu panel open. An open panel is
   white, so the bar above it must be solid and dark-inked too.
   (ink-dark mode needs no overrides — the default header ink is already dark.) */

/* logo is two-tone (#14A14D mark + #31352D wordmark); both go white */
body.pef-header-ink-light .elementor-location-header:not(.is-scrolled):not(:has([aria-expanded="true"])) a.logo svg,
body.pef-header-ink-light .elementor-location-header:not(.is-scrolled):not(:has([aria-expanded="true"])) a.logo svg *{
  fill:#FFFFFF !important;
}

/* nav labels, chevrons, mobile MENU/CLOSE */
body.pef-header-ink-light .elementor-location-header:not(.is-scrolled):not(:has([aria-expanded="true"])) :is(.e-n-menu-title-container,.e-n-menu-title-text,.e-n-menu-toggle,.e-n-menu-dropdown-icon){
  color:#FFFFFF !important;
}
body.pef-header-ink-light .elementor-location-header:not(.is-scrolled):not(:has([aria-expanded="true"])) .e-n-menu-dropdown-icon svg{
  fill:#FFFFFF !important;
}

/* Apply: outline goes white-on-transparent. Its normal hover fills dark,
   which would sit at 2.55:1 on the green, so invert the hover too. */
body.pef-header-ink-light .elementor-location-header:not(.is-scrolled):not(:has([aria-expanded="true"])) .btn-outline{
  background-color:transparent !important;color:#FFFFFF !important;border-color:#FFFFFF !important;
}
body.pef-header-ink-light .elementor-location-header:not(.is-scrolled):not(:has([aria-expanded="true"])) .btn-outline:hover{
  background-color:#FFFFFF !important;color:#31352D !important;
}

/* Donate: a dark fill would be a 2.55:1 edge on the green, so invert to white */
body.pef-header-ink-light .elementor-location-header:not(.is-scrolled):not(:has([aria-expanded="true"])) .btn-primary{
  background-color:#FFFFFF !important;color:#31352D !important;border-color:#FFFFFF !important;
}
body.pef-header-ink-light .elementor-location-header:not(.is-scrolled):not(:has([aria-expanded="true"])) .btn-primary:hover{
  background-color:transparent !important;color:#FFFFFF !important;
}

/* focus ring: --focus-ring #0081F3 is 1.26:1 on the green, invisible */
body.pef-header-ink-light .elementor-location-header:not(.is-scrolled):not(:has([aria-expanded="true"])) :focus-visible{
  outline-color:#FFFFFF !important;
}

/* --- Cross-fade ------------------------------------------------------- */
body.pef-header-transparent .elementor-location-header :is(a.logo svg, a.logo svg *, .e-n-menu-title-container, .e-n-menu-dropdown-icon svg, .e-button-base){
  transition:color .25s ease, background-color .25s ease, border-color .25s ease, fill .25s ease;
}


/* ============================================================================
   11. REDUCED MOTION
   ----------------------------------------------------------------------------
   ONE block for the whole site. There were six, scattered across the seven
   files, and between them they still missed the toggle labels and the footer
   chevron.

   Motion is decoration here, so it is dropped for anyone who has asked the OS
   to reduce it. Only the transitions go — the clip-path, grid-track and
   visibility values are load-bearing, being what keeps a closed panel or row
   hidden and inert, so they are deliberately left in place to apply instantly.
   Everything that starts an animation hidden is forced back to fully visible,
   and the button press scale is dropped entirely since it is pure motion.

   The duration tokens are zeroed too, which covers every transition written
   as var(--dur-*) without naming it here.
   ========================================================================= */
@media (prefers-reduced-motion:reduce){
  :root{--dur-fast:0ms; --dur-base:0ms; --dur-slow:0ms;}

  .elementor-location-header .header-bar,
  .e-n-menu-content,
  .e-n-menu-wrapper,
  .e-n-menu-item,
  .e-n-menu-toggle::before,
  .e-n-menu-toggle::after,
  .e-n-menu-dropdown-icon .e-n-menu-dropdown-icon-closed::after,
  .e-n-menu-dropdown-icon .e-n-menu-dropdown-icon-opened::after,
  .mega-panel,
  .mega-panel .elementor-icon-list-item,
  .mega-panel > .e-image-base,
  .pef-cta-in-menu,
  .footer-groups > .footer-group > .footer-links,
  .footer-groups .elementor-icon-list-item,
  .footer-groups > .footer-group > .footer-eyebrow::after,
  .elementor-location-footer a:not(.btn):not(.e-svg-base),
  .elementor-location-footer a:not(.btn):not(.e-svg-base) .elementor-icon-list-text::after,
  .elementor-location-footer a.social-icon svg,
  .elementor-location-footer a.social-icon svg *,
  .elementor .btn,
  .elementor .btn-text::after,
  .elementor .card-link,
  body.pef-header-transparent .elementor-location-header *,
  body.pef-header-transparent .elementor-location-header .header-bar{
    transition:none !important;
  }

  .e-n-menu-item,
  .pef-cta-in-menu,
  .mega-panel .elementor-icon-list-item,
  .mega-panel > .e-image-base{opacity:1 !important;transform:none !important;}
  .mega-panel{transform:none !important;}
  .footer-groups > .footer-group.is-open .elementor-icon-list-item{opacity:1 !important;}
  .elementor .btn:active{transform:none !important;}
}
