@charset "UTF-8";
/* --------------------------------------------------------------------------
   1. Variables
   -------------------------------------------------------------------------- */
:root {
  --v-ink:       #071d27; /* dark teal — dominant dark ground */
  --v-cream:     #f2d4af; /* headline + body text on dark */
  --v-blue:      #50a1bf; /* eyebrows / accents on dark */
  --v-blue-mid:  #2c75a6; /* mid-blue section ground */
  --v-red:       #ee3624; /* CTAs, active states */
  --v-white:     #fff;
  --v-gray:      #222;    /* body text on white — matches the theme's default */

  --v-font: 'Gotham A', 'Gotham B', 'Helvetica Neue', Arial, sans-serif;

  /* Type scale — Zeplin sizes, fluid between mobile and the 1440 comp */
  --v-fs-eyebrow: 14px;
  --v-fs-body:    17px;
  --v-fs-lead:    22px;
  --v-fs-h3:      clamp(26px, 2.6vw, 36px);
  --v-fs-h2:      clamp(36px, 4.6vw, 64px);
  --v-fs-display: clamp(52px, 8.4vw, 120px);

  --v-shell:   1200px; /* content column on the 1440 comp */
  --v-gutter:  120px;  /* comp side margin: (1440 - 1200) / 2 */
  --v-gap:     24px;   /* card gap throughout */
  --v-radius:  8px;
}

*, *::before, *::after { box-sizing: border-box; }

body.vision-page {
  margin: 0;
  padding: 0;
  background: var(--v-ink);
  color: var(--v-white);
  font: 400 var(--v-fs-body)/28px var(--v-font);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
}

/* The element part of each reset is wrapped in :where(), which adds no
   specificity — so these weigh (0,1,0), the same as a single component class,
   and lose to every component rule below on source order.
   Without it, `.vision-page p` would be (0,1,1) and silently outrank
   .v-eyebrow / .v-hero__lede / .v-commitments__figure etc., zeroing their
   margins. Same trap the .v-btn--* colours hit. */
.vision-page :where(img) { max-width: 100%; height: auto; display: block; }
.vision-page :where(h1, h2, h3, h4, p) { margin: 0; }
.vision-page :where(ul) { margin: 0; padding: 0; list-style: none; }
.vision-page :where(a) { color: inherit; text-decoration: none; transition: background-color .3s ease, color .3s ease, border-color .3s ease, opacity .3s ease; }

.visually-hidden {
  position: absolute !important;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}
.visually-hidden:focus {
  position: static !important;
  width: auto; height: auto;
  margin: 0; padding: 12px 20px;
  clip: auto;
  background: var(--v-red);
  color: var(--v-white);
}

/* --------------------------------------------------------------------------
   2. Shared primitives
   -------------------------------------------------------------------------- */
.v-shell {
  width: 100%;
  max-width: var(--v-shell);
  margin: 0 auto;
  padding: 0 24px;
}
.v-shell--narrow { max-width: 1064px; }

.v-section { padding: 72px 0; }

.v-eyebrow {
  margin: 0 0 16px;
  font-size: 14px;
  font-weight: 700;
  line-height: 1.14;
  letter-spacing: .16px;
  text-transform: uppercase;
  color: var(--v-blue);
}
.v-eyebrow--ink   { color: var(--v-ink); }
.v-eyebrow--blue   { color: var(--v-blue); }
.v-eyebrow--wide  { letter-spacing: .18em; font-size: 12px; }

.v-h2 {
  font-size: var(--v-fs-h2);
  font-weight: 700;
  line-height: 1.06;
  letter-spacing: -.05em;
}
/* Display-size red title, left-aligned — the 1-5-10-20 figure's type, reused
   on the Vision quote and the This Fall / What's Ahead / Resources h2s. The
   figure is a single line and keeps its tighter .84 leading (see section 6);
   the titles can wrap, so they get .9 to keep wrapped lines from touching. */
.v-h2--display,
.v-commitments__figure {
  font-size: var(--v-fs-display);
  font-weight: 700;
  line-height: .9;
  letter-spacing: -.087em;
  color: var(--v-red);
}
.v-h3 {
  font-size: var(--v-fs-h3);
  font-weight: 700;
  line-height: 1.22;
  letter-spacing: -.05em;
}
/* 22px/32 bold. Only The Vision's two pull paragraphs use this. */
.v-lead {
  font-size: var(--v-fs-lead);
  font-weight: 700;
  line-height: 32px;
  letter-spacing: -.03em;
}
/* 17px/28 bold — the emphasised intro lines in This Fall, Welcome Home and
   Reach One Labs. Same size as body copy, just bolder; NOT .v-lead. */
