/*
 Theme Name:   WpConsults PRO
 Theme URI:    https://www.wpconsults.com
 Description:  Child of Hello Elementor. Carries the Aspire in Ecology brand tokens.
 Author:       info.wpconsults@gmail.com
 Author URI:   https://www.wpconsults.com/abdullah-nouman
 Template:     hello-elementor
 Version:      1.1
 License:      GNU General Public License v2 or later
 License URI:  http://www.gnu.org/licenses/gpl-2.0.html
*/

/* ==========================================================================
   ASPIRE IN ECOLOGY
   Brand tokens and the watermark helper.

   Read this before editing:
   - Colours and fonts are ALSO set in Elementor Site Settings. That is where
     you change them for widgets. The variables below exist so custom CSS,
     loop items and anything hand written can reach the same values.
   - Nothing here styles a widget. If a rule starts fighting Elementor,
     the rule is in the wrong place.
   ========================================================================== */

:root {

  /* --- Colour ------------------------------------------------------------ */
  --aspire-forest:    #2B4521;   /* headings, dark sections, footer          */
  --aspire-brand:     #5A6E3A;   /* buttons, links, active states            */
  --aspire-sage:      #8E9B66;   /* watermark, dividers, quiet accents       */
  --aspire-sun:       #F5DE7A;   /* hot jobs, highlights, reversed text      */
  --aspire-paper:     #EFEDE2;   /* alternating section ground               */
  --aspire-mint:      #E8F2E5;   /* second section ground, from Ecology Ready*/
  --aspire-white:     #FFFFFF;   /* cards, main ground                       */
  --aspire-ink:       #1B2116;   /* body text                                */
  --aspire-muted:     #6B7263;   /* captions, meta, secondary text           */
  --aspire-line:      #DDDACC;   /* card and input borders                   */
  --aspire-line-soft: #E9E6DA;   /* quiet dividers                           */

  /* --- Type -------------------------------------------------------------- */
  --aspire-display: "DM Serif Display", Georgia, "Times New Roman", serif;
  --aspire-sans:    "DM Sans", system-ui, -apple-system, "Helvetica Neue", Arial, sans-serif;

  /* --- Layout ------------------------------------------------------------ */
  /* One fluid container. It fills a large monitor, stops at 1500 so a line of
     text never gets silly, and is a percentage below that, so tablet and
     mobile need no special case. Elementor's Site Settings only accepts a
     plain pixel number, so 1500 is set there as the ceiling and the fluid
     part is applied to its container further down this file. */
  --aspire-container:    min(92vw, 1500px);
  --aspire-reading:      720px;   /* article column, around 70 characters    */
  --aspire-section-y:    96px;    /* section padding, top and bottom         */
  --aspire-gap:          24px;    /* grid gap                                */
  --aspire-radius-card:  10px;
  --aspire-radius-btn:   6px;

  /* --- Watermark --------------------------------------------------------- */
  /* The leaf mark, copied into the theme so it does not depend on the media
     library or on the domain. Used as a mask, so the colour comes from
     --aspire-wm-colour below and can be flipped to white on dark grounds. */
  --aspire-leaf: url("assets/aspire-leaf.avif");
  --aspire-wm-size:    520px;
  --aspire-wm-opacity: 0.12;      /* the design system allows 0.08 to 0.15   */
  --aspire-wm-colour:  var(--aspire-sage);
}

@media (max-width: 767px) {
  :root {
    --aspire-section-y:  56px;
    --aspire-gap:        16px;
    --aspire-wm-size:    320px;
    --aspire-wm-opacity: 0.08;
  }
}

/* ==========================================================================
   THE WATERMARK

   How to use it: add the class to an Elementor CONTAINER, not to a widget.

     aspire-wm                  turns the container into a watermarked section
     aspire-wm--left            bleeds off the left edge instead of the right
     aspire-wm--top-right       bleeds off the top right corner
     aspire-wm--bottom-left     bleeds off the bottom left corner
     aspire-wm--sm  /  --lg     smaller or larger mark
     aspire-wm--8 --10 --15     opacity, default is 12 per cent
     aspire-wm--light           white mark, for use on a forest ground

   Example class list: aspire-wm aspire-wm--left aspire-wm--10

   The rules from the design system, and how they are held:
     1. Alternating sections only, never two in a row.   YOU, by hand.
     2. Opacity between 8 and 15 per cent.               Held by the variants.
     3. Always bleeding off an edge.                     Held by the offsets.
     4. Never behind a paragraph of body text.           YOU, by hand.
     5. Never in the same section as an advert.          Held below, the mark
                                                         hides itself if an
                                                         advert is present.
   ========================================================================== */

@supports ((-webkit-mask-image: url("")) or (mask-image: url(""))) {

  .aspire-wm {
    position: relative;
    overflow: hidden;
    isolation: isolate;
  }

  .aspire-wm::before {
    content: "";
    position: absolute;
    z-index: 0;
    pointer-events: none;
    width:  var(--aspire-wm-size);
    height: var(--aspire-wm-size);
    background-color: var(--aspire-wm-colour);
    opacity: var(--aspire-wm-opacity);

    -webkit-mask-image: var(--aspire-leaf);
            mask-image: var(--aspire-leaf);
    -webkit-mask-repeat: no-repeat;
            mask-repeat: no-repeat;
    -webkit-mask-position: center;
            mask-position: center;
    -webkit-mask-size: contain;
            mask-size: contain;

    /* default: bleeding off the right edge, vertically centred.
       `left: auto` is not spare. Elementor gives every container's ::before a
       background-overlay rule of its own that sets `left: 0`, and an absolutely
       positioned box with both left and right set ignores the right in a
       left-to-right page. Without this line the mark lands on the left edge,
       behind the copy, which is the one place rule 4 says it must never be. */
    top: 50%;
    left: auto;
    right: calc(var(--aspire-wm-size) * -0.3);
    transform: translateY(-50%);
  }

  /* everything the editor puts in the container sits above the mark */
  .aspire-wm > * { position: relative; z-index: 1; }

  /* --- where it bleeds off ---------------------------------------------- */
  .aspire-wm--left::before {
    right: auto;
    left: calc(var(--aspire-wm-size) * -0.3);
  }

  .aspire-wm--top-right::before {
    top: calc(var(--aspire-wm-size) * -0.35);
    left: auto;
    right: calc(var(--aspire-wm-size) * -0.2);
    transform: none;
  }

  .aspire-wm--bottom-left::before {
    top: auto;
    bottom: calc(var(--aspire-wm-size) * -0.35);
    left: calc(var(--aspire-wm-size) * -0.2);
    right: auto;
    transform: none;
  }

  /* --- size -------------------------------------------------------------- */
  .aspire-wm--sm { --aspire-wm-size: 360px; }
  .aspire-wm--lg { --aspire-wm-size: 680px; }

  /* --- opacity, capped at the design system limits ----------------------- */
  .aspire-wm--8  { --aspire-wm-opacity: 0.08; }
  .aspire-wm--10 { --aspire-wm-opacity: 0.10; }
  .aspire-wm--12 { --aspire-wm-opacity: 0.12; }
  .aspire-wm--15 { --aspire-wm-opacity: 0.15; }

  /* --- on a forest ground ------------------------------------------------ */
  .aspire-wm--light { --aspire-wm-colour: var(--aspire-white); }

  /* --- rule 5, enforced -------------------------------------------------- */
  .aspire-wm:has(.aspire-ad)::before { display: none; }

  /* --- print, and anyone who has asked for less ------------------------- */
  @media print {
    .aspire-wm::before { display: none; }
  }
}

/* ==========================================================================
   CONTAINER WIDTH

   Elementor's Site Settings only takes a plain pixel number, so the ceiling
   is set there and the fluid part is set here.

   This changes one variable and nothing else, which is deliberate. Elementor
   already computes its own content width as min(100%, container-max-width),
   and the max-width only ever lands on a boxed container's inner wrapper.
   So a full width section is untouched, and no container can ever be wider
   than the screen. The `body` prefix is only there to win on specificity,
   which is cheaper and safer than reaching for !important.
   ========================================================================== */

body .e-con {
  --container-max-width: var(--aspire-container);
}

/* ==========================================================================
   SMALL SAFETIES
   Things Elementor will not do for us. Nothing decorative belongs here.
   ========================================================================== */

/* Keyboard users need to see where they are. Elementor does not provide this. */
a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
[tabindex]:focus-visible {
  outline: 3px solid var(--aspire-brand);
  outline-offset: 2px;
}

/* Headings read better when the last line is not a single orphan word. */
h1, h2, h3, h4 { text-wrap: balance; }

/* The article column. Put this on the container that holds post content. */
.aspire-reading {
  max-width: var(--aspire-reading);
  margin-inline: auto;
}

/* An advert is always paid space and always says so. The frame itself is
   built in Elementor. This class only exists so the watermark can see it,
   so keep it on the advert wrapper. */
.aspire-ad { position: relative; }

/* ==========================================================================
   COMPONENTS

   Read this before adding to it.

   Layout, spacing, background and the type on headings all stay in Elementor,
   because those are the things a person opens the editor to change. What lives
   here is the handful of small parts Elementor either cannot draw at all, or
   would take thirty controls and a repeat on every card to draw once.

   Every class below is applied through a widget or container's CSS Classes
   field. Nothing here targets an Elementor class, so nothing here can fight
   the editor. If a rule ever starts doing that, it belongs in Elementor.

   Added 5 September 2026 with the homepage build. See DECISIONS.md.
   ========================================================================== */

/* --- the wordmark ------------------------------------------------------- */
/* There is no Aspire in Ecology logo file. The mark is the leaf as a CSS
   mask, so it takes its colour from the theme and needs no second image for
   the footer. Markup lives in an HTML widget in the header and footer. */

/* One scale number drives the whole lockup, so a bigger mark stays in
   proportion instead of needing five numbers changed by hand. The header and
   footer use it at 1. The For Employers band uses --xl. */

.aspire-mark {
  --aspire-mark-scale: 1;
  display: inline-flex;
  align-items: center;
  gap: calc(12px * var(--aspire-mark-scale));
  text-decoration: none;
}

.aspire-mark__leaf {
  width:  calc(42px * var(--aspire-mark-scale));
  height: calc(46px * var(--aspire-mark-scale));
  flex: none;
  background-color: var(--aspire-forest);
  -webkit-mask-image: var(--aspire-leaf);
          mask-image: var(--aspire-leaf);
  -webkit-mask-size: contain;
          mask-size: contain;
  -webkit-mask-repeat: no-repeat;
          mask-repeat: no-repeat;
  -webkit-mask-position: center;
          mask-position: center;
}

.aspire-mark__name {
  display: block;
  font-family: var(--aspire-display);
  font-size: calc(30px * var(--aspire-mark-scale));
  line-height: 1;
  color: var(--aspire-forest);
}

.aspire-mark__sub {
  display: block;
  margin-top: calc(4px * var(--aspire-mark-scale));
  font-family: var(--aspire-sans);
  font-size: calc(10.5px * var(--aspire-mark-scale));
  font-weight: 500;
  letter-spacing: 0.2em;
  color: var(--aspire-brand);
}

/* on a forest ground */
.aspire-mark--light .aspire-mark__leaf { background-color: var(--aspire-sun); }
.aspire-mark--light .aspire-mark__name { color: var(--aspire-white); }
.aspire-mark--light .aspire-mark__sub  { color: var(--aspire-sun); }

@media (max-width: 767px) {
  .aspire-mark { --aspire-mark-scale: 0.82; }
}

/* --- small labels ------------------------------------------------------- */
/* One kicker, used above eight section headings. */
.aspire-kicker {
  font-family: var(--aspire-sans);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--aspire-brand);
}
.aspire-kicker--sun { color: var(--aspire-sun); }

/* A larger kicker, for the homepage hero only. Garry asked for that line to
   carry more weight on 10 September. The letter spacing comes down slightly
   as the size goes up, because 0.14em at 15px starts to sprawl. */
.aspire-kicker--lg {
  font-size: 15px;
  letter-spacing: 0.12em;
}

@media (max-width: 767px) {
  .aspire-kicker--lg { font-size: 13px; }
}

/* --- pills -------------------------------------------------------------- */
/* Membership tiers, specialism tags, growth signals and the Hot Job flag are
   all the same shape at different weights. One base, then the variants. */

.aspire-pill {
  display: inline-block;
  font-family: var(--aspire-sans);
  font-size: 11.5px;
  font-weight: 500;
  line-height: 1.4;
  padding: 4px 10px;
  border-radius: 20px;
  background: var(--aspire-paper);
  color: var(--aspire-brand);
  white-space: nowrap;
}

/* the Hot Job flag, and anything else that needs to shout quietly */
.aspire-pill--flag {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  padding: 4px 9px;
  border-radius: 3px;
  background: var(--aspire-sun);
  color: #8A7212;
}

