/* ==========================================================================
   Euromonitor Passport — block styles
   --------------------------------------------------------------------------
   Every selector is namespaced `pp-` so nothing can leak into, or be
   overridden by, the host Optimizely site's Bootstrap 5 styles.
   Design tokens are mirrored from Figma file "passport v1A".
   ========================================================================== */

.pp-block {
  /* --- brand palette (Figma: emi_*) ------------------------------------- */
  --pp-linen: #f2f2f5;
  --pp-orange: #ff6a13;
  --pp-yellow: #ff9e1b;
  --pp-yellow-hover: #f08d00;
  --pp-cyan: #00aed9;
  --pp-cyan-sat: #0fd0ff;
  /* emi_core/cyan_saturated */
  --pp-dark-cyan: #34657f;
  --pp-royal-blue: #1e22aa;
  --pp-royal-blue-sat: #0006c8;
  /* emi_secondary/royal-blue_saturated */
  --pp-periwinkle: #8394f2;
  --pp-crimson: #a83d72;
  --pp-pink: #f73081;
  --pp-dark: #01172a;
  /* Frosted tint used behind icons + thumbs (Figma: cyan_saturated @ 10%). */
  --pp-tint: rgba(15, 208, 255, 0.1);

  /* --- text (Figma: text/*) --------------------------------------------- */
  --pp-ink: #222426;
  /* text/headlines/text_headline */
  --pp-body: #313335;
  /* text/body/text_body */
  --pp-ink-contrast: #f9f9fa;
  /* text/headlines/text_headline_contrast */
  --pp-muted: #45474d;
  /* buttons+links/disabled/button_disabled_text */
  --pp-line: #7b8089;
  /* form/form_outline */

  /* --- gradients --------------------------------------------------------- */
  /* Headline accent + factoid wash: cyan_saturated -> royal-blue_saturated. */
  --pp-grad-accent: linear-gradient(90deg, #0fd0ff 0%, #0006c8 100%);
  /* 1px hairline rules (FAQ, section splits). */
  --pp-grad-divider: linear-gradient(0.44deg, #8394f2 0%, #3c41b4 32.55%, #8c43ac 98.12%);
  /* Vertical pill bars beside numbered steps (sampled from Figma export). */
  --pp-grad-bar: linear-gradient(180deg, #0fd0ff 0%, #c91a72 100%);
  --pp-grad-wash: linear-gradient(90deg, #00aed9 0%, #a83d72 100%);

  /* --- shape ------------------------------------------------------------- */
  --pp-radius-sm: 8px;
  --pp-radius: 16px;
  --pp-radius-lg: 24px;
  --pp-radius-xl: 64px;
  --pp-radius-pill: 1024px;
  --pp-shadow: 0 22px 13px rgba(85, 105, 135, 0.58);

  /* --- rhythm ------------------------------------------------------------ */
  --pp-max: 1320px;
  --pp-gutter: clamp(20px, 4vw, 48px);
  --pp-section-y: clamp(64px, 8vw, 128px);

  /* --- type -------------------------------------------------------------- */
  /* The host site already loads Proxima Nova; `inherit` lets live typography
     win. Preview pages set --pp-font to a close substitute. */
  --pp-font: inherit;
  --pp-font-btn: var(--pp-font);
  --pp-fs-giga: clamp(2.25rem, 1.35rem + 2.9vw, 3.625rem);
  /* 58px */
  --pp-fs-mega: clamp(2rem, 1.32rem + 2.2vw, 3.25rem);
  /* 52px */
  --pp-fs-h1: clamp(1.75rem, 1.36rem + 1.25vw, 2.5625rem);
  /* 41px */
  --pp-fs-h2: clamp(1.5rem, 1.29rem + 0.7vw, 2.0625rem);
  /* 33px */
  --pp-fs-h3: clamp(1.25rem, 1.13rem + 0.4vw, 1.625rem);
  /* 26px */
  --pp-fs-lg: 1.25rem;
  /* 20px */
  --pp-fs-md: 1.125rem;
  /* 18px */
  --pp-fs-sm: 0.875rem;
  /* 14px */

  position: relative;
  /* `clip` (not `hidden`) so descendant position:sticky keeps working. */
  overflow: clip;
  color: var(--pp-body);
  font-family: var(--pp-font);
  font-size: var(--pp-fs-md);
  line-height: 1.5;
  background: var(--pp-linen);
}

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

.pp-block img,
.pp-block video {
  max-width: 100%;
}

/* The Optimizely template restyles bare h1-h6 and p, so a block that relies on
   the browser default drifts once it is pasted into the CMS. Pin the three
   properties the site touches. Declared above the .pp-h* classes so those,
   being equally specific, still win. */
.pp-block :is(h1, h2, h3, h4, h5, h6) {
  margin: 0;
  color: inherit;
  font-weight: inherit;
}

.pp-block p {
  margin: 0;
  color: inherit;
}

/* The host footer rounds its top-right corner by 30px and the page background
   shows through the notch. The Optimizely body is white, which reads as a
   stray white triangle against our linen page, so assert the page colour.
   Literal value: custom properties are scoped to .pp-block, not to <body>. */
body:has(.pp-block) {
  background-color: #f2f2f5;
}

/* --------------------------------------------------------------------------
   Layout helpers
   -------------------------------------------------------------------------- */

.pp-container {
  width: 100%;
  max-width: calc(var(--pp-max) + var(--pp-gutter) * 2);
  margin-inline: auto;
  padding-inline: var(--pp-gutter);
}

.pp-section {
  padding-block: var(--pp-section-y);
}

/* These all carry a `&nbsp;` in the markup, because Optimizely's sanitiser
   deletes any element with no content. Zeroing the font keeps it out of the
   layout. */
.pp-ribbon,
.pp-hero__shadow,
.pp-hero__device,
.pp-hero__screen,
.pp-form__decor,
.pp-video__play,
.pp-dots button {
  font-size: 0;
  line-height: 0;
}

/* The soft "ribbon" photograph that sits behind most sections. */
.pp-ribbon {
  position: absolute;
  inset: 0;
  pointer-events: none;
  overflow: hidden;
}

/* The artwork is painted as a background rather than an <img>. Optimizely's
   server-side handler rewrites every <img src> inside a CMS block to
   `?width=1024&quality=80`, which visibly softens art this large.
   Backgrounds are left untouched by that handler. */
.pp-ribbon:not(.pp-ribbon--motion)::before {
  content: "";
  position: absolute;
  inset: 0;
  background: url("ribbon-gradient-left.png") center / cover no-repeat;
  background-size: 125%;
}

.pp-ribbon video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 99%;
  object-fit: cover;
  mix-blend-mode: multiply;
}

.pp-ribbon--faint::before {
  opacity: 0.35;
}

/* Figma runs this ribbon much larger than the film so only its arcs peek out —
   above the top-right corner, below the lower edge, and a magenta tail that
   bleeds off the left of the page. Sized against the 800x450 film box. The
   artwork is on a white ground and composites with `multiply`, so the crop
   edges vanish into the linen and need no mask. */
.pp-ribbon--vid {
  inset: -76% -15% -32% -45%;
}

@media (max-width: 768px) {
  .pp-ribbon--vid {
    inset: -76% -42% -29% -41%;
  }
}

/* Doubled class to out-rank `.pp-ribbon:not(.pp-ribbon--motion)::before`,
   whose `background` shorthand would otherwise reset this. */
.pp-ribbon.pp-ribbon--vid::before {
  background-position: center;
}

/* Fades in once the loop is running so the hero does not flash an empty frame. */
.pp-ribbon--motion video {
  opacity: 0;
  transition: opacity 0.6s ease;
}

.pp-ribbon--motion video.is-playing {
  opacity: 1;
}

/* --------------------------------------------------------------------------
   Typography
   -------------------------------------------------------------------------- */

.pp-eyebrow {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  margin: 0;
  color: var(--pp-ink);
  font-size: var(--pp-fs-md);
  font-weight: 500;
  line-height: 1.5;
}

/* Figma ships this as a 7x16 svg with a 7px dot whose centre sits 12.5px down,
   i.e. it hangs off the baseline rather than centring on the cap height. */
.pp-eyebrow::before {
  content: "";
  flex: 0 0 auto;
  width: 7px;
  height: 7px;
  margin-top: 9px;
  border-radius: 50%;
  background: var(--pp-yellow);
}

.pp-eyebrow--center {
  justify-content: center;
}

.pp-h1,
.pp-h2,
.pp-h3,
.pp-mega,
.pp-giga {
  margin: 0;
  color: var(--pp-ink);
  font-family: var(--pp-font);
  font-weight: 600;
}

.pp-giga {
  font-size: var(--pp-fs-giga);
  line-height: 1.2;
  letter-spacing: -0.02em;
}

.pp-mega {
  font-size: var(--pp-fs-mega);
  line-height: 1.2;
  letter-spacing: -0.02em;
}

.pp-h1 {
  font-size: var(--pp-fs-h1);
  line-height: 1.2;
  letter-spacing: -0.01em;
}

.pp-h2 {
  font-size: var(--pp-fs-h2);
  line-height: 1.3;
}

.pp-h3 {
  font-size: var(--pp-fs-h3);
  line-height: 1.3;
}

/* Gradient-filled accent words, exactly as in Figma. */
.pp-accent {
  background: var(--pp-grad-accent);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
}

.pp-lead {
  font-size: var(--pp-fs-lg);
  line-height: 1.5;
  color: var(--pp-ink);
}

.pp-body {
  font-size: var(--pp-fs-md);
  line-height: 1.5;
  color: var(--pp-ink);
}

.pp-small {
  font-size: var(--pp-fs-sm);
  line-height: 1.5;
}

.pp-center {
  text-align: center;
}

.pp-on-dark,
.pp-on-dark .pp-h1,
.pp-on-dark .pp-h2,
.pp-on-dark .pp-h3,
.pp-on-dark .pp-mega,
.pp-on-dark .pp-giga,
.pp-on-dark .pp-eyebrow,
.pp-on-dark .pp-lead,
.pp-on-dark .pp-body {
  color: var(--pp-ink-contrast);
}

.pp-on-dark .pp-eyebrow::before {
  background: #fff;
}

/* --------------------------------------------------------------------------
   Buttons, tags, dividers
   -------------------------------------------------------------------------- */

.pp-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 48px;
  padding-inline: 40px;
  border: 0;
  border-radius: var(--pp-radius-pill);
  color: var(--pp-body);
  font-family: var(--pp-font-btn);
  font-size: var(--pp-fs-md);
  font-weight: 500;
  line-height: 1.3;
  text-align: center;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  transition: background-color 0.18s ease, color 0.18s ease, transform 0.18s ease;
}

.pp-btn:hover {
  transform: translateY(-1px);
  text-decoration: none;
}

.pp-btn:focus-visible {
  outline: 3px solid var(--pp-royal-blue);
  outline-offset: 3px;
}

.pp-btn--primary {
  background: var(--pp-yellow);
  color: var(--pp-body);
}

.pp-btn--primary:hover {
  background: var(--pp-yellow-hover);
  color: var(--pp-body);
}

.pp-btn--outline {
  background: #fff;
  border: 2px solid var(--pp-yellow);
  color: var(--pp-body);
}

.pp-btn--outline:hover {
  background: var(--pp-yellow);
  color: var(--pp-body);
}

/* Sits on the dark panels, where yellow-on-navy is too loud. */
.pp-btn--light {
  background: var(--pp-linen);
  color: var(--pp-ink);
}

.pp-btn--light:hover {
  background: #fff;
  color: var(--pp-ink);
}

.pp-btns {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.pp-filters {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.pp-filter {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 32px;
  padding-inline: 16px;
  border: 1px solid var(--pp-cyan);
  border-radius: var(--pp-radius-pill);
  background: transparent;
  color: var(--pp-body);
  font-family: var(--pp-font-btn);
  font-size: var(--pp-fs-sm);
  font-weight: 500;
  line-height: 1.3;
  white-space: nowrap;
  cursor: pointer;
  transition: background-color 0.18s ease, color 0.18s ease, border-color 0.18s ease;
}

.pp-filter:hover {
  background: rgba(0, 174, 217, 0.12);
}

.pp-filter.is-active {
  background: var(--pp-dark-cyan);
  border-color: var(--pp-royal-blue);
  color: var(--pp-ink-contrast);
}

.pp-filter:focus-visible {
  outline: 3px solid var(--pp-royal-blue);
  outline-offset: 2px;
}

.pp-tag {
  display: inline-flex;
  align-items: center;
  padding: 6px 10px;
  border-radius: 4px;
  background: #dfecf5;
  backdrop-filter: blur(6px);
  color: var(--pp-body);
  font-size: 11px;
  font-weight: 600;
  line-height: 1.5;
  white-space: nowrap;
}

.pp-divider {
  width: 100%;
  height: 1px;
  border: 0;
  margin: 0;
  opacity: 0.5;
  background: var(--pp-grad-divider);
}

/* Gradient rule down the left of numbered items. Drawn with a pseudo-element
   rather than a <span>: Optimizely's HTML sanitiser deletes empty inline
   elements, so the markup version vanishes once pasted into a CMS block. */
.pp-step__row::before,
.pp-form__step::before {
  content: "";
  flex: 0 0 8px;
  align-self: stretch;
  border-radius: 999px;
  background: var(--pp-grad-bar);
}

/* --------------------------------------------------------------------------
   01 — Hero / banner
   -------------------------------------------------------------------------- */

.pp-hero {
  padding-block: clamp(48px, 6vw, 89px) 0;
}

.pp-hero__inner {
  position: relative;
  z-index: 1;
}

.pp-hero__head {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
  max-width: 1094px;
  margin-inline: auto;
  text-align: center;
}

.pp-hero__lead {
  max-width: 798px;
}

.pp-hero__logo {
  width: clamp(160px, 15vw, 232px);
  height: auto;
  margin-bottom: 16px;
}

.pp-hero__btns {
  justify-content: center;
  margin-top: clamp(20px, 2.5vw, 31px);
}

/* Figma fades the ribbon behind the headline with a 333px white panel across
   the top of the 1157px section — 29%. Match that rather than hiding the whole
   upper half, so the loop reads across the hero the way the design does. The
   hero is `overflow: clip`, so anything past the edges is cut off. */
.pp-hero .pp-ribbon--motion {
  inset: 0;
}

/* Figma runs the device stage full-bleed at 1600px, outside the 1320 grid. */
.pp-hero__stage {
  position: relative;
  z-index: 1;
  margin-top: 0;
  aspect-ratio: 1600 / 728;
}

@media (max-width: 768px) {
  .pp-hero__stage {
    aspect-ratio: 1600 / 768;
  }
}

/* Hero artwork is painted as backgrounds rather than <img> so Optimizely's
   image handler cannot downsample it (see .pp-ribbon above). Because a <div>
   has no intrinsic size, each layer restates its source aspect ratio. */
.pp-hero__device,
.pp-hero__screen {
  position: absolute;
  left: 50%;
  translate: -50% 0;
  background: center / contain no-repeat;
}

.pp-hero__device {
  top: 8.93%;
  width: 77.94%;
  aspect-ratio: 1600 / 683;
  background-image: url("hero-device.png");
}

.pp-hero__screen {
  top: 12.91%;
  width: 69.94%;
  aspect-ratio: 1400 / 545;
  background-image: url("hero-screen.png");
}

/* Full-bleed ground shadow (Figma Rectangle291, 1600x106 at y=1051). It is a
   soft gradient, so stretching the 1024px source to the full width is fine. */
.pp-hero__shadow {
  position: absolute;
  left: 0;
  top: 85.44%;
  width: 100%;
  height: 14.56%;
  background: url("hero-ground-shadow.png") 0 0 / 100% 100% no-repeat;
}

@media (max-width: 768px) {
  .pp-hero__shadow {
    top: 85.94%;
  }
}

/* Floating "banner info" cards. Translucent so the device reads through them. */
.pp-hero__card {
  position: absolute;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 8px;
  border-radius: var(--pp-radius);
  background: rgba(255, 255, 255, 0.72);
  backdrop-filter: blur(12px);
  filter: drop-shadow(0 22px 13px rgba(85, 105, 135, 0.38));
  animation: pp-float 9s ease-in-out infinite;
}

.pp-hero__card img {
  display: block;
  width: 100%;
  height: auto;
}

/* Cards are positioned with percentage offsets, so the drift has to ride on
   `translate` rather than `top`. */
@keyframes pp-float {

  0%,
  100% {
    translate: 0 0;
  }

  50% {
    translate: 0 -12px;
  }
}

/* Figma places all three cards at 332x169 inside the 1600x728 stage. */
.pp-hero__card--a {
  left: 64.19%;
  top: 0;
  width: 20.75%;
}

.pp-hero__card--b {
  left: 4.31%;
  top: 35.99%;
  width: 20.75%;
  animation-duration: 11s;
  animation-delay: -3.5s;
}

.pp-hero__card--c {
  left: 74.44%;
  top: 39.7%;
  width: 20.75%;
  animation-duration: 10s;
  animation-delay: -6s;
}

@media (max-width: 768px) {

  /* The comps keep all three cards on the phone, scaled down and allowed to
     bleed off both edges so they frame the device rather than crowd it. */
  .pp-hero__card {
    width: 34%;
    padding: 5px;
    border-radius: 12px;
  }

  .pp-hero__card--a {
    left: 56%;
    top: 1%;
  }

  .pp-hero__card--b {
    left: -10%;
    top: 46%;
  }

  .pp-hero__card--c {
    left: 61%;
    top: 43%;
  }

  /* The loop is composed for a wide, short hero. In a narrow portrait one
     `cover` blows it up until the ribbon sits right behind the body copy, so
     pin it to the bottom around the device and fade its top edge out, which
     is how the mobile comps treat it. 32% is set by the narrowest case (360px,
     where the lead runs longest) so the band clears the copy at every width. */
  .pp-hero .pp-ribbon--motion {
    inset: auto 0 0 0;
    height: 60%;
    -webkit-mask-image: linear-gradient(to bottom, transparent 0%, #000 35%);
    mask-image: linear-gradient(to bottom, transparent 0%, #000 35%);
    bottom: -40px;
  }
}

/* --------------------------------------------------------------------------
   02 — Intro (centred statement)
   -------------------------------------------------------------------------- */

.pp-intro {
  padding-block: clamp(48px, 5vw, 72px) 40px;
}

.pp-intro__inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
  text-align: center;
}

.pp-intro__title {
  max-width: 1094px;
}

/* --------------------------------------------------------------------------
   03 — Logo marquee
   -------------------------------------------------------------------------- */

.pp-logos {
  padding-block: 16px 40px;
}

.pp-logos__viewport {
  display: flex;
  width: 100%;
  overflow: hidden;
  mask-image: linear-gradient(90deg, transparent 0, #000 6%, #000 94%, transparent 100%);
  -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 6%, #000 94%, transparent 100%);
}

.pp-logos__track {
  display: flex;
  flex: 0 0 auto;
  align-items: center;
  gap: 84px;
  padding-right: 84px;
  animation: pp-marquee 42s linear infinite;
}

.pp-logos__item {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 150px;
  height: 85px;
}

.pp-logos__item img {
  max-width: 100%;
  max-height: 72px;
  object-fit: contain;
  mix-blend-mode: multiply;
}

/* Square lockups are drawn edge to edge in their source file, so they need a
   lower ceiling to carry the same optical weight as the wordmarks. */
.pp-logos__item--tall img {
  max-height: 52px;
}

/* Figma fits three marks across a 428px screen, so the desktop pitch has to
   come down or only two ever make it into view. */
@media (max-width: 767.98px) {
  .pp-logos__track {
    gap: 48px;
    padding-right: 48px;
  }

  .pp-logos__item {
    width: 108px;
    height: 60px;
  }

  .pp-logos__item img {
    max-height: 44px;
  }

  .pp-logos__item--tall img {
    max-height: 34px;
  }
}

/* Slow ambient movement for the decorative orb layers. Animates `translate`
   so it does not fight the `transform` those layers already use for framing. */
@keyframes pp-drift {

  0%,
  100% {
    translate: -50% -50%;
  }

  33% {
    translate: -47% -53%;
  }

  66% {
    translate: -53% -48%;
  }
}

@keyframes pp-marquee {
  from {
    transform: translate3d(0, 0, 0);
  }

  to {
    transform: translate3d(-100%, 0, 0);
  }
}

/* --------------------------------------------------------------------------
   04 — Stats strip
   -------------------------------------------------------------------------- */

.pp-stats {
  padding-block: 0 48px;
}

.pp-stats__inner {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.pp-stats__head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: clamp(24px, 5vw, 96px);
}

.pp-stats__head .pp-mega {
  max-width: 613px;
}

.pp-stats__kicker {
  max-width: 432px;
}

.pp-stats__grid {
  --pp-stat-gap: 24px;
  --pp-stat-cols: 6;
  display: grid;
  grid-template-columns: repeat(var(--pp-stat-cols), minmax(0, 1fr));
  gap: var(--pp-stat-gap);
  margin-top: 24px;
}

.pp-stat {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: 8px;
  /* 200px is the Figma card at the 1320 grid; the card grows rather than
     clipping when a longer label needs more room. */
  min-height: 200px;
  padding: 16px 24px 24px;
  border-radius: var(--pp-radius);
  overflow: hidden;
}

/* One cyan -> royal-blue wash runs the full width of the row; each card shows
   its own slice, so the gaps read as cut-outs rather than separate fills.
   --pp-stat-i is the card's zero-based column index (set in the markup). */
.pp-stat::before {
  content: "";
  position: absolute;
  inset-block: 0;
  left: calc(-1 * var(--pp-stat-i, 0) * (100% + var(--pp-stat-gap)));
  width: calc(var(--pp-stat-cols) * 100% + (var(--pp-stat-cols) - 1) * var(--pp-stat-gap));
  background: var(--pp-grad-accent);
  opacity: 0.5;
}

.pp-stat__value,
.pp-stat__label {
  position: relative;
}

.pp-stat__value {
  margin: 0;
  color: #000;
  font-size: var(--pp-fs-h1);
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: -0.01em;
}

.pp-stat__label {
  margin: 0;
  color: #000;
  font-size: var(--pp-fs-lg);
  line-height: 1.5;
}

@media (max-width: 1199.98px) {
  .pp-stats__head {
    flex-direction: column;
    align-items: flex-start;
    gap: 16px;
  }

  .pp-stats__grid {
    --pp-stat-cols: 3;
  }

  /* Below the six-across layout the row no longer lines up, so give every
     card the whole gradient instead of a slice. */
  .pp-stat::before {
    left: 0;
    width: 100%;
  }
}

/* Two across is the narrowest the design goes — the mobile comps keep the
   cards paired all the way down. */
@media (max-width: 767.98px) {
  .pp-stats__grid {
    --pp-stat-cols: 2;
    --pp-stat-gap: 16px;
  }
}

@media (max-width: 575.98px) {
  .pp-stat {
    min-height: 0;
    padding: 16px;
  }

  .pp-stat__value {
    font-size: 24px;
  }

  .pp-stat__label {
    font-size: 14px;
  }
}

/* --------------------------------------------------------------------------
   05 — Video / "boardroom"
   -------------------------------------------------------------------------- */

.pp-vid {
  padding-block: clamp(72px, 9vw, 136px);
}

/* Figma: the 800x450 video is column one; copy sits to its right. */
.pp-vid__grid {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 800px) minmax(0, 1fr);
  align-items: center;
  gap: 0;
}

/* Anchors the bleeding artwork that sits behind the film. */
.pp-vid__stage {
  position: relative;
}

.pp-vid__copy {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  position: relative;
  /* left-aligned, per design */
  gap: 16px;
  padding-left: 80px;
  text-align: left;
}

/* Design puts 24px between body paragraphs, on top of the 16px column gap. */
.pp-vid__copy .pp-body+.pp-body {
  margin-top: 8px;
}

.pp-vid__copy .pp-btn {
  margin-top: 16px;
}

.pp-video {
  position: relative;
  aspect-ratio: 16 / 9;
  border-radius: var(--pp-radius-lg);
  overflow: hidden;
  background: #0d1b26;
}

.pp-video video {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Click-to-load embeds: the still frame stands in until the visitor presses
   play, at which point the provider's iframe replaces it. */
.pp-video__poster {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.pp-video__frame {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
}

.pp-video__play {
  position: absolute;
  left: 50%;
  top: 50%;
  translate: -50% -50%;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 72px;
  height: 72px;
  padding: 8px;
  border: 6px solid rgba(255, 255, 255, 0.4);
  border-radius: 999px;
  background: var(--pp-yellow);
  backdrop-filter: blur(4px);
  cursor: pointer;
  transition: transform 0.18s ease, background-color 0.18s ease, opacity 0.18s ease;
}

.pp-video__play:hover {
  transform: scale(1.07);
  background: var(--pp-yellow-hover);
}

.pp-video__play:focus-visible {
  outline: 3px solid #fff;
  outline-offset: 3px;
}

/* --- Product tour band ---------------------------------------------------- */
.pp-tour {
  padding-block: clamp(48px, 6vw, 80px);
}

.pp-tour__inner {
  max-width: calc(var(--pp-max) + var(--pp-gutter) * 2);
  margin-inline: auto;
  padding-inline: var(--pp-gutter);
}

.pp-video--wide {
  aspect-ratio: 1536 / 885;
  border-radius: var(--pp-radius-lg);
}

/* Background rather than <img>: the CMS handler rasterises SVGs at their
   intrinsic size, which leaves the glyph blurry on retina screens. */
.pp-video__play::before {
  content: "";
  width: 48px;
  height: 48px;
  margin-left: 3px;
  background: url("icon-play.svg") center / contain no-repeat;
}

.pp-video.is-playing .pp-video__play {
  opacity: 0;
  pointer-events: none;
}

@media (max-width: 1199.98px) {
  .pp-vid__grid {
    grid-template-columns: 1fr;
    gap: 32px;
  }

  .pp-vid__copy {
    padding-left: 0;
  }
}

/* Stacked, the comps lead with the copy and close with the film. Source order
   keeps the film first so the desktop grid needs no reordering. */
@media (max-width: 767.98px) {
  .pp-vid__stage {
    order: 2;
  }

  .pp-vid__copy {
    order: 1;
  }
}

/* --------------------------------------------------------------------------
   06 — Passport AI (dark gradient panel)
   -------------------------------------------------------------------------- */

.pp-ai {
  padding: 0 clamp(16px, 2vw, 32px) clamp(72px, 9vw, 160px);
}

.pp-ai__panel {
  position: relative;
  padding: clamp(48px, 6vw, 96px) clamp(24px, 4vw, 108px);
  border-radius: clamp(24px, 4vw, 64px);
  overflow: hidden;
  background: rgba(30, 34, 170, 0.95);
}

.pp-ai__panel .pp-ribbon::before {
  opacity: 0.12;
}

/* Full bleed on the phone, exactly as the comps run it. */
@media (max-width: 767.98px) {
  .pp-ai {
    padding-inline: 0;
  }

  .pp-ai__panel {
    border-radius: 0;
  }
}

.pp-ai__orbs {
  position: absolute;
  left: 50%;
  top: 50%;
  translate: -50% -50%;
  width: 128%;
  max-width: none;
  transform: rotate(180deg) scaleY(-1);
  pointer-events: none;
  animation: pp-drift 26s ease-in-out infinite;
}

.pp-ai__grid {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: minmax(0, 417px) minmax(0, 1fr);
  align-items: center;
  gap: clamp(40px, 6vw, 120px);
  max-width: var(--pp-max);
  margin-inline: auto;
}

.pp-ai__copy {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

/* Design uses the medium body weight throughout this panel. */
.pp-ai__copy .pp-lead,
.pp-ai__rowtext .pp-lead {
  font-weight: 500;
}

.pp-ai__copy .pp-btn {
  align-self: flex-start;
  margin-top: 16px;
}

.pp-ai__rows {
  display: flex;
  flex-direction: column;
  gap: 32px;
}

.pp-ai__row {
  display: flex;
  align-items: center;
  gap: 32px;
}

/* 128x128 square. The exported artwork already carries the frosted panel,
   1px periwinkle border and 12px radius, so nothing is re-drawn here. */
.pp-ai__thumb {
  flex: 0 0 128px;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 128px;
  height: 128px;
  border-radius: 12px;
  overflow: hidden;
}

.pp-ai__thumb img {
  width: 100%;
  height: 100%;
  object-fit: contain;
}

.pp-ai__rowtext {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.pp-ai__link {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  align-self: flex-start;
  color: var(--pp-yellow);
  font-size: var(--pp-fs-md);
  font-weight: 500;
  line-height: 1.3;
  text-decoration: none;
}

.pp-ai__link:hover {
  color: var(--pp-yellow);
  text-decoration: underline;
}

.pp-ai__link:focus-visible {
  outline: 3px solid #fff;
  outline-offset: 3px;
}

/* Masked so the shared arrow icon picks up the link colour. A pseudo-element
   because Optimizely strips the empty <span> this used to live in. */
.pp-ai__link::after {
  content: "";
  flex: 0 0 24px;
  height: 24px;
  background: currentColor;
  mask: url("icon-arrow-right.svg") center / contain no-repeat;
  -webkit-mask: url("icon-arrow-right.svg") center / contain no-repeat;
  transition: translate 0.18s ease;
}

.pp-ai__link:hover::after {
  translate: 4px 0;
}

@media (max-width: 1199.98px) {
  .pp-ai__grid {
    grid-template-columns: 1fr;
  }
}

@media (max-width: 575.98px) {
  .pp-ai__row {
    flex-direction: column;
    align-items: flex-start;
    gap: 16px;
  }
}

/* --------------------------------------------------------------------------
   07 — Six pillars
   -------------------------------------------------------------------------- */

.pp-pillars {
  padding-block: 0;
}

.pp-pillars__head {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 16px;
}

.pp-pillars__row {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 32px;
  width: 100%;
}

.pp-pillars__title {
  max-width: 1032px;
}

.pp-pillars__grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 56px 24px;
  width: 100%;
  padding-top: 40px;
}

.pp-pillar {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 8px;
}

.pp-pillar__icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border-radius: 9999px;
  background: var(--pp-tint);
}

.pp-pillar__icon img {
  width: 24px;
  height: 24px;
}

@media (max-width: 991.98px) {
  .pp-pillars__grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 40px 24px;
  }

  .pp-pillars__row {
    flex-direction: column;
    align-items: flex-start;
  }
}

/* The mobile comps keep the pillars two across rather than stacking. */
@media (max-width: 575.98px) {
  .pp-pillars__grid {
    gap: 32px 16px;
  }

  .pp-pillar p {
    font-size: 16px;
  }
}

/* --------------------------------------------------------------------------
   08 — Video CTA (message from the product team)
   -------------------------------------------------------------------------- */

.pp-vcta {
  padding: clamp(48px, 6vw, 80px) clamp(16px, 2vw, 32px);
}

.pp-vcta__panel {
  position: relative;
  padding: clamp(48px, 6vw, 96px) clamp(24px, 4vw, 108px);
  border-radius: clamp(24px, 4vw, 64px);
  overflow: hidden;
  /* One flattened export from Figma: the arch artwork with the navy-to-teal
     wash already composited into it, so no blend layers are needed here. */
  background: #0c2643 url("outer.webp") center / cover no-repeat;
}

/* Once the two columns sit side by side the panel is close to the artwork's own
   2.3:1 ratio, so stretch it to the box instead of cropping — that keeps the
   whole arch composition inside the rounded corners. Below this the panel is
   portrait and `cover` is the only sensible fit. */
@media (min-width: 1200px) {
  .pp-vcta__panel {
    background-size: 100% 100%;
  }
}

/* Figma: a 536px copy column and a 648px media column, pushed apart inside the
   1320px content width. Expressed as fr so the ratio survives narrow viewports —
   fixed px tracks would shrink to the same width once space ran out. */
.pp-vcta__grid {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: minmax(0, 536fr) minmax(0, 648fr);
  align-items: center;
  gap: clamp(40px, 6vw, 136px);
  max-width: var(--pp-max);
  margin-inline: auto;
}

.pp-vcta__copy {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 16px;
}

/* The dot stays brand yellow here; .pp-on-dark would otherwise whiten it. */
.pp-vcta .pp-eyebrow::before {
  background: var(--pp-yellow);
}

/* Only the headline carries weight in this panel — the semi-bold the design
   system defaults to reads too heavy against the dark ground. */
.pp-vcta__copy .pp-eyebrow,
.pp-vcta__copy .pp-lead {
  font-weight: 400;
}

.pp-vcta__copy .pp-btn {
  height: 64px;
  margin-top: 8px;
}

.pp-vcta__media {
  display: flex;
  flex-direction: column;
  gap: 32px;
}

.pp-vcta__author {
  display: flex;
  align-items: center;
  gap: 16px;
}

.pp-vcta__avatar {
  flex: 0 0 auto;
  width: 72px;
  height: 72px;
  border-radius: 50%;
  object-fit: cover;
  /* Portrait source, so bias the crop towards the head rather than the middle. */
  object-position: top center;
}

.pp-vcta__byline {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.pp-vcta__byline .pp-h3,
.pp-vcta__role {
  margin: 0;
  color: var(--pp-linen);
  line-height: 1.3;
}

.pp-vcta__byline .pp-h3 {
  font-weight: 500;
}

.pp-vcta__role {
  font-size: clamp(1.125rem, 1.06rem + 0.3vw, 1.3125rem);
  /* 21px */
  font-weight: 400;
}

@media (max-width: 1199.98px) {
  .pp-vcta__grid {
    grid-template-columns: minmax(0, 1fr);
    gap: 40px;
  }
}

/* --------------------------------------------------------------------------
   09 — Benefits (sticky scrollytelling)
   -------------------------------------------------------------------------- */

/* `visible` so position:sticky inside is not clipped. */
.pp-benefits {
  overflow: visible;
  padding-block: 0 clamp(72px, 9vw, 128px);
}

.pp-benefits__decor {
  position: absolute;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
}

.pp-benefits__grid {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 564px) minmax(0, 1fr);
  align-items: start;
  gap: 0;
}

.pp-benefits__steps {
  display: flex;
  flex-direction: column;
  gap: clamp(140px, 20vw, 384px);
  padding: clamp(160px, 24vw, 512px) clamp(32px, 6vw, 120px) clamp(120px, 16vw, 300px) 0;
}

.pp-step {
  display: flex;
  align-items: center;
  gap: 24px;
  opacity: 0.45;
  transition: opacity 0.35s ease;
}

.pp-step.is-active {
  opacity: 1;
}

.pp-step__body {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.pp-benefits__sticky {
  align-self: stretch;
  padding-top: clamp(80px, 12vw, 200px);
}

.pp-benefits__frame {
  position: sticky;
  top: 12vh;
  padding: 17px;
  border: 1px solid var(--pp-periwinkle);
  border-radius: var(--pp-radius-lg);
  background: rgba(255, 255, 255, 0.6);
  backdrop-filter: blur(14px);
  aspect-ratio: 864 / 718;
  max-height: 76vh;
}

.pp-benefits__shots {
  position: relative;
  width: 100%;
  height: 100%;
}

.pp-benefits__shot {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border-radius: var(--pp-radius);
  object-fit: cover;
  object-position: top center;
  opacity: 0;
  transform: scale(1.015);
  transition: opacity 0.5s ease, transform 0.5s ease;
}

.pp-benefits__shot.is-active {
  opacity: 1;
  transform: none;
}

@media (max-width: 1199.98px) {
  .pp-benefits__grid {
    grid-template-columns: 1fr;
  }

  .pp-benefits__steps {
    gap: 48px;
    padding: 0 0 40px;
  }

  /* The inline screenshot below joins this flex line once it is shown, so
     stack instead — side by side it squeezes the copy to a word per line. */
  .pp-step {
    flex-direction: column;
    align-items: stretch;
    opacity: 1;
  }

  /* Each step carries its own inline screenshot below this breakpoint, so the
     sticky column would only ever render an empty frame. */
  .pp-benefits__sticky {
    display: none;
  }
}

/* Below the sticky breakpoint each step carries its own inline screenshot. */
.pp-step__row {
  display: flex;
  align-items: center;
  gap: 24px;
}

.pp-step__frame {
  display: none;
  margin-top: 24px;
  padding: 17px;
  border: 1px solid var(--pp-periwinkle);
  border-radius: var(--pp-radius-lg);
  background: rgba(255, 255, 255, 0.6);
  backdrop-filter: blur(14px);
}

.pp-step__shot {
  display: block;
  width: 100%;
  height: auto;
  border-radius: var(--pp-radius);
}

@media (max-width: 1199.98px) {
  .pp-step__frame {
    display: block;
  }
}

/* On phones the steps become a stack of full-height cards: each one pins
   directly below the site header and the following step scrolls up over it,
   then the page carries on scrolling normally once the last one is reached.
   --pp-header-h is measured at runtime by passport.js, because the header
   belongs to the page template rather than this bundle. */
@media (max-width: 767.98px) {
  .pp-benefits__steps {
    display: block;
    gap: 0;
    padding: 0;
  }

  .pp-step {
    position: sticky;
    top: var(--pp-header-h, 0px);
    height: calc(100vh - var(--pp-header-h, 0px));
    height: calc(100svh - var(--pp-header-h, 0px));
    /* Now the frame is capped at square it no longer fills the card, so centre
       the copy and screenshot as a pair with matching space above and below. */
    justify-content: center;
    gap: 0;
    padding-block: 32px;
    /* Opaque, so a step completely covers the one it slides over. */
    background: var(--pp-linen);
  }

  .pp-step__row {
    flex: 0 0 auto;
  }

  /* Square at most: the frame takes the height left over from the copy, but
     never grows taller than it is wide. It can still shrink below square on
     short screens, which is why it stays shrinkable rather than fixed. */
  .pp-step__frame {
    display: flex;
    flex: 0 1 auto;
    aspect-ratio: 1;
    min-height: 0;
    margin-top: 20px;
  }

  .pp-step__shot {
    flex: 1 1 auto;
    min-height: 0;
    object-fit: cover;
    object-position: top center;
  }
}

/* --------------------------------------------------------------------------
   10 — Testimonials
   -------------------------------------------------------------------------- */

.pp-quotes {
  padding: 0 clamp(16px, 2vw, 32px) clamp(72px, 9vw, 160px);
}

.pp-quotes__panel {
  position: relative;
  padding: clamp(56px, 8vw, 128px) clamp(24px, 4vw, 108px) clamp(48px, 6vw, 72px);
  border-radius: clamp(24px, 4vw, 64px);
  overflow: hidden;
  /* Figma: white base with a top-to-bottom cyan wash at 20%. */
  background-image:
    linear-gradient(180deg, rgba(255, 255, 255, 0.2) 0%, rgba(0, 174, 217, 0.2) 100%),
    linear-gradient(90deg, #fff 0%, #fff 100%);
}

.pp-quotes__panel .pp-ribbon::before {
  opacity: 0.1;
}

.pp-quotes__orbs {
  position: absolute;
  left: 50%;
  top: 42%;
  translate: -50% -50%;
  width: 128%;
  max-width: none;
  transform: rotate(180deg) scaleY(-1);
  opacity: 0.5;
  pointer-events: none;
  animation: pp-drift 34s ease-in-out -8s infinite;
}

.pp-quotes__inner {
  position: relative;
  z-index: 1;
  max-width: var(--pp-max);
  margin-inline: auto;
}

.pp-quotes__head {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
  margin-bottom: 40px;
  text-align: center;
}

.pp-quotes__head .pp-mega {
  max-width: 1000px;
}

.pp-quotes__viewport {
  overflow: hidden;
  /* Matched to the track's slide so the two move together when the script
     clips this to the height of a single quote. See initQuotes. */
  transition: height 0.5s cubic-bezier(0.22, 0.61, 0.36, 1);
}

.pp-quotes__track {
  display: flex;
  transition: transform 0.5s cubic-bezier(0.22, 0.61, 0.36, 1);
}

.pp-quotes__slide {
  flex: 0 0 100%;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(32px, 6vw, 120px);
  align-items: stretch;
}

.pp-quote {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: 24px;
}

.pp-quote__body {
  display: flex;
  flex-direction: column;
  gap: 24px;
  padding-bottom: 24px;
}

/* Pseudo-element for the same reason as .pp-ai__link::after. */
.pp-quote__body::before {
  content: "";
  flex: none;
  width: 61px;
  height: 48px;
  background: url("quote-mark.svg") 0 0 / contain no-repeat;
}

/* Figma sets the quote at the h3 size but in the regular weight. */
.pp-quote blockquote {
  margin: 0;
  font-weight: 400;
}

.pp-quote__meta {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
}

.pp-quote__org {
  color: var(--pp-body);
  font-size: var(--pp-fs-sm);
  line-height: 1.5;
}

.pp-quote__logo {
  width: 150px;
  height: 85px;
  object-fit: contain;
  object-position: left center;
  mix-blend-mode: multiply;
}

/* 12px pills, the active one stretched to 49px. Euromonitor asked for the dots
   to carry the same orange as the buttons rather than the accent gradient. */
.pp-dots {
  display: flex;
  justify-content: center;
  gap: 12px;
  margin-top: 32px;
}

.pp-dots button {
  width: 12px;
  height: 12px;
  padding: 0;
  border: 0;
  border-radius: 999px;
  background: var(--pp-yellow);
  opacity: 0.3;
  cursor: pointer;
  transition: width 0.2s ease, opacity 0.2s ease;
}

.pp-dots button.is-active {
  width: 49px;
  opacity: 1;
}

.pp-dots button:focus-visible {
  outline: 3px solid var(--pp-royal-blue);
  outline-offset: 3px;
}

@media (max-width: 991.98px) {
  .pp-quotes__slide {
    grid-template-columns: 1fr;
  }

  .pp-quotes__slide .pp-quote:nth-child(2) {
    display: none;
  }

  /* A flex row is as tall as its tallest item, so every slide was being held
     at the height of the longest quote in the set. Letting each keep its own
     height is half the fix; the script clips the viewport to whichever slide
     is on show. */
  .pp-quotes__track {
    align-items: flex-start;
  }

  /* With one quote to a slide there is no second caption for this one to line
     up against, so space-between has nothing left to do but push the
     attribution to the bottom of whatever height the slide has. */
  .pp-quote {
    justify-content: flex-start;
  }
}

/* --------------------------------------------------------------------------
   Thought leadership (no block currently ships this)
   -------------------------------------------------------------------------- */

.pp-insights {
  padding-block: clamp(64px, 8vw, 96px);
}

/* Full-bleed molten-glass backdrop behind the case-study cards. The artwork is
   very saturated, so it runs as a soft wash that fades out at both edges. */
.pp-insights__decor {
  position: absolute;
  inset: -7% -6%;
  z-index: 0;
  opacity: 0.22;
  pointer-events: none;
  -webkit-mask-image: linear-gradient(180deg, transparent, #000 18%, #000 82%, transparent);
  mask-image: linear-gradient(180deg, transparent, #000 18%, #000 82%, transparent);
}

.pp-insights__decor img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.pp-insights>.pp-container,
.pp-insights>.pp-carousel {
  position: relative;
  z-index: 1;
}

.pp-insights__head {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 24px;
  text-align: center;
}

.pp-insights__head .pp-mega {
  max-width: 1150px;
}

.pp-insights__head .pp-filters {
  justify-content: center;
}

.pp-carousel {
  position: relative;
  margin-top: 8px;
}

.pp-carousel__track {
  display: flex;
  gap: 24px;
  padding-block: 40px;
  overflow-x: auto;
  scroll-snap-type: x proximity;
  scroll-padding-inline: var(--pp-gutter);
  scrollbar-width: none;
}

/* The card rail runs edge to edge on wide screens: the inline padding keeps the
   first card flush with the 1320 grid while the rest bleed off the viewport. */
.pp-insights .pp-carousel>.pp-container {
  max-width: none;
  padding-inline: 0;
}

.pp-insights .pp-carousel__track {
  padding-inline: max(var(--pp-gutter), calc((100% - var(--pp-max)) / 2));
  scroll-padding-inline: max(var(--pp-gutter), calc((100% - var(--pp-max)) / 2));
}

.pp-carousel__track::-webkit-scrollbar {
  display: none;
}

.pp-carousel__track.is-dragging {
  cursor: grabbing;
  scroll-snap-type: none;
}

.pp-card {
  position: relative;
  flex: 0 0 424px;
  max-width: 424px;
  display: flex;
  flex-direction: column;
  gap: 24px;
  padding: 24px;
  border-radius: var(--pp-radius-lg);
  background: #fff;
  scroll-snap-align: start;
  filter: drop-shadow(0 22px 13px rgba(85, 105, 135, 0.58));
  transition: transform 0.18s ease;
}

.pp-card:hover {
  transform: translateY(-4px);
}

.pp-card__media {
  position: relative;
}

.pp-card__media img {
  display: block;
  width: 100%;
  aspect-ratio: 367 / 245;
  border-radius: var(--pp-radius-sm);
  object-fit: cover;
}

.pp-card__type {
  position: absolute;
  top: 8px;
  right: 8px;
}

.pp-card__play {
  position: absolute;
  left: 50%;
  top: 50%;
  translate: -50% -50%;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 72px;
  height: 72px;
  border: 6px solid rgba(255, 255, 255, 0.4);
  border-radius: 999px;
  background: var(--pp-yellow);
  backdrop-filter: blur(4px);
}

.pp-card__play img {
  width: 48px;
  height: 48px;
  margin-left: 3px;
}

.pp-card__text {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.pp-card__text .pp-h3 {
  color: #000;
}

.pp-card__excerpt {
  color: #000;
}

.pp-card__foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin-top: auto;
}

.pp-card__tags {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}

.pp-card__link {
  display: inline-flex;
}

/* The arrow is the card's only link; this stretches its hit area over the card. */
.pp-card__link::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
}

@supports selector(:has(*)) {
  .pp-card__link:focus-visible {
    outline: none;
  }

  .pp-card:has(.pp-card__link:focus-visible) {
    outline: 3px solid var(--pp-royal-blue);
    outline-offset: 3px;
  }
}

.pp-card__link img {
  width: 24px;
  height: 24px;
  transition: transform 0.18s ease;
}

.pp-card:hover .pp-card__link img {
  transform: translateX(4px);
}

.pp-carousel__nav {
  display: flex;
  justify-content: flex-end;
  gap: 12px;
}

.pp-carousel__btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 48px;
  height: 48px;
  border: 1px solid var(--pp-cyan);
  border-radius: 999px;
  background: #fff;
  cursor: pointer;
  transition: background-color 0.18s ease, opacity 0.18s ease;
}

.pp-carousel__btn:hover:not(:disabled) {
  background: rgba(0, 174, 217, 0.12);
}

.pp-carousel__btn:disabled {
  opacity: 0.35;
  cursor: default;
}

.pp-carousel__btn img {
  width: 24px;
  height: 24px;
}

.pp-carousel__btn--prev img {
  rotate: 180deg;
}

@media (max-width: 575.98px) {
  .pp-card {
    flex-basis: 82vw;
    max-width: 82vw;
  }
}

/* --------------------------------------------------------------------------
   11 — FAQs
   -------------------------------------------------------------------------- */

.pp-faq {
  padding-block: 0 clamp(72px, 9vw, 128px);
  overflow: visible;
}

.pp-faq__grid {
  display: grid;
  grid-template-columns: minmax(0, 512px) minmax(0, 1fr);
  align-items: start;
  gap: 0;
}

.pp-faq__aside {
  position: sticky;
  top: 96px;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 16px;
  padding-right: 80px;
}

.pp-faq__aside .pp-btn {
  margin-top: 16px;
}

.pp-faq__list {
  display: flex;
  flex-direction: column;
  gap: 24px;
  padding-top: 28px;
}

.pp-faq__filters {
  justify-content: flex-end;
  padding-bottom: 24px;
}

.pp-acc__item {
  display: flex;
  flex-direction: column;
  gap: 24px;
}

/* The rule belongs to the item so filtering it out takes the rule with it. */
.pp-acc__item::after {
  content: "";
  display: block;
  width: 100%;
  height: 1px;
  opacity: 0.5;
  background: var(--pp-grad-divider);
}

/* The heading is only a semantic wrapper; the button inside carries the type.
   Classed rather than left bare so no host stylesheet can reach it. */
.pp-acc__heading {
  margin: 0;
  padding: 0;
  font: inherit;
  color: inherit;
}

.pp-acc__btn {
  display: flex;
  align-items: center;
  gap: 32px;
  width: 100%;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--pp-ink);
  font-family: var(--pp-font);
  font-size: var(--pp-fs-h3);
  font-weight: 600;
  line-height: 1.3;
  text-align: left;
  cursor: pointer;
}

.pp-acc__btn>span:first-child {
  flex: 1 1 auto;
}

/* Figma wraps the chevron in a 40px tinted circle. */
.pp-acc__icon {
  flex: 0 0 40px;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border-radius: 9999px;
  background: var(--pp-tint);
  transition: rotate 0.25s ease;
}

.pp-acc__btn img {
  flex: 0 0 24px;
  width: 24px;
  height: 24px;
}

.pp-acc__btn[aria-expanded="true"] .pp-acc__icon {
  rotate: 180deg;
}

.pp-acc__btn:focus-visible {
  outline: 3px solid var(--pp-royal-blue);
  outline-offset: 4px;
}

.pp-acc__panel {
  padding-bottom: 16px;
  color: var(--pp-body);
}

@media (max-width: 991.98px) {
  .pp-faq__grid {
    grid-template-columns: 1fr;
    gap: 32px;
  }

  .pp-faq__aside {
    position: static;
    padding-right: 0;
  }

  .pp-faq__filters {
    justify-content: flex-start;
  }
}

/* --------------------------------------------------------------------------
   12 — Request a demo (form)
   -------------------------------------------------------------------------- */

.pp-form {
  padding-block: clamp(64px, 8vw, 128px) clamp(72px, 9vw, 160px);
}

/* Two stacked artworks from Figma: the arches wash pinned to the top of the
   section at its natural 2953:1434 ratio, plus a linen-to-white strip that
   fades it in from the band above. */
.pp-form__decor {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  /* 148.53% of the section width at the artwork's native 2953:1434 ratio. */
  aspect-ratio: 1.386;
  z-index: 0;
  pointer-events: none;
  background-image: url("decor-form.png");
  background-repeat: no-repeat;
  background-position: 23.2% top;
  background-size: 148.53% 100%;
  mix-blend-mode: darken;
  /* The live section runs taller than the 1154px frame, so the artwork is
     faded out rather than cut off at its bottom edge. */
  -webkit-mask-image: linear-gradient(180deg, #000 60%, transparent 100%);
  mask-image: linear-gradient(180deg, #000 60%, transparent 100%);
}

.pp-form__decor::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  aspect-ratio: 1600 / 333;
  background: url("decor-form-top.png") center / 100% 100% no-repeat;
}

/* The mobile comp moves the artwork to the foot of the section: it fills the
   bottom half, blown up to ~3.6x the screen width so only the arch curves read,
   with the linen strip fading it in from the copy above rather than sitting at
   the top of the section. */
@media (max-width: 767.98px) {
  .pp-form {
    padding-bottom: calc(clamp(72px, 9vw, 160px) + 20px);
  }

  /* Host-site footer, so no `pp-` prefix. It is pulled up to close the gap the
     extra section padding opens above it. */
  .e-footer-body {
    margin-top: -28px;
  }

  .pp-form__decor {
    top: auto;
    bottom: 0;
    height: 50%;
    aspect-ratio: auto;
    /* Figma offsets the artwork -175.78% into a box 359.89% wide, which lands
       at 67.6% of the 259.89% of overflow. */
    background-position: 67.6% bottom;
    background-size: 359.89% 100%;
    -webkit-mask-image: none;
    mask-image: none;
  }

  /* Figma keeps the strip at its native 333px against a 1524px frame — a
     little under half the band — rather than scaling it with the width. */
  .pp-form__decor::before {
    aspect-ratio: auto;
    height: 44%;
    background-size: 100% 100%;
  }
}

.pp-form>.pp-container {
  position: relative;
  z-index: 1;
}

.pp-form__grid {
  display: grid;
  grid-template-columns: minmax(0, 512px) minmax(0, 648px);
  justify-content: space-between;
  align-items: start;
  gap: 0;
}

.pp-form__copy {
  display: flex;
  flex-direction: column;
  gap: 40px;
  padding-right: 80px;
}

.pp-form__head {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.pp-form__steps {
  display: flex;
  flex-direction: column;
  gap: 24px;
}

.pp-form__step {
  display: flex;
  gap: 16px;
}

.pp-form__step-body {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.pp-form__slot {
  padding: 28px 0 0 80px;
}

/* The live form is the Euromonitor Marketo embed; this is the shell it drops into. */
.pp-form__embed {
  display: flex;
  flex-direction: column;
  gap: 24px;
  min-height: 560px;
  padding: 32px;
  border-radius: var(--pp-radius-lg);
  background: #fff;
  filter: drop-shadow(0 22px 13px rgba(85, 105, 135, 0.58));
}

.pp-form__loading {
  color: var(--pp-muted);
}

.pp-form__thanks {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.pp-form__thanks[hidden] {
  display: none;
}

/* Marketo's own stylesheet is removed at runtime, so the form is restyled here. */
.pp-form__embed .mktoForm {
  display: flex;
  flex-direction: column;
  gap: 20px;
  width: 100% !important;
  padding: 0 !important;
  font-family: var(--pp-font);
  font-size: var(--pp-fs-md);
  color: var(--pp-body);
}

.pp-form__embed .mktoForm .mktoOffset,
.pp-form__embed .mktoForm .mktoGutter,
.pp-form__embed .mktoForm .mktoClear {
  display: none !important;
}

/* Spacer rows carry no field. This is a live :has() test rather than a JS flag
   because Marketo renders conditional rows after the form-ready callback. */
.pp-form__embed .mktoForm .mktoFormRow:not(:has(input:not([type="hidden"]), select, textarea, button)) {
  display: none;
}

.pp-form__embed .mktoForm .mktoFormCol,
.pp-form__embed .mktoForm .mktoFieldWrap {
  float: none !important;
  width: 100% !important;
  min-height: 0 !important;
}

/* Figma pairs the label with the field on one row, but the live Marketo field
   names are far longer than the mock's, so they stay stacked and only inherit
   the design's label typography. */
.pp-form__embed .mktoForm .mktoFormCol {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.pp-form__embed .mktoForm .mktoLabel {
  float: none !important;
  width: auto !important;
  padding: 0 !important;
  /* Marketo emits the asterisk before the label text; reversing puts it after. */
  display: flex;
  flex-direction: row-reverse;
  justify-content: flex-end;
  gap: 2px;
  font-size: var(--pp-fs-md);
  font-weight: 400;
  line-height: 24px;
  color: var(--pp-muted);
}

.pp-form__embed .mktoForm .mktoAsterix {
  float: none;
  color: var(--pp-orange);
}

.pp-form__embed .mktoForm input[type="text"],
.pp-form__embed .mktoForm input[type="email"],
.pp-form__embed .mktoForm input[type="tel"],
.pp-form__embed .mktoForm input[type="url"],
.pp-form__embed .mktoForm input[type="number"],
.pp-form__embed .mktoForm select,
.pp-form__embed .mktoForm textarea {
  width: 100% !important;
  height: 40px;
  padding: 0 16px;
  border: 1px solid #d5d8de;
  border-radius: var(--pp-radius-sm);
  background: #fff;
  font: inherit;
  color: var(--pp-ink);
}

.pp-form__embed .mktoForm textarea {
  height: auto;
  min-height: 120px;
  padding: 12px 16px;
  resize: vertical;
}

.pp-form__embed .mktoForm input:focus,
.pp-form__embed .mktoForm select:focus,
.pp-form__embed .mktoForm textarea:focus {
  outline: 2px solid var(--pp-royal-blue);
  outline-offset: 1px;
  border-color: transparent;
}

.pp-form__embed .mktoForm .mktoRadioList,
.pp-form__embed .mktoForm .mktoCheckboxList {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 20px;
  width: 100% !important;
  padding: 0 !important;
}

.pp-form__embed .mktoForm .mktoRadioList label,
.pp-form__embed .mktoForm .mktoCheckboxList label {
  margin: 0 0 0 6px;
  font-size: var(--pp-fs-md);
}

.pp-form__embed .mktoForm .mktoButtonRow {
  display: flex;
}

.pp-form__embed .mktoForm .mktoButtonWrap {
  margin-left: 0 !important;
}

.pp-form__embed .mktoForm button.mktoButton {
  padding: 12px 32px;
  border: 0;
  border-radius: var(--pp-radius-pill);
  background: var(--pp-yellow) !important;
  color: var(--pp-ink);
  font-family: var(--pp-font-btn);
  font-size: var(--pp-fs-md);
  font-weight: 600;
  line-height: 1.4;
  cursor: pointer;
  transition: background-color 0.18s ease;
}

.pp-form__embed .mktoForm button.mktoButton:hover {
  background: var(--pp-yellow-hover) !important;
}

.pp-form__embed .mktoForm .mktoError {
  position: static !important;
}

.pp-form__embed .mktoForm .mktoErrorMsg {
  margin-top: 6px;
  padding: 0;
  border: 0;
  background: none;
  box-shadow: none;
  color: #c02b1a;
  font-size: var(--pp-fs-sm);
}

.pp-form__embed .mktoForm .mktoErrorArrow {
  display: none;
}

@media (max-width: 991.98px) {
  .pp-form__grid {
    grid-template-columns: 1fr;
    gap: 40px;
  }

  .pp-form__copy {
    padding-right: 0;
  }

  .pp-form__slot {
    padding: 0;
  }
}

/* --------------------------------------------------------------------------
   Scroll reveal
   -------------------------------------------------------------------------- */

.pp-reveal {
  opacity: 0;
  transform: translateY(20px);
  transition: opacity 0.45s ease var(--pp-delay, 0ms), transform 0.45s ease var(--pp-delay, 0ms);
}

.pp-reveal.is-in {
  opacity: 1;
  transform: none;
}

@media (prefers-reduced-motion: reduce) {

  .pp-block *,
  .pp-block *::before,
  .pp-block *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }

  .pp-reveal {
    opacity: 1;
    transform: none;
  }

  .pp-logos__track {
    animation: none;
  }

  .pp-hero__card {
    animation: none;
  }

  .pp-step {
    opacity: 1;
  }

  .pp-ai__orbs,
  .pp-quotes__orbs {
    animation: none !important;
  }
}