.v-body--strong {
  font-size: var(--v-fs-body);
  font-weight: 700;
  line-height: 28px;
}
.v-body + .v-body,
.v-body + .v-body--strong,
.v-body--strong + .v-body,
.v-body + .v-lead,
.v-lead + .v-body { margin-top: 28px; }

/* Buttons — radius 8, 48–52px tall, per the comp */
.v-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  min-height: 48px;
  padding: 13px 28px;
  border: 2px solid transparent;
  border-radius: var(--v-radius);
  font-size: var(--v-fs-body);
  font-weight: 700;
  line-height: 21px;
  letter-spacing: -.04em;
  text-transform: uppercase;
  cursor: pointer;
}
/* Scoped with .vision-page so these beat `.vision-page a { color: inherit }`
   above — a bare .v-btn--* modifier loses to it on specificity (0,1,0 vs 0,1,1)
   and the button silently inherits its parent's text colour. */
.vision-page .v-btn--light { background: var(--v-white); border-color: var(--v-white); color: var(--v-ink); }
.vision-page .v-btn--light:hover { background: transparent; color: var(--v-white); }

.vision-page .v-btn--ghost { background: transparent; border-color: var(--v-white); color: var(--v-white); }
.vision-page .v-btn--ghost:hover { background: var(--v-white); color: var(--v-ink); }

.vision-page .v-btn--red { background: var(--v-red); border-color: var(--v-red); color: var(--v-white); }
.vision-page .v-btn--red:hover { background: transparent; color: var(--v-red); }

.vision-page .v-btn--ink { background: var(--v-ink); border-color: var(--v-ink); color: var(--v-white); }
.vision-page .v-btn--ink:hover { background: transparent; color: var(--v-ink); }
/* Inline <svg>, stroked with currentColor — it inherits the button's text
   colour, so hover states recolour the icon along with the label for free. */
.v-btn__icon { width: 24px; height: 24px; flex: none; display: block; }

/* --------------------------------------------------------------------------
   3. Hero
   -------------------------------------------------------------------------- */
.v-hero {
  position: relative;
  min-height: 762px;
  display: flex;
  align-items: center;
  overflow: hidden;
  background: var(--v-ink);
}
.v-hero__media {
  position: absolute;
  inset: 0;
}
.v-hero__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
/* Background video sits over the poster image and fills the panel. It stays at
   opacity 0 until JS injects a <source> (desktop only), so on phones — where no
   source is ever added — the image simply shows through. */
.v-hero__video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  transition: opacity .6s ease;
  pointer-events: none;
}
.v-hero__video[data-loaded] { opacity: 1; }
/* Zeplin ships this as a "Gradient" shape over the poster */
.v-hero__media::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg, rgba(7,29,39,.92) 0%, rgba(7,29,39,.72) 45%, rgba(7,29,39,.25) 100%);
}
.v-hero__inner {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: 850px;
  margin: 0 auto;
  padding: 0 24px;
  /* Rises and fades in on load. `both` holds the start frame before the delay
     so there's no flash of final-position content first. If @keyframes were
     ever unsupported the shorthand is simply ignored and the content renders
     normally — it can't get stuck invisible.
     The reduced-motion block near the end of this file collapses the duration,
     so those users get the finished state immediately. */
  animation: v-hero-rise .9s cubic-bezier(.22, .68, .3, 1) .15s both;
}
@keyframes v-hero-rise {
  from { opacity: 0; transform: translateY(28px); }
  to   { opacity: 1; transform: none; }
}

/* --------------------------------------------------------------------------
   Scroll reveal
   Anything marked .js-reveal slides up and fades in the first time it enters
   the viewport. The hidden state is scoped to .has-js (set in the <head>) so a
   visitor without scripting sees the content normally instead of a blank
   section. The reduced-motion block at the end of this file collapses the
   transition, so those users get the finished state with no movement.
   -------------------------------------------------------------------------- */
.has-js .js-reveal {
  opacity: 0;
  transform: translateY(28px);
  transition: opacity .9s cubic-bezier(.22, .68, .3, 1),
              transform .9s cubic-bezier(.22, .68, .3, 1);
  /* Siblings that should arrive one after another set --reveal-delay inline
     (see the This Fall cards); everything else falls back to no delay. */
  transition-delay: var(--reveal-delay, 0s);
  will-change: opacity, transform;
}
.has-js .js-reveal.is-revealed {
  opacity: 1;
  transform: none;
  will-change: auto;
}
/* Horizontal variant — enters from the right. Used on the carousels, where a
   sideways entry echoes the direction they scroll. Safe against the page's
   width because body.vision-page already clips overflow-x. */