/* membership tier, on an employer card */
.aspire-pill--tier {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  padding: 4px 9px;
  border-radius: 3px;
}
.aspire-pill--premium  { background: var(--aspire-forest); color: var(--aspire-sun); }
.aspire-pill--standard { background: var(--aspire-paper);  color: var(--aspire-brand); }
.aspire-pill--free     { background: var(--aspire-white);  color: var(--aspire-muted);
                         border: 1px solid var(--aspire-line); }

/* a growth signal, e.g. Expanding */
.aspire-pill--signal {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 5px 11px;
  background: rgba(90, 110, 58, 0.13);
  color: var(--aspire-brand);
}

/* a filter chip on the directory teaser */
.aspire-pill--filter {
  font-size: 14px;
  font-weight: 500;
  padding: 9px 16px;
  background: var(--aspire-white);
  border: 1px solid var(--aspire-line);
  color: var(--aspire-ink);
  text-decoration: none;
}
.aspire-pill--filter:hover,
.aspire-pill--filter.is-on {
  background: var(--aspire-forest);
  border-color: var(--aspire-forest);
  color: var(--aspire-white);
}

/* --- the growth signal dot ---------------------------------------------- */
.aspire-dot::before {
  content: "";
  display: block;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--aspire-brand);
}

/* --- the advert frame --------------------------------------------------- */
/* Paid space always says so, and the label reads down the left edge so it
   cannot be mistaken for part of the advert. */
.aspire-adframe__label {
  writing-mode: vertical-rl;
  transform: rotate(180deg);
  font-family: var(--aspire-sans);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--aspire-muted);
}

/* --- card imagery ------------------------------------------------------- */
/* Two jobs. First, every card in a row is the same shape whatever the file
   happens to be, which is a crop the browser can do and a server-side resize
   cannot always be trusted to. Second, a slow lift on hover: Elementor has a
   hover zoom, but only on its own image widget, and these are featured
   images inside loop items. */
.aspire-zoom img {
  width: 100%;
  aspect-ratio: 16 / 10;
  object-fit: cover;
  transition: transform 0.5s ease;
}

.aspire-zoom--4x3 img { aspect-ratio: 4 / 3; }
.aspire-zoom--square img { aspect-ratio: 1 / 1; }
.aspire-zoom:hover img,
.e-loop-item:hover .aspire-zoom img {
  transform: scale(1.04);
}

@media (prefers-reduced-motion: reduce) {
  .aspire-zoom img { transition: none; }
  .aspire-zoom:hover img,
  .e-loop-item:hover .aspire-zoom img { transform: none; }
}

/* --- the hero headline -------------------------------------------------- */
/* The second half of the line is serif italic in Sun. It is one <em> inside
   the heading widget, so it needs one rule. */
.aspire-hero-title em {
  font-style: italic;
  color: var(--aspire-sun);
}

/* --- a rule between rows ------------------------------------------------ */
/* Who's Growing is a list, not a grid of cards. Hairlines only. */
.aspire-ruled-list .e-loop-item {
  border-bottom: 1px solid rgba(43, 69, 33, 0.13);
}
.aspire-ruled-list .e-loop-item:first-child {
  border-top: 1px solid rgba(43, 69, 33, 0.13);
}

/* --- making a whole card clickable -------------------------------------- */
/* Elementor will not turn a container into a link from a dynamic tag. The
   control saves, the anchor never renders, and every card on the site was
   silently unclickable because of it. So the title heading carries the link
   and this stretches its anchor over the whole card.
   Anything that has to stay separately clickable inside a card, a tag pill
   for instance, needs a z-index above the overlay, which is what the last
   rule does. */
.aspire-cardlink { position: relative; }

/* Elementor gives every widget position: relative, which would trap the
   overlay inside the title. Unsetting it on this one widget lets the overlay
   resolve against the card instead. */
.aspire-cardlink .e-con,
.aspire-cardlink .elementor-widget { position: static !important; }

.aspire-cardlink__title a::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
}

.aspire-cardlink a {
  position: relative;
  z-index: 2;
}

/* the title anchor must stay unpositioned, or its overlay measures itself
   against the anchor instead of the card */
.aspire-cardlink__title a { position: static; }

/* --- a tick list -------------------------------------------------------- */
/* Used on the membership tiers and the profile contents. It is a plain <ul>
   in a text editor widget, so the client can add a line without touching
   anything else. The tick is a mask rather than a character, so it takes the
   colour of whatever ground it sits on. */
.aspire-ticks,
.aspire-ticks ul {
  list-style: none;
  margin: 0;
  padding: 0;
}

.aspire-ticks li {
  position: relative;
  padding-left: 26px;
  margin-bottom: 10px;
  font-family: var(--aspire-sans);
  font-size: 15px;
  line-height: 1.5;
  color: var(--aspire-ink);
}

.aspire-ticks li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 6px;
  width: 13px;
  height: 10px;
  background-color: var(--aspire-brand);
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 13 10'%3E%3Cpath d='M1 5l3.5 3.5L12 1' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
          mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 13 10'%3E%3Cpath d='M1 5l3.5 3.5L12 1' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  -webkit-mask-repeat: no-repeat;
          mask-repeat: no-repeat;
  -webkit-mask-size: contain;
          mask-size: contain;
}

/* on a forest ground */
.aspire-ticks--light li { color: rgba(255, 255, 255, 0.9); }
.aspire-ticks--light li::before { background-color: var(--aspire-sun); }

/* A tick means "you get this". Where the list is a sequence rather than a
   set of benefits, it gets a dash instead, because ticking the description
   of the thing we are arguing against reads as approving of it. */
.aspire-ticks--step li { color: var(--aspire-muted); }
.aspire-ticks--step li::before {
  -webkit-mask-image: none;
          mask-image: none;
  background-color: var(--aspire-muted);
  width: 11px;
  height: 1px;
  top: 12px;
}

/* --- the employer card overview ----------------------------------------- */
/* Printed by [aspire_employer_overview] rather than an Elementor dynamic tag,
   because from 13 September a Free listing is a name and a location and the
   dynamic tag had no way of asking what tier the employer was on. The
   typography here has to match what that widget was set to, or every paid
   card in the directory changes shape. */
.aspire-card-overview {
  margin: 0;
  font-family: var(--aspire-sans);
  font-size: 15px;
  line-height: 1.55;
  color: var(--aspire-ink);
}

/* "Show the talent you're interested in" is in Garry's Premium list alone,
   so this line is Premium only and printed by [aspire_employer_opento]. */
.aspire-card-opento {
  font-family: var(--aspire-sans);
  font-size: 14px;
  line-height: 1.5;
  color: var(--aspire-muted);
}

/* --- the membership tier cards ------------------------------------------ */
/* Garry finalised the three tiers and their prices on 13 September, so the
   block that had been deliberately price-free became a real price table. A
   price table only works if the number is the loudest thing on the card, and
   if the card you want people to pick looks picked. Hence the big serif
   figure, the rule under it, and the raised Premium card.

   Read this before editing: the containers on page 24 carry their custom
   class under the key css_classes, not _css_classes, because that is how they
   were built. Setting _css_classes on them does nothing at all, silently.
   Check which key a container already uses before adding a class to it. */
.aspire-tier-price {
  display: flex;
  align-items: baseline;
  gap: 8px;
  margin: 16px 0 20px;
  padding-bottom: 20px;
  border-bottom: 1px solid var(--aspire-line-soft);
}

.aspire-tier-price__num {
  font-family: var(--aspire-display);
  font-size: 46px;
  line-height: 1;
  color: var(--aspire-forest);
}

.aspire-tier-price__per {
  font-family: var(--aspire-sans);
  font-size: 14px;
  line-height: 1.4;
  color: var(--aspire-muted);
}

.aspire-tier-price.is-on-dark { border-bottom-color: rgba(255, 255, 255, 0.22); }
.aspire-tier-price.is-on-dark .aspire-tier-price__num { color: var(--aspire-sun); }
.aspire-tier-price.is-on-dark .aspire-tier-price__per { color: rgba(255, 255, 255, 0.72); }

/* Free has three lines and Premium has fourteen, so without this the short
   card is mostly empty space. Pushing the link to the base gives every card
   the same footing and the same next step. */
.aspire-tier-cta {
  margin-top: auto;
  padding-top: 24px;
}

.aspire-tier-cta a {
  font-family: var(--aspire-sans);
  font-size: 15px;
  font-weight: 600;
  color: var(--aspire-brand);
  text-decoration: none;
  border-bottom: 1px solid currentColor;
  padding-bottom: 2px;
}

.aspire-tier-cta a.is-on-dark { color: var(--aspire-sun); }
.aspire-tier-cta a:hover { opacity: 0.8; }

/* the card we want them to choose sits slightly forward of the other two */
.aspire-tier-card { transition: transform 0.2s ease, box-shadow 0.2s ease; }

.aspire-tier-card.is-dark {
  transform: translateY(-10px);
  box-shadow: 0 18px 40px rgba(27, 33, 22, 0.16);
}

@media (max-width: 1024px) {
  .aspire-tier-card.is-dark { transform: none; box-shadow: none; }
}

/* --- the Hot Job showcase ------------------------------------------------ */
/* Garry's note on 13 September: good message, poor image, and he does not like
   blank white boxes. The band had copy on the left and nothing at all on the
   right, on white, between two other light sections.

   So it is a forest band now, which is the only dark thing between the hero
   and the close, and the empty half carries a mockup of the Hot Job card as it
   actually appears on the homepage. The mockup is drawn in CSS rather than
   saved as a picture on purpose: it stays sharp on any screen, it reflows on a
   phone, and when the real card changes this one can be changed with it
   instead of quietly going out of date.

   Nothing here is a screenshot and nothing here is a claim. The role, the
   employer and the town are the same sample records the homepage carousel is
   showing, so the two always agree. */
.aspire-hotjob {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 64px;
  align-items: center;
}

.aspire-hotjob__copy { max-width: 560px; }

.aspire-hotjob__kicker {
  display: block;
  margin-bottom: 18px;
  font-family: var(--aspire-sans);
  font-size: 11px;
  font-weight: 500;
  line-height: 1;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--aspire-sun);
}

/* the element selector is deliberate. Elementor's kit stylesheet loads after
   this file and sets h2 colour and size, so a class on its own loses */
.aspire-hotjob h2.aspire-hotjob__title {
  margin: 0 0 18px;
  font-family: var(--aspire-display);
  font-size: 40px;
  line-height: 1.16;
  color: var(--aspire-white);
}

.aspire-hotjob p.aspire-hotjob__lead {
  margin: 0 0 24px;
  font-family: var(--aspire-sans);
  font-size: 17px;
  line-height: 1.62;
  color: rgba(255, 255, 255, 0.82);
}

.aspire-hotjob__copy .aspire-ticks { margin-bottom: 26px; }

.aspire-hotjob a.aspire-hotjob__link {
  font-family: var(--aspire-sans);
  font-size: 15px;
  font-weight: 600;
  color: var(--aspire-sun);
  text-decoration: none;
  border-bottom: 1px solid currentColor;
  padding-bottom: 2px;
}

.aspire-hotjob a.aspire-hotjob__link:hover { opacity: 0.8; }

/* --- the mockup --------------------------------------------------------- */
/* Media 674. Abdullah's call on 13 September: the first version drew a browser
   window in CSS, and a browser window is what a software product shows. This
   is not a software product, it is where ecologists read about employers, so
   the mockup is a printed card on a desk, with pressed leaves and handwritten
   notes pointing at the two things an employer is buying. Generated once and
   stored, rather than drawn on every page view.

   If the real Hot Job card is redesigned, this picture does not follow it.
   Whoever changes the card should look at this too. */
.aspire-hotjob__img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 14px;
  box-shadow: 0 30px 70px rgba(10, 16, 8, 0.35);
}

@media (max-width: 1100px) {
  .aspire-hotjob { gap: 44px; }
  .aspire-hotjob h2.aspire-hotjob__title { font-size: 34px; }
}

@media (max-width: 900px) {
  .aspire-hotjob {
    grid-template-columns: 1fr;
    gap: 36px;
  }
  .aspire-hotjob__copy { max-width: none; }
  .aspire-hotjob h2.aspire-hotjob__title { font-size: 30px; }
  .aspire-hotjob__img { max-width: 460px; }
}

/* --- the employer enquiry ------------------------------------------------ */
/* Garry's note on 13 September: the fields stretched most of the way across
   the screen, which made an invitation read like an administrative form. The
   block is held to a comfortable width and centred, and only the headings are
   centred with it. Labels stay left, because a centred label above a left
   aligned input is harder to scan, not easier. */
.aspire-enquiry--narrow {
  max-width: 780px;
  margin-inline: auto;
}

