/*
 * RE2 Design System — layout helpers for the Elementor build
 *
 * Everything here exists because an Elementor container or widget control cannot
 * express it. Anything that CAN be done with native controls — padding, gaps,
 * background images and overlays, min-height, flex direction, responsive
 * visibility — is done there instead, so the page stays editable in the builder.
 *
 * Each rule notes why it needs CSS. If a future Elementor version adds the
 * control, the rule should be deleted rather than kept "just in case".
 */

/* ============================================================
   TOPBAR — thin contact strip above the header
   ============================================================ */

.re2 .re2-topbar { font-size: 13px; }
.re2 .re2-topbar .elementor-icon-list-item { font-size: 13px; }
.re2 .re2-topbar a { color: rgba(255, 255, 255, .86); transition: color .25s; }
.re2 .re2-topbar a:hover { color: var(--yellow); }

/* ============================================================
   HEADER
   ============================================================ */

/*
 * Sticky is available on containers, but the "shadow appears once you scroll"
 * state is not — Elementor has no scroll-state trigger without Pro's motion
 * effects, so a class is toggled from JS instead.
 */
.re2 .re2-header { transition: box-shadow .3s var(--ease), background .3s var(--ease); }
.re2 .re2-header.is-scrolled { box-shadow: 0 6px 26px rgba(0, 0, 0, .10); }

/*
 * JetBlocks nav menu.
 *
 * The widget renders a wrapper <div class="jet-nav__item"> around the actual
 * <a class="menu-item-link">, so the link itself has to be targeted — styling
 * the wrapper leaves the anchor with its own inherited colour, which is how the
 * hover ended up the wrong shade. Colours match the HTML original: ink at rest,
 * brand pink on hover and for the current page.
 */
.re2 .re2-nav .jet-nav__item > .menu-item-link {
  font-family: var(--font-head);
  font-weight: 500;
  font-size: 15.5px;
  color: var(--ink);
  padding: 10px 18px;
  position: relative;
  transition: color .3s;
}

.re2 .re2-nav .jet-nav__item > .menu-item-link:hover,
.re2 .re2-nav .jet-nav__item.current-menu-item > .menu-item-link,
.re2 .re2-nav .jet-nav__item.current_page_item > .menu-item-link { color: var(--red); }

/* Underline wipes in from the left, exactly as the original did. */
.re2 .re2-nav .jet-nav__item > .menu-item-link::after {
  content: "";
  position: absolute;
  left: 18px;
  right: 18px;
  bottom: 5px;
  height: 3px;
  border-radius: 3px;
  background: var(--red);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform .35s var(--ease);
}

.re2 .re2-nav .jet-nav__item > .menu-item-link:hover::after,
.re2 .re2-nav .jet-nav__item.current-menu-item > .menu-item-link::after,
.re2 .re2-nav .jet-nav__item.current_page_item > .menu-item-link::after { transform: scaleX(1); }

/*
 * No hamburger at any width. With two links and one button there is nothing to
 * collapse, and a toggle for two items is worse than the items themselves.
 *
 * JetBlocks still stamps its m-layout-mobile class on the wrapper below its
 * breakpoint and styles the list as a drop-down panel, so the panel behaviour
 * is unwound here: back to a plain inline row, and the trigger hidden in case
 * a future update re-enables it.
 */
@media (max-width: 1024px) {
  .re2 .re2-nav .jet-nav,
  .re2 .re2-nav .jet-nav.m-layout-mobile {
    display: flex !important;
    flex-direction: row !important;
    position: static !important;
    width: auto !important;
    height: auto !important;
    opacity: 1 !important;
    visibility: visible !important;
    transform: none !important;
    background: none !important;
    box-shadow: none !important;
    padding: 0 !important;
  }

  .re2 .re2-nav .jet-nav__item { display: block !important; width: auto !important; }
  .re2 .re2-nav .jet-nav__mobile-trigger,
  .re2 .re2-nav .jet-mobile-menu-cover { display: none !important; }

  .re2 .re2-nav .jet-nav__item > .menu-item-link { padding: 9px 12px; font-size: 15px; }
}

/* Two links, a button and a logo have to share one row on a phone, so the
   whole cluster steps down rather than wrapping. */
@media (max-width: 767px) {
  .re2 .re2-nav .jet-nav__item > .menu-item-link { padding: 8px 9px; font-size: 14px; }
  .re2 .re2-nav .jet-nav__item > .menu-item-link::after { left: 9px; right: 9px; }
  .re2 .re2-logo img { width: 108px; }
  .re2 .re2-header .elementor-widget-button.btn .elementor-button { padding: 10px 18px; font-size: 13px; }
}

@media (max-width: 420px) {
  .re2 .re2-nav .jet-nav__item > .menu-item-link { padding: 6px 6px; font-size: 13px; }
  .re2 .re2-logo img { width: 92px; }
  .re2 .re2-header .elementor-widget-button.btn .elementor-button { padding: 9px 13px; font-size: 12px; gap: 6px; }
  .re2 .re2-header .elementor-widget-button.btn .elementor-button svg { width: 14px; height: 14px; }
}

/* ============================================================
   HERO
   ============================================================ */

/*
 * The kicker is a pill with a pulsing dot. Elementor can colour and pad a
 * heading, but the ::before dot and its animation need CSS.
 */
.re2 .re2-hero-kicker {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 9px 20px;
  border-radius: var(--r-pill);
  background: var(--yellow);
  border: 2.5px solid var(--black);
  box-shadow: 4px 4px 0 var(--black);
  font-family: var(--font-head);
  font-weight: 700;
  font-size: 12.5px;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--black);
}

/* Elementor wraps the heading text in its own element, which carries the colour. */
.re2 .re2-hero-kicker .elementor-heading-title { color: var(--black); }

.re2 .re2-hero-kicker::before {
  content: "";
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--red);
  flex: none;
  animation: re2Pulse 1.8s ease-in-out infinite;
}

@keyframes re2Pulse {
  0%, 100% { transform: scale(1); opacity: 1; }
  50% { transform: scale(1.45); opacity: .55; }
}

/*
 * The typed word keeps a neon underline and a blinking caret.
 *
 * The span is inline, not inline-block, so "Computer Systems" can break across
 * lines like any other text. box-decoration-break: clone makes the underline
 * paint on each line fragment rather than stretching once across the whole
 * box, so a wrapped phrase gets an underline under each part.
 *
 * The caret is this span's ::after rather than the separate .re2-caret element
 * in the markup: a pseudo-element belongs to the span's box and always follows
 * the last character, wherever that lands. As a sibling it could be pushed to
 * a line of its own.
 *
 * The trade-off of allowing the break: while the text types in, a completed
 * word can push the line, so the headline may reflow once mid-animation. That
 * is the reason this was nowrap before.
 */
.re2 .re2-typed {
  display: inline;
  white-space: normal;
  -webkit-box-decoration-break: clone;
  box-decoration-break: clone;
  padding-bottom: 2px;
  background-image: radial-gradient(closest-side, var(--red) 78%, transparent 79%);
  background-repeat: no-repeat;
  background-position: left bottom;
  background-size: 100% 10px;
}

.re2 .re2-typed::after {
  content: "";
  display: inline-block;
  width: 3px;
  height: .92em;
  margin-left: 4px;
  background: var(--yellow);
  vertical-align: -.08em;
  animation: re2Blink 1s steps(1) infinite;
}

/* The markup keeps the caret element for anyone without CSS; the pseudo-element
   above draws the one that is actually seen. */
.re2 .re2-caret { display: none; }

@keyframes re2Blink { 0%, 50% { opacity: 1; } 50.01%, 100% { opacity: 0; } }

/*
 * The hero veil.
 *
 * Elementor's overlay control only offers two colour stops, and a straight
 * two-stop fade sits far heavier over the middle of the photo than the original
 * design did. So the overlay element Elementor already renders (its ::before) is
 * kept, and only its background-image is replaced with the original's five-stop
 * curve: dense behind the headline, almost clear by the student on the right.
 *
 * This is the one place ::before is touched, and only to restyle an overlay that
 * is already there — never defined from scratch, which would delete the veil.
 */
.re2 .re2-hero-bg::before {
  background-image: linear-gradient(95deg,
    rgba(8, 8, 8, .92) 0%,
    rgba(10, 10, 10, .82) 30%,
    rgba(12, 12, 12, .55) 52%,
    rgba(14, 14, 14, .22) 72%,
    rgba(16, 16, 16, .06) 100%) !important;
  opacity: 1 !important;
}

@media (max-width: 1024px) {
  .re2 .re2-hero-bg::before {
    background-image: linear-gradient(95deg,
      rgba(8, 8, 8, .93) 0%,
      rgba(10, 10, 10, .8) 46%,
      rgba(12, 12, 12, .45) 78%,
      rgba(14, 14, 14, .2) 100%) !important;
  }
}

@media (max-width: 767px) {
  .re2 .re2-hero-bg::before {
    background-image: linear-gradient(180deg,
      rgba(8, 8, 8, .72) 0%,
      rgba(8, 8, 8, .85) 55%,
      rgba(8, 8, 8, .92) 100%) !important;
  }
}

@media (prefers-reduced-motion: reduce) {
  .re2 .re2-hero-kicker::before { animation: none; }
}

/* ============================================================
   BENEFITS STAIR
   ============================================================ */

/*
 * Two things Elementor cannot express on a container:
 *  1. align-items:end on the ROW so panels of different heights share a baseline
 *     (Elementor sets align-items but stretches children back out via width rules)
 *  2. the first panel's left padding calculated from the viewport, so its text
 *     lines up with the site content width while the panel bleeds to the edge.
 */
.re2 .re2-stair {
  align-items: flex-end !important;
  /* The band rides up over the bottom of the hero, exactly as in the original.
     The hero carries matching extra bottom padding so nothing is covered. */
  margin-top: -120px;
  position: relative;
  z-index: 5;
}

.re2 .re2-stair > .e-con,
.re2 .re2-stair > .e-child { align-self: flex-end; }

.re2 .re2-stair-1 { padding-left: max(4vw, calc((100vw - var(--re2-content-width)) / 2)) !important; }

@media (max-width: 1024px) {
  .re2 .re2-stair { margin-top: -100px; }
  .re2 .re2-stair-1 { padding-left: 36px !important; }
}

@media (max-width: 767px) {
  .re2 .re2-stair { align-items: stretch !important; margin-top: -70px; }
}

/* ============================================================
   ABOUT — thumbnail strip
   ============================================================ */

/*
 * Three square crops. Elementor sizes an image widget from the file, so a
 * portrait shot next to two landscape ones leaves a ragged row; forcing a 1/1
 * ratio with object-fit crops instead of distorting.
 */
.re2 .re2-about-thumbs { align-items: stretch !important; }

.re2 .re2-about-thumbs > .e-con,
.re2 .re2-about-thumbs > .elementor-widget { flex: 1 1 0; min-width: 0; }

.re2 .re2-about-thumbs img {
  width: 100%;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  display: block;
  border-radius: 8px;
  transition: transform .5s var(--ease), box-shadow .5s var(--ease);
}

.re2 .re2-about-thumbs img:hover {
  transform: translateY(-6px);
  box-shadow: 0 14px 30px rgba(38, 66, 30, .22);
}

/*
 * The tall panel is 315px against its neighbours' 250px, with copy pinned to
 * the bottom, so it carries a band of empty headroom. Rather than park an
 * object in it, the same device the Core Values cards use fills it: an
 * oversized ring running off the corner, cropped by the panel. It reads as
 * texture at a glance and never competes with the copy.
 */
.re2 .re2-stair-panel { overflow: hidden; }

.re2 .re2-stair-panel::after {
  content: "";
  position: absolute;
  top: -70px;
  right: -70px;
  width: 210px;
  height: 210px;
  border-radius: 50%;
  border: 30px solid rgba(0, 0, 0, .07);
  pointer-events: none;
  z-index: 0;
}

/* Keep the copy above the ring. */
.re2 .re2-stair-panel > .e-con,
.re2 .re2-stair-panel > .elementor-widget { position: relative; z-index: 1; }

@media (max-width: 1024px) {
  .re2 .re2-stair-panel::after { width: 160px; height: 160px; border-width: 24px; top: -55px; right: -55px; }
}

/*
 * Entrance: the coloured blocks slide up into the band.
 *
 * No fade — the panels stay fully opaque and rise from below their own slot,
 * which the row clips. While they are down the band is empty and the banner
 * photo shows through, which is fine here: the stair is pulled up under the
 * banner, so what is exposed is artwork rather than a gap.
 *
 * The reveal class sits on the ROW, not the panels. A panel translated out of
 * a clipped row has no intersection with the viewport at all, so an observer
 * watching the panels would never fire and they would stay down forever. The
 * row never moves, so it is always a safe thing to watch.
 */
.re2 .re2-stair { overflow: hidden; }
.re2 .re2-stair.reveal { opacity: 1; transform: none; transition: none; }

.re2 .re2-stair-panel {
  opacity: 1;
  transform: translateY(100%);
  transition: transform .8s var(--ease);
}

.re2 .re2-stair.is-visible > .re2-stair-panel { transform: none; }

/* Left to right, a beat apart. */
.re2 .re2-stair-panel.d1 { transition-delay: .12s; }
.re2 .re2-stair-panel.d2 { transition-delay: .24s; }

@media (prefers-reduced-motion: reduce) {
  .re2 .re2-stair-panel { transform: none; transition: none; }
}

/* Icon flourish on hover, per panel. */
.re2 .re2-stair-panel:hover .elementor-icon svg { animation: re2IconBounce .7s var(--ease); }

@keyframes re2IconBounce {
  0% { transform: translateY(0); }
  40% { transform: translateY(-6px); }
  70% { transform: translateY(2px); }
  100% { transform: translateY(0); }
}

/* ============================================================
   PROGRAMME CARDS
   ============================================================ */

/*
 * The original card puts the photo on the right and washes a brand-coloured
 * gradient across it, opaque on the left where the copy sits and almost clear
 * on the right. That gradient is set natively as the container's background
 * overlay, so nothing here touches ::before — it is Elementor's own overlay
 * element and redefining it would delete the wash.
 */