.has-js .js-reveal--x {
  transform: translateX(72px);
}
.v-hero h1 {
  max-width: 12ch;
  margin: 0 0 32px;
  font-size: var(--v-fs-display);
  font-weight: 700;
  line-height: .84;
  letter-spacing: -.064em;
  text-transform: uppercase;
  color: var(--v-cream);
}
.v-hero__lede {
  max-width: 60ch;
  margin: 0 0 48px;
  color: var(--v-white);
}
.v-hero__actions { display: flex; flex-wrap: wrap; gap: 16px; }

/* --------------------------------------------------------------------------
   4. Sticky section nav
   -------------------------------------------------------------------------- */
.v-sectionnav {
  position: sticky;
  top: 0;
  z-index: 20;
  background: var(--v-ink);
  border-bottom: 1px solid rgba(242,212,175,.14);
}
.v-sectionnav ul {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 8px;
  padding: 16px 24px;
}
.v-sectionnav a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 11px 26px;
  border: 2px solid rgba(242, 212, 175, 0.22);
  border-radius: var(--v-radius);
  font-size: var(--v-fs-body);
  font-weight: 700;
  line-height: 22px;
  letter-spacing: -.04em;
  text-transform: uppercase;
  color: var(--v-white);
}
.v-sectionnav a:hover { border-color: var(--v-blue); }
.v-sectionnav a.is-active { background: var(--v-red); border-color: var(--v-red); }

/* --------------------------------------------------------------------------
   5. Section 3 — The Vision
   -------------------------------------------------------------------------- */
.v-vision { background: var(--v-ink); color: var(--v-cream); }
.v-vision .v-shell { max-width: 760px; }
.v-vision blockquote {
  margin: 0 0 40px;
  max-width: 22ch;
}
.v-vision .v-body { max-width: 68ch; }

/* Rich-text output from any panel WYSIWYG field. Paragraphs come back without classes, so
   rhythm is structural; a paragraph the editor marks as `v-lead` still picks up
   the global 22px lead rule. The base reset strips list markers and link
   underlines, so both are restored inside editor content only. */
.v-rte > * + * { margin-top: 28px; }
.v-rte ul,
.v-rte ol { padding-left: 24px; list-style: revert; }
.v-rte li + li { margin-top: 8px; }
.v-rte a { text-decoration: underline; }
.v-rte a:hover { color: var(--v-red); }
.v-rte strong { font-weight: 700; }
.v-rte em { font-style: italic; }
.v-rte blockquote {margin:28px 0 0; max-width:none; padding-left:24px; border-left:4px solid var(--v-red);}

.v-vision__close {
  margin-top: 40px;
  font-size: var(--v-fs-h3);
  font-weight: 700;
  line-height: 44px;
  letter-spacing: -.06em;
  color: var(--v-red);
}

/* --------------------------------------------------------------------------
   6. Section 4 — 1-5-10-20 commitments
   -------------------------------------------------------------------------- */
.v-commitments { background: var(--v-cream); color: var(--v-ink); }
.v-commitments__figure {
  margin: 0 0 64px;
  line-height: .84;
}
.v-commitments .v-carousel__head { color: var(--v-ink); }

.v-commit-card {
  position: relative;
  height: 535px;
  border-radius: 16px;
  overflow: hidden;
  display: flex;
  align-items: flex-end;
  background: var(--v-ink);
}
.v-commit-card img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.v-commit-card::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(7,29,39,0) 35%, rgba(7,29,39,.88) 100%);
}
.v-commit-card__body {
  position: relative;
  z-index: 1;
  padding: 32px;
  color: var(--v-white);
}
.v-commit-card__body h3 {
  margin: 0 0 8px;
  font-size: var(--v-fs-lead);
  font-weight: 500;
  line-height: 32px;
  letter-spacing: -.034em;
}

/* --------------------------------------------------------------------------
   7. Section 5 — This Fall
   -------------------------------------------------------------------------- */
.v-thisfall { background: var(--v-white); color: var(--v-gray); }
.v-thisfall__intro { max-width: 1064px; margin: 0 auto 96px; text-align: left; }
/* The 96px only separates the intro from the boxes; with p3_show_boxes off the
   intro is the shell's last child and the section padding does the job. */
.v-thisfall__intro:last-child { margin-bottom: 0; }
.v-thisfall__intro .v-h2 { margin-bottom: 32px; }
/* Left-aligned by default (inherited from the intro). The WYSIWYG writes
   style="text-align: center" inline when an editor centres a paragraph, and
   that beats any class rule here — so no override is needed for CMS centring. */