.aspire-enquiry--narrow > .e-con-inner > .elementor-widget-heading .elementor-heading-title,
.aspire-enquiry--narrow .elementor-widget-heading .elementor-heading-title {
  text-align: center;
}

.aspire-enquiry--narrow .frm-fluent-form .elementor-heading-title { text-align: left; }

/* Work email and Company share a row. Fluent Forms has no column control on a
   free form, so the fieldset becomes the row and only those two fields are
   told to take half of it. Everything else stays full width. The hidden
   inputs above them are display:none, so they lay out nothing. */
.aspire-enquiry--narrow .frm-fluent-form fieldset {
  display: flex;
  flex-wrap: wrap;
  column-gap: 18px;
}

.aspire-enquiry--narrow .frm-fluent-form fieldset > * { flex: 1 1 100%; }

.aspire-enquiry--narrow .frm-fluent-form fieldset > .ff-el-group:has(input[name="email"]),
.aspire-enquiry--narrow .frm-fluent-form fieldset > .ff-el-group:has(input[name="company"]) {
  flex: 1 1 calc(50% - 9px);
  min-width: 220px;
}

@media (max-width: 600px) {
  .aspire-enquiry--narrow .frm-fluent-form fieldset > .ff-el-group:has(input[name="email"]),
  .aspire-enquiry--narrow .frm-fluent-form fieldset > .ff-el-group:has(input[name="company"]) {
    flex-basis: 100%;
  }
}

/* --- the employer logo on a growth row ---------------------------------- */
/* Who's Growing is a list of companies, so it should look like one. The box is
   a fixed square with the logo contained inside it, because employer logos
   arrive as SVGs at wildly different proportions and a row of them only reads
   as a list if every box is the same size. */
.aspire-growth-logo {
  display: flex;
  flex: none;
  align-items: center;
  justify-content: center;
  width: 64px;
  height: 64px;
  padding: 9px;
  background: var(--aspire-white);
  border: 1px solid var(--aspire-line-soft);
  border-radius: 8px;
  transition: border-color 0.2s ease;
}

.aspire-growth-logo img {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
}

.e-loop-item:hover .aspire-growth-logo { border-color: var(--aspire-sage); }

@media (max-width: 767px) {
  .aspire-growth-logo { width: 52px; height: 52px; padding: 7px; }
}

/* --- the article rail --------------------------------------------------- */
/* The advert beside an article follows the reader down the page. 112px clears
   the sticky header, which is 88 tall, with room to breathe.
   Two things this rule depends on, so do not change them without checking:
   the row container holding the article and the rail must be set to align
   items at flex-start in Elementor, because a stretched item is as tall as
   its parent and can never stick; and nothing above it may have overflow
   hidden, which quietly kills position: sticky with no error anywhere.
   Below 1024 the rail drops under the article. A 300px column next to a
   phone is not a column, it is a squeeze. */
.aspire-rail {
  position: sticky;
  top: 112px;
}

@media (max-width: 1024px) {
  .aspire-rail {
    position: static;
    top: auto;
  }
}

/* ==========================================================================
   THE DIRECTORY FILTERS

   Elementor's Taxonomy Filter widget draws a flat row of buttons. Four of
   those is four lines of tags before you reach an employer, so a small script
   in assets/aspire-filters.js folds each one into a dropdown. Elementor still
   does the filtering. This is the shell around it.

   Note the exception. The rules under .aspire-filter__panel do target
   Elementor's own classes, which nothing else in this file does. It is
   deliberate: the panel contains Elementor's markup and has to restyle it.
   Every one of those rules is scoped inside the panel, so it cannot reach
   anything else on the site.
   ========================================================================== */

.aspire-filters {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
}

/* Elementor gives a child container width:100%, which would put one dropdown
   per line. These sit to their own width and let the row wrap naturally. */
.aspire-filter {
  position: relative;
  width: auto;
  flex: 0 0 auto;
}

.aspire-filter__trigger {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-family: var(--aspire-sans);
  font-size: 14.5px;
  font-weight: 500;
  line-height: 1.2;
  padding: 10px 16px;
  border: 1px solid var(--aspire-line);
  border-radius: 20px;
  background: var(--aspire-white);
  color: var(--aspire-ink);
  cursor: pointer;
}
.aspire-filter__trigger:hover { border-color: var(--aspire-brand); }

.aspire-filter__caret {
  width: 0;
  height: 0;
  border-left: 4px solid transparent;
  border-right: 4px solid transparent;
  border-top: 5px solid currentColor;
  opacity: 0.55;
}

/* something is chosen, so the pill says so without being read */
.aspire-filter.has-selection .aspire-filter__trigger {
  background: var(--aspire-forest);
  border-color: var(--aspire-forest);
  color: var(--aspire-white);
}

.aspire-filter.is-open .aspire-filter__trigger { border-color: var(--aspire-brand); }
.aspire-filter.is-open .aspire-filter__caret { transform: rotate(180deg); }

.aspire-filter__panel {
  display: none;
  position: absolute;
  z-index: 40;
  top: calc(100% + 8px);
  left: 0;
  min-width: 260px;
  max-width: min(340px, 90vw);
  max-height: 320px;
  overflow-y: auto;
  padding: 8px;
  background: var(--aspire-white);
  border: 1px solid var(--aspire-line);
  border-radius: var(--aspire-radius-card);
  box-shadow: 0 14px 32px rgba(27, 33, 22, 0.14);
}
.aspire-filter.is-open .aspire-filter__panel { display: block; }

/* --- Elementor's own markup, restyled inside the panel ------------------ */
/* The whole widget is moved in here, so its own box needs to fill the panel
   rather than keep whatever width it had out on the row. */
.aspire-filter__panel .elementor-widget-taxonomy-filter {
  width: 100%;
  max-width: none;
}

.aspire-filter__panel .e-filter {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 2px;
}

.aspire-filter__panel .e-filter-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  width: 100%;
  padding: 9px 12px;
  border: 0;
  border-radius: var(--aspire-radius-btn);
  background: none;
  font-family: var(--aspire-sans);
  font-size: 14.5px;
  font-weight: 400;
  line-height: 1.35;
  text-align: left;
  color: var(--aspire-ink);
  cursor: pointer;
}
.aspire-filter__panel .e-filter-item:hover { background: var(--aspire-paper); }

/* Elementor puts its "All" item last. At the top it reads as "clear this
   filter", which is what somebody reaching for it actually wants. */
.aspire-filter__panel .e-filter-item[data-filter="__all"] {
  order: -1;
  margin-bottom: 4px;
  padding-bottom: 11px;
  border-bottom: 1px solid var(--aspire-line-soft);
  border-radius: 0;
  color: var(--aspire-muted);
}
.aspire-filter__panel .e-filter-item[data-filter="__all"]::after { content: none; }

.aspire-filter__panel .e-filter-item[aria-pressed="true"] {
  background: var(--aspire-mint);
  color: var(--aspire-forest);
  font-weight: 600;
}
.aspire-filter__panel .e-filter-item[aria-pressed="true"]::after {
  content: "\2713";
  font-size: 13px;
  color: var(--aspire-brand);
}

@media (max-width: 767px) {
  .aspire-filter { width: 100%; }
  .aspire-filter__trigger { width: 100%; justify-content: space-between; }
  .aspire-filter__panel { min-width: 0; max-width: none; width: 100%; }
}

/* ==========================================================================
   THE EMPLOYER PROFILE

   One template serves Free, Standard and Premium. aspire-core puts the tier
   on the body, and the two rules below hide what the employer has not paid
   for. Mark a container in Elementor with aspire-tier--standard or
   aspire-tier--premium and it looks after itself.

   Elementor's own display conditions cannot see a taxonomy term, which is why
   this is CSS rather than a setting in the editor. Keep the marker classes on
   containers, never on a widget, so a whole block goes at once.

   The rest of this section styles the repeater output from
   aspire-core/includes/profile.php. That markup is structure only, so
   everything it looks like is decided here.
   ========================================================================== */

/* --- what each tier gets ------------------------------------------------ */
/* --standard and --premium mean "this tier or better". --free-only is the
   other way round: it is the short summary a thin profile leans on, and it
   would only repeat itself once the fuller About us block is there. */
body:not(.aspire-tier-standard):not(.aspire-tier-premium) .aspire-tier--standard { display: none; }
body:not(.aspire-tier-premium) .aspire-tier--premium { display: none; }
body.aspire-tier-standard .aspire-tier--free-only,
body.aspire-tier-premium  .aspire-tier--free-only { display: none; }

/* --- the "currently interested in" card, Premium only ------------------- */
/* The one place on the site where a colour steps outside the section palette.
   It is the field that separates us from a job board, so it is allowed to. */
.aspire-interested {
  background: var(--aspire-white);
  border: 1px solid var(--aspire-sun);
  border-top: 4px solid var(--aspire-sun);
  border-radius: var(--aspire-radius-card);
}

/* --- at a glance -------------------------------------------------------- */
.aspire-glance { margin: 0; }

.aspire-glance > div {
  display: flex;
  gap: 16px;
  padding: 10px 0;
  border-bottom: 1px solid var(--aspire-line-soft);
  font-family: var(--aspire-sans);
  font-size: 15px;
}
.aspire-glance > div:last-child { border-bottom: 0; }

.aspire-glance dt { flex: none; width: 96px; color: var(--aspire-muted); }
.aspire-glance dd { margin: 0; font-weight: 500; }

/* --- why work with us, as tiles ----------------------------------------- */
.aspire-tiles {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--aspire-gap);
}

.aspire-tile {
  background: var(--aspire-mint);
  border-radius: var(--aspire-radius-card);
  padding: 22px;
}
.aspire-tile h3 {
  font-family: var(--aspire-sans);
  font-size: 16.5px;
  font-weight: 700;
  line-height: 1.3;
  color: var(--aspire-forest);
  margin: 0 0 6px;
}
.aspire-tile p {
  margin: 0;
  font-size: 14.5px;
  line-height: 1.55;
  color: var(--aspire-muted);
}

/* --- our people --------------------------------------------------------- */
.aspire-people {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--aspire-gap);
}

.aspire-person {
  display: flex;
  gap: 18px;
  padding: 22px;
  border: 1px solid var(--aspire-line);
  border-radius: var(--aspire-radius-card);
}

.aspire-person__photo {
  width: 76px;
  height: 76px;
  flex: none;
  border-radius: 50%;
  object-fit: cover;
}

.aspire-person__name {
  display: block;
  font-weight: 700;
  font-size: 16.5px;
  color: var(--aspire-forest);
}
.aspire-person__role {
  display: block;
  font-size: 13.5px;
  color: var(--aspire-muted);
  margin-bottom: 10px;
}
.aspire-person__quote {
  display: block;
  font-size: 15px;
  line-height: 1.55;
}

/* --- projects ----------------------------------------------------------- */
.aspire-projects {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--aspire-gap);
}

.aspire-project {
  border: 1px solid var(--aspire-line);
  border-radius: var(--aspire-radius-card);
  overflow: hidden;
}
.aspire-project__image img {
  width: 100%;
  aspect-ratio: 16 / 10;
  object-fit: cover;
}
.aspire-project__body { padding: 20px 22px 24px; }
.aspire-project__body h3 {
  font-family: var(--aspire-sans);
  font-size: 17px;
  font-weight: 700;
  line-height: 1.3;
  color: var(--aspire-forest);
  margin: 0 0 6px;
}
.aspire-project__body p {
  margin: 0;
  font-size: 14.5px;
  line-height: 1.55;
  color: var(--aspire-muted);
}

/* --- career pathways ---------------------------------------------------- */
/* A line down the left with a dot at each stage. It reads as progression,
   which a plain list does not. */
.aspire-path {
  border-left: 2px solid var(--aspire-line);
  padding-left: 26px;
  margin-left: 8px;
}

.aspire-step {
  position: relative;
  padding-bottom: 26px;
}
.aspire-step:last-child { padding-bottom: 0; }

.aspire-step::before {
  content: "";
  position: absolute;
  left: -33px;
  top: 6px;
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: var(--aspire-brand);
  border: 3px solid var(--aspire-white);
  box-shadow: 0 0 0 2px var(--aspire-brand);
}

.aspire-step__stage {
  display: block;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--aspire-brand);
  margin-bottom: 4px;
}
.aspire-step h3 {
  font-family: var(--aspire-sans);
  font-size: 17px;
  font-weight: 700;
  color: var(--aspire-forest);
  margin: 0 0 4px;
}
.aspire-step p {
  margin: 0;
  font-size: 15px;
  color: var(--aspire-muted);
}

/* --- latest from us ----------------------------------------------------- */
.aspire-latest { border-top: 1px solid var(--aspire-line-soft); }