.re2 .re2-prog-card { overflow: hidden; transition: transform .4s var(--ease), box-shadow .4s var(--ease); }
.re2 .re2-prog-card:hover { transform: translateY(-6px); box-shadow: 0 26px 56px rgba(38, 66, 30, .26); }

/* Badge: pulled out of the flow so the copy can sit hard against the bottom. */
.re2 .re2-prog-badge {
  position: absolute;
  top: 22px;
  left: 22px;
  z-index: 3;
  width: auto !important;
}

.re2 .re2-prog-level {
  display: inline-block;
  padding: 9px 20px;
  border-radius: var(--r-pill);
  background: #fff;
  color: var(--black);
  font-family: var(--font-head);
  font-weight: 700;
  font-size: 13.5px;
  line-height: 1;
  border: 2.5px solid var(--black);
  box-shadow: 3px 3px 0 rgba(0, 0, 0, .4);
}

.re2 .re2-prog-level .elementor-heading-title { color: var(--black); font: inherit; }

.re2 .re2-prog-content { position: relative; z-index: 2; max-width: 62%; }

.re2 .re2-prog-code .elementor-heading-title {
  font-family: var(--font-mono);
  font-size: 13px;
  font-weight: 400;
  letter-spacing: .08em;
  color: rgba(0, 0, 0, .65);
}

/* Icon-only circular action, bottom-right. The label stays in the DOM for
   screen readers — an unlabelled arrow tells a screen-reader user nothing. */
.re2 .re2-prog-arrow {
  position: absolute;
  right: 30px;
  bottom: 30px;
  z-index: 3;
  width: auto !important;
}

.re2 .re2-prog-arrow .elementor-button {
  width: 62px;
  height: 62px;
  padding: 0;
  border-radius: 50%;
  background: #1c1c1c;
  border: 3px solid var(--black);
  box-shadow: 4px 4px 0 rgba(0, 0, 0, .45);
  display: grid;
  place-items: center;
}

.re2 .re2-prog-arrow .elementor-button-content-wrapper { gap: 0; }

.re2 .re2-prog-arrow .elementor-button-text {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
}

.re2 .re2-prog-arrow .elementor-button svg { width: 24px; height: 24px; fill: #fff; }
.re2 .re2-prog-arrow .elementor-button:hover { background: var(--teal); transform: translate(2px, 2px); box-shadow: 1px 1px 0 rgba(0, 0, 0, .45); }
.re2 .re2-prog-arrow .elementor-button:hover svg { fill: #000; }

@media (max-width: 767px) {
  .re2 .re2-prog-content { max-width: 100%; }
  .re2 .re2-prog-arrow .elementor-button { width: 52px; height: 52px; }
}

/* ============================================================
   HOME — Programme course-detail expand
   ============================================================ */

/*
 * Clicking a programme card grows it, in place, into a centred detail view —
 * no page load. The expanded shell copies the card's own background image and
 * overlay at open time (so whatever the builder sets stays true), and its
 * header IS a clone of the clicked card, which keeps the first and last frame
 * of the animation pixel-identical to the real thing. The detail copy lives
 * in hidden .re2-cd-detail containers on the page, so it stays editable in
 * Elementor; they are shown normally inside the editor.
 */
.re2 .re2-cd-details { display: none; }
.elementor-editor-active .re2-cd-details { display: block; border: 2px dashed rgba(0, 0, 0, .25); padding: 20px; }

.re2 .re2-cd-overlay {
  position: fixed;
  inset: 0;
  z-index: 900;
  background: rgba(20, 26, 16, 0);
  pointer-events: none;
  transition: background .38s var(--ease);
}
.re2 .re2-cd-overlay.is-open { background: rgba(20, 26, 16, .55); pointer-events: auto; }

.re2 .re2-cd-card {
  position: fixed;
  z-index: 910;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  /* Transparent stand-in for any card border so the content box and the
     background crop match the clicked card to the pixel at frame zero. */
  border: 1px solid transparent;
  background-color: #fff;
  background-size: cover;
  background-position: center right;
  background-repeat: no-repeat;
  box-shadow: 0 30px 80px rgba(0, 0, 0, .35);
  will-change: top, left, width, height;
}

/* The brand-colour wash, copied from the card's own Elementor overlay by JS. */
.re2 .re2-cd-tint { position: absolute; inset: 0; z-index: 0; }

/*
 * Second wash for the expanded state. The card's own gradient goes almost
 * transparent on the right — fine under a 62%-wide copy column, unreadable
 * under the full-width detail head. Gradients themselves can't animate, so
 * this stronger sweep (built by JS from the same accent colour) sits on top
 * at opacity 0 and crossfades in with the grow, back out on collapse.
 */
.re2 .re2-cd-tint2 {
  position: absolute;
  inset: 0;
  z-index: 0;
  opacity: 0;
  transition: opacity .5s var(--ease);
}
.re2 .re2-cd-card.is-grown .re2-cd-tint2 { opacity: 1; }

.re2 .re2-cd-accent {
  position: relative;
  z-index: 1;
  flex: none;
  height: 0;
  opacity: 0;
  transition: opacity .28s var(--ease), height .5s var(--ease);
}
.re2 .re2-cd-card.is-grown .re2-cd-accent {
  height: 8px;
  opacity: 1;
  transition: opacity .4s var(--ease) .16s, height .5s var(--ease);
}

/*
 * The head is a live clone of the clicked card: same classes, same Elementor
 * styling, same padding — only its own background is stripped, because the
 * shell carries the photo (a second copy would crop differently as the shell
 * grows).
 */
.re2 .re2-cd-card .re2-cd-head {
  position: relative;
  z-index: 1;
  flex: none;
  width: auto !important;
  background: none !important;
  box-shadow: none !important;
  transform: none !important;
  opacity: 1 !important;
  cursor: default;
  transition: min-height .5s var(--ease), padding .5s var(--ease);
}
.re2 .re2-cd-card .re2-cd-head::before { display: none !important; }

/*
 * The live card is a tall, bottom-anchored banner (380px+ min-height). As the
 * shell grows, the head sheds that minimum and tightens its padding, so the
 * photo band settles into a compact header and the white detail gets the
 * room — the same proportions as the approved preview.
 */
.re2 .re2-cd-card.is-grown .re2-cd-head {
  min-height: 0 !important;
  padding: 30px 34px 26px !important;
}

/*
 * On the card, the badge floats absolute over the photo and the copy column
 * is capped at 62% so it clears the picture. In the compact header neither
 * treatment fits: the copy would run underneath the badge and the title
 * would wrap. So the copy column widens to full and takes a top margin that
 * clears the badge — all animated, so the reflow is part of the grow motion.
 */
.re2 .re2-cd-card .re2-cd-head .re2-prog-content {
  transition: max-width .5s var(--ease), margin-top .5s var(--ease);
}
.re2 .re2-cd-card.is-grown .re2-cd-head .re2-prog-content {
  /* Wide enough that the title sits on one line, but stops before the photo
     side so the picture stays visible next to the copy. */
  max-width: 72%;
  margin-top: 52px;
}

.re2 .re2-cd-card .re2-cd-head .re2-prog-badge { transition: top .5s var(--ease), left .5s var(--ease); }
.re2 .re2-cd-card.is-grown .re2-cd-head .re2-prog-badge { top: 26px; left: 34px; }

/* The card's display-size title wraps inside the 72% detail column — shrink
   it just enough that the longest programme name sits on one line, animated
   with the rest of the grow. The NOSS code line keeps its own small size. */
.re2 .re2-cd-card .re2-cd-head .re2-prog-content .elementor-widget-heading:not(.re2-prog-code) .elementor-heading-title {
  transition: font-size .5s var(--ease);
}
.re2 .re2-cd-card.is-grown .re2-cd-head .re2-prog-content .elementor-widget-heading:not(.re2-prog-code) .elementor-heading-title {
  font-size: 24px;
}

/* The enquire button rides along on the clone but bows out of the detail
   view — it fades back in as the card shrinks home. */
.re2 .re2-cd-card .re2-prog-arrow { transition: opacity .25s var(--ease); }
.re2 .re2-cd-card.is-grown .re2-prog-arrow { opacity: 0; pointer-events: none; }

.re2 .re2-cd-body {
  position: relative;
  z-index: 1;
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  background: #fff;
  padding: 26px 32px 32px;
  opacity: 0;
  transition: opacity .28s var(--ease);
}
.re2 .re2-cd-card.is-grown .re2-cd-body {
  opacity: 1;
  transition: opacity .4s var(--ease) .16s;
}
.re2 .re2-cd-body::-webkit-scrollbar { width: 6px; }
.re2 .re2-cd-body::-webkit-scrollbar-track { background: transparent; }
.re2 .re2-cd-body::-webkit-scrollbar-thumb { background: rgba(0, 0, 0, .25); border-radius: 3px; }

/* Desktop padding reads as generous margins; on a phone the same 32px is a
   third of the line length. Tighten so the copy gets the width. */
@media (max-width: 767px) {
  .re2 .re2-cd-body { padding: 16px 16px 20px; }
}

/* Short lead-in line between the "Course Objectives" heading and the list. */
.re2 .re2-cd-objintro { font-size: 14.5px; line-height: 1.6; color: rgba(0, 0, 0, .75); margin-bottom: 12px; }

.re2 .re2-cd-close {
  position: absolute;
  top: 16px;
  right: 16px;
  z-index: 2;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: #fff;
  border: 2.5px solid var(--black);
  box-shadow: 3px 3px 0 rgba(0, 0, 0, .3);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  padding: 0;
  opacity: 0;
  transition: opacity .28s var(--ease), background .2s, transform .2s, box-shadow .2s;
}
.re2 .re2-cd-card.is-grown .re2-cd-close { opacity: 1; transition: opacity .4s var(--ease) .16s, background .2s, transform .2s, box-shadow .2s; }
.re2 .re2-cd-close:hover { background: var(--yellow); transform: translate(1px, 1px); box-shadow: 1px 1px 0 rgba(0, 0, 0, .3); }
.re2 .re2-cd-close svg { width: 16px; height: 16px; }

/* ---- detail content, both hidden on the page and cloned into the body ---- */

.re2 .re2-cd-lead { font-size: 15.5px; line-height: 1.7; color: rgba(0, 0, 0, .75); margin-bottom: 24px; }

.re2 .re2-cd-vmrow { margin-bottom: 24px; }

.re2 .re2-cd-vm { border-radius: 14px; padding: 20px; min-width: 0; flex: 1 1 0; width: auto !important; }
.re2 .re2-cd-vm-vision { background-color: var(--blue); }
.re2 .re2-cd-vm-mission { background-color: var(--red); }
.re2 .re2-cd-vm-icon { margin-bottom: 10px; }
.re2 .re2-cd-vm-title .elementor-heading-title { font-family: var(--font-head); font-size: 16px; font-weight: 700; color: var(--black); }
.re2 .re2-cd-vm-title { margin-bottom: 8px; }
.re2 .re2-cd-vm-text { font-size: 14px; line-height: 1.55; color: rgba(0, 0, 0, .78); }

.re2 .re2-cd-objtitle { margin-bottom: 12px; }
.re2 .re2-cd-objtitle .elementor-heading-title { font-family: var(--font-head); font-size: 16px; font-weight: 700; color: var(--black); }

.re2 .re2-cd-objbox {
  background: #FAFAF7;
  border: 1px solid #ECECEC;
  border-radius: 14px;
  padding: 6px 18px;
}
.re2 .re2-cd-objbox ul { margin: 0; padding: 14px 0 14px 18px; }
.re2 .re2-cd-objbox li { font-size: 14.5px; line-height: 1.55; margin-bottom: 10px; color: rgba(0, 0, 0, .78); }
.re2 .re2-cd-objbox li:last-child { margin-bottom: 0; }

body.re2-cd-lock { overflow: hidden !important; }

/* ============================================================
   COURSE DETAIL PAGE — standalone programme pages
   ============================================================ */

/*
 * A full page per programme, in the same neo-brutalist language as the rest
 * of the site. Everything keys off --course-accent, set by a modifier class
 * on each section (re2-course-l3 / re2-course-l4), so the second programme
 * page is just different content with a different modifier.
 */
.re2 .re2-course-l3 { --course-accent: var(--red); --course-accent-soft: rgba(252, 138, 123, .12); }
.re2 .re2-course-l4 { --course-accent: var(--blue); --course-accent-soft: rgba(186, 218, 85, .12); }

/* ---- hero ---- */
.re2 .re2-course-hero { position: relative; overflow: hidden; }
.re2 .re2-course-hero::before {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(100deg, var(--course-accent) 40%, var(--course-accent-soft) 100%);
}
.re2 .re2-course-hero > * { position: relative; z-index: 1; }

/* Same wave divider as the About/Contact page heroes. */
.re2 .re2-course-hero::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -1px;
  height: 74px;
  z-index: 3;
  pointer-events: none;
  background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1440 74' preserveAspectRatio='none'><path d='M0,40 C240,80 480,0 720,28 C960,56 1200,14 1440,45 L1440,74 L0,74 Z' fill='%23FFFFFF'/></svg>") no-repeat center bottom / 100% 100%;
}

.re2 .re2-course-badge .elementor-heading-title {
  display: inline-block;
  padding: 9px 20px;
  border-radius: 300px;
  background: #fff;
  color: var(--black);
  font-family: var(--font-head);
  font-weight: 700;
  font-size: 13.5px;
  line-height: 1;
  border: 2.5px solid var(--black);
  box-shadow: 3px 3px 0 rgba(0, 0, 0, .4);
}
.re2 .re2-course-badge { margin-bottom: 20px; }

.re2 .re2-course-code .elementor-heading-title {
  font-family: var(--font-mono);
  font-size: 13px;
  font-weight: 400;
  letter-spacing: .08em;
  color: rgba(0, 0, 0, .65);
}
.re2 .re2-course-code { margin-bottom: 10px; }

.re2 .re2-course-title .elementor-heading-title {
  font-family: var(--font-head);
  font-size: clamp(30px, 4.4vw, 44px);
  font-weight: 800;
  letter-spacing: -.01em;
  color: var(--black);
}
.re2 .re2-course-title { margin-bottom: 14px; max-width: 60%; }

/* Kept on the solid-colour side of the wash, dark and semi-bold, so it never
   fights the photo for legibility. */
.re2 .re2-course-teaser,
.re2 .re2-course-hero .re2-course-teaser {
  font-size: 16.5px;
  line-height: 1.6;
  font-weight: 600;
  color: rgba(0, 0, 0, .82);
  max-width: 540px !important;
  margin-bottom: 4px;
}

@media (max-width: 860px) {
  .re2 .re2-course-title { max-width: 100%; }
}

/* ---- facts strip (sits just below the hero's wave) ---- */
.re2 .re2-course-facts {
  position: relative;
  z-index: 2;
  background: #fff;
  border: 3px solid var(--black);
  border-radius: 16px;
  box-shadow: 7px 7px 0 var(--black);
  overflow: hidden;
}
.re2 .re2-course-fact { border-right: 3px solid var(--black); }
.re2 .re2-course-fact:last-child { border-right: none; }
.re2 .re2-course-fact-k .elementor-heading-title {
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 400;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: rgba(0, 0, 0, .48);
}
.re2 .re2-course-fact-k { margin-bottom: 6px; }
.re2 .re2-course-fact-v .elementor-heading-title {
  font-family: var(--font-head);
  font-size: 15.5px;
  font-weight: 700;
  line-height: 1.35;
  color: var(--black);
}

@media (max-width: 1024px) {
  .re2 .re2-course-facts { flex-direction: column; }
  .re2 .re2-course-fact { border-right: none; border-bottom: 3px solid var(--black); }
  .re2 .re2-course-fact:last-child { border-bottom: none; }
}

/* ---- sticky enquire button, bottom centre while reading ---- */
.re2 .re2-course-sticky {
  position: fixed !important;
  left: 0;
  right: 0;
  bottom: 18px;
  z-index: 500;
  display: flex;
  justify-content: center;
  padding: 0 16px;
  pointer-events: none;
  width: auto !important;
}
.re2 .re2-course-sticky .elementor-button-wrapper,
.re2 .re2-course-sticky .elementor-button { pointer-events: auto; }
.re2 .re2-course-sticky .elementor-button { box-shadow: 4px 4px 0 var(--black), 0 14px 34px rgba(0, 0, 0, .28); }

/* ---- section headings ---- */
.re2 .re2-course-label .elementor-heading-title {
  font-family: var(--font-mono);
  font-size: 12.5px;
  font-weight: 400;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: rgba(0, 0, 0, .48);
}
.re2 .re2-course-label { margin-bottom: 8px; }
.re2 .re2-course-h2 .elementor-heading-title {
  font-family: var(--font-head);
  font-size: 26px;
  font-weight: 800;
  color: var(--black);
}
.re2 .re2-course-h2 { margin-bottom: 16px; }
.re2 .re2-course-lead { font-size: 16px; line-height: 1.75; color: rgba(0, 0, 0, .75); max-width: 760px; }

/* ---- vision / mission ---- */
.re2 .re2-course-vm {
  border: 3px solid var(--black);
  border-radius: 16px;
  box-shadow: 6px 6px 0 var(--black);
}
.re2 .re2-course-vm-vision { background-color: var(--blue); }
.re2 .re2-course-vm-mission { background-color: var(--red); }
.re2 .re2-course-vm .re2-course-vm-icon { margin-bottom: 12px; }
.re2 .re2-course-vm-h .elementor-heading-title { font-family: var(--font-head); font-size: 18px; font-weight: 800; color: var(--black); }
.re2 .re2-course-vm-h { margin-bottom: 10px; }
.re2 .re2-course-vm-p { font-size: 14.5px; line-height: 1.6; color: rgba(0, 0, 0, .78); }

/* ---- objectives: one list, rendered as tick cards ---- */
.re2 .re2-course-obj ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px;
}
.re2 .re2-course-obj li {
  position: relative;
  background: #fff;
  border: 2.5px solid var(--black);
  border-radius: 14px;
  padding: 16px 18px 16px 56px;
  box-shadow: 4px 4px 0 rgba(0, 0, 0, .85);
  font-size: 14.5px;
  line-height: 1.55;
  color: rgba(0, 0, 0, .8);
}
.re2 .re2-course-obj li::before {
  content: "✓";
  position: absolute;
  top: 15px;
  left: 17px;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: var(--course-accent);
  border: 2px solid var(--black);
  font-family: var(--font-head);
  font-weight: 700;
  font-size: 14px;
  line-height: 23px;
  text-align: center;
  color: var(--black);
}
@media (max-width: 767px) {
  .re2 .re2-course-obj ul { grid-template-columns: 1fr; }
}