.v-thisfall_content { max-width: 754px; margin-inline: 0; }
/* This panel spaces paragraphs 24px rather than the 28px .v-rte default.
   The inherited top margin has to be zeroed first — otherwise the two margins
   collapse to the larger of the pair and the gap stays 28px.
   Declared after .v-rte (line 286) so it wins the (0,1,0) tie on source order. */
.v-thisfall_content > * + * { margin-top: 0; }
.v-thisfall_content p { margin-bottom: 24px; }
.v-thisfall_content p:last-child { margin-bottom: 0; }

.v-steps {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--v-gap);
}
.v-step {
  display: flex;
  flex-direction: column;
  gap: 20px;
  min-height: 400px;
  padding: 40px;
  border-radius: 16px;
}
.v-step--light { background: var(--v-cream); color: var(--v-ink); }
.v-step--l-blue { background: var(--v-blue); color: var(--v-ink); }
.v-step--dark  { background: var(--v-ink);  color: var(--v-white); }
.v-step--dark .v-eyebrow { color: var(--v-white); margin:0 0 16px;}
.v-step h3 { margin: 0; }
.v-step .v-btn { align-self: flex-start; margin-top: auto; }

/* --------------------------------------------------------------------------
   8. Welcome Home band (sections 6–7 — one band in the source)
   -------------------------------------------------------------------------- */
.v-welcome { background: var(--v-white); color: var(--v-gray); }
/* (0,2,0) so it also beats the 56px .v-section override in the mobile query. */
.v-section.v-welcome { padding-top: 0; }
/* Left-aligned like Panel 3. Editor-centred paragraphs still centre: the
   WYSIWYG writes style="text-align: center" inline, which beats these rules. */
.v-welcome__intro { text-align: left; max-width: 1064px; margin: 0 auto 56px; }
.v-welcome__intro .v-h2 { margin-bottom: 24px; }
.v-welcome__intro .v-body--strong { max-width: 50ch; margin: 0 0 24px; }
.v-welcome__intro .v-body { max-width: 76ch; margin: 0; }
.v-welcome__main {max-width:650px; margin:0;}
/* The editor's "Highlight paragraph" format applies .v-lead (22px/32), but this
   panel's emphasised line is 17px/28 in the comp. (0,2,0) beats the global
   .v-lead. Side margins are zero so the narrow measure shares the intro's left edge. */
.v-welcome__main .v-lead {
  max-width: 412px;
  margin-left: 0;
  margin-right: 0;
  font-size: var(--v-fs-body);
  line-height: 28px;
}

/* Enhancement card — the comp's Article is 1200x454, radius 24, with every
   element centred and spaced a uniform 24px apart. The nav buttons belong
   visually inside the card, so they're a sibling of .swiper-container
   positioned over it (one nav for all slides, not one per slide). */
.v-enh-carousel { position: relative; }
/* (0,3,0) to beat `.v-carousel .swiper-container { padding: 8px 24px }` further
   down — that 24px side padding would inset this card 48px narrower than every
   other section's content column. No peeking slide here, so no padding wanted. */
.v-welcome .v-enh-carousel .swiper-container { padding: 0; width: 100%; flex: 1 1 auto; }
/* (0,3,0) so it beats `.v-carousel .swiper-slide { width: 384px }` further down,
   which would otherwise shrink these full-width slides to a 384px column. */
.v-welcome .swiper-slide.v-enh__slide { width: 100%; height: auto; }

/* The card is a static shell: kicker, counter and arrows live here, and only
   .v-enh__slide is swapped by Swiper. The swiper area flex-grows so the arrows
   stay put regardless of how tall the active slide's copy is. */
.v-enhancement {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 24px;
  min-height: 454px;
  padding: 40px 48px;
  border-radius: 24px;
  background: var(--v-ink);
  color: var(--v-white);
  text-align: center;
}
.v-enh__slide {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 24px;
}
.v-enh__kicker {
  font-size: var(--v-fs-h3);
  font-weight: 700;
  line-height: 44px;
  letter-spacing: -.06em;
  text-transform: uppercase;
  color: var(--v-blue);
}
.v-enh__count {
  font-size: var(--v-fs-eyebrow);
  font-weight: 700;
  line-height: 16px;
  letter-spacing: .16em;
  color: var(--v-blue);
}
.v-enh__title {
  font-size: var(--v-fs-h3);
  font-weight: 700;
  line-height: 44px;
  letter-spacing: -.06em;
  color: var(--v-white);
}
.v-enh__body { max-width: 450px; color: var(--v-white); }

/* Now a normal flex child at the foot of the card rather than absolutely
   positioned — the shell keeps it in place on its own. */