.aspire-latest__item {
  padding: 18px 0;
  border-bottom: 1px solid var(--aspire-line-soft);
}
.aspire-latest__when {
  display: block;
  font-size: 12.5px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--aspire-muted);
  margin-bottom: 4px;
}
.aspire-latest__item h3 {
  font-family: var(--aspire-sans);
  font-size: 17px;
  font-weight: 700;
  color: var(--aspire-forest);
  margin: 0 0 4px;
}
.aspire-latest__item p {
  margin: 0;
  font-size: 15px;
  color: var(--aspire-muted);
}

/* --- gallery ------------------------------------------------------------ */
.aspire-gallery {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 12px;
}
.aspire-gallery img {
  width: 100%;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  border-radius: 8px;
}

/* --- the careers contact ------------------------------------------------ */
.aspire-contact__name {
  display: block;
  font-weight: 700;
  font-size: 16.5px;
  color: var(--aspire-forest);
}
.aspire-contact__role {
  display: block;
  font-size: 14px;
  color: var(--aspire-muted);
  margin-bottom: 14px;
}
.aspire-contact__link {
  display: inline-block;
  font-size: 14px;
  font-weight: 600;
  padding: 10px 18px;
  border: 2px solid var(--aspire-brand);
  border-radius: var(--aspire-radius-btn);
  color: var(--aspire-brand);
  text-decoration: none;
}
.aspire-contact__link:hover {
  background: var(--aspire-brand);
  color: var(--aspire-white);
}

/* --- the claim line on a Free profile ----------------------------------- */
/* Quiet, and always below the content. The page belongs to the reader first,
   and to the sales pitch second. */
.aspire-claim {
  border: 1px dashed var(--aspire-line);
  border-radius: var(--aspire-radius-card);
  background: var(--aspire-paper);
  padding: 22px;
  font-size: 15px;
  color: var(--aspire-muted);
}
.aspire-claim strong {
  display: block;
  color: var(--aspire-forest);
  margin-bottom: 4px;
}

@media (max-width: 1199px) {
  .aspire-tiles { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 1024px) {
  .aspire-gallery { grid-template-columns: repeat(3, 1fr); }
}

@media (max-width: 767px) {
  .aspire-tiles,
  .aspire-people,
  .aspire-projects { grid-template-columns: 1fr; }
  .aspire-gallery { grid-template-columns: repeat(2, 1fr); }
  .aspire-person { flex-direction: column; }
  .aspire-glance dt { width: 84px; }
}

/* --- career stories on an employer profile ------------------------------ */
/* [aspire_employer_stories] in aspire-core, and the byline on the story
   itself. A ruled list rather than a grid, because a profile is not an
   archive and this never shows more than four. */
.aspire-stories h3.aspire-stories__title {
  font-family: var(--aspire-display);
  font-size: 22px;
  line-height: 1.25;
  color: var(--aspire-forest);
  margin: 0 0 14px;
}

.aspire-stories__list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.aspire-stories__list li {
  padding: 14px 0;
  border-bottom: 1px solid var(--aspire-line-soft);
}

.aspire-stories__list li:first-child {
  border-top: 1px solid var(--aspire-line-soft);
}

.aspire-stories__list a {
  display: block;
  font-family: var(--aspire-sans);
  font-size: 16px;
  font-weight: 500;
  line-height: 1.4;
  color: var(--aspire-forest);
  text-decoration: none;
}

.aspire-stories__list a:hover {
  color: var(--aspire-brand);
}

.aspire-stories__who {
  display: block;
  margin-top: 3px;
  font-family: var(--aspire-sans);
  font-size: 14px;
  color: var(--aspire-muted);
}

/* The byline sits under a story title. The person is not a link, because they
   are not a page on this site and should not look like one. */
.aspire-story-byline {
  margin: 0;
  color: var(--aspire-muted);
}

.aspire-story-byline .aspire-story-person {
  color: var(--aspire-ink);
  font-weight: 500;
}

/* --- Ask Aspire and the Hub rows ---------------------------------------- */
/* The signposts at the end of an answer reuse the story list above, so all
   that is new here is the heading, the byline and the bare domain that tells
   a reader where a row is about to send them. */
.aspire-answer-signposts { margin-top: 8px; }

.aspire-answer-signposts h2.aspire-answer-signposts__title {
  font-family: var(--aspire-display);
  font-size: 26px;
  line-height: 1.2;
  color: var(--aspire-forest);
  margin: 0 0 14px;
}

.aspire-asked-by {
  margin: 0;
  color: var(--aspire-muted);
}

.aspire-signpost__host {
  display: block;
  font-family: var(--aspire-sans);
  font-size: 14px;
  color: var(--aspire-ink);
  white-space: nowrap;
}

.aspire-stories__list .aspire-signpost__host { margin-top: 4px; }

/* --- follow an employer ------------------------------------------------- */
/* [aspire_follow] in aspire-core, a card in the profile sidebar. One field
   and one button, because that is all a follow is. The status line under
   it is where the reply lands without a page reload. */
.aspire-follow__lead {
  margin: 0 0 12px;
  font-family: var(--aspire-sans);
  font-size: 14.5px;
  line-height: 1.55;
  color: var(--aspire-muted);
}

.aspire-follow__lead strong {
  display: block;
  margin-bottom: 2px;
  font-size: 16px;
  color: var(--aspire-forest);
}

.aspire-follow__form {
  display: flex;
  gap: 8px;
}

.aspire-follow__input {
  flex: 1 1 auto;
  min-width: 0;
  padding: 11px 12px;
  font-family: var(--aspire-sans);
  font-size: 15px;
  color: var(--aspire-ink);
  background: var(--aspire-white);
  border: 1px solid var(--aspire-line);
  border-radius: var(--aspire-radius-btn);
}

.aspire-follow__input:focus {
  outline: 2px solid var(--aspire-brand);
  outline-offset: 1px;
  border-color: var(--aspire-brand);
}

.aspire-follow__button {
  flex: none;
  padding: 11px 18px;
  font-family: var(--aspire-sans);
  font-size: 15px;
  font-weight: 600;
  color: var(--aspire-white);
  background: var(--aspire-brand);
  border: 2px solid var(--aspire-brand);
  border-radius: var(--aspire-radius-btn);
  cursor: pointer;
  transition: background 0.2s ease, border-color 0.2s ease;
}

.aspire-follow__button:hover,
.aspire-follow__button:focus-visible {
  background: var(--aspire-forest);
  border-color: var(--aspire-forest);
}

.aspire-follow__button[disabled] {
  opacity: 0.6;
  cursor: default;
}

/* the honeypot: off screen, never hidden with display none, because some
   bots skip fields that are display none and fill in the ones that are not */
.aspire-follow__hp {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  opacity: 0;
}

.aspire-follow__status {
  margin: 10px 0 0;
  min-height: 1em;
  font-family: var(--aspire-sans);
  font-size: 14px;
  line-height: 1.5;
  color: var(--aspire-brand);
}

.aspire-follow__status--error { color: #9A3B2E; }

.aspire-follow--done p {
  margin: 0;
  font-family: var(--aspire-sans);
  font-size: 14.5px;
  line-height: 1.55;
  color: var(--aspire-ink);
}

.aspire-follow--done strong { color: var(--aspire-forest); }

/* --- employer comparison ------------------------------------------------ */
/* Three parts: the Compare toggle on a card or profile, the bar that appears
   at the foot of the page once something is picked, and the table on the
   compare page. All markup comes from aspire-core, see compare.php. */

/* the toggle: a quiet pill that fills when pressed. It sits inside a card
   whose whole surface is a link, so it has to float above that overlay */
.aspire-compare-toggle {
  position: relative;
  z-index: 3;
  display: inline-flex;
  align-items: center;
  padding: 6px 12px;
  font-family: var(--aspire-sans);
  font-size: 12.5px;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--aspire-brand);
  background: var(--aspire-white);
  border: 1px solid var(--aspire-line);
  border-radius: 999px;
  cursor: pointer;
  transition: background 0.2s ease, color 0.2s ease, border-color 0.2s ease;
}

.aspire-compare-toggle:hover,
.aspire-compare-toggle:focus-visible {
  border-color: var(--aspire-brand);
}

.aspire-compare-toggle.is-on {
  color: var(--aspire-white);
  background: var(--aspire-brand);
  border-color: var(--aspire-brand);
}

.aspire-compare-toggle[disabled] {
  opacity: 0.45;
  cursor: default;
}

.aspire-compare-toggle .aspire-compare-toggle__on  { display: none; }
.aspire-compare-toggle.is-on .aspire-compare-toggle__on  { display: inline; }
.aspire-compare-toggle.is-on .aspire-compare-toggle__off { display: none; }

/* on the profile header the toggle sits beside two proper buttons and
   should stand as tall as they do */
.aspire-compare-toggle-w .aspire-compare-toggle {
  padding: 13px 20px;
  font-size: 14px;
  border-radius: var(--aspire-radius-btn);
  border-width: 2px;
}

/* the bar */
.aspire-compare-bar {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 60;
  background: var(--aspire-forest);
  color: var(--aspire-white);
  box-shadow: 0 -6px 24px rgba(20, 32, 14, 0.18);
}

.aspire-compare-bar__inner {
  max-width: var(--aspire-container);
  margin: 0 auto;
  padding: 12px 24px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  font-family: var(--aspire-sans);
  font-size: 14.5px;
}

.aspire-compare-bar__names {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: rgba(255, 255, 255, 0.85);
}

.aspire-compare-bar__actions {
  display: flex;
  align-items: center;
  gap: 10px;
  flex: none;
}

.aspire-compare-bar__go {
  display: inline-block;
  padding: 10px 18px;
  font-weight: 600;
  color: var(--aspire-forest);
  background: var(--aspire-sun);
  border-radius: var(--aspire-radius-btn);
  text-decoration: none;
}

.aspire-compare-bar__go.is-disabled {
  opacity: 0.5;
  cursor: default;
}

.aspire-compare-bar__clear {
  padding: 10px 12px;
  font-family: var(--aspire-sans);
  font-size: 14px;
  color: rgba(255, 255, 255, 0.85);
  background: transparent;
  border: 1px solid rgba(255, 255, 255, 0.35);
  border-radius: var(--aspire-radius-btn);
  cursor: pointer;
}

/* the table */
.aspire-compare { overflow-x: auto; }

.aspire-compare__table {
  width: 100%;
  min-width: 640px;
  border-collapse: collapse;
  font-family: var(--aspire-sans);
  font-size: 15px;
  line-height: 1.5;
  color: var(--aspire-ink);
}

.aspire-compare__table th,
.aspire-compare__table td {
  padding: 16px 18px;
  text-align: left;
  vertical-align: top;
  border-bottom: 1px solid var(--aspire-line-soft);
}

.aspire-compare__table thead th {
  border-bottom: 2px solid var(--aspire-line);
}

.aspire-compare__label {
  width: 140px;
  font-size: 13px;
  font-weight: 500;
  color: var(--aspire-muted);
}

.aspire-compare__logo {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 72px;
  height: 72px;
  margin-bottom: 12px;
  padding: 10px;
  background: var(--aspire-white);
  border: 1px solid var(--aspire-line-soft);
  border-radius: 8px;
}

.aspire-compare__logo img { max-width: 100%; max-height: 100%; object-fit: contain; }

.aspire-compare__name {
  display: block;
  font-family: var(--aspire-display);
  font-size: 22px;
  line-height: 1.2;
  color: var(--aspire-forest);
  text-decoration: none;
}

.aspire-compare__remove {
  margin-top: 8px;
  padding: 0;
  font-family: var(--aspire-sans);
  font-size: 12.5px;
  color: var(--aspire-muted);
  background: none;
  border: 0;
  cursor: pointer;
  text-decoration: underline;
}

.aspire-compare__none { color: var(--aspire-line); }

.aspire-compare__go,
.aspire-compare__more a {
  font-weight: 600;
  color: var(--aspire-brand);
  text-decoration: none;
}

.aspire-compare__more {
  margin: 20px 0 0;
  font-family: var(--aspire-sans);
  font-size: 15px;
  color: var(--aspire-muted);
}

.aspire-compare-empty {
  max-width: var(--aspire-reading);
  font-family: var(--aspire-sans);
  font-size: 17px;
  line-height: 1.7;
  color: var(--aspire-ink);
}

@media (max-width: 767px) {
  .aspire-compare-bar__inner { flex-direction: column; align-items: stretch; text-align: center; }
  .aspire-compare-bar__names { white-space: normal; }
  .aspire-compare-bar__actions { justify-content: center; }
  .aspire-compare__table th, .aspire-compare__table td { padding: 12px 10px; font-size: 14px; }
  .aspire-compare__label { width: 96px; }
  .aspire-compare__name { font-size: 18px; }
}

/* --- the employer map --------------------------------------------------- */
/* [aspire_map] in aspire-core. Leaflet draws into the canvas; these rules
   are the frame around it and the popup inside it. Leaflet's own stylesheet
   is loaded from cdnjs on the map page only. */
.aspire-map {
  position: relative;
  width: 100%;
  border-radius: var(--aspire-radius-card);
  overflow: hidden;
  border: 1px solid var(--aspire-line-soft);
  background: var(--aspire-paper);
}

.aspire-map__canvas {
  position: absolute;
  inset: 0;
  z-index: 1;
}

.aspire-map__status {
  position: absolute;
  left: 50%;
  top: 50%;
  z-index: 2;
  transform: translate(-50%, -50%);
  margin: 0;
  padding: 10px 16px;
  font-family: var(--aspire-sans);
  font-size: 14.5px;
  color: var(--aspire-muted);
  background: rgba(255, 255, 255, 0.92);
  border-radius: var(--aspire-radius-btn);
  pointer-events: none;
}

.aspire-map__status[hidden] { display: none; }

/* Leaflet's popup, in our type */
.aspire-map__popup .leaflet-popup-content-wrapper {
  border-radius: var(--aspire-radius-card);
  box-shadow: 0 8px 28px rgba(20, 32, 14, 0.18);
}

.aspire-map__popup .leaflet-popup-content {
  margin: 14px 16px;
  font-family: var(--aspire-sans);
  font-size: 14px;
  line-height: 1.5;
  color: var(--aspire-ink);
}

.aspire-map__pop { display: flex; gap: 12px; align-items: flex-start; }

.aspire-map__pop-logo {
  flex: none;
  width: 48px;
  height: 48px;
  padding: 6px;
  object-fit: contain;
  background: var(--aspire-white);
  border: 1px solid var(--aspire-line-soft);
  border-radius: 8px;
}

.aspire-map__pop-name {
  display: block;
  font-family: var(--aspire-display);
  font-size: 18px;
  line-height: 1.2;
  color: var(--aspire-forest);
  text-decoration: none;
}

.aspire-map__pop-meta { margin-top: 3px; color: var(--aspire-muted); font-size: 13px; }
.aspire-map__pop-specs { margin-top: 4px; font-size: 13px; }

.aspire-map__pop-go {
  display: inline-block;
  margin-top: 8px;
  font-weight: 600;
  color: var(--aspire-brand);
  text-decoration: none;
}

/* the tier key under the map */
.aspire-map-key {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 22px;
  margin: 14px 0 0;
  padding: 0;
  list-style: none;
  font-family: var(--aspire-sans);
  font-size: 13.5px;
  color: var(--aspire-muted);
}

.aspire-map-key li { display: flex; align-items: center; gap: 8px; }

.aspire-map-key li::before {
  content: "";
  width: 12px;
  height: 12px;
  border-radius: 50%;
  border: 2px solid var(--aspire-white);
  box-shadow: 0 0 0 1px var(--aspire-line);
}

.aspire-map-key .is-premium::before  { background: var(--aspire-forest); }
.aspire-map-key .is-standard::before { background: var(--aspire-brand); }
.aspire-map-key .is-free::before     { background: var(--aspire-sage); }

@media (max-width: 767px) {
  .aspire-map { border-radius: 8px; }
}


/* =========================================================================
   Career ladder (Salary and career insights, aspire-core/includes/insights.php)
   Five rungs, one shared salary scale, so the eye reads the climb.
   ========================================================================= */

.aspire-ladder__notice {
  margin: 0 0 32px;
  padding: 16px 20px;
  border-left: 4px solid var(--aspire-sun);
  background: var(--aspire-paper);
  border-radius: 0 var(--aspire-radius-btn) var(--aspire-radius-btn) 0;
  font-family: var(--aspire-sans);
  font-size: 15px;
  line-height: 1.55;
  color: var(--aspire-ink);
}

.aspire-ladder__notice p { margin: 0; }

.aspire-ladder {
  margin: 0;
  padding: 0;
  list-style: none;
  counter-reset: none;
}

.aspire-ladder__stage {
  position: relative;
  padding: 32px 0 36px;
  border-top: 1px solid var(--aspire-line);
}

.aspire-ladder__stage:last-child { border-bottom: 1px solid var(--aspire-line); }

.aspire-ladder__head {
  display: flex;
  align-items: flex-start;
  gap: 18px;
  margin-bottom: 18px;
}

.aspire-ladder__num {
  flex: none;
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: var(--aspire-forest);
  color: var(--aspire-sun);
  font-family: var(--aspire-display);
  font-size: 22px;
  line-height: 1;
}

.aspire-ladder__title {
  margin: 4px 0 0;
  font-family: var(--aspire-display);
  font-size: clamp(24px, 2.2vw, 30px);
  line-height: 1.15;
  color: var(--aspire-forest);
}

.aspire-ladder__years {
  margin: 4px 0 0;
  font-family: var(--aspire-sans);
  font-size: 14.5px;
  color: var(--aspire-muted);
}

/* the bar */
.aspire-ladder__bar {
  position: relative;
  height: 14px;
  margin: 0 0 40px;
  background: var(--aspire-line-soft);
  border-radius: 7px;
}

.aspire-ladder__range {
  position: absolute;
  top: 0;
  bottom: 0;
  border-radius: 7px;
  background: linear-gradient(90deg, var(--aspire-brand), var(--aspire-forest));
}

.is-placeholder .aspire-ladder__range {
  background: repeating-linear-gradient(135deg, var(--aspire-sage) 0 6px, var(--aspire-brand) 6px 12px);
  opacity: 0.85;
}

.aspire-ladder__figures {
  position: absolute;
  top: 22px;
  left: 0;
  font-family: var(--aspire-sans);
  font-size: 15px;
  font-weight: 600;
  color: var(--aspire-forest);
  white-space: nowrap;
}

.aspire-ladder__figures em {
  font-style: normal;
  font-weight: 500;
  font-size: 12.5px;
  margin-left: 6px;
  padding: 2px 8px;
  border-radius: 999px;
  background: var(--aspire-sun);
  color: var(--aspire-forest);
  vertical-align: 1px;
}

/* the three columns */
.aspire-ladder__body {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--aspire-gap) 32px;
}