/* ---- learn grid: numbered cells, one fused frame ---- */
.re2 .re2-course-learn {
  border: 3px solid var(--black);
  border-radius: 16px;
  overflow: hidden;
  box-shadow: 7px 7px 0 var(--black);
  background: #fff;
  counter-reset: re2learn;
}
.re2 .re2-course-learn-cell {
  flex: 1 1 33.33% !important;
  min-width: 0;
  width: auto !important;
  border-right: 3px solid var(--black);
  border-bottom: 3px solid var(--black);
  counter-increment: re2learn;
}
.re2 .re2-course-learn-cell:nth-child(3n) { border-right: none; }
.re2 .re2-course-learn-cell:nth-last-child(-n+3) { border-bottom: none; }
.re2 .re2-course-learn-cell::before {
  content: "0" counter(re2learn);
  display: block;
  font-family: var(--font-mono);
  font-size: 12px;
  color: rgba(0, 0, 0, .42);
  margin-bottom: 8px;
}
.re2 .re2-course-learn-h .elementor-heading-title { font-family: var(--font-head); font-size: 15.5px; font-weight: 700; color: var(--black); }
.re2 .re2-course-learn-h { margin-bottom: 6px; }
.re2 .re2-course-learn-p { font-size: 13.5px; line-height: 1.55; color: rgba(0, 0, 0, .68); }

@media (max-width: 1024px) {
  .re2 .re2-course-learn-cell { flex: 1 1 50% !important; }
  .re2 .re2-course-learn-cell:nth-child(3n) { border-right: 3px solid var(--black); }
  .re2 .re2-course-learn-cell:nth-child(2n) { border-right: none; }
  .re2 .re2-course-learn-cell:nth-last-child(-n+3) { border-bottom: 3px solid var(--black); }
  .re2 .re2-course-learn-cell:nth-last-child(-n+2) { border-bottom: none; }
}
@media (max-width: 640px) {
  .re2 .re2-course-learn-cell { flex: 1 1 100% !important; border-right: none !important; border-bottom: 3px solid var(--black) !important; }
  .re2 .re2-course-learn-cell:last-child { border-bottom: none !important; }
}

/* ---- career / entry panels ---- */
.re2 .re2-course-panel {
  background: #fff;
  border: 3px solid var(--black);
  border-radius: 16px;
  box-shadow: 6px 6px 0 var(--black);
  flex: 1 1 0 !important;
  min-width: 0;
  width: auto !important;
}
.re2 .re2-course-panel-h .elementor-heading-title { font-family: var(--font-head); font-size: 18px; font-weight: 800; color: var(--black); }
.re2 .re2-course-panel-h { margin-bottom: 14px; }
.re2 .re2-course-chips p { display: flex; flex-wrap: wrap; gap: 10px; margin: 0; }
.re2 .re2-course-chips span {
  font-family: var(--font-head);
  font-weight: 600;
  font-size: 13.5px;
  color: var(--black);
  background: var(--course-accent);
  border: 2px solid var(--black);
  border-radius: 300px;
  padding: 8px 16px;
  box-shadow: 2.5px 2.5px 0 var(--black);
}
.re2 .re2-course-panel-body { font-size: 14.5px; line-height: 1.65; color: rgba(0, 0, 0, .78); }
.re2 .re2-course-panel-note { font-size: 13.5px; line-height: 1.6; color: rgba(0, 0, 0, .62); margin-top: 14px; }

/* ---- pathway strip ---- */
.re2 .re2-course-path {
  background: #fff;
  border: 3px solid var(--black);
  border-radius: 16px;
  box-shadow: 6px 6px 0 var(--black);
}
.re2 .re2-course-path-steps p {
  display: flex;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
  margin: 0;
  font-family: var(--font-head);
  font-weight: 700;
  font-size: 18px;
}
.re2 .re2-course-path-steps span {
  font-size: 14.5px;
  padding: 12px 20px;
  border: 2.5px solid var(--black);
  border-radius: 12px;
  background: #F6F6EF;
  color: var(--black);
}
.re2 .re2-course-path-steps span.is-here { background: var(--course-accent); box-shadow: 3px 3px 0 var(--black); }
.re2 .re2-course-path-steps span a { color: inherit; text-decoration: none; }
.re2 .re2-course-path-steps span a:hover { text-decoration: underline; }
.re2 .re2-course-path-note { font-size: 13.5px; color: rgba(0, 0, 0, .62); margin-top: 14px; }

/* ============================================================
   WHAT YOU LEARN — 2x2 tiles
   ============================================================ */

/*
 * One flush row of four, hairline-divided rather than four floating cards —
 * the divider lives on each tile's right edge and the row carries the outer
 * frame, so no double borders appear when the row wraps on smaller screens.
 */