.v-enh-nav {
  display: flex;
  gap: 24px;
  flex: none;
  color: var(--v-white);
}

.v-enhancement a.v-inline {
  font-weight: 700;
  line-height: 28px;
  color: var(--v-white);
}
.v-enhancement a.v-inline:hover { color: var(--v-red); text-decoration: underline; }

.v-involve { text-align: center; max-width: 1064px; margin: 64px auto 48px; }
/* Both lines above the prompt are 22px/32 regular in the comp — not headings. */
.v-involve__body { font-size: var(--v-fs-lead); line-height: 1.45; letter-spacing: -.08em; max-width: 56ch; margin: 0 auto 32px; }
/* p4_bottom_content arrives as class-less editor paragraphs — give them the
   same 22px treatment .v-involve__body used to carry. */
.v-involve__content p { font-size: var(--v-fs-lead); line-height: 1.45; letter-spacing: -.08em; max-width: 56ch; margin-left: auto; margin-right: auto; }
.v-involve__content + .v-involve__prompt { margin-top: 32px; }
.v-involve__prompt { font-size: var(--v-fs-lead); font-weight: 700; line-height:1.45; letter-spacing: -.08em; color: var(--v-ink); }

.v-involve-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--v-gap);
}
/* Colour is set here rather than inherited — the section ground is white/gray. */
.v-involve-card { border-radius: var(--v-radius); overflow: hidden; background: var(--v-ink); color: var(--v-white); }
.v-involve-card img { width: 100%; height: 392px; object-fit: cover; }
.v-involve-card__body { padding: 40px; display: flex; flex-direction: column; gap: 16px; }
.v-involve-card__body h3 {
  margin: 0;
  font-size: var(--v-fs-lead);
  font-weight: 500;
  line-height: 32px;
  letter-spacing: -.08em;
}
.v-involve-card .v-btn { align-self: flex-start; margin-top: 8px; }

/* --------------------------------------------------------------------------
   9. Section 8 — Reach One Labs
   -------------------------------------------------------------------------- */
.v-labs { background: var(--v-ink); color: var(--v-cream); }
.v-labs__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 64px;
  align-items: center;
}
.v-labs__grid .v-h2 { margin-bottom: 24px; }
.v-labs__list {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 16px 32px;
  margin: 64px 0;
}
.v-labs__list li {
  display: flex;
  align-items: center;
  gap: 16px;
  font-size: var(--v-fs-lead);
  font-weight: 700;
  line-height: 22px;
  letter-spacing: -.034em;
}
.v-labs__list img { width: 32px; height: 32px; flex: none; }

/* Editor content. The comp's emphasised intro line here is 17px/28 bold, so the
   "Highlight paragraph" format (.v-lead, 22px) is scaled back in this panel —
   same treatment as .v-welcome__main. */
.v-labs__top .v-lead { font-size: var(--v-fs-body); line-height: 28px; }
/* Same row treatment as .v-hero__actions: side by side, left-aligned, wrapping on narrow screens. */
.v-labs__cta { margin-top: 32px; display: flex; flex-wrap: wrap; justify-content: flex-start; gap: 16px; }
.v-labs__bottom {padding-bottom:16px;}
.v-labs__media { display: grid; gap: var(--v-gap); }
.v-labs__media img { border-radius:18px; width: 100%; object-fit: cover; }

/* --------------------------------------------------------------------------
   10. Section 9 — Looking Ahead
   -------------------------------------------------------------------------- */
.v-ahead { background-color: var(--v-white); color: var(--v-ink); }

/* Optional ACF background art (p6_background_image). The class is only present
   when an image was set, so with the field empty the white fill above is all
   that renders. background-color stays underneath as the fallback. Over a photo
   the head copy flips to white — the eyebrow's default blue would sink into
   most artwork. */
.v-ahead--image {
  background-repeat: no-repeat;
  background-position: center;
  background-size: cover;
  color: var(--v-white);
}
.v-ahead--image .v-eyebrow { color: var(--v-white); }

/* Only over the photo: the eyebrow sits directly on the artwork with nothing
   behind it, so it needs the shadow to hold contrast. The title is left clean
   on purpose. On the plain white fill the shadow would just muddy the type. */
.v-ahead--image .v-eyebrow { text-shadow: 0 2px 6px rgba(0, 0, 0, .5); }
.v-ahead__head { margin-bottom: 64px; }

/* Two columns: a sticky feature card on the left, a scrolling stack on the
   right. --v-nav-h is measured from .v-sectionnav by JS; the 76px fallback is
   its height at the default type size. */