.aspire-ladder__col h4 {
  margin: 0 0 8px;
  font-family: var(--aspire-sans);
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--aspire-brand);
}

.aspire-ladder__col p {
  margin: 0;
  font-family: var(--aspire-sans);
  font-size: 15.5px;
  line-height: 1.6;
  color: var(--aspire-ink);
}

.aspire-ladder__sources,
.aspire-ladder__empty {
  margin: 24px 0 0;
  font-family: var(--aspire-sans);
  font-size: 14px;
  line-height: 1.55;
  color: var(--aspire-muted);
}

@media (max-width: 1023px) {
  .aspire-ladder__body { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 767px) {
  .aspire-ladder__stage { padding: 26px 0 30px; }
  .aspire-ladder__num { width: 38px; height: 38px; font-size: 19px; }
  .aspire-ladder__body { grid-template-columns: 1fr; gap: 18px; }
  .aspire-ladder__figures { white-space: normal; font-size: 14.5px; left: 0 !important; right: auto !important; text-align: left !important; }
  .aspire-ladder__bar { margin-bottom: 48px; }
}


/* =========================================================================
   University profile (aspire-core/includes/university.php, template 412)
   Built 6 September after the QA sweep found four university pages with
   nothing on them but the title.
   ========================================================================= */

.aspire-uni__tags { display: flex; flex-wrap: wrap; gap: 6px; }

.aspire-uni__tag {
  display: inline-block;
  padding: 4px 11px;
  border-radius: 999px;
  background: var(--aspire-mint);
  color: var(--aspire-forest);
  font-family: var(--aspire-sans);
  font-size: 12.5px;
  font-weight: 600;
  letter-spacing: 0.02em;
}

.aspire-uni__place {
  font-family: var(--aspire-sans);
  font-size: 15px;
  color: var(--aspire-muted);
}

.aspire-uni__site {
  display: inline-block;
  margin-top: 4px;
  font-family: var(--aspire-sans);
  font-size: 15px;
  font-weight: 600;
  color: var(--aspire-brand);
  text-decoration: none;
}

.aspire-uni__site:hover { text-decoration: underline; }

.aspire-uni__empty {
  margin: 0;
  padding: 20px 22px;
  border: 1px dashed var(--aspire-line);
  border-radius: var(--aspire-radius-card);
  font-family: var(--aspire-sans);
  font-size: 15px;
  color: var(--aspire-muted);
}

.aspire-uni-courses { margin: 0; padding: 0; list-style: none; }

.aspire-uni-courses__row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  padding: 18px 0;
  border-bottom: 1px solid var(--aspire-line-soft);
}

.aspire-uni-courses__row:first-child { border-top: 1px solid var(--aspire-line-soft); }

.aspire-uni-courses__main { display: flex; flex-direction: column; gap: 4px; min-width: 0; }

.aspire-uni-courses__title {
  font-family: var(--aspire-display);
  font-size: 20px;
  line-height: 1.25;
  color: var(--aspire-forest);
  text-decoration: none;
}

a.aspire-uni-courses__title:hover { color: var(--aspire-brand); }

.aspire-uni-courses__meta {
  font-family: var(--aspire-sans);
  font-size: 14px;
  color: var(--aspire-muted);
}

.aspire-uni-courses__go {
  flex: none;
  font-family: var(--aspire-sans);
  font-size: 14.5px;
  font-weight: 600;
  color: var(--aspire-brand);
  white-space: nowrap;
}

@media (max-width: 767px) {
  .aspire-uni-courses__row { flex-direction: column; align-items: flex-start; gap: 6px; padding: 16px 0; }
  .aspire-uni-courses__title { font-size: 18px; }
}

/* =========================================================================
   HEADER NAVIGATION, the two mega panels
   Added 12 September, replacing three thin dropdowns.

   Read this before editing.

   The structure comes from the WordPress menu, not from this file. A top
   level item carrying .aspire-mega-parent is a label with no page behind
   it, so its href is "#" and it only opens a panel. Inside a panel, a
   second level item that HAS children is a column heading and a second
   level item with NO children is a plain link. That one rule is why the
   same CSS lays out Employers, which is a single column of three links,
   and Your Career, which is two columns under Learn and Develop.

   Two traps, both of which cost time on 12 September.

   One. Elementor puts .elementor-nav-menu--main and
   .elementor-nav-menu--dropdown on the NAV element, not on the list, so
   every selector needs the " > ul " step. Worse, it puts that same
   --dropdown class on every sub menu UL as well, so a selector written
   without the nav tag will match the desktop panel too. Both roots below
   are therefore written as nav.

   Two. Elementor drives this menu with SmartMenus, which writes display,
   top and left straight onto the element as inline styles. A stylesheet
   rule only beats an inline one when it is marked important, which is why
   the third level carries !important. Nothing else here needs it.
   ========================================================================= */

/* --- The panel ---------------------------------------------------------- */

nav.elementor-nav-menu--main > ul > li.aspire-mega-parent > ul.sub-menu {
  /* max-content, not auto. The panel is absolutely positioned, so auto makes
     it shrink to the width of the menu item above it and the second column
     wraps under the first. max-content asks for the width the columns
     actually want, and the max-width below stops that running away. */
  width: max-content !important;
  min-width: 240px;
  max-width: min(92vw, 640px);
  padding: 24px 28px 22px;
  border: 1px solid var(--aspire-line-soft);
  border-radius: var(--aspire-radius-card);
  box-shadow: 0 20px 44px rgba(27, 33, 22, .12);
  /* Columns are inline-block, so the whitespace between two list items in
     the markup would otherwise show up as a gap. Zeroing the font size on
     the panel kills it, and each column sets its own size back. */
  font-size: 0;
}

/* --- A column, or a plain link where there is no column ----------------- */
/* Only an item that has children becomes a column. An item with no children
   is a plain link and stays a full width row, which is what makes the
   Employers panel a stacked list and the Your Career panel two columns
   without either of them needing a rule of its own. */

nav.elementor-nav-menu--main > ul > li.aspire-mega-parent > ul.sub-menu > li {
  font-size: 15px;
}

nav.elementor-nav-menu--main > ul > li.aspire-mega-parent > ul.sub-menu > li.menu-item-has-children {
  display: inline-block;
  vertical-align: top;
  width: auto;
  min-width: 190px;
}

nav.elementor-nav-menu--main > ul > li.aspire-mega-parent > ul.sub-menu > li.menu-item-has-children + li.menu-item-has-children {
  margin-left: 34px;
}

/* --- A column heading, which is a second level item with children ------- */

nav.elementor-nav-menu--main > ul > li.aspire-mega-parent > ul.sub-menu > li.menu-item-has-children > a {
  pointer-events: none;
  margin: 0 0 6px;
  padding: 0 0 9px !important;
  border-bottom: 1px solid var(--aspire-line-soft);
  font-family: var(--aspire-sans);
  font-size: 12px !important;
  font-weight: 700;
  letter-spacing: .10em;
  text-transform: uppercase;
  color: var(--aspire-muted) !important;
  background: none !important;
}