.re2 .re2-learn-row { border: 1px solid #e3e3e3; }
.re2 .re2-learn-row > .e-con:last-child { border-right: 0; }

.re2 .re2-learn-tile { transition: transform .35s var(--ease); }

/* The icon floats in the top-left corner while the copy stays pinned to the
   bottom, so tiles of different text lengths still line up. */
.re2 .re2-learn-tile .re2-learn-icon {
  position: absolute;
  top: 34px;
  left: 34px;
  z-index: 2;
  width: auto !important;
  transition: transform .5s var(--ease);
}

.re2 .re2-learn-tile:hover .re2-learn-icon { transform: translateY(-5px); }
.re2 .re2-learn-tile .re2-learn-icon .elementor-icon svg { width: 46px; height: 46px; }

.re2 .re2-learn-tile .elementor-widget-heading,
.re2 .re2-learn-tile .elementor-widget-text-editor { position: relative; z-index: 2; }

@media (max-width: 1024px) {
  .re2 .re2-learn-row > .e-con { border-bottom: 1px solid #e3e3e3; }
  .re2 .re2-learn-row > .e-con:nth-child(even) { border-right: 0; }
}

@media (max-width: 767px) {
  .re2 .re2-learn-row > .e-con { border-right: 0; }
  .re2 .re2-learn-tile .re2-learn-icon { top: 26px; left: 26px; }
}

/* ============================================================
   LEARNING APPROACH — numbered steps
   ============================================================ */

/* The number is a fixed square chip, so it must not shrink when the heading
   beside it wraps — hence flex: none rather than a width alone. */
.re2 .re2-step-num {
  flex: none !important;
  width: 44px !important;
  height: 44px;
  border-radius: 12px;
  background: var(--red);
  display: grid;
  place-items: center;
}

.re2 .re2-step-num .elementor-heading-title {
  font-family: var(--font-mono);
  font-weight: 600;
  font-size: 14px;
  line-height: 1;
  color: var(--black);
}

/* Scoped away from the number chip, which sits inside the same step and would
   otherwise inherit this size and colour. */
.re2 .re2-step > .elementor-widget-heading:not(.re2-step-num) .elementor-heading-title { color: var(--ink); font-size: 20px; }

/* Keep the section title on one line; it is the anchor of the whole column. */
.re2 .re2-approach-copy .sec-title .elementor-heading-title,
.re2 .re2-approach-copy .sec-title { white-space: nowrap; }

@media (max-width: 1024px) {
  .re2 .re2-approach-copy .sec-title .elementor-heading-title,
  .re2 .re2-approach-copy .sec-title { white-space: normal; }
}

/* ============================================================
   TESTIMONIALS — seamless marquee
   ============================================================ */

/*
 * The carousel widget is Elementor Pro, so this is a plain Container of cards
 * that re2-ui.js slides. Two in view on desktop, one below 1024px.
 *
 * The viewport keeps horizontal padding and matching negative margins so the
 * cards' soft shadows are not sheared off by overflow: hidden.
 */
/*
 * The viewport has to clip horizontally so off-stage cards stay hidden, and
 * overflow cannot be clipped on one axis only. So the padding is opened up far
 * enough to contain the hover shadow (0 24px 50px on a card lifted 6px), and an
 * equal negative margin cancels it again — the box grows, the layout does not.
 */
.re2 .re2-testi-viewport {
  overflow: hidden;
  cursor: grab;
  touch-action: pan-y;
  /* Horizontal window must stay INSIDE the 12px card gap — the next card's
     paint starts 12px past the track edge, so 6px leaves a safety margin
     against subpixel rounding while still giving shadows a little room. */
  padding: 40px 6px 80px;
  margin: -26px -6px -46px;
}

.re2 .re2-testi-track {
  display: flex;
  flex-wrap: nowrap !important;
  align-items: stretch;
  transition: transform .65s var(--ease);
}

.re2 .re2-testi-viewport.is-dragging {
  cursor: grabbing;
  user-select: none;
  -webkit-user-select: none;
}
.re2 .re2-testi-viewport.is-dragging .re2-testi-card { pointer-events: none; }

/*
 * Elementor's `.e-con.e-flex` declares `flex: var(--flex-grow) var(--flex-shrink)
 * var(--flex-basis)` — same specificity as anything writable here, and loaded
 * from a stylesheet whose order relative to this one is not guaranteed. When it
 * wins, every card collapses to a shrink-to-fit sliver. The longhands are
 * therefore forced; the matching variables are set too so the builder's own
 * shorthand resolves to the same values.
 *
 * The 24px of margin is subtracted from the basis so a card's OUTER width is
 * exactly half the track. The slider steps by 50% per card, so any mismatch
 * between basis and outer width compounds into visible drift.
 */
.re2 .re2-testi-card {
  --flex-grow: 0;
  --flex-shrink: 0;
  --flex-basis: calc(50% - 24px);
  flex-grow: 0 !important;
  flex-shrink: 0 !important;
  flex-basis: calc(50% - 24px) !important;
  width: auto !important;
  max-width: none;
  margin: 0 12px;
  /*
   * Two painted layers instead of pseudo-elements: ::before on an Elementor
   * container is its background-overlay element, and redefining it here would
   * break any overlay set in the editor. Layer one is the low-opacity quote
   * mark, layer two the brand stripe across the top; both are clipped by the
   * card's own border-radius.
   */
  background-image:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='150' height='150'%3E%3Ctext x='0' y='122' font-family='Georgia,serif' font-size='175' font-weight='700' fill='%2361A62F' fill-opacity='.09'%3E%E2%80%9D%3C/text%3E%3C/svg%3E"),
    linear-gradient(90deg, var(--red), var(--teal), var(--blue));
  background-repeat: no-repeat, no-repeat;
  background-position: right 14px bottom -14px, left top;
  background-size: 130px auto, 100% 5px;
  transition: transform .45s var(--ease), box-shadow .45s var(--ease);
}

.re2 .re2-testi-card:hover { transform: translateY(-6px); box-shadow: 0 24px 50px rgba(38, 66, 30, .16) !important; }

@media (max-width: 767px) {
  .re2 .re2-testi-card { --flex-basis: calc(100% - 24px); flex-basis: calc(100% - 24px) !important; }

  /* The heading block already carries the standoff; the viewport's own top
     padding only needs to clear the card's hover shadow. */
  .re2 .re2-testi-viewport { padding-top: 26px; margin-top: -26px; padding-bottom: 60px; margin-bottom: -38px; }
}

@media (max-width: 1024px) {

  /*
   * The viewport's side padding is what was leaking the next card into view.
   * overflow: hidden clips at the PADDING edge, not the content edge, so the
   * 30px of breathing room added for the hover shadow was also 30px of the
   * neighbouring slide showing on each side. Touch has no hover, so below
   * desktop the horizontal padding — and its cancelling negative margin — go
   * to zero and the slide ends exactly where the frame does.
   */
  .re2 .re2-testi-viewport {
    padding-left: 0;
    padding-right: 0;
    margin-left: 0;
    margin-right: 0;
  }
}

/*
 * Desktop keeps horizontal room for the hover shadow, which means the clip edge
 * sits outside the two visible cards — and the third card was showing through
 * that strip. Widening the gutter fixes it without giving the shadow room back:
 * each card now carries a 20px margin, so the incoming card's own margin is
 * wider than the 18px of shadow room and nothing of it can reach the clip edge.
 *
 * The track is pulled out by that same 20px so the first card's painted edge
 * still lines up with the section heading rather than sitting inset. Card outer
 * width stays exactly half the track, which is what the 50%-per-step slider
 * depends on.
 */
@media (min-width: 1025px) {
  .re2 .re2-testi-viewport {
    padding-left: 0;
    padding-right: 0;
    margin-left: 0;
    margin-right: 0;
  }

  .re2 .re2-testi-track {
    margin-left: 0;
    margin-right: -36px;
  }

  .re2 .re2-testi-card {
    --flex-basis: calc(50% - 40px);
    flex-basis: calc(50% - 40px) !important;
    margin-left: 20px;
    margin-right: 20px;
  }
}

/* ---- Controls ---- */

.re2 .re2-testi-nav {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 22px;
  margin-top: 12px;
}

/* The cards are soft, but the controls belong to the same button family as the
   rest of the site: ink border, hard offset shadow, press-into-the-shadow hover. */
.re2 .re2-testi-arrow {
  width: 52px;
  height: 52px;
  min-width: 0;
  border-radius: 50%;
  border: 3px solid var(--black) !important;
  background: #fff;
  color: var(--black);
  cursor: pointer;
  display: grid;
  place-items: center;
  padding: 0 !important;
  box-shadow: 4px 4px 0 var(--black) !important;
  transition: background .25s, color .25s, transform .18s var(--ease), box-shadow .18s var(--ease);
}

.re2 .re2-testi-arrow svg { width: 20px; height: 20px; }
.re2 .re2-testi-arrow:hover { background: var(--teal); color: var(--black); transform: translate(2px, 2px); box-shadow: 1px 1px 0 var(--black) !important; }
.re2 .re2-testi-arrow:active { transform: translate(4px, 4px); box-shadow: 0 0 0 var(--black) !important; }
.re2 .re2-testi-arrow:focus-visible { outline: 3px solid var(--blue); outline-offset: 3px; }

.re2 .re2-testi-dots { display: flex; align-items: center; gap: 9px; }

/* Astra's own button shadow is still reset; the ink outline is ours. */
.re2 .re2-testi-dots button {
  width: 13px;
  height: 13px;
  min-width: 0;
  min-height: 0;
  padding: 0;
  margin: 0;
  border: 2px solid var(--black) !important;
  border-radius: 50%;
  background: #fff;
  box-shadow: none !important;
  -webkit-appearance: none;
  appearance: none;
  cursor: pointer;
  transition: width .35s var(--ease), background .35s var(--ease), border-radius .35s var(--ease);
}

.re2 .re2-testi-dots button:hover { background: var(--teal); }
.re2 .re2-testi-dots button.is-active { background: var(--red); width: 34px; border-radius: 7px; }
.re2 .re2-testi-dots button:focus-visible { outline: 2px solid var(--blue-dark); outline-offset: 3px; }

/* ============================================================
   CTA — panel with the enquiry card overlapping it
   ============================================================ */

/*
 * Grid tracks rather than absolute positioning: an absolutely-positioned card
 * escapes its container's height, and inside Elementor that collapses the
 * section and spills the card over whatever follows.
 */
/*
 * The grid goes on .e-con-inner, NOT on the container itself.
 *
 * A "boxed" Elementor container wraps its children in an .e-con-inner div, so
 * styling the outer element produces a grid with exactly one item and the
 * overlap silently never happens. Full-width containers have no such wrapper —
 * which is why the stair band above can be styled directly.
 */
.re2 .re2-cta-wrap > .e-con-inner {
  display: grid;
  grid-template-columns: 1fr 490px 50px;
  align-items: center;
}

/*
 * align-self is forced because Elementor gives a child container a stretch
 * alignment of its own, which makes both grid items the height of the taller
 * one. The design depends on them being DIFFERENT heights: the panel sizes to
 * its copy and the form card, being taller, overhangs it top and bottom.
 */
.re2 .re2-cta-panel { grid-column: 1 / 3; grid-row: 1; align-self: center !important; }
.re2 .re2-cta-card { grid-column: 2 / 4; grid-row: 1; z-index: 2; align-self: center !important; }

@media (max-width: 1024px) {
  .re2 .re2-cta-wrap > .e-con-inner { display: flex; flex-direction: column; }
  .re2 .re2-cta-panel { align-self: stretch !important; }
  .re2 .re2-cta-card { width: calc(100% - 36px); margin: -10px auto 0; align-self: center !important; }
}

/* Faint logo watermark behind the panel copy. */
.re2 .re2-cta-watermark {
  position: absolute;
  right: -40px;
  bottom: -60px;
  width: 420px;
  max-width: 55%;
  filter: brightness(0) invert(1);
  opacity: .28;
  pointer-events: none;
  z-index: 0;
}

/* Keep the panel's own content above the watermark. */
.re2 .re2-cta-panel > *:not(.re2-cta-watermark) { position: relative; z-index: 1; }

@media (max-width: 1024px) {
  .re2 .re2-cta-watermark { right: -30px; bottom: -40px; width: 300px; opacity: .22; }
}

/*
 * Circuit traces across the CTA panel, matching the printed banner artwork —
 * 45-degree runs with ring pads, on theme for a computer systems college.
 *
 * The fade is baked into the SVG as a userSpaceOnUse gradient rather than
 * painted over the top with a second layer, so the pattern dies away on its own
 * and the rule does not have to know what colour the panel underneath is. (With
 * the default objectBoundingBox units each pad would get its OWN copy of the
 * gradient and render as a crescent rather than a ring.)
 *
 * A background layer, not a pseudo-element: ::before on an Elementor container
 * is its background-overlay slot, and the panel's fill arrives from the builder
 * as background-COLOR, so background-image cannot collide with it. Desktop only
 * — the tablet and mobile CTA is a different section.
 */
@media (min-width: 1025px) {
  .re2 .re2-cta-panel {
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='1200' height='340' viewBox='0 0 1200 340'><defs><linearGradient id='f' gradientUnits='userSpaceOnUse' x1='0' y1='0' x2='1200' y2='0'><stop offset='0' stop-color='%23fff' stop-opacity='.17'/><stop offset='.5' stop-color='%23fff' stop-opacity='.08'/><stop offset='1' stop-color='%23fff' stop-opacity='0'/></linearGradient></defs><g fill='none' stroke='url(%23f)' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'><path d='M-20 260 140 100 220 20 320 20 M-20 -60 140 100 220 180 220 340 420 340 620 140 620 60 M-20 380 120 380 M-60 140 40 240 240 240 380 100 460 100 560 200 640 200 M-80 60 20 -40 M-60 -20 60 100 200 240 200 320 M-80 300 0 380 160 380 320 380 M-40 220 80 100 80 -60 180 -60 M-20 100 100 220 300 220 500 20 640 20 M-80 180 20 80 160 80 360 80 440 80 M-20 20 60 -60 M400 160 600 -40 M520 300 640 180 780 40 M80 200 220 200 420 400 M140 120 260 240 360 340 M80 140 280 140 380 140 M460 220 620 60'/><circle cx='320' cy='20' r='6'/><circle cx='620' cy='60' r='5'/><circle cx='640' cy='200' r='5'/><circle cx='200' cy='320' r='5'/><circle cx='640' cy='20' r='5'/><circle cx='440' cy='80' r='6'/><circle cx='400' cy='160' r='4'/><circle cx='780' cy='40' r='4'/><circle cx='80' cy='200' r='4'/><circle cx='380' cy='140' r='4'/><circle cx='460' cy='220' r='4'/><circle cx='760' cy='140' r='4'/><circle cx='500' cy='260' r='4'/><circle cx='240' cy='300' r='4'/><circle cx='540' cy='240' r='4'/><circle cx='240' cy='80' r='4'/><circle cx='640' cy='300' r='4'/><circle cx='720' cy='260' r='4'/><circle cx='440' cy='200' r='4'/><circle cx='480' cy='40' r='4'/><circle cx='540' cy='120' r='4'/></g></svg>"),
      /*
       * The lockup runs deep green under the copy and only reaches neon past
       * the halfway point. That is not decoration — white type needs the darker
       * end to stay legible, and the neon is safe on the right where the form
       * card sits over it. Painted here rather than in the builder because
       * Elementor's gradient control carries two stops and this needs four.
       */
      linear-gradient(100deg, #629130 0%, #84C441 34%, #BADA55 72%, #EEFF42 100%);
    background-repeat: no-repeat, no-repeat;
    background-position: left top, left top;
    background-size: 100% 100%, 100% 100%;
  }
}

/*
 * The enquiry card is a large flat white panel, which reads as unfinished next
 * to the illustrated band beside it. Two painted layers give it texture without
 * competing with the form: a circuit-and-chip motif in the bottom-right corner
 * — on theme for a computer systems college — over a faint dot grid.
 *
 * These are background layers rather than pseudo-elements because ::before on
 * an Elementor container is its overlay slot, and the white fill arrives from
 * the builder as background-COLOR, so background-image cannot collide with it.
 * Opacity is baked into the SVG so the card's own contrast is untouched.
 */
.re2 .re2-cta-card {
  background-image:
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='300' height='300' viewBox='0 0 300 300' fill='none' stroke='%235C8718' stroke-opacity='0.16' stroke-width='4' stroke-linecap='round'><rect x='118' y='118' width='74' height='74' rx='12'/><rect x='140' y='140' width='30' height='30' rx='5'/><path d='M155 118V92M139 118v-16M171 118v-16M118 155H92M118 139h-16M118 171h-16M192 155h26M192 139h16M192 171h16M155 192v26M139 192v16M171 192v16'/><path d='M20 246h44l26-26h28M280 246h-40l-24 26h-34M40 286v-30l30-30M246 286v-26'/><circle cx='20' cy='246' r='6'/><circle cx='280' cy='246' r='6'/><circle cx='40' cy='286' r='6'/><circle cx='246' cy='286' r='6'/><circle cx='118' cy='220' r='6'/><circle cx='182' cy='272' r='6'/></svg>"),
    radial-gradient(rgba(92, 135, 24, .07) 1.5px, transparent 1.5px);
  background-repeat: no-repeat, repeat;
  background-position: right -30px bottom -30px, left top;
  background-size: 300px 300px, 22px 22px;
}

@media (max-width: 767px) {
  .re2 .re2-cta-card { background-size: 210px 210px, 22px 22px; }
}

/*
 * Compact field sizing for the CTA card only.
 *
 * The base field rule in components.css carries five compound selectors
 * (:not(.wpcf7-submit):not([type="checkbox"]):not([type="radio"]) each count),
 * so a shorter selector here loses on specificity even though it is more
 * specific in intent. The chain is repeated to match it and then beaten by the
 * extra .re2-cta-card class.
 */
.re2 .re2-cta-card .wpcf7-form-control:not(.wpcf7-submit):not([type="checkbox"]):not([type="radio"]) {
  padding: 10px 14px;
  font-size: 14.5px;
  border-width: 2px;
  box-shadow: 3px 3px 0 var(--black);
  border-radius: 10px;
}

.re2 .re2-cta-card select.wpcf7-form-control:not(.wpcf7-submit):not([type="checkbox"]):not([type="radio"]):not([multiple]) {
  padding: 10px 40px 10px 14px;
  font-size: 14.5px;
  background-position: right 14px center;
}

/* height, not min-height: the textarea's height comes from its rows attribute,
   which a floor cannot bring down. */
.re2 .re2-cta-card textarea.wpcf7-form-control { height: 76px; min-height: 76px; }
.re2 .re2-cta-card .wpcf7 label { font-size: 12.5px; margin-bottom: 4px; }

/* Tighter rows: the card sits beside the panel copy, so vertical bulk here
   pushes the whole band taller than the panel it is meant to overlap. */
.re2 .re2-cta-card .wpcf7 .form-grid { gap: 8px 12px; }
.re2 .re2-cta-card .wpcf7 p { margin: 0; }
.re2 .re2-cta-card .wpcf7-submit { padding: 11px 26px; }

/* ============================================================
   FOOTER
   ============================================================ */

.re2 .re2-footer a { color: rgba(255, 255, 255, .74); transition: color .25s, padding-left .25s; }
.re2 .re2-footer a:hover { color: var(--yellow); }
.re2 .re2-footer .elementor-icon-list-item:hover a { padding-left: 5px; }

/* The logo art has a white plate baked in; inverting it makes the mark read
   as pure white on the dark footer without re-exporting the asset. */
.re2 .re2-footer-logo img { filter: brightness(0) invert(1); }

/*
 * The address runs to two lines, so a vertically-centred pin floats in the gap
 * between them. Aligning every list item to the top keeps the icon beside the
 * first line, and the small nudge optically centres it against the cap height.
 */
.re2 .re2-footer .elementor-icon-list-item,
.re2 .re2-footer .elementor-icon-list-item a { align-items: flex-start; }
.re2 .re2-footer .elementor-icon-list-icon { margin-top: 4px; }

.re2 .re2-footer-credit a {
  color: rgba(255, 255, 255, .72);
  text-decoration: underline;
  text-underline-offset: 3px;
}

.re2 .re2-footer-credit a:hover { color: var(--yellow); }

/*
 * The slogan carries the brand now that the logo has moved out of the top row,
 * so it is set as a statement rather than a caption: display size, tight
 * leading, and a slight negative tracking that keeps a long line from looking
 * loose at that weight.
 */
.re2 .re2-footer-slogan .elementor-widget-container {
  font-family: var(--font-head);
  letter-spacing: -.02em;
}

.re2 .re2-footer-slogan strong { font-weight: 800; }

/* ------------------------------------------------------------
   Footer particle wordmark
   ------------------------------------------------------------
   The band itself is an empty Elementor container. The canvas is built by
   re2-ui.js, which samples the hidden source image to place the glyphs, so if
   the script never runs the footer just ends at the legal bar with no gap.
   The two custom properties below are the script's colour inputs — retune the
   resting ink or the disturbance highlight here rather than in the JS. */

.re2 .re2-fp-band {
  --fp-hot: #84C441;
  --fp-ink: #8A8A8A;
  position: relative;
  width: 100%;
}

/* The source has to stay in the document for the canvas to read its pixels, but
   it must never be seen or occupy space. visibility:hidden rather than
   display:none, because a display:none image is not guaranteed to decode. */
.re2 .re2-fp-band .re2-fp-src {
  position: absolute;
  top: 0;
  left: 0;
  width: 1px;
  height: 1px;
  overflow: hidden;
  visibility: hidden;
  pointer-events: none;
}

.re2 .re2-fp-canvas {
  display: block;
  width: 100%;
  height: clamp(140px, 21vw, 300px);
  cursor: crosshair;
}

/* ============================================================
   SCROLL PROGRESS + BACK TO TOP
   ============================================================ */

#re2-progress {
  position: fixed;
  top: 0;
  left: 0;
  height: 3px;
  width: 0;
  background: linear-gradient(90deg, var(--red), var(--blue));
  z-index: 9999;
  transition: width .1s linear;
  pointer-events: none;
}

/* Astra pads and min-widths every button, which stretched this one wider than
   tall; the size is forced so it stays an exact square with the arrow centred. */
#re2-totop {
  position: fixed;
  right: 26px;
  bottom: 26px;
  width: 50px !important;
  height: 50px !important;
  min-width: 0;
  min-height: 0;
  padding: 0 !important;
  line-height: 1;
  aspect-ratio: 1 / 1;
  display: grid;
  place-items: center;
  border-radius: 14px;
  border: 3px solid var(--black);
  background: var(--red);
  color: var(--black);
  box-shadow: 4px 4px 0 var(--black);
  cursor: pointer;
  opacity: 0;
  visibility: hidden;
  transform: translateY(12px);
  transition: opacity .3s var(--ease), transform .3s var(--ease), visibility .3s, background .25s;
  z-index: 9998;
}

#re2-totop.is-visible { opacity: 1; visibility: visible; transform: none; }
#re2-totop:hover { background: var(--teal); transform: translate(2px, 2px); box-shadow: 2px 2px 0 var(--black); }
#re2-totop svg { width: 20px; height: 20px; display: block; margin: 0; stroke: currentColor; fill: none; stroke-width: 2.6; }

@media (max-width: 767px) {
  #re2-totop { right: 16px; bottom: 16px; width: 44px; height: 44px; border-radius: 12px; }
}

/*
 * Astra ships its own scroll-to-top. Its Customizer setting is switched off
 * alongside this, but the rule stays as a backstop: a second button stacked
 * under this one is the kind of thing that quietly reappears after a theme
 * update, and two of them in the same corner looks broken.
 */
.ast-scroll-top-icon,
#ast-scroll-top { display: none !important; }

/* ============================================================
   JETPOPUP LOGIN FORM
   ============================================================ */

/*
 * The JetBlocks login widget renders WordPress's own wp_login_form(), so its
 * submit button carries core's .button classes rather than anything Elementor
 * controls — there is no widget setting to reach it. These selectors give it the
 * same neo-brutalist treatment as every other button on the site.
 */
.re2 .jet-login input[type="submit"],
.re2 .jet-login #wp-submit,
.re2 .jet-login .login-submit input {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  font-family: var(--font-head);
  font-weight: 700;
  font-size: var(--sz-sm);
  line-height: 1.2;
  padding: 14px 32px;
  border-radius: var(--r-pill);
  border: 3px solid var(--black);
  background: var(--red);
  color: var(--black);
  cursor: pointer;
  box-shadow: 5px 5px 0 var(--black);
  text-shadow: none;
  transition: transform .18s var(--ease), box-shadow .18s var(--ease), background .25s, color .25s;
}

.re2 .jet-login input[type="submit"]:hover,
.re2 .jet-login #wp-submit:hover {
  background: var(--teal);
  color: var(--black);
  transform: translate(3px, 3px);
  box-shadow: 2px 2px 0 var(--black);
}