.v-ahead__cols {
  display: grid;
  grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
  gap: var(--v-gap);
  /* No align-items:start — the left column must stretch to the full row height
     (i.e. the height of the right-hand stack) or the sticky card has nothing to
     travel within and unpins almost immediately. */
}
.v-ahead__sticky { min-height: 100%; }

.v-ahead__rule {
  display: block;
  width: 32px;
  height: 3px;
  margin-bottom: 16px;
  background: var(--v-blue);
  border-radius: 2px;
}

/* Sticky lives on the card itself, inside the full-height column. --v-nav-h is
   measured from .v-sectionnav by JS; 76px is a sane fallback. */
.v-ahead__feature {
  position: sticky;
  top: calc(var(--v-nav-h, 76px) + 36px);
  display: flex;
  flex-direction: column;
  padding: 140px 48px 48px;
  border-radius: 16px;
  background: var(--v-ink);
}
.v-ahead__count {
  margin: 0 0 20px;
  font-size: var(--v-fs-eyebrow);
  font-weight: 700;
  line-height: 1.14;
  letter-spacing: .16em;
  color: var(--v-blue);
}
.v-ahead__feature h3 {
  margin: 0 0 16px;
  font-size: clamp(34px, 3.9vw, 56px);
  font-weight: 700;
  line-height: 1.07;
  letter-spacing: -.052em;
  color: var(--v-cream);
}
/* Textarea fields: the JS swaps copy via textContent, which can't carry <br>,
   so authored line breaks are honoured in CSS instead. Applied to the stack too
   so both render identically. */
.v-ahead__feature .v-body,
.v-ahead__item p { white-space: pre-line; }
.v-ahead__feature .v-body { color: var(--v-cream); max-width: 46ch; }
.v-ahead__more { margin: 40px 0 0; color: var(--v-blue); }

/* Right column: one card per item, stacked. */
.v-ahead__list {
  display: flex;
  flex-direction: column;
  gap: 16px;
}
.v-ahead__item {
  padding: 49px 48px 48px;
  border-radius: 16px;
  background: var(--v-ink);
}
.v-ahead__item h4 {
  margin: 0 0 12px;
  font-size: var(--v-fs-eyebrow);
  font-weight: 700;
  line-height: 1.14;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--v-blue);
}
.v-ahead__item p { color: var(--v-cream); }

/* --------------------------------------------------------------------------
   11. Section 10 — Resources
   -------------------------------------------------------------------------- */
.v-resources { background: var(--v-ink); color: var(--v-cream); }
.v-resources__head,
.v-panel8__head { margin-bottom: 56px; }

/* Panel 8 is Resources' twin on the same ink ground, so the light-blue accents
   (eyebrow, scroll hint, card rule, focus ring) are shared with it unchanged.
   It joins the disabled-arrow / active-dot ink-ground exceptions below. */
.v-panel8 { background: var(--v-ink); color: var(--v-cream); }

/* Values from the comp: 1px cream-38% outline at radius 16, no card fill (the
   section ground shows through), a hairline under the media, a tinted gradient
   over the still and a translucent play badge centred on it. */
.v-episode {
  position: relative;      /* anchors the stretched link */
  display: flex;
  flex-direction: column;
  min-height: 384px;       /* grows with longer body copy */
  border: 1px solid rgba(242, 212, 175, .38);
  border-radius: 16px;
  overflow: hidden;
  background: transparent;
}
/* Covers the whole slide so the entire card is the click target. */
.v-episode__link {
  position: absolute;
  inset: 0;
  z-index: 3;
}
.v-episode--linked { cursor: pointer; }
.v-episode--linked .v-episode__play,
.v-episode--linked .v-episode__media img { transition: transform .3s ease, background-color .3s ease; }
.v-episode--linked:hover .v-episode__play { background: rgba(255, 255, 255, .28); transform: translate(-50%, -50%) scale(1.08); }
.v-episode--linked:hover .v-episode__media img { transform: scale(1.04); }
.v-episode__link:focus-visible { outline: 2px solid var(--v-blue); outline-offset: 2px; }
.v-episode__media {
  position: relative;
  flex: none;
  overflow: hidden;        /* clips the hover zoom to the media area */
  border-bottom: 1px solid rgba(242, 212, 175, .38);
  background: var(--v-ink);
}
.v-episode__media img { width: 100%; height: 215px; object-fit: cover; }
/* Gradient sits over the still, under the play badge. */
.v-episode__media::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(7, 29, 39, .24) 0%, rgba(7, 29, 39, .55) 100%);
}
.v-episode__play {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  z-index: 1;
  width: 56px;
  height: 56px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 2px solid rgba(255, 255, 255, .45);
  border-radius: 999px;
  background: rgba(255, 255, 255, .12);
}
.v-episode__play svg { width: 20px; height: 20px; fill: var(--v-white); }