/* --- The third level, held open inside the panel ------------------------ */

nav.elementor-nav-menu--main > ul > li.aspire-mega-parent > ul.sub-menu > li > ul.sub-menu {
  display: block !important;
  position: static !important;
  top: auto !important;
  left: auto !important;
  width: auto !important;
  min-width: 0;
  margin: 0;
  padding: 0;
  border: 0 !important;
  border-radius: 0;
  box-shadow: none !important;
  background: transparent !important;
}

/* --- Every link in a panel ---------------------------------------------- */

nav.elementor-nav-menu--main > ul > li.aspire-mega-parent ul.sub-menu a.elementor-sub-item {
  padding: 8px 0 !important;
  font-family: var(--aspire-sans);
  font-size: 15px;
  line-height: 1.35;
  white-space: nowrap;
}

/* --- Hover and current page, inside a panel ----------------------------- */
/* Elementor fills the whole item with a dark block for hover and for the page
   you are on. In a floating white panel that reads as a bug rather than a
   state, so the ground stays clear and the colour does the work. */

nav.elementor-nav-menu--main > ul > li.aspire-mega-parent ul.sub-menu a.elementor-sub-item:hover,
nav.elementor-nav-menu--main > ul > li.aspire-mega-parent ul.sub-menu a.elementor-sub-item:focus,
nav.elementor-nav-menu--main > ul > li.aspire-mega-parent ul.sub-menu a.elementor-sub-item.elementor-item-active,
nav.elementor-nav-menu--main > ul > li.aspire-mega-parent ul.sub-menu a.elementor-sub-item.highlighted {
  background: transparent !important;
  color: var(--aspire-brand) !important;
}

nav.elementor-nav-menu--main > ul > li.aspire-mega-parent ul.sub-menu a.elementor-sub-item.elementor-item-active {
  font-weight: 600;
}

/* --- The caret on a top level parent ------------------------------------ */
/* Elementor already prints a caret, an inline SVG inside a .sub-arrow span,
   on any item with children. We keep that rather than drawing one, and
   simply turn it over while the panel is open. Inside a panel the caret is
   noise, so it is hidden there: a column heading is not a control. */

nav.elementor-nav-menu--main > ul > li.aspire-mega-parent > a {
  cursor: pointer;
}

nav.elementor-nav-menu--main > ul > li.aspire-mega-parent > a .sub-arrow svg {
  transition: transform .18s ease;
}

nav.elementor-nav-menu--main > ul > li.aspire-mega-parent.highlighted > a .sub-arrow svg {
  transform: rotate(180deg);
}

nav.elementor-nav-menu--main ul.sub-menu .sub-arrow {
  display: none !important;
}

/* --- The mobile nav ------------------------------------------------------ */
/* Elementor renders a second, separate list for the burger. Here a panel is
   an accordion rather than a floating box, so the only thing that changes
   is that a column heading reads as a heading and the links under it are
   already open, rather than sitting behind a second tap. */

nav.elementor-nav-menu--dropdown .aspire-mega-parent > a {
  cursor: pointer;
}

nav.elementor-nav-menu--dropdown > ul > li > ul.sub-menu > li.menu-item-has-children > a {
  pointer-events: none;
  font-family: var(--aspire-sans);
  font-size: 12px !important;
  font-weight: 700;
  letter-spacing: .10em;
  text-transform: uppercase;
  color: var(--aspire-muted) !important;
}

nav.elementor-nav-menu--dropdown > ul > li > ul.sub-menu > li.menu-item-has-children > a .sub-arrow {
  display: none !important;
}

nav.elementor-nav-menu--dropdown > ul > li > ul.sub-menu > li > ul.sub-menu {
  display: block !important;
  padding-left: 16px;
}

/* =========================================================================
   THE LOGO
   Added 12 September, when Garry sent the real Aspire in Ecology mark and the
   .aspire-mark stand-in wordmark came out of the header and the footer.

   Two files, one lockup. The mark Garry supplied is a reversed one, light
   type on a dark ground, so it can only ever sit on forest or brand green.
   The dark file is the same shapes recoloured for a white ground, which is
   what the header needs. Neither is a different logo, they are the positive
   and the reverse of one.

   Height is set here rather than on the image, and the width is auto, so the
   lockup keeps its proportions whatever we do to the header later.
   ========================================================================= */

.aspire-logo {
  display: inline-block;
  line-height: 0;
}

.aspire-logo img {
  display: block;
  width: auto;
  height: 52px;
}

.aspire-logo--footer img { height: 58px; }

@media (max-width: 1024px) {
  .aspire-logo img { height: 46px; }
}

@media (max-width: 767px) {
  .aspire-logo img { height: 40px; }
  .aspire-logo--footer img { height: 46px; }
}

/* =========================================================================
   FORMS
   Added 12 September. Fluent Forms ships a blue submit button and a blue
   focus ring, and both were live on For Employers and Ask Aspire without
   anyone noticing, because the form only shows up at the bottom of a long
   page. Two commercial pages asking for an enquiry should not do it in a
   colour that appears nowhere else on the site.

   This styles the button and the focus state and nothing else. Field
   layout, spacing and validation are Fluent Forms' own and are left alone.
   ========================================================================= */

/* Fluent Forms prints its own <style> block inside the page, further down
   than this file, and it paints the button from a variable rather than a
   colour: form.fluent_form_N .ff-btn-submit { background: var(--fluentform-primary) }.
   Fighting that with a background rule loses on specificity and on order.
   Redefining the variable on the form element wins on both, because a
   variable set on an element always beats the same variable set on :root,
   whatever the stylesheet order. */

form.frm-fluent-form {
  --fluentform-primary: #5A6E3A;
  --fluentform-secondary: #2B4521;
}

.fluentform .ff-btn-submit {
  border: 1px solid var(--aspire-brand);
  border-radius: var(--aspire-radius-btn);
  padding: 13px 26px;
  font-family: var(--aspire-sans);
  font-size: 15px;
  font-weight: 600;
  line-height: 1.2;
  color: #FFFFFF;
  transition: background .18s ease, border-color .18s ease;
}

.fluentform .ff-btn-submit:hover,
.fluentform .ff-btn-submit:focus {
  background: var(--aspire-forest);
  border-color: var(--aspire-forest);
  color: #FFFFFF;
}

.fluentform input[type="text"]:focus,
.fluentform input[type="email"]:focus,
.fluentform input[type="tel"]:focus,
.fluentform input[type="url"]:focus,
.fluentform select:focus,
.fluentform textarea:focus {
  border-color: var(--aspire-brand);
  box-shadow: 0 0 0 3px rgba(90, 110, 58, .18);
  outline: none;
}

/* --- the tick box list -------------------------------------------------- */
/* Added 13 September with Garry's "What are you interested in?" list. Fluent
   Forms ships a browser default checkbox and a tight line, which on a list of
   eight reads as a wall. These are bigger, spaced, and the whole row is the
   target, so it is easy to hit on a phone. */
.fluentform .ff-el-group .ff_list_buttons,
.fluentform .ff-el-form-check {
  margin-bottom: 2px;
}

.fluentform .ff-el-form-check label.ff-el-form-check-label {
  display: flex;
  align-items: flex-start;
  gap: 11px;
  padding: 7px 0;
  font-family: var(--aspire-sans);
  font-size: 15px;
  line-height: 1.5;
  color: var(--aspire-ink);
  cursor: pointer;
}

.fluentform .ff-el-form-check input[type="checkbox"],
.fluentform .ff-el-form-check input[type="radio"] {
  flex: none;
  width: 19px;
  height: 19px;
  margin: 1px 0 0;
  accent-color: var(--aspire-brand);
  cursor: pointer;
}

.fluentform .ff-el-form-check label.ff-el-form-check-label:hover { color: var(--aspire-brand); }

/* =========================================================================
   THE PROMOTE BAND
   The strip above the footer on every page. Rebuilt on 12 September because
   the first version was one small line and a text link, and it read as part
   of the footer rather than as an offer.

   The layout is here rather than in Elementor on purpose. A container child
   in Elementor takes its width from a `--width` custom property that the
   panel sets to 100 per cent, and the width control that overrides it is not
   reachable from the API in a way that survives a save. Two rules here do
   what four fields in the panel would not.
   ========================================================================= */

.aspire-promo {
  display: flex;
  flex-direction: row;
  align-items: center;
  justify-content: space-between;
  gap: 36px;
}

/* the copy column: let it take the space that is left, and let it shrink */
.aspire-promo > .e-con {
  --width: auto;
  width: auto;
  flex: 1 1 auto;
  min-width: 0;
}

/* the button: never shrink, never stretch */
.aspire-promo > .elementor-widget-button {
  width: auto;
  flex: 0 0 auto;
}

@media (max-width: 767px) {
  .aspire-promo {
    flex-direction: column;
    align-items: flex-start;
    gap: 22px;
  }
  .aspire-promo > .e-con { width: 100%; }
}

/* ==== THE EMPLOYER CARD LOGO, 12 September =============================
   Standard and Premium print a logo on their directory card, Free does not.
   The shortcode decides; this only sizes it.
   ==================================================================== */

.aspire-employer-logo {
  display: flex;
  flex: none;
  align-items: center;
  justify-content: center;
  width: 56px;
  height: 56px;
  overflow: hidden;
  border-radius: 8px;
  background: var(--aspire-white);
}

.aspire-employer-logo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* ==== THE JOURNEY, About Us, 12 September ===============================
   Garry's five steps across the page: Be seen, Tell your story, Build
   connections, Attract talent, Recruit when ready. Five equal paper boxes
   with a sage arrow between them on desktop; they stack on a phone and the
   arrow turns to point down.
   ==================================================================== */

.aspire-journey { align-items: stretch; }

.aspire-journey__step {
  position: relative;
  --width: auto;
  --flex-grow: 1;
  --flex-shrink: 1;
  --flex-basis: 0;
  width: auto;
  flex: 1 1 0;
  min-width: 0;
}

.aspire-journey__step:not(:last-child)::after {
  content: "";
  position: absolute;
  right: -12px;
  top: 50%;
  width: 12px;
  height: 2px;
  background: var(--aspire-sage);
  transform: translateY(-50%);
}

@media (max-width: 767px) {
  .aspire-journey__step { width: 100%; flex-basis: auto; }
  .aspire-journey__step:not(:last-child)::after {
    right: auto;
    left: 20px;
    top: auto;
    bottom: -12px;
    width: 2px;
    height: 12px;
    transform: none;
  }
}

/* ==== UNIVERSITY CARD, simplified 12 September ==========================
   Name, location, Visit university. A logo sits above the name when the
   record has one; an empty field renders an empty image widget, which is
   closed up here so the name starts at the top of the card. */

.aspire-uni-logo img { max-height: 44px; width: auto; object-fit: contain; }
.aspire-uni-logo:not(:has(img)) { display: none; }

/* ==== ADVERTS, redesigned 12 September ==================================
   Garry liked the Partner frame, so it stays. What changed is what sits
   inside it and what colour it is.

   Every advert carries its own brand colour, and the renderer in
   aspire-core/includes/adverts.php works out light or dark type from it and
   passes the whole palette down as custom properties. That is why there is
   no colour in this file beyond the fallbacks: a new advertiser is a hex
   code on a record, not a stylesheet edit.

   The shape is the advertiser's logo, then their tagline set large as the
   headline, then one optional line of description, then the button. The
   logo is what says who they are, so the name is only set as type when an
   advert has no logo. An advertiser who insists on running their own
   artwork gets that instead, on their own colour.
   ==================================================================== */

.aspire-adframe,
.aspire-adstrip,
.aspire-adtall {
  --ad-bg: #33404A;
  --ad-fg: #FFFFFF;
  --ad-muted: rgba(255, 255, 255, 0.78);
  --ad-btn: #F5DE7A;
  --ad-btn-text: #2B4521;
  --ad-plate: #FFFFFF;
}

/* --- the in-content banner ---------------------------------------------- */

.aspire-adframe {
  display: flex;
  align-items: stretch;
  overflow: hidden;
  background: var(--ad-bg);
  border: 1px solid var(--aspire-line-soft);
  border-radius: 10px;
}

.aspire-adframe__tab,
.aspire-adtall__tab,
.aspire-adstrip__tab,
.aspire-adframe__name,
.aspire-adstrip__name {
  font-family: "DM Sans", sans-serif;
  font-size: 11px;
  font-weight: 500;
  line-height: 1;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}

/* the vertical Partner tab, the part of the old frame Garry pointed at */
.aspire-adframe__tab {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  background: var(--aspire-paper);
  color: var(--aspire-muted);
  writing-mode: vertical-rl;
  transform: rotate(180deg);
}

.aspire-adframe__body {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 30px;
  min-height: 168px;
  padding: 26px 32px;
  color: var(--ad-fg);
  text-decoration: none;
}