.re2 .jet-login input[type="submit"]:active,
.re2 .jet-login #wp-submit:active { transform: translate(5px, 5px); box-shadow: 0 0 0 var(--black); }

.re2 .jet-login input[type="submit"]:focus-visible,
.re2 .jet-login #wp-submit:focus-visible { outline: 3px solid var(--blue); outline-offset: 3px; }

/* Matching fields, so the button does not sit above plain browser inputs. */
.re2 .jet-login input.input,
.re2 .jet-login input[type="text"],
.re2 .jet-login input[type="password"] {
  width: 100%;
  font-family: var(--font-body);
  font-size: 15.5px;
  color: var(--ink);
  background: #fff;
  border: 2.5px solid var(--black);
  border-radius: 12px;
  padding: 13px 17px;
  box-shadow: 4px 4px 0 var(--black);
  -webkit-appearance: none;
  transition: transform .18s var(--ease), box-shadow .18s var(--ease), background .25s;
}

.re2 .jet-login input.input:focus,
.re2 .jet-login input[type="text"]:focus,
.re2 .jet-login input[type="password"]:focus {
  outline: none;
  transform: translate(2px, 2px);
  box-shadow: 2px 2px 0 var(--blue);
  border-color: var(--blue);
}

.re2 .jet-login label {
  font-family: var(--font-head);
  font-weight: 600;
  font-size: 13.5px;
  color: var(--ink);
}

.re2 .jet-login .login-remember label { font-weight: 400; }
.re2 .jet-login .login-submit { margin-top: 18px; }

/* ============================================================
   IN-PAGE ANCHORS
   ============================================================ */

/*
 * Anchor targets have to clear the sticky header, or clicking a nav link lands
 * the section heading underneath it. scroll-margin is the modern fix — no
 * offset maths in JS, and it works for keyboard focus jumps too.
 */
.re2 [id^="home-"],
.re2 [id^="about-"],
.re2 [id^="contact-"] { scroll-margin-top: 110px; }

html { scroll-behavior: smooth; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
}

/* ============================================================
   SCROLL SPY RAIL
   ============================================================ */

/*
 * A fixed rail of dots down the right edge, one per section, with the current
 * one highlighted. Built by JS from the section anchors already on the page, so
 * adding or removing a section in Elementor updates it with no extra work.
 */
#re2-spy {
  position: fixed;
  right: 26px;
  top: 50%;
  transform: translateY(-50%);
  /* Above the sticky header (z-index 100, set on the header container in
     Elementor). The rail is centred on the viewport, so on a short window its
     top nodes run under the header and disappear. */
  z-index: 120;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0;
}

/*
 * The node is a <button>, and Astra gives every button a white background, a
 * radius and a drop shadow — which showed up as a card sitting behind each dot
 * and breaking the dashed connector. Resetting the button chrome (including the
 * interaction states, which Astra styles separately) leaves only the ::before
 * ring visible.
 */
#re2-spy .re2-spy-node,
#re2-spy .re2-spy-node:hover,
#re2-spy .re2-spy-node:focus,
#re2-spy .re2-spy-node:active {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  min-width: 0;
  min-height: 0;
  background: none !important;
  background-color: transparent !important;
  border: 0 !important;
  border-radius: 0;
  box-shadow: none !important;
  text-shadow: none;
  padding: 0;
  margin: 0;
  -webkit-appearance: none;
  appearance: none;
  filter: none;
  outline: none;
  cursor: pointer;
}

/*
 * Open rings, not filled discs: a hollow circle on the page background reads as
 * "not here yet", and the current section fills that same shape with the brand
 * ring plus a soft halo. Sizes are a step up from the original build, where the
 * dots were too small to register against a full-width page.
 *
 * The node box is 34px so the active ring (24px outer) and its 5px halo have
 * room without the rail jumping wider as the active dot moves.
 */
#re2-spy .re2-spy-node::before {
  content: "";
  width: 14px;
  height: 14px;
  border-radius: 50%;
  border: 2px solid var(--grey);
  background: #fff;
  box-shadow: none !important;
  filter: none;
  transition: width .35s var(--ease), height .35s var(--ease), border-color .35s var(--ease), box-shadow .35s var(--ease);
}

#re2-spy .re2-spy-node:hover::before { border-color: var(--blue); }

#re2-spy .re2-spy-node.is-active::before {
  width: 18px;
  height: 18px;
  background: #fff;
  border: 3px solid var(--red);
  /* !important because the base ring forces box-shadow off to strip the theme's
     button shadow; the halo has to opt back in. */
  box-shadow: 0 0 0 5px rgba(252, 138, 123, .32) !important;
}

#re2-spy .re2-spy-node:focus-visible::before { border-color: var(--blue-dark); }
#re2-spy .re2-spy-node:focus-visible { outline: 2px solid var(--blue-dark) !important; outline-offset: 2px; border-radius: 50%; }

/* Dashed connector between dots. */
#re2-spy .re2-spy-link {
  height: 24px;
  width: 2px;
  background: repeating-linear-gradient(var(--grey) 0 4px, transparent 4px 8px);
}

/* Label on hover, styled as a code tag to match the site's tone. */
#re2-spy .re2-spy-tip {
  position: absolute;
  right: 40px;
  top: 50%;
  transform: translateY(-50%) translateX(8px);
  background: var(--ink);
  color: #fff;
  font-family: var(--font-mono);
  font-size: 11px;
  padding: 5px 12px;
  border-radius: 6px;
  white-space: nowrap;
  opacity: 0;
  pointer-events: none;
  transition: opacity .3s, transform .3s;
}

#re2-spy .re2-spy-tip::before { content: "< "; color: var(--yellow); }
#re2-spy .re2-spy-tip::after { content: " />"; color: var(--yellow); }

#re2-spy .re2-spy-node:hover .re2-spy-tip,
#re2-spy .re2-spy-node:focus-visible .re2-spy-tip { opacity: 1; transform: translateY(-50%) translateX(0); }

/* Below this width the rail would crowd the content. */
@media (max-width: 1120px) {
  #re2-spy { display: none; }
}

/* ============================================================
   ABOUT — page banner
   ============================================================ */

/*
 * Three things stack on this banner: the photo (container background), a dark
 * gradient, and a faint 48px grid. Elementor gives exactly one overlay layer,
 * so the grid rides along inside the overlay's background-image rather than
 * claiming a pseudo-element of its own — ::after is spent on the wave below.
 */
.re2 .re2-page-hero { position: relative; overflow: hidden; text-align: center; }

.re2 .re2-page-hero::before {
  background-image:
    linear-gradient(rgba(255, 255, 255, .05) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255, 255, 255, .05) 1px, transparent 1px),
    linear-gradient(180deg, rgba(14, 18, 8, .55), rgba(14, 18, 8, .72)) !important;
  background-size: 48px 48px, 48px 48px, auto !important;
  opacity: 1 !important;
}

/* The wave sits above the copy, exactly as in the original, so it can bite into
   the bottom of the banner without leaving a seam. */
.re2 .re2-page-hero::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -1px;
  height: 74px;
  z-index: 3;
  pointer-events: none;
  background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1440 74' preserveAspectRatio='none'><path d='M0,40 C240,80 480,0 720,28 C960,56 1200,14 1440,45 L1440,74 L0,74 Z' fill='%23FFFFFF'/></svg>") no-repeat center bottom / 100% 100%;
}

.re2 .re2-crumbs { margin-top: 12px; }
.re2 .re2-crumbs p { display: inline-flex; gap: 10px; align-items: center; margin: 0; }
.re2 .re2-crumbs a { color: var(--yellow); }
.re2 .re2-crumbs a:hover { text-decoration: underline; }

/* ============================================================
   ABOUT — Who We Are image stack
   ============================================================ */

.re2 .re2-img-stack { position: relative; }

/* Dotted flourish, top-right. On a widget wrapper both pseudo-elements are
   free, so the yellow-green frame below can take ::before on the photo. */