.v-episode__body { padding: 32px; }
.v-episode__rule {
  display: block;
  width: 34px;
  height: 3px;
  margin-bottom: 24px;
  border-radius: 1px;
  background: var(--v-blue);
}
.v-episode__body h3 {
  margin: 0;
  font-size: var(--v-fs-lead);
  font-weight: 500;
  line-height: 32px;
  letter-spacing: -.08em;
  color: var(--v-cream);
}
.v-episode__body p { margin-top: 16px; color: var(--v-white); }

/* --------------------------------------------------------------------------
   12. Carousels (Swiper 4.4.1)
   vision.php loads this file AFTER swiper.min.css so these cosmetic overrides
   win on source order. Swiper's structural rules (.swiper-wrapper flex, slide
   transforms) are deliberately left untouched.
   -------------------------------------------------------------------------- */
.v-carousel__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--v-gap);
  max-width: var(--v-shell);
  margin: 0 auto 32px;
  padding: 0 24px;
}
.v-carousel__nav { display: flex; gap: 8px; flex: none; align-items: center; }
/* Static "Scroll to Explore" label sitting before the arrows. */
.v-carousel__hint { margin: 0 16px 0 0; white-space: nowrap; }

/* Carousel arrows are styled by STATE, not by direction — the comp's outlined
   arrow next to a red one is simply the disabled/enabled pair on slide 1.
     enabled          red fill, white arrow; hover keeps the colours and scales up
     disabled         transparent, ink border + ink arrow, inert on hover
     disabled on ink  cream at 38% (the ink border would vanish on #071d27) */
.v-nav-btn {
  width: 48px;
  height: 48px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: 2px solid var(--v-red);
  border-radius: 999px;
  background: var(--v-red);
  color: var(--v-white);
  cursor: pointer;
  transition: transform .25s ease, background-color .25s ease, border-color .25s ease, color .25s ease;
}
.v-nav-btn svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 2.5; }

/* Enabled hover: same palette, just a touch larger. */
.v-nav-btn:not(.swiper-button-disabled):not([aria-disabled="true"]):hover {
  transform: scale(1.12);
}

/* Disabled: outline only. Covers both the class Swiper adds and the a11y attr. */
.v-nav-btn.swiper-button-disabled,
.v-nav-btn[aria-disabled="true"] {
  background: transparent;
  border-color: var(--v-ink);
  color: var(--v-ink);
  cursor: default;
  transform: none;
}

/* On an ink ground (#resources, the Welcome enhancement card) an ink outline would disappear. */
.v-resources .v-nav-btn.swiper-button-disabled,
.v-resources .v-nav-btn[aria-disabled="true"],
.v-panel8 .v-nav-btn.swiper-button-disabled,
.v-panel8 .v-nav-btn[aria-disabled="true"],
.v-enhancement .v-nav-btn.swiper-button-disabled,
.v-enhancement .v-nav-btn[aria-disabled="true"],
.v-labs .v-nav-btn.swiper-button-disabled,
.v-labs .v-nav-btn[aria-disabled="true"] {
  border-color: rgba(242, 212, 175, .38);
  color: rgba(242, 212, 175, .38);
}

/* The comp bleeds slides off the right edge: 3 full cards + a 96px peek. */
.v-carousel .swiper-container {
  width: 100%;
  padding: 8px 24px 8px;
  overflow: hidden;
}
.v-carousel .swiper-slide {
  width: 384px;
}
/* The card IS the slide, so its height has to be declared at this specificity.
   A bare `.v-commit-card { height }` is (0,1,0) and loses to the (0,2,0) rule
   above, which collapses the card to content height and crops the photo to a
   thin strip. */
.v-carousel .swiper-slide.v-commit-card { height: 535px; }
/* Episodes are NOT fixed: body copy varies per item and a hard height clipped
   it. .swiper-wrapper is a flex row (align-items: stretch by default), so with
   the slide left at auto height every episode in the row stretches to match
   the tallest one; .v-episode's min-height keeps short cards at comp size. */
.v-carousel .swiper-slide.v-episode     { height: auto; }

/* Pagination lives outside .swiper-container, so undo Swiper's absolute
   positioning and let it sit in normal flow. */
.v-carousel .v-dots.swiper-pagination {
  position: static;
  transform: none;
}
.v-dots {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 16px;
  margin-top: 32px;
}
.v-dots .swiper-pagination-bullet {
  width: 11px;
  height: 11px;
  margin: 0;
  border-radius: 999px;
  background: var(--v-white);
  opacity: 1;
  transition: width .3s ease, opacity .3s ease;
}
.v-dots .swiper-pagination-bullet-active {
  width: 29px;
  background: var(--v-ink);
}
/* On an ink ground the ink pill disappears into the background — go cream.
   (0,3,0) to beat the rule above. Mirrors the disabled nav-button exception. */