/* artwork speaks for itself, so it gets the middle and nothing else */
.aspire-adframe__body:has(.aspire-adframe__art) {
  justify-content: center;
  padding: 18px 24px;
}

.aspire-adframe__art {
  display: block;
  max-width: 100%;
  height: auto;
}

/* the logo, on a white plate so any colour of logo reads on any colour of
   ground. An advertiser whose logo already has its own ground is set to no
   plate on the record, and then it simply blends */
.aspire-adframe__logo {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
}

.aspire-adframe__logo.is-plate {
  padding: 13px 17px;
  background: var(--ad-plate);
  border-radius: 8px;
}

.aspire-adframe__logo img {
  display: block;
  width: auto;
  height: auto;
  max-width: 240px;
  max-height: 66px;
  object-fit: contain;
}

.aspire-adframe__logo.is-bare img { max-height: 84px; }

.aspire-adframe__copy {
  flex: 1 1 auto;
  min-width: 0;
  max-width: 720px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

/* only ever printed when there is no logo to carry the name */
.aspire-adframe__name { color: var(--ad-muted); }

/* the headline, and the thing the advertiser is actually paying for */
.aspire-adframe__tag {
  font-family: "DM Serif Display", serif;
  font-size: 30px;
  line-height: 1.18;
  color: var(--ad-fg);
}

/* one line on a laptop, two at most on a phone, cut rather than allowed to
   push the banner out of shape */
.aspire-adframe__desc {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 1;
  overflow: hidden;
  font-family: "DM Sans", sans-serif;
  font-size: 15px;
  line-height: 1.55;
  color: var(--ad-muted);
}

.aspire-adframe__btn {
  flex: none;
  /* hard right, so the banner reads logo, message, action, the same way an
     advertiser's own artwork does */
  margin-left: auto;
  padding: 13px 24px;
  background: var(--ad-btn);
  color: var(--ad-btn-text);
  border-radius: 6px;
  font-family: "DM Sans", sans-serif;
  font-size: 15px;
  font-weight: 600;
  line-height: 1;
  transition: transform 0.18s ease;
}

.aspire-adframe__body:hover .aspire-adframe__btn { transform: translateY(-1px); }

@media (max-width: 1100px) {
  .aspire-adframe__tag { font-size: 26px; }
}

@media (max-width: 880px) {
  .aspire-adframe__body {
    flex-wrap: wrap;
    gap: 18px;
    padding: 22px 20px;
    min-height: 0;
  }
  .aspire-adframe__copy { flex-basis: 100%; order: 2; }
  .aspire-adframe__btn { order: 3; margin-left: 0; }
  .aspire-adframe__logo img { max-height: 52px; max-width: 180px; }
  .aspire-adframe__tag { font-size: 22px; }
  .aspire-adframe__desc { -webkit-line-clamp: 2; }
}

/* --- the strip across the top of every page ------------------------------ */

.aspire-adstrip {
  display: block;
  background: var(--ad-bg);
  color: var(--ad-fg);
  text-decoration: none;
}

.aspire-adstrip__inner {
  width: var(--aspire-container);
  margin-inline: auto;
  display: flex;
  align-items: center;
  gap: 18px;
  min-height: 74px;
  padding: 8px 24px;
}

.aspire-adstrip__tab { flex: none; color: var(--ad-muted); }

.aspire-adstrip__logo { flex: none; display: flex; align-items: center; }

.aspire-adstrip__logo.is-plate {
  padding: 6px 11px;
  background: var(--ad-plate);
  border-radius: 6px;
}

.aspire-adstrip__logo img {
  display: block;
  width: auto;
  height: auto;
  max-width: 170px;
  max-height: 36px;
  object-fit: contain;
}

.aspire-adstrip__logo.is-bare img { max-height: 44px; }

.aspire-adstrip__name { flex: none; color: var(--ad-muted); }

/* the bar is one line tall, so the tagline is never allowed to become two */
.aspire-adstrip__tag {
  flex: 0 1 auto;
  min-width: 0;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  font-family: "DM Serif Display", serif;
  font-size: 19px;
  line-height: 1.2;
  color: var(--ad-fg);
}

.aspire-adstrip__btn {
  margin-left: auto;
  flex: none;
  padding-left: 18px;
  font-family: "DM Sans", sans-serif;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ad-btn);
}

/* a leaderboard fills the bar rather than sitting in a corner of it */
.aspire-adstrip__art {
  display: block;
  margin-inline: auto;
  width: auto;
  height: auto;
  max-height: 62px;
  max-width: 100%;
}

@media (max-width: 900px) {
  .aspire-adstrip__inner { gap: 12px; min-height: 62px; padding: 7px 16px; }
  .aspire-adstrip__tag { font-size: 16px; }
  .aspire-adstrip__art { max-height: 44px; }
}

@media (max-width: 600px) {
  .aspire-adstrip__tab { display: none; }
  .aspire-adstrip__btn { display: none; }
}

/* --- the tall one in an article sidebar ---------------------------------- */

.aspire-adtall {
  display: flex;
  flex-direction: column;
  overflow: hidden;
  /* a half page is 300 by 600 and is drawn at that size. Stretching it to
     fill a wider rail upscaled the artwork and made the column enormous */
  max-width: 300px;
  margin-inline: auto;
  background: var(--ad-bg);
  border: 1px solid var(--aspire-line-soft);
  border-radius: 10px;
}

/* Only the advert follows you down a profile, never the whole rail. Elementor
   Pro's own sticky effect fixes the element, which took the At a glance and
   Follow panels out of the flow and floated them over the sections below and
   over the footer. A CSS sticky cannot do that: it is held inside its own
   column and stops at the bottom of it. */
.aspire-rail-ad {
  position: sticky;
  top: 112px;
  align-self: flex-start;
}

/* the column has to be as tall as the profile beside it, or the advert runs
   out of room to travel after a few hundred pixels. The row is set to
   flex-start in Elementor, which is right for the panels, so only this one
   column is stretched */
.aspire-rail-col { align-self: stretch; }

@media (max-width: 1024px) {
  .aspire-rail-ad { position: static; top: auto; }
}

.aspire-adtall__tab {
  flex: none;
  padding: 9px 13px;
  background: var(--aspire-paper);
  color: var(--aspire-muted);
}

/* the same reading order as the wide banner, only stacked: who they are,
   what they are saying, one optional line, then the action */
.aspire-adtall__body {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 16px;
  padding: 24px 22px 26px;
  color: var(--ad-fg);
  text-decoration: none;
}

/* artwork fills the card edge to edge, so it loses the padding */
.aspire-adtall__body:has(.aspire-adtall__art) { padding: 0; }

.aspire-adtall__art { display: block; width: 100%; height: auto; }

.aspire-adtall__logo {
  display: flex;
  align-items: center;
  justify-content: center;
}

.aspire-adtall__logo.is-plate {
  padding: 12px 15px;
  background: var(--ad-plate);
  border-radius: 8px;
}

.aspire-adtall__logo img {
  display: block;
  width: auto;
  height: auto;
  max-width: 200px;
  max-height: 58px;
  object-fit: contain;
}

.aspire-adtall__logo.is-bare img { max-height: 74px; }

/* only ever printed when there is no logo to carry the name */
.aspire-adtall__name { color: var(--ad-muted); }

.aspire-adtall__tag {
  font-family: "DM Serif Display", serif;
  font-size: 26px;
  line-height: 1.2;
  color: var(--ad-fg);
}

/* a rail is narrow, so the description gets three lines here rather than the
   one it gets across a full width banner, and is still cut rather than
   allowed to run the card down the page */
.aspire-adtall__desc {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
  overflow: hidden;
  font-family: "DM Sans", sans-serif;
  font-size: 15px;
  line-height: 1.55;
  color: var(--ad-muted);
}

.aspire-adtall__btn {
  margin-top: 2px;
  padding: 12px 22px;
  background: var(--ad-btn);
  color: var(--ad-btn-text);
  border-radius: 6px;
  font-family: "DM Sans", sans-serif;
  font-size: 15px;
  font-weight: 600;
  line-height: 1;
  transition: transform 0.18s ease;
}

.aspire-adtall__body:hover .aspire-adtall__btn { transform: translateY(-1px); }

/* ==== PLACEMENT DIAGRAMS, Promote with Us, 15 September =================
   Promote with Us described the placements in words, which told a company
   nothing about where their brand would land. The cards below carry a small
   page wireframe with the bought slot in sun yellow, drawn as inline SVG in
   aspire-core/includes/placements.php.

   The worked examples under them are the real advert classes, not copies of
   them, so they cannot drift away from what an advertiser actually gets.
   The only thing this block adds for those is a size for an inline SVG logo,
   because the advert rules size an img and the example logo is a vector in
   the page so it can use DM Sans.
   ==================================================================== */

.aspire-placements {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 28px;
}

.aspire-placement {
  display: flex;
  flex-direction: column;
  background: var(--aspire-white);
  border: 1px solid var(--aspire-line);
  border-radius: var(--aspire-radius-card);
  overflow: hidden;
}

.aspire-placement__diagram {
  padding: 22px 22px 16px;
  background: var(--aspire-mint);
  border-bottom: 1px solid var(--aspire-line);
}

.aspire-placement__svg {
  display: block;
  width: 100%;
  max-width: 420px;
  height: auto;
  margin-inline: auto;
}

.aspire-placement__caption {
  display: block;
  margin-top: 12px;
  font-family: var(--aspire-sans);
  font-size: 13px;
  line-height: 1.5;
  text-align: center;
  color: var(--aspire-muted);
}

.aspire-placement__body { padding: 26px 26px 30px; }

.aspire-placement__kicker {
  display: block;
  font-family: var(--aspire-sans);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--aspire-brand);
}

.aspire-placement__title {
  margin: 10px 0 0;
  font-family: var(--aspire-display);
  font-size: 26px;
  font-weight: 400;
  line-height: 1.2;
  color: var(--aspire-forest);
}

.aspire-placement__text {
  margin: 10px 0 0;
  font-family: var(--aspire-sans);
  font-size: 16px;
  line-height: 1.65;
  color: var(--aspire-ink);
}

.aspire-placement .aspire-ticks { margin-top: 18px; }

@media (max-width: 880px) {
  .aspire-placements { grid-template-columns: 1fr; gap: 20px; }
  .aspire-placement__body { padding: 22px 20px 26px; }
  .aspire-placement__title { font-size: 23px; }
}

/* --- the worked examples ------------------------------------------------ */

.aspire-exhibit {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 340px;
  gap: 34px 40px;
  align-items: start;
}

/* a grid track defaults to the min-content width of what is in it, and an
   advert is a flex row that does not want to be narrow. Without this the
   examples push the page sideways on a phone. */
.aspire-exhibit > * { min-width: 0; }

.aspire-exhibit__item--wide { grid-column: 1; }

.aspire-exhibit__item--tall {
  grid-column: 2;
  grid-row: 1 / span 2;
}

.aspire-exhibit__label {
  display: block;
  margin-bottom: 10px;
  font-family: var(--aspire-sans);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--aspire-muted);
}

/* the strip is normally full bleed in the header, so inside a section it is
   given the card's own corners rather than running off the edge */
.aspire-exhibit .aspire-adstrip {
  border-radius: var(--aspire-radius-card);
  overflow: hidden;
}

.aspire-exhibit .aspire-adstrip__inner {
  width: 100%;
  padding-inline: 20px;
}

.aspire-exhibit .aspire-adtall { max-width: 340px; }

/* nothing here is clickable, so the pointer should not suggest it is */
.aspire-exhibit .aspire-adframe__body,
.aspire-exhibit .aspire-adtall__body,
.aspire-exhibit .aspire-adstrip { cursor: default; }

.aspire-exhibit__note {
  grid-column: 1 / -1;
  margin: 4px 0 0;
  font-family: var(--aspire-sans);
  font-size: 14px;
  line-height: 1.6;
  color: var(--aspire-muted);
}

@media (max-width: 720px) {
  .aspire-exhibit .aspire-adstrip__inner { flex-wrap: wrap; row-gap: 8px; }
  .aspire-exhibit .aspire-adstrip__tag { flex: 1 1 100%; white-space: normal; }
  /* the tall unit is 300 wide in real life, so it is centred rather than
     stretched, or the example would misrepresent what is being sold */
  .aspire-exhibit .aspire-adtall { margin-inline: auto; }
}

/* the example logo is inline SVG, so it needs the sizes the img rules give */
.aspire-adframe__logo > svg { display: block; width: auto; height: 46px; }
.aspire-adstrip__logo > svg { display: block; width: auto; height: 26px; }
.aspire-adtall__logo  > svg { display: block; width: auto; height: 38px; }

@media (max-width: 1024px) {
  .aspire-exhibit { grid-template-columns: minmax(0, 1fr); gap: 30px; }
  .aspire-exhibit__item--wide,
  .aspire-exhibit__item--tall { grid-column: 1; grid-row: auto; }
}