.re2 .re2-img-stack::after {
  content: "";
  position: absolute;
  top: -24px;
  right: -24px;
  width: 130px;
  height: 130px;
  background-image: radial-gradient(var(--blue) 2.5px, transparent 2.5px);
  background-size: 18px 18px;
  opacity: .5;
  z-index: 0;
  pointer-events: none;
}

.re2 .re2-img-frame { position: relative; z-index: 1; }

.re2 .re2-img-frame::before {
  content: "";
  position: absolute;
  left: -18px;
  bottom: -18px;
  width: 60%;
  height: 60%;
  border: 4px solid var(--blue);
  border-radius: var(--r-lg);
  z-index: -1;
}

.re2 .re2-img-frame img {
  width: 100%;
  aspect-ratio: 4 / 3.4;
  object-fit: cover;
  border-radius: var(--r-lg);
  box-shadow: 0 20px 46px rgba(38, 66, 30, .18);
  transition: transform .8s var(--ease);
}

.re2 .re2-img-frame:hover img { transform: scale(1.04); }

.re2 .re2-img-overlap {
  position: absolute;
  right: -26px;
  bottom: -34px;
  width: 46% !important;
  border-radius: 18px;
  overflow: hidden;
  border: 6px solid #fff;
  box-shadow: 0 20px 45px rgba(234, 76, 156, .3);
  z-index: 3;
  animation: re2Floaty 7s ease-in-out infinite;
}

/* Elementor sizes an image widget from the file, so without this the photo
   filled only part of the frame and the big picture showed through beside it. */
.re2 .re2-img-overlap .elementor-widget-image,
.re2 .re2-img-overlap .elementor-widget-container,
.re2 .re2-img-overlap figure,
.re2 .re2-img-overlap img { width: 100% !important; max-width: none; display: block; }
.re2 .re2-img-overlap img { aspect-ratio: 4 / 3; object-fit: cover; }

@keyframes re2Floaty {
  0%, 100% { transform: translateY(0) rotate(0); }
  50% { transform: translateY(-20px) rotate(4deg); }
}

@media (max-width: 1024px) {
  .re2 .re2-img-overlap { right: 4px; bottom: -20px; }
}

@media (prefers-reduced-motion: reduce) {
  .re2 .re2-img-overlap { animation: none; }
}

/* ============================================================
   ABOUT — Business Philosophy panes
   ============================================================ */

/*
 * A horizontally expanding set. Elementor's accordion only opens downwards, so
 * the panes are plain containers and re2-ui.js moves the .is-open class; the
 * width change is a flex-grow transition, which animates smoothly where an
 * explicit width would not.
 */
.re2 .re2-vm {
  margin-top: 52px;
  border-radius: 12px;
  overflow: hidden;
  min-height: 240px;
  box-shadow: 0 22px 55px rgba(38, 66, 30, .15);
}

.re2 .re2-vm-pane {
  position: relative;
  overflow: hidden;
  transition: flex .6s var(--ease);
  width: auto !important;
  /* The builder's 42px vertical padding made the whole band taller than it
     needs to be — trimmed here since !important is what beats the element's
     own padding vars. */
  padding-top: 30px !important;
  padding-bottom: 30px !important;
}

.re2 .re2-vm-static { flex: 1.05 1 0 !important; cursor: default; }
.re2 .re2-vm-ex { flex: .6 1 0 !important; cursor: pointer; }
.re2 .re2-vm-ex.is-open { flex: 2.4 1 0 !important; }

.re2 .re2-vm-vision { background-color: var(--blue); }
.re2 .re2-vm-mission { background-color: var(--red); }
.re2 .re2-vm-objectives { background-color: var(--teal); }

.re2 .re2-vm-icon { margin-bottom: 14px; }

/* One size across all three panes, open or closed — 21px titles, 15.5px body
   to match the rest of the page's body copy (e.g. the core values). */
.re2 .re2-vm-title .elementor-heading-title { font-size: 21px; white-space: nowrap; }

.re2 .re2-vm-body {
  max-height: 0;
  opacity: 0;
  overflow-y: auto;
  overflow-x: hidden;
  font-size: 15.5px;
  line-height: 1.6;
  scrollbar-width: thin;
  scrollbar-color: rgba(0, 0, 0, .28) transparent;
  transition: max-height .55s var(--ease), opacity .45s, margin .45s;
}

.re2 .re2-vm-body::-webkit-scrollbar { width: 5px; }
.re2 .re2-vm-body::-webkit-scrollbar-track { background: transparent; }
.re2 .re2-vm-body::-webkit-scrollbar-thumb { background: rgba(0, 0, 0, .28); border-radius: 3px; }

/*
 * Objectives has more points than Vision or Mission ever did. Rather than let
 * the pane grow taller than the others, its body keeps the same 170px cap and
 * scrolls internally — the card never changes size, only its content does.
 */
.re2 .re2-vm-body-scroll { padding-right: 10px; }

.re2 .re2-vm-list { margin: 0; padding-left: 18px; }
.re2 .re2-vm-list li { margin-bottom: 8px; }
.re2 .re2-vm-list li:last-child { margin-bottom: 0; }

.re2 .re2-vm-ex.is-open .re2-vm-body { max-height: 170px; opacity: 1; margin-top: 12px; }

.re2 .re2-vm-ex::after {
  content: "+";
  position: absolute;
  top: 18px;
  right: 22px;
  font-family: var(--font-head);
  font-weight: 700;
  font-size: 26px;
  line-height: 1;
  color: rgba(0, 0, 0, .5);
  transition: transform .4s;
}

.re2 .re2-vm-ex.is-open::after { transform: rotate(45deg); }
.re2 .re2-vm-ex:focus-visible { outline: 3px solid var(--yellow); outline-offset: -3px; }

/*
 * A quiet affordance cue in the free top-left corner (::after is the "+").
 * Only collapsed panes carry it — once a pane is open the hint has done its
 * job, so it fades rather than flipping to different wording mid-animation.
 */
.re2 .re2-vm-ex::before {
  content: "Click to expand";
  position: absolute;
  top: 24px;
  left: 26px;
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: rgba(0, 0, 0, .48);
  white-space: nowrap;
  opacity: 1;
  transition: opacity .3s;
  pointer-events: none;
}

.re2 .re2-vm-ex.is-open::before { opacity: 0; }

@media (max-width: 1024px) {
  /* The 52px standoff is sized for a wide three-across band sitting under a
     centred title. Once the panes stack it just reads as dead space. */
  .re2 .re2-vm { min-height: 0; margin-top: 26px; }
  .re2 .re2-vm-pane, .re2 .re2-vm-ex, .re2 .re2-vm-ex.is-open, .re2 .re2-vm-static { flex: 1 1 auto !important; }
  .re2 .re2-vm-title .elementor-heading-title { white-space: normal; }
  .re2 .re2-vm-body { max-height: none; opacity: 1; margin-top: 12px; }
  .re2 .re2-vm-body-scroll { padding-right: 0; }
  .re2 .re2-vm-ex::after { display: none; }
  /* Stacked panes show their bodies permanently, so there is nothing to expand. */
  .re2 .re2-vm-ex::before { display: none; }
}

@media (max-width: 767px) {
  .re2 .re2-vm { margin-top: 16px; }
  /* On phones every pane is stacked and fully shown, so the 170px scroll cap
     on whichever pane happens to carry .is-open just truncates it for no
     reason — let all bodies run their full height like the others do. */
  .re2 .re2-vm-ex.is-open .re2-vm-body { max-height: none; }
}

/* ============================================================
   ABOUT — Vision / Mission / Objectives (fused strip, one drawer)
   ============================================================ */

/*
 * One continuous neo-brutalist strip: three always-visible segments in a row
 * (no gaps, just a divider), sharing a single drawer beneath the whole strip.
 * re2-ui.js toggles .is-open/.is-active and swaps which .re2-vmx-panel shows —
 * there is only ever one drawer, so a short closed segment can never expose
 * blank space the way per-segment drawers used to.
 */
.re2 .re2-vmx {
  margin-top: 52px;
  border: 3px solid var(--black);
  border-radius: 16px;
  box-shadow: 8px 8px 0 var(--black);
  overflow: hidden;
  background: #fff;
}

.re2 .re2-vmx-head { display: flex; }

.re2 .re2-vmx-seg {
  position: relative;
  flex: 1 1 0;
  min-width: 0;
  padding: 28px 58px 28px 26px;
  cursor: pointer;
  border-right: 3px solid var(--black);
  transition: filter .15s;
}
.re2 .re2-vmx-seg:last-child { border-right: none; }
.re2 .re2-vmx-seg:hover { filter: brightness(1.06); }
.re2 .re2-vmx-seg:active { filter: brightness(.96); }

.re2 .re2-vmx-vision { background-color: var(--blue); }
.re2 .re2-vmx-mission { background-color: var(--red); }
.re2 .re2-vmx-objectives { background-color: var(--teal); }

.re2 .re2-vmx-icon { margin-bottom: 14px; }

.re2 .re2-vmx-title .elementor-heading-title {
  font-family: var(--font-head);
  font-size: 21px;
  font-weight: 800;
  letter-spacing: -.01em;
  color: var(--black);
}

.re2 .re2-vmx-seg::after {
  content: "+";
  position: absolute;
  top: 20px;
  right: 20px;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  background: #fff;
  border: 2.5px solid var(--black);
  box-shadow: 3px 3px 0 var(--black);
  font-family: var(--font-head);
  font-weight: 700;
  font-size: 20px;
  line-height: 30px;
  text-align: center;
  color: var(--black);
  transition: transform .4s cubic-bezier(.34, 1.56, .64, 1), background .25s, box-shadow .15s;
}
.re2 .re2-vmx-seg.is-active::after { transform: rotate(135deg); background: var(--yellow); }
.re2 .re2-vmx-seg:active::after { box-shadow: 1px 1px 0 var(--black); }
.re2 .re2-vmx-seg:focus-visible { outline: 3px solid var(--yellow); outline-offset: -3px; }

.re2 .re2-vmx-drawer {
  max-height: 0;
  opacity: 0;
  overflow: hidden;
  border-top: 0 solid var(--black);
  transition: max-height .5s cubic-bezier(.34, 1.2, .64, 1), opacity .4s, border-top-width .1s;
}
.re2 .re2-vmx.is-open .re2-vmx-drawer { max-height: 280px; opacity: 1; border-top-width: 3px; }

.re2 .re2-vmx-drawer::before {
  content: "";
  display: block;
  height: 6px;
  background: var(--blue);
  transition: background .3s;
}
.re2 .re2-vmx-drawer[data-active="mission"]::before { background: var(--red); }
.re2 .re2-vmx-drawer[data-active="objectives"]::before { background: var(--teal); }

.re2 .re2-vmx-panel { display: none; padding: 22px 28px 26px; max-height: 250px; overflow-y: auto; }
.re2 .re2-vmx-panel.is-active { display: block; }
.re2 .re2-vmx-panel::-webkit-scrollbar { width: 5px; }
.re2 .re2-vmx-panel::-webkit-scrollbar-thumb { background: rgba(0, 0, 0, .25); border-radius: 3px; }

.re2 .re2-vmx-panel p { font-size: 15px; line-height: 1.65; color: rgba(0, 0, 0, .75); margin: 0; }
.re2 .re2-vmx-panel ul { margin: 0; padding-left: 18px; }
.re2 .re2-vmx-panel li { font-size: 14px; line-height: 1.55; margin-bottom: 10px; color: rgba(0, 0, 0, .75); }
.re2 .re2-vmx-panel li:last-child { margin-bottom: 0; }

.re2 .re2-vmx-panel-objectives ul { columns: 2; column-gap: 32px; }
.re2 .re2-vmx-panel-objectives li { break-inside: avoid; }

@media (max-width: 1024px) {
  .re2 .re2-vmx { margin-top: 26px; }
  .re2 .re2-vmx-head { flex-direction: column; }
  .re2 .re2-vmx-seg { border-right: none; border-bottom: 3px solid var(--black); }
  .re2 .re2-vmx-seg:last-child { border-bottom: none; }
}

@media (max-width: 767px) {
  .re2 .re2-vmx { margin-top: 16px; }
  .re2 .re2-vmx-panel-objectives ul { columns: 1; }
}

/* ============================================================
   ABOUT — Core Values
   ============================================================ */

.re2 .re2-value-card {
  position: relative;
  overflow: hidden;
  color: #1c1c1c;
  transition: transform .35s var(--ease), box-shadow .35s var(--ease);
}

/*
 * Fan-deal entrance. The cards start stacked and rotated as if held in one
 * hand, then spring into the row. They reuse the existing reveal observer, so
 * the transform has to beat .reveal's own translateY — hence the higher
 * specificity here and the !important on the resting state, which the
 * :nth-child rules would otherwise outweigh.
 */
.re2 .re2-value-card.re2-fan {
  opacity: 0;
  transform-origin: 50% 120%;
  transition: transform .95s var(--ease), opacity .55s ease;
}

.re2 .re2-values-row > .re2-fan:nth-child(1) { transform: translate(230%, 60px) rotate(-16deg); transition-delay: .05s; }
.re2 .re2-values-row > .re2-fan:nth-child(2) { transform: translate(112%, 30px) rotate(-8deg); transition-delay: .12s; }
.re2 .re2-values-row > .re2-fan:nth-child(3) { transform: translate(0, 14px) rotate(0); transition-delay: .19s; }
.re2 .re2-values-row > .re2-fan:nth-child(4) { transform: translate(-112%, 30px) rotate(8deg); transition-delay: .26s; }
.re2 .re2-values-row > .re2-fan:nth-child(5) { transform: translate(-230%, 60px) rotate(16deg); transition-delay: .33s; }

.re2 .re2-values-row > .re2-fan.is-visible { opacity: 1; transform: none !important; }

.re2 .re2-value-card.re2-fan:hover { transform: translateY(-10px) rotate(-1.5deg) !important; transition: transform .35s var(--ease); }