.v-resources .v-dots .swiper-pagination-bullet-active,
.v-panel8 .v-dots .swiper-pagination-bullet-active,
.v-labs .v-dots .swiper-pagination-bullet-active {
  background: var(--v-cream);
}

/* --------------------------------------------------------------------------
   13. Responsive
   -------------------------------------------------------------------------- */
@media (min-width: 1441px) {
  .v-carousel .swiper-container { padding-left: calc((100vw - var(--v-shell)) / 2); }
}

@media (max-width: 1024px) {
  .v-labs__grid { grid-template-columns: minmax(0, 1fr); gap: 40px; }
  .v-labs__media { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 900px) {
  .v-section { padding: 56px 0; }
  .v-hero { min-height: 600px; padding: 96px 0 56px; }
  .v-hero__media::after { background: linear-gradient(180deg, rgba(7,29,39,.55) 0%, rgba(7,29,39,.9) 100%); }
  .v-steps,
  .v-involve-grid { grid-template-columns: minmax(0, 1fr); }
  /* Single column: the card pins 16px below the nav and the stack scrolls
     underneath it, swapping the card's content exactly as on desktop.
     .v-ahead__sticky is dissolved with display:contents so the card's
     containing block becomes .v-ahead__cols — left as a wrapper it is only as
     tall as the card, and sticky would have no travel at all. */
  .v-ahead__cols { display: block; }
  .v-ahead__sticky { display: contents; }
  .v-ahead__feature {
    position: sticky;
    top: calc(var(--v-nav-h, 76px) + 16px);
    z-index: 5;              /* paints over the stack sliding beneath it */
    /* No bottom margin: a sticky element's travel is capped by its containing
       block MINUS its own margins, so a margin here would unpin the card that
       many pixels early and leave the foot of the last item showing below it.
       The gap lives on .v-ahead__list instead — same visual result, full travel. */
    margin-bottom: 0;
    /* Shadow in the section's own ground colour: invisible against the
       background, but it masks the cards sliding underneath so the two dark
       panels never appear to merge. Desktop needs none — the columns sit side
       by side there and nothing passes behind the card. */
    box-shadow: 0 16px 24px 12px var(--v-blue-mid);
  }
  /* The gap between card and stack, carried here rather than as a margin on the
     card. 56px so the card's shadow (16px offset + 12px spread + blur) has faded
     out before it reaches the first item. JS clears its inline padding-top when
     stacked, so this rule applies unopposed on mobile. */
  /* Stagger is a side-by-side refinement. Once rows are stacked each item
     already arrives on its own, so a delay just makes it start late — and the
     later items in a group would otherwise sit waiting while their turn passes
     off-screen. (0,2,0) here, same as the base rule, but later in the file, and
     it targets transition-delay directly rather than the inline --reveal-delay
     custom property, which a stylesheet can't override.) */
  .has-js .js-reveal { transition-delay: 0s; }

  .v-ahead__list { padding-top: 56px; }
  .v-ahead__feature, .v-ahead__item { padding: 32px 28px; }
  .v-enhancement { padding: 40px 28px; }
  .v-involve { margin-top: 64px; }
  .v-carousel .swiper-slide { width: 300px; }
  .v-carousel .swiper-slide.v-commit-card { height: 440px; }
  /* .v-episode keeps its 384px min-height here — the 232px image plus body
     padding and two lines of copy leaves no room to shrink. */
}

@media (max-width: 640px) {
  .v-sectionnav ul { flex-wrap: nowrap; overflow-x: auto; justify-content: flex-start; -webkit-overflow-scrolling: touch; }
  .v-sectionnav a { white-space: nowrap; padding: 11px 18px; }
  .v-hero__actions .v-btn { width: 100%; }
  .v-labs__list { grid-template-columns: minmax(0, 1fr); }
  .v-labs__media { grid-template-columns: minmax(0, 1fr); }
  .v-step, .v-involve-card__body { padding: 28px; }
  .v-ahead__feature { padding: 32px 24px; }
  .v-carousel .swiper-slide { width: 82vw; }
  .v-carousel__head { flex-direction: column; align-items: flex-start; }
}

/* Respect reduced-motion for the scroll-reveal transitions */
@media (prefers-reduced-motion: reduce) {
  .vision-page *,
  .vision-page *::before,
  .vision-page *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
}