/* ==== SITE REVIEW FIXES, 16 September ====================================
   The small things the full site read-through turned up. Each part says
   which finding in "Aspire in Ecology - Site Review 16 Sept 2026.html" it
   answers, so the reason is never lost.
   ==================================================================== */

/* --- 22. A heading with nothing under it does not print ----------------- */
/* Every profile section is an Elementor heading followed by a shortcode
   that prints nothing when the field is empty. Elementor's shortcode
   widget wraps its output in a div with no whitespace of its own, so an
   empty result is a truly empty div, and the heading before it can go. */
.elementor-widget-heading:has(+ .elementor-widget-shortcode .elementor-shortcode:empty) {
  display: none;
}

/* --- 27. The open item in the phone menu is a brand colour -------------- */
/* Elementor paints the tapped row slate grey, its own default and the one
   colour on the site that is not in the palette. */
nav.elementor-nav-menu--dropdown a.elementor-item:hover,
nav.elementor-nav-menu--dropdown a.elementor-item:focus,
nav.elementor-nav-menu--dropdown a.elementor-item.highlighted,
nav.elementor-nav-menu--dropdown a.elementor-item.elementor-item-active,
nav.elementor-nav-menu--dropdown a.elementor-sub-item:hover,
nav.elementor-nav-menu--dropdown a.elementor-sub-item.highlighted,
nav.elementor-nav-menu--dropdown a.elementor-sub-item.elementor-item-active {
  background: var(--aspire-mint) !important;
  color: var(--aspire-forest) !important;
}

/* --- 26. The partner strip on a phone is the logo, nothing else --------- */
/* The tab and the button already hide below 600. The tagline was left
   behind, cut off mid sentence, under a second "aspire" logo. */
@media (max-width: 600px) {
  .aspire-adstrip__tag { display: none; }
  .aspire-adstrip__inner { justify-content: center; min-height: 52px; }
}

/* --- 1. A line of description under a menu link ------------------------- */
/* Printed by wpconsults_child_menu_description() in functions.php from the
   menu item's own Description field. The link is nowrap so the panel sizes
   itself; the description is allowed to wrap under it. */
.aspire-menu-desc {
  display: block;
  flex: 1 1 100%;
  margin-top: 2px;
  max-width: 230px;
  font-family: var(--aspire-sans);
  font-size: 12.5px;
  font-weight: 400;
  line-height: 1.35;
  letter-spacing: 0;
  text-transform: none;
  white-space: normal;
  color: var(--aspire-muted);
}

nav.elementor-nav-menu--main > ul > li.aspire-mega-parent ul.sub-menu a.elementor-sub-item:hover .aspire-menu-desc {
  color: var(--aspire-muted);
}

/* Elementor lays a menu link out as a flex row so the caret can sit on the
   right. In a panel the caret is hidden, and a flex row inside a shrink to
   fit column sizes itself to hold label and description side by side, so
   the link goes back to a block and the description sits under the label. */
nav.elementor-nav-menu--main > ul > li.aspire-mega-parent ul.sub-menu a.elementor-sub-item:has(> .aspire-menu-desc) {
  display: block;
}

nav.elementor-nav-menu--dropdown a:has(> .aspire-menu-desc) {
  flex-wrap: wrap;
}

nav.elementor-nav-menu--dropdown .aspire-menu-desc {
  flex: 1 1 100%;
  max-width: none;
  font-size: 13px;
}

/* --- 10. The growth row headline is the link, and it carries a month ---- */
.aspire-growth-title {
  font-family: var(--aspire-sans);
  font-size: 16.5px;
  font-weight: 600;
  line-height: 1.35;
  color: var(--aspire-ink);
  text-decoration: none;
}

.e-loop-item:hover .aspire-growth-title { color: var(--aspire-brand); }

.aspire-growth-month {
  display: inline-block;
  font-family: var(--aspire-sans);
  font-size: 12.5px;
  line-height: 1;
  white-space: nowrap;
  color: var(--aspire-muted);
}

/* --- 9. Live Hot Jobs in the profile rail ------------------------------- */
.aspire-rail-jobs {
  padding: 18px 20px 16px;
  background: var(--aspire-white);
  border: 1px solid var(--aspire-line);
  border-radius: var(--aspire-radius-card);
}

.aspire-rail-jobs__kicker {
  display: block;
  margin-bottom: 12px;
  font-family: var(--aspire-sans);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--aspire-brand);
}

.aspire-rail-jobs__item {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 12px 0;
  border-top: 1px solid var(--aspire-line-soft);
}

.aspire-rail-jobs__item:last-child { padding-bottom: 2px; }

.aspire-rail-jobs__pill {
  align-self: flex-start;
  padding: 4px 9px;
  background: var(--aspire-sun);
  border-radius: 999px;
  font-family: var(--aspire-sans);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--aspire-forest);
}

.aspire-rail-jobs__title {
  font-family: var(--aspire-sans);
  font-size: 15.5px;
  font-weight: 700;
  line-height: 1.3;
  color: var(--aspire-forest);
}

.aspire-rail-jobs__where {
  font-family: var(--aspire-sans);
  font-size: 13.5px;
  color: var(--aspire-muted);
}

.aspire-rail-jobs__link {
  margin-top: 2px;
  font-family: var(--aspire-sans);
  font-size: 14px;
  font-weight: 600;
  color: var(--aspire-brand);
  text-decoration: none;
}

.aspire-rail-jobs__link:hover { text-decoration: underline; }

/* --- 6 and 12. The "Keep going" row ------------------------------------- */
/* Three image cards, the same shape as the image cards built in Elementor
   elsewhere, printed by [aspire_keep_going] so the row is identical on
   every Career Support page and under every article. */
.aspire-kg {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--aspire-gap);
}

.aspire-kg__card {
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background: var(--aspire-white);
  border: 1px solid var(--aspire-line);
  border-radius: var(--aspire-radius-card);
  text-decoration: none;
  color: inherit;
}

.aspire-kg__img { display: block; overflow: hidden; }
.aspire-kg__img img { display: block; }

.aspire-kg__body {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 22px 24px 26px;
}

.aspire-kg__title {
  font-family: var(--aspire-display);
  font-size: 23px;
  line-height: 1.2;
  color: var(--aspire-forest);
}

.aspire-kg__text {
  font-family: var(--aspire-sans);
  font-size: 15px;
  line-height: 1.6;
  color: var(--aspire-ink);
}

.aspire-kg__more {
  margin-top: 4px;
  font-family: var(--aspire-sans);
  font-size: 14.5px;
  font-weight: 600;
  color: var(--aspire-brand);
}

.aspire-kg__card:hover .aspire-kg__more { text-decoration: underline; }

@media (max-width: 900px) {
  .aspire-kg { grid-template-columns: 1fr; }
}

/* --- 21. A Free directory card says what it is --------------------------- */
.aspire-card-overview.is-basic {
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.04em;
  color: var(--aspire-muted);
}

/* --- 11. List and Map, on both pages ------------------------------------- */
/* a pill that is a heading widget with a link: the link must take the pill's
   colour, or the white text on the active pill is painted brand green by the
   kit's link colour and disappears */
.aspire-pill--filter .elementor-heading-title > a { color: inherit; }

.aspire-viewswitch { --width: auto; }
.aspire-filters .aspire-viewswitch { margin-left: auto; }
@media (max-width: 767px) {
  .aspire-filters .aspire-viewswitch { margin-left: 0; --width: 100%; }
}

/* --- 29. The Hub, grouped on one page ------------------------------------ */
.aspire-hubgroups { display: flex; flex-direction: column; gap: 44px; }

.aspire-hubgroup__title {
  margin: 0 0 6px;
  padding-bottom: 12px;
  border-bottom: 2px solid var(--aspire-forest);
  font-family: var(--aspire-display);
  font-size: 24px;
  font-weight: 400;
  line-height: 1.2;
  color: var(--aspire-forest);
}

.aspire-hubgroup__count {
  display: inline-block;
  margin-left: 8px;
  padding: 2px 9px;
  border-radius: 999px;
  background: var(--aspire-mint);
  font-family: var(--aspire-sans);
  font-size: 12px;
  font-weight: 700;
  vertical-align: middle;
  color: var(--aspire-brand);
}

.aspire-hubgroup__row {
  display: flex;
  align-items: center;
  gap: 18px;
  padding: 18px 0;
  border-bottom: 1px solid var(--aspire-line-soft);
  text-decoration: none;
  color: inherit;
}

.aspire-hubgroup__row:last-child { border-bottom: 0; }

.aspire-hubgroup__text { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 3px; }

.aspire-hubgroup__name {
  font-family: var(--aspire-sans);
  font-size: 16.5px;
  font-weight: 600;
  line-height: 1.35;
  color: var(--aspire-ink);
}

a.aspire-hubgroup__row:hover .aspire-hubgroup__name { color: var(--aspire-brand); }

.aspire-hubgroup__summary {
  font-family: var(--aspire-sans);
  font-size: 14.5px;
  line-height: 1.5;
  color: var(--aspire-muted);
}

.aspire-hubgroup__host {
  flex: none;
  font-family: var(--aspire-sans);
  font-size: 13px;
  white-space: nowrap;
  color: var(--aspire-muted);
}

/* the pills above the groups are jump links, so a group needs room under
   the sticky header when it lands */
.aspire-hubgroup { scroll-margin-top: 110px; }

@media (max-width: 640px) {
  .aspire-hubgroup__row { flex-wrap: wrap; gap: 12px 14px; }
  .aspire-hubgroup__host { flex-basis: 100%; padding-left: 66px; }
}

/* --- 19. Three ways into the Hub, on the homepage ----------------------- */
.aspire-hubtypes {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--aspire-gap);
}

.aspire-hubtypes__card {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 24px 24px 22px;
  background: var(--aspire-white);
  border: 1px solid var(--aspire-line);
  border-radius: var(--aspire-radius-card);
  text-decoration: none;
  color: inherit;
}

.aspire-hubtypes__count {
  font-family: var(--aspire-display);
  font-size: 40px;
  line-height: 1;
  color: var(--aspire-sage);
}

.aspire-hubtypes__name {
  margin-top: 6px;
  font-family: var(--aspire-display);
  font-size: 22px;
  line-height: 1.2;
  color: var(--aspire-forest);
}

.aspire-hubtypes__text {
  font-family: var(--aspire-sans);
  font-size: 14.5px;
  line-height: 1.55;
  color: var(--aspire-ink);
}

.aspire-hubtypes__more {
  margin-top: 8px;
  font-family: var(--aspire-sans);
  font-size: 14px;
  font-weight: 600;
  color: var(--aspire-brand);
}

.aspire-hubtypes__card:hover .aspire-hubtypes__more { text-decoration: underline; }

@media (max-width: 1024px) { .aspire-hubtypes { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 600px) { .aspire-hubtypes { grid-template-columns: 1fr; } }

/* --- 7. The Promote band on paper where the page above it ends dark ------ */
/* About, Who's Growing, Ecology Ready and the University Directory all
   close on a forest or photo band, and the green Promote band sat straight
   under it: two dark bands with a button each, back to back. On those four
   pages the band goes to paper and its type to the dark palette. Nothing
   else about it changes, and the template stays one template. The page ids
   are the Elementor body classes; add one here if a new page ends dark. */
/* Elementor paints a container's ground through a :not() selector, which
   counts as a class, so this one has to carry two more classes to win. */
body.page-id-437 .e-con.e-parent.elementor-element.aspire-promo-band,
body.page-id-20 .e-con.e-parent.elementor-element.aspire-promo-band,
body.page-id-23 .e-con.e-parent.elementor-element.aspire-promo-band,
body.page-id-29 .e-con.e-parent.elementor-element.aspire-promo-band {
  background-color: var(--aspire-paper);
  border-top: 1px solid var(--aspire-line);
}

body.page-id-437 .elementor-element.aspire-promo-band .elementor-widget-heading .elementor-heading-title,
body.page-id-20 .elementor-element.aspire-promo-band .elementor-widget-heading .elementor-heading-title,
body.page-id-23 .elementor-element.aspire-promo-band .elementor-widget-heading .elementor-heading-title,
body.page-id-29 .elementor-element.aspire-promo-band .elementor-widget-heading .elementor-heading-title {
  color: var(--aspire-forest);
}

body.page-id-437 .elementor-element.aspire-promo-band .aspire-kicker .elementor-heading-title,
body.page-id-20 .elementor-element.aspire-promo-band .aspire-kicker .elementor-heading-title,
body.page-id-23 .elementor-element.aspire-promo-band .aspire-kicker .elementor-heading-title,
body.page-id-29 .elementor-element.aspire-promo-band .aspire-kicker .elementor-heading-title {
  color: var(--aspire-brand);
}