/*
 * The deal only works while all five cards share one row. Below the desktop
 * breakpoint they wrap two-up, and the fifth — dealt 230% of its own width to
 * the left of a half-width row — starts completely outside the viewport. The
 * reveal observer needs 12% of an element visible before it fires, so that
 * card never qualified, never got .is-visible, and sat at opacity 0 forever:
 * laid out, taking up space, invisible. A plain rise has no horizontal
 * component, so there is nothing to fall out of view.
 */
@media (max-width: 1024px) {
  .re2 .re2-value-card.re2-fan { transition: transform .6s var(--ease), opacity .45s ease; }

  .re2 .re2-values-row > .re2-fan:nth-child(1),
  .re2 .re2-values-row > .re2-fan:nth-child(2),
  .re2 .re2-values-row > .re2-fan:nth-child(3),
  .re2 .re2-values-row > .re2-fan:nth-child(4),
  .re2 .re2-values-row > .re2-fan:nth-child(5) {
    transform: translateY(26px) rotate(0);
  }

  .re2 .re2-values-row > .re2-fan:nth-child(1) { transition-delay: .04s; }
  .re2 .re2-values-row > .re2-fan:nth-child(2) { transition-delay: .10s; }
  .re2 .re2-values-row > .re2-fan:nth-child(3) { transition-delay: .16s; }
  .re2 .re2-values-row > .re2-fan:nth-child(4) { transition-delay: .22s; }
  .re2 .re2-values-row > .re2-fan:nth-child(5) { transition-delay: .28s; }
}

/* Stacked on a phone the fan would fling cards off-screen, so it is dropped. */
@media (max-width: 767px) {
  .re2 .re2-value-card.re2-fan { opacity: 1 !important; transform: none !important; }
}

@media (prefers-reduced-motion: reduce) {
  .re2 .re2-value-card.re2-fan { opacity: 1 !important; transform: none !important; transition: none; }
}

/* Faint ring bleeding off the bottom-left corner. */
.re2 .re2-value-card::after {
  content: "";
  position: absolute;
  left: -30px;
  bottom: -30px;
  width: 110px;
  height: 110px;
  border-radius: 50%;
  border: 16px solid rgba(0, 0, 0, .06);
  pointer-events: none;
}

.re2 .re2-value-num {
  position: absolute;
  top: 12px;
  right: 16px;
  width: auto !important;
  z-index: 2;
}

.re2 .re2-value-num .elementor-heading-title {
  font-family: var(--font-head);
  font-weight: 800;
  font-size: 44px;
  line-height: 1;
}

.re2 .re2-value-icon {
  width: 56px !important;
  height: 56px;
  border-radius: 15px;
  background: rgba(0, 0, 0, .1);
  display: grid;
  place-items: center;
  margin-bottom: 16px;
  position: relative;
  z-index: 2;
}

.re2 .re2-value-card .elementor-widget-heading:not(.re2-value-num) .elementor-heading-title { font-size: 17.5px; margin-bottom: 8px; }
.re2 .re2-value-card .elementor-widget-text-editor { font-size: 13.6px; position: relative; z-index: 2; }

/* ============================================================
   ABOUT — Learning approach hotspots
   ============================================================ */

.re2 .re2-hcard-stage { overflow: visible; }

.re2 .re2-hcard {
  position: relative;
  overflow: visible;
  max-width: 80vw;
  box-shadow: 0 30px 70px rgba(38, 66, 30, .22);
}

.re2 .re2-hcard-img { position: absolute; inset: 0; overflow: hidden; }
.re2 .re2-hcard-img img { width: 100%; height: 100%; object-fit: cover; display: block; }

/*
 * Each hotspot starts as a 64px disc and grows into a card. Hover opens it;
 * clicking pins it open, which is what makes it usable on touch where there is
 * no hover at all.
 */
.re2 .re2-hi {
  position: absolute;
  width: 64px !important;
  max-height: 64px;
  border-radius: 50% !important;
  overflow: hidden;
  cursor: pointer;
  z-index: 4;
  box-shadow: 5px 5px 0 var(--black);
  animation: re2PlusRing 2s var(--ease) infinite;
  transition: width .55s var(--ease), max-height .55s var(--ease), border-radius .4s, box-shadow .4s;
}

.re2 .re2-hi-1 { top: 16%; right: calc(100% - 32px); --ring: 113, 214, 192; }
.re2 .re2-hi-2 { bottom: 12%; left: calc(100% - 32px); --ring: 252, 138, 123; }

.re2 .re2-hi::after {
  content: "+";
  position: absolute;
  top: 0;
  left: 0;
  width: 58px;
  height: 58px;
  display: grid;
  place-items: center;
  font-family: var(--font-head);
  font-weight: 700;
  font-size: 32px;
  line-height: 1;
  color: #1c1c1c;
  animation: re2PlusAttention 2s var(--ease) infinite;
  transition: opacity .3s, transform .4s var(--ease);
}

.re2 .re2-hi > .elementor-element {
  opacity: 0;
  transform: translateY(14px);
  transition: opacity .35s ease, transform .35s ease;
}

.re2 .re2-hi:hover,
.re2 .re2-hi.is-open,
.re2 .re2-hi:focus-visible {
  width: min(370px, 86vw) !important;
  max-height: 560px;
  border-radius: 14px !important;
  box-shadow: 8px 8px 0 var(--black);
  animation: none;
}

.re2 .re2-hi:hover::after,
.re2 .re2-hi.is-open::after,
.re2 .re2-hi:focus-visible::after { opacity: 0; transform: rotate(90deg); animation: none; }

.re2 .re2-hi:hover > .elementor-element,
.re2 .re2-hi.is-open > .elementor-element,
.re2 .re2-hi:focus-visible > .elementor-element { opacity: 1; transform: none; transition-delay: .3s; }

.re2 .re2-hi:focus-visible { outline: 3px solid var(--blue-dark); outline-offset: 3px; }

.re2 .re2-hi-chip {
  width: 50px !important;
  height: 50px;
  border-radius: 13px;
  background: #fff !important;
  border: 0 !important;
  display: grid;
  place-items: center;
  margin-bottom: 18px;
}

.re2 .re2-hi-chip .elementor-icon { background: none !important; border: 0 !important; padding: 0 !important; }
.re2 .re2-hi > .elementor-widget-heading .elementor-heading-title { margin-top: 4px; line-height: 1.3; }

@keyframes re2PlusAttention {
  0%, 58%, 100% { transform: scale(1) rotate(0); }
  64% { transform: scale(1.22) rotate(-12deg); }
  70% { transform: scale(1.22) rotate(12deg); }
  76% { transform: scale(1.22) rotate(-8deg); }
  84% { transform: scale(1.08) rotate(0); }
}

/*
 * Two rings a beat apart, plus a scale on the disc itself. A single soft ring
 * was easy to miss against a busy photo, and nothing on the page tells you the
 * hotspot is interactive except this movement.
 */
@keyframes re2PlusRing {
  0% { box-shadow: 5px 5px 0 var(--black), 0 0 0 0 rgba(var(--ring), .95), 0 0 0 0 rgba(var(--ring), .55); transform: scale(1); }
  45% { transform: scale(1.06); }
  70% { box-shadow: 5px 5px 0 var(--black), 0 0 0 18px rgba(var(--ring), 0), 0 0 0 30px rgba(var(--ring), .18); }
  100% { box-shadow: 5px 5px 0 var(--black), 0 0 0 26px rgba(var(--ring), 0), 0 0 0 44px rgba(var(--ring), 0); transform: scale(1); }
}

@media (prefers-reduced-motion: reduce) {
  .re2 .re2-hi, .re2 .re2-hi::after { animation: none; }
}

@media (max-width: 900px) {
  .re2 .re2-hi-1 { right: calc(100% - 60px); }
  .re2 .re2-hi-2 { left: calc(100% - 60px); }
}

/*
 * From tablet down the hotspots hang off the edge of the screen, so the whole
 * device becomes plain stacked cards under a cropped photo. Touch has no
 * hover, and there is nothing left to discover once every card is already
 * open, so the disc, the plus, the attention ring and the expand all switch
 * off here.
 *
 * The open state has to be neutralised explicitly. `.re2-hi:hover` and
 * `.re2-hi.is-open` carry one more class-level than `.re2-hi`, so their
 * `width: min(370px, 86vw)` outranked the stacked `width: 100%` even from
 * inside this media query — whichever card the script had pinned open came out
 * a different width from its neighbour.
 */
@media (max-width: 1024px) {
  .re2 .re2-hcard {
    width: 100% !important;
    max-width: none;
    min-height: 0 !important;
    box-shadow: none;
  }

  .re2 .re2-hcard-img { position: relative !important; height: 420px; border-radius: 14px; }

  .re2 .re2-hi,
  .re2 .re2-hi:hover,
  .re2 .re2-hi.is-open,
  .re2 .re2-hi:focus-visible {
    position: relative !important;
    inset: auto !important;
    width: 100% !important;
    max-width: none !important;
    max-height: none;
    border-radius: 14px !important;
    margin-top: 14px;
    animation: none;
    box-shadow: 5px 5px 0 var(--black);
    cursor: default;
    transition: none;
  }

  .re2 .re2-hi::after { display: none; }

  .re2 .re2-hi > .elementor-element,
  .re2 .re2-hi:hover > .elementor-element,
  .re2 .re2-hi.is-open > .elementor-element {
    opacity: 1;
    transform: none;
    transition-delay: 0s;
  }
}

/* A phone is narrower, so the photo takes a shallower crop to stay in view. */
@media (max-width: 767px) {
  .re2 .re2-hcard-img { height: 320px; }
}

/*
 * A tablet has the width to sit the two cards side by side under the photo.
 * Grid rather than flex on purpose: Elementor drives container layout through
 * --display / --flex-direction custom properties at the same specificity this
 * rule can reach, so a flex-direction override is a coin toss on load order.
 * `display: grid` sidesteps that argument entirely, and stretch alignment
 * gives the two cards a matching height for free.
 */
@media (min-width: 768px) and (max-width: 1024px) {
  .re2 .re2-hcard {
    display: grid !important;
    grid-template-columns: 1fr 1fr;
    column-gap: 18px;
    row-gap: 0;
  }

  .re2 .re2-hcard-img { grid-column: 1 / -1; }

  /* The cards ride up over the bottom edge of the photo rather than sitting
     under it. Row-gap is zeroed so the negative margin is the only thing
     setting the overlap, and z-index lifts them clear of the image — they are
     later siblings, but the image carries its own stacking from the radius
     and clip. */
  .re2 .re2-hi,
  .re2 .re2-hi:hover,
  .re2 .re2-hi.is-open,
  .re2 .re2-hi:focus-visible {
    margin-top: -80px;
    z-index: 2;
  }
}

/* ============================================================
   CONTACT
   ============================================================ */

.re2 .re2-ci-card { transition: transform .45s var(--ease), box-shadow .45s var(--ease); }
.re2 .re2-ci-card:hover { transform: translateY(-8px); box-shadow: 0 22px 45px rgba(38, 66, 30, .16) !important; }

/* The tint behind each icon is a washed-out version of that card's accent, so
   the chip reads as part of the card rather than a second colour. */
.re2 .re2-ci-icon {
  width: 54px !important;
  height: 54px;
  border-radius: 15px;
  display: grid;
  place-items: center;
  margin-bottom: 12px;
}

.re2 .re2-ci-grid > .e-con:nth-child(1) .re2-ci-icon { background: rgba(252, 138, 123, .22); }
.re2 .re2-ci-grid > .e-con:nth-child(2) .re2-ci-icon { background: rgba(113, 214, 192, .28); }
.re2 .re2-ci-grid > .e-con:nth-child(3) .re2-ci-icon { background: rgba(186, 218, 85, .28); }

.re2 .re2-ci-card .elementor-widget-heading .elementor-heading-title { font-size: 17px; }

.re2 .re2-ci-card .elementor-widget-text-editor {
  font-size: 14.5px;
  color: var(--grey);
  line-height: 1.75;
  /* A shorter measure keeps the address to two tidy lines instead of running
     the full width of the card. */
  max-width: 30ch;
}

.re2 .re2-ci-card .elementor-widget-text-editor a { color: var(--grey); }
.re2 .re2-ci-card .elementor-widget-text-editor a:hover { color: var(--red); }

/* ---- Form shell ---- */

/*
 * The brand stripe is painted as a background layer rather than a pseudo-
 * element: ::before on a container belongs to Elementor's overlay, and the
 * white fill here comes from the builder as background-color, so a
 * background-image cannot collide with it.
 */
.re2 .re2-form-shell {
  position: relative;
  overflow: hidden;
  background-image: linear-gradient(90deg, var(--red), var(--teal), var(--blue));
  background-repeat: no-repeat;
  background-size: 100% 6px;
  background-position: left top;
}

.re2 .wpcf7 .submit-row { display: flex; align-items: center; gap: 18px; margin-top: 24px; flex-wrap: wrap; }

/* ---- Map ---- */

.re2 .re2-map {
  border-radius: var(--r-lg);
  overflow: hidden;
  box-shadow: 0 14px 34px rgba(38, 66, 30, .14);
  line-height: 0;
}

/* The dark edge was the browser's default iframe border, which Astra keeps. */
.re2 .re2-map .elementor-custom-embed,
.re2 .re2-map .elementor-widget-container { border-radius: var(--r-lg); overflow: hidden; line-height: 0; }

.re2 .re2-map iframe {
  border: 0 !important;
  outline: 0 !important;
  display: block;
  border-radius: var(--r-lg);
}

/* ---- Operating hours ---- */

.re2 .re2-hours-title .elementor-heading-title { font-size: 19px; display: flex; align-items: center; gap: 10px; }

.re2 .re2-hours-title .elementor-heading-title::before {
  content: "";
  width: 22px;
  height: 22px;
  flex: none;
  background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2'><circle cx='12' cy='12' r='10'/><path d='M12 6v6l4 2'/></svg>") no-repeat center / contain;
}

/* Astra puts a solid border on every table cell, which showed up as a grid
   through the panel. Everything is cleared first, then only the row rule
   returns. */
.re2 .re2-hours-table table,
.re2 .re2-hours-table th,
.re2 .re2-hours-table td { border: 0 !important; background: none !important; }

.re2 .re2-hours-table table { width: 100%; border-collapse: collapse; font-size: 14.5px; }
.re2 .re2-hours-table td { padding: 7px 0; border-bottom: 1px dashed rgba(0, 0, 0, .25) !important; }
.re2 .re2-hours-table tr:last-child td { border-bottom: 0; }

.re2 .re2-hours-table td:last-child {
  text-align: right;
  font-weight: 600;
  font-family: var(--font-head);
  font-size: 13.5px;
}

/* ---- Follow us ---- */

.re2 .re2-social-panel { position: relative; overflow: hidden; }

.re2 .re2-social-panel::after {
  content: "@";
  position: absolute;
  right: -10px;
  bottom: -34px;
  font-family: var(--font-head);
  font-weight: 800;
  font-size: 130px;
  line-height: 1;
  color: rgba(255, 255, 255, .06);
  pointer-events: none;
}

.re2 .re2-social-title .elementor-heading-title { font-size: 20px; }

/*
 * Two rows of text beside a fixed tile. A grid lets all three widgets stay
 * direct children of the container — wrapping the text in a fourth container
 * just to stack it would double the markup for no gain.
 */
.re2 .re2-social-row {
  display: grid !important;
  grid-template-columns: 38px 1fr;
  grid-template-rows: auto auto;
  column-gap: 14px;
  align-items: center;
  position: relative;
  z-index: 2;
  background: rgba(255, 255, 255, .07);
  border: 1px solid rgba(255, 255, 255, .12);
  transition: background .35s, transform .35s var(--ease);
}

.re2 .re2-social-row:hover { background: rgba(255, 255, 255, .15); transform: translateX(6px); }

.re2 .re2-social-ic {
  grid-row: 1 / 3;
  grid-column: 1;
  width: 38px !important;
  height: 38px;
  border-radius: 11px;
  display: grid;
  place-items: center;
}

.re2 .re2-social-1 .re2-social-ic { background: #1877F2; }
.re2 .re2-social-2 .re2-social-ic { background: linear-gradient(45deg, #f09433, #e6683c, #dc2743, #cc2366, #bc1888); }
.re2 .re2-social-3 .re2-social-ic { background: #0A66C2; }

.re2 .re2-social-name { grid-column: 2; grid-row: 1; align-self: end; }
.re2 .re2-social-name .elementor-heading-title { font-family: var(--font-head); font-weight: 600; font-size: 14.5px; }
.re2 .re2-social-name a { color: inherit; }

/* Elementor's container-level Link control renders nothing on a full-width
   container, so the anchor lives on the name and is stretched over the whole
   row. One real <a> keeps it keyboard-reachable and announced correctly. */
.re2 .re2-social-name a::after { content: ""; position: absolute; inset: 0; z-index: 3; }
.re2 .re2-social-handle { grid-column: 2; grid-row: 2; align-self: start; font-size: 12.5px; }
.re2 .re2-social-handle p { margin: 0; }

/*
 * A tablet is wide enough to keep the desktop shape: three info cards across,
 * and the form beside the map. Only the type and padding come down, so the
 * page reads the same on an iPad as it does on a laptop. Phones are the only
 * place anything stacks.
 */
@media (max-width: 1024px) {
  .re2 .re2-ci-card { padding: 22px 16px !important; }

  .re2 .re2-ci-icon {
    width: 46px !important;
    height: 46px;
    border-radius: 13px;
    margin-bottom: 10px;
  }

  .re2 .re2-ci-card .elementor-widget-heading .elementor-heading-title { font-size: 15px; }

  /* The measure that keeps the address tidy on desktop is wider than the card
     itself here, and an email address has no break point of its own. */
  .re2 .re2-ci-card .elementor-widget-text-editor {
    font-size: 13px;
    line-height: 1.65;
    max-width: none;
    overflow-wrap: anywhere;
  }

  .re2 .re2-contact-side .re2-hours,
  .re2 .re2-contact-side .re2-social-panel { padding: 24px 20px !important; }

  .re2 .re2-hours-table table { font-size: 13.5px; }
  .re2 .re2-hours-table td:last-child { font-size: 12.5px; }
  .re2 .re2-social-handle { font-size: 11.5px; overflow-wrap: anywhere; }
}

@media (max-width: 767px) {
  .re2 .re2-contact-left, .re2 .re2-contact-side { width: 100% !important; }
  .re2 .re2-ci-card { padding: 26px 22px !important; }
  .re2 .re2-ci-card .elementor-widget-text-editor { font-size: 14px; }
}

/* Very narrow phones: the header now carries a logo, two links and the CTA on
   one nowrap row, so everything steps down once more rather than overflowing. */
@media (max-width: 360px) {
  .re2 .re2-logo img { width: 80px; }
  .re2 .re2-nav .jet-nav__item > .menu-item-link { padding: 5px 5px; font-size: 12px; }
  .re2 .re2-header .elementor-widget-button.btn .elementor-button { padding: 8px 11px; font-size: 11px; }
}

/* ============================================================
   NO HORIZONTAL SCROLL (re2-no-h-scroll)
   ============================================================

   Several sections deliberately bleed past their container: the dotted
   flourish on the Who We Are photo, the overlapping second image, the ring on
   a value card, the @ behind Follow Us. On desktop the page gutters absorb
   that. On a tablet or phone the gutters are 40px and 20px, so the same
   decorations poke past the viewport, the document grows wider than the
   screen, and every full-width band stops short of the scroll width - which
   is the empty strip down the right-hand side.

   `clip` rather than `hidden` on purpose: `overflow: hidden` turns the element
   into a scroll container, which silently kills `position: sticky` on the
   header. `clip` trims the overflow without that side effect.
   ============================================================ */

@media (max-width: 1024px) {
  html { overflow-x: clip; }
  body { overflow-x: clip; max-width: 100%; }
}

/*
 * Footer on a phone.
 *
 * Quick Links and Contact Us sit side by side rather than stacking, so each
 * column is only ~46% of a narrow screen. The contact list carries a full
 * street address and an email that has no natural break point, so the type
 * steps down and long strings are allowed to break mid-word — otherwise the
 * email pushes its own column wider and the pair wraps again, which is the
 * thing this layout is meant to stop.
 */
@media (max-width: 767px) {
  .re2 .re2-footer .elementor-icon-list-item,
  .re2 .re2-footer .elementor-icon-list-item a { font-size: 12.5px; line-height: 1.55; }

  .re2 .re2-footer .elementor-icon-list-text { overflow-wrap: anywhere; }
  .re2 .re2-footer .elementor-icon-list-icon { margin-top: 3px; }
  .re2 .re2-footer .elementor-icon-list-icon svg,
  .re2 .re2-footer .elementor-icon-list-icon i { font-size: 11px; }

  /* The centred brand block reads as one unit, so the social row centres with
     it rather than hugging the left edge it no longer has. */
  .re2 .re2-footer .elementor-social-icons-wrapper { justify-content: center; }
}

/*
 * The wrapped stair row on tablet.
 *
 * The lead panel takes the full width and the other two share the line below
 * it. Those two carry different amounts of copy — one title wraps to two lines
 * and the other does not — so left alone they size independently and the row
 * ends on a ragged edge. Stretch is forced rather than inherited because
 * Elementor drives container alignment through --align-items, which an
 * unset control leaves empty; relying on the flex default here means relying
 * on nothing being set, which is not a guarantee worth depending on.
 */
@media (min-width: 768px) and (max-width: 1024px) {
  .re2 .re2-stair { align-items: stretch !important; }
  .re2 .re2-stair > .re2-stair-panel { align-self: stretch !important; }
}

/*
 * Programme cards on tablet.
 *
 * The copy block is capped at 62% of the card so it clears the arrow sitting
 * bottom-right. On desktop that leaves a comfortable measure; on a 330px
 * tablet card it leaves about 205px, which is why the description was running
 * to six short lines and colliding with both the badge above it and the arrow
 * beside it.
 *
 * Moving the arrow to the top-right frees the entire bottom of the card, so
 * the copy can use the full width. Badge left, arrow right, text beneath —
 * the same three elements, arranged for a narrow card rather than a wide one.
 */
@media (max-width: 1024px) {
  .re2 .re2-prog-content { max-width: 100%; }

  .re2 .re2-prog-arrow {
    top: 20px;
    right: 20px;
    bottom: auto;
  }

  .re2 .re2-prog-arrow .elementor-button { width: 52px; height: 52px; }
  .re2 .re2-prog-arrow .elementor-button svg { width: 21px; height: 21px; }
}

/*
 * Programme card overlay below desktop.
 *
 * The overlay is a gradient at 100deg — solid brand colour on the left, fading
 * to 12% alpha on the right. That is aimed at the desktop layout, where the
 * copy is capped at 62% and sits entirely in the solid half. Once the copy
 * runs the full width of the card, its right-hand end lands on bare photo and
 * stops being readable.
 *
 * Rotating the gradient to run bottom-to-top puts the solid colour under the
 * whole text block instead of one side of it, and keeps the photo legible
 * across the top where only the badge and arrow sit.
 *
 * ::before on an Elementor container IS the background-overlay element, so
 * only background-image is overridden here — everything else about the
 * overlay, including the opacity the builder controls, is left alone.
 */
@media (max-width: 1024px) {
  .re2 .re2-prog-card:nth-child(1)::before {
    background-image: linear-gradient(0deg, #FC8A7B 0%, #FC8A7B 46%, rgba(252, 138, 123, .12) 100%) !important;
  }

  .re2 .re2-prog-card:nth-child(2)::before {
    background-image: linear-gradient(0deg, #BADA55 0%, #BADA55 46%, rgba(186, 218, 85, .12) 100%) !important;
  }
}

/*
 * Learn tiles: solid fill on hover.
 *
 * All four tiles now carry a photo, so the alternating white/photo rhythm the
 * original used in a single row of four is gone — it only ever read as rhythm
 * unwrapped, and turned into a white column beside a photo column the moment
 * the row broke to 2x2.
 *
 * Hover swaps the photo for a flat brand fill. ::after is used rather than
 * ::before because ::before on an Elementor container is its background
 * overlay, which is already carrying the dark tint that makes the copy legible
 * at rest. The fill sits at z-index 1, under the icon and copy at z-index 2.
 *
 * The fill is the deep green rather than the salmon: white type on #5C8718
 * clears AA, white on #FC8A7B does not, and the whole point of the state is
 * that the words stay readable when the photograph disappears.
 */
.re2 .re2-learn-tile::after {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--e-global-color-primary, #FC8A7B);
  opacity: 0;
  transition: opacity .4s var(--ease);
  z-index: 1;
  pointer-events: none;
}

.re2 .re2-learn-tile:hover::after { opacity: 1; }

/*
 * The fill is RE2 Pink straight from the kit's global colours, so it stays in
 * step if that swatch is ever edited in the builder. White type does not clear
 * AA on it — about 2:1 — so the copy flips to black for the hover state, which
 * is how the salmon is treated everywhere else on the site.
 */
.re2 .re2-learn-tile:hover .elementor-widget-heading .elementor-heading-title { color: var(--black) !important; }
.re2 .re2-learn-tile:hover .elementor-widget-text-editor { color: rgba(0, 0, 0, .8) !important; }
.re2 .re2-learn-tile:hover .re2-learn-icon .elementor-icon { color: var(--black) !important; }
.re2 .re2-learn-tile:hover .re2-learn-icon .elementor-icon svg { fill: var(--black) !important; stroke: var(--black); }

/* Every tile is a photo tile now, so the type is white across the board. The
   builder writes per-widget colours at a specificity this cannot beat on
   selector weight alone. */
.re2 .re2-learn-tile .elementor-widget-heading .elementor-heading-title { color: #fff !important; }
.re2 .re2-learn-tile .elementor-widget-text-editor { color: rgba(255, 255, 255, .92) !important; }

/*
 * Programme card: the code line on a phone.
 *
 * The overlay runs solid to 46% of the card height, which covers the title and
 * description. On a 330px-tall mobile card the copy block is proportionally
 * taller, so the code sits just above that line, in the part of the gradient
 * that has already started fading — grey type at 65% opacity over a
 * photograph, which is effectively invisible.
 *
 * The solid band is extended to clear the whole copy block, and the code is
 * darkened to sit closer to the title it labels.
 */
@media (max-width: 767px) {
  .re2 .re2-prog-card:nth-child(1)::before {
    background-image: linear-gradient(100deg, rgba(252, 138, 123, 1) 0%, rgba(252, 138, 123, .94) 55%, rgba(252, 138, 123, .58) 100%) !important;
  }

  .re2 .re2-prog-card:nth-child(2)::before {
    background-image: linear-gradient(100deg, rgba(186, 218, 85, 1) 0%, rgba(186, 218, 85, .94) 55%, rgba(186, 218, 85, .58) 100%) !important;
  }

  .re2 .re2-prog-code .elementor-heading-title { color: rgba(0, 0, 0, .9); font-weight: 500; }
}

/*
 * The step rows keep the title beside its number.
 *
 * A container defaults to flex-wrap: wrap, so the moment a title was long
 * enough not to fit on one line it was pushed below the number entirely -
 * step 01 broke, step 02 did not, purely on string length. The row is set to
 * nowrap and the title is allowed to shrink instead: a flex item will not go
 * below its content's intrinsic width unless min-width is cleared, which is
 * what would otherwise force the overflow the wrap was hiding.
 * (re2-step: keep the title beside its number)
 */
.re2 .re2-step > .elementor-widget-heading:not(.re2-step-num) { min-width: 0; }
.re2 .re2-step > .re2-step-num { flex: none; }

/*
 * Footer column headings sit close to their lists.
 *
 * Elementor writes a widget's margin as
 * `calc(var(--kit-widget-spacing) + <your value>)`, and this kit sets that
 * variable to 20px. So the 2px bottom margin set on "Quick Links" and
 * "Contact Us" was really 22px, plus the column's own gap on top of it - the
 * builder value alone could never close the gap.
 *
 * A flat margin here ignores the kit variable entirely; the column gap then
 * provides the whole of the spacing, which is what makes it predictable.
 */
@media (max-width: 1024px) {
  .re2 .re2-footer .elementor-widget-heading { margin-bottom: 0 !important; }
}
