/**
 * Partners page.
 *
 * Loaded only on that page. Shared components (the header, the footer, the
 * eyebrow base rule) come from main.css; this file covers the eight bands that
 * exist only here.
 *
 * Written against the 1728px Figma frame, which is where every literal below
 * comes from: the content column is 1280 centred, so at 1728 the gutter is
 * 224 either side and every measurement in this file is 1:1 with the design.
 * Below 1360 the column takes a gutter of its own and the fixed grid tracks
 * shrink; the numbers stop being 1:1 there on purpose.
 */

/* -------------------------------------------------------------------------
 * Out of the full-screen floor.
 *
 * `main > section` carries min-height: 100vh with display: grid. Every band on
 * this page below the hero is measured — the pillars 2880 — and a viewport
 * floor would stretch whichever of them happened to be shorter than the window
 * and push the whole page past its 7963px. Both declarations are needed: the
 * grid is what centres content in the taller box, so dropping the floor without
 * dropping the grid leaves the align-content behind.
 * ---------------------------------------------------------------------- */

.zouma-ptn-hero,
.zouma-ptn-intro,
.zouma-ptn-pillars,
.zouma-ptn-routes,
.zouma-ptn-journey,
.zouma-ptn-tiers,
.zouma-ptn-stories,
.zouma-ptn-cta {
  min-height: auto;
  display: block;
}

/* -------------------------------------------------------------------------
 * Shared
 * ---------------------------------------------------------------------- */

/* The content column. 1280, not .zouma-shell's 1320 — the design's gutter is
 * 224 either side of 1728 and the shell's is 204.
 *
 * min-width: 0 because the grids below it hold fixed tracks and a scrolling
 * story track, and a grid item keeps min-width: auto: it refuses to shrink
 * under its own content and pushes the column wider than the viewport, where
 * .zouma-site's overflow-x: clip swallows it without a scrollbar to show for
 * it. */
.zouma-ptn__inner {
  max-width: 1280px;
  margin-inline: auto;
  min-width: 0;
}

/* No padding at the design width — 1280 inside 1728 already leaves the gutter.
 * The padding only appears once the viewport stops providing one. */
@media (max-width: 1360px) {
  .zouma-ptn__inner {
    padding-inline: clamp(1rem, calc(3 * var(--zouma-vw)), 2.5rem);
  }
}

.zouma-ptn-eyebrow {
  margin: 0;
  gap: 8px;
  color: var(--zouma-dark);
  font-family: var(--zouma-font-body);
  font-size: 12px;
  font-weight: 600;
  line-height: 16px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.zouma-ptn-eyebrow--light {
  color: #fff;
}

.zouma-ptn-eyebrow .zouma-icon--spark {
  flex: none;
  color: var(--zouma-cyan);
}

/* One size for all seven section headings, stated at element-plus-class so it
 * ties with main.css's own h2.class rule and wins on load order. A bare
 * .class would lose to it outright. */
h2.zouma-ptn-intro__title,
h2.zouma-ptn-pillars__title,
h2.zouma-ptn-routes__title,
h2.zouma-ptn-journey__title,
h2.zouma-ptn-tiers__title,
h2.zouma-ptn-stories__title,
h2.zouma-ptn-cta__title {
  margin: 0;
  font-family: var(--zouma-font-heading);
  font-size: 48px;
  font-weight: 700;
  line-height: 50px;
  letter-spacing: 0;
}

/* Buttons.
 *
 * style.css repaints every bare `button` — a filled primary background, its own
 * padding, a radius and a hover — and that hover is `button:hover`, (0,1,1).
 * A plain `.zouma-ptn-btn:hover` is (0,1,1) too and would only tie, so these
 * are written with the element in front of the class: `a.` for what the page
 * actually renders and `button.` beside it so the reset still holds if one of
 * these ever becomes a real button. Every state repaints its own background,
 * because a state that inherits is a state style.css can reach.
 */
a.zouma-ptn-btn,
button.zouma-ptn-btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  width: auto;
  padding: 8px 16px;
  border: 0;
  border-radius: 4px;
  font-family: var(--zouma-font-body);
  font-size: 16px;
  font-weight: 600;
  line-height: 26px;
  text-decoration: none;
  cursor: pointer;
  transition: transform var(--zouma-transition);
}

a.zouma-ptn-btn:hover,
button.zouma-ptn-btn:hover,
a.zouma-ptn-btn:focus-visible,
button.zouma-ptn-btn:focus-visible {
  transform: translateY(-1px);
}

a.zouma-ptn-btn:focus-visible,
button.zouma-ptn-btn:focus-visible {
  outline: 2px solid var(--zouma-cyan);
  outline-offset: 3px;
}

a.zouma-ptn-btn .zouma-icon,
button.zouma-ptn-btn .zouma-icon {
  flex: none;
  width: 16px;
  height: 16px;
}

a.zouma-ptn-btn--primary,
button.zouma-ptn-btn--primary,
a.zouma-ptn-btn--primary:hover,
button.zouma-ptn-btn--primary:hover,
a.zouma-ptn-btn--primary:focus-visible,
button.zouma-ptn-btn--primary:focus-visible {
  background: var(--zouma-cyan);
  color: #fff;
}

a.zouma-ptn-btn--light,
button.zouma-ptn-btn--light,
a.zouma-ptn-btn--light:hover,
button.zouma-ptn-btn--light:hover,
a.zouma-ptn-btn--light:focus-visible,
button.zouma-ptn-btn--light:focus-visible {
  background: #fff;
  color: var(--zouma-dark);
}

a.zouma-ptn-btn--dark,
button.zouma-ptn-btn--dark,
a.zouma-ptn-btn--dark:hover,
button.zouma-ptn-btn--dark:hover,
a.zouma-ptn-btn--dark:focus-visible,
button.zouma-ptn-btn--dark:focus-visible {
  background: var(--zouma-dark);
  color: #fff;
}

/* -------------------------------------------------------------------------
 * 01 · Hero — one screen
 *
 *   Section  #121212, the photograph filling the right half under a radial
 *            wash and the dot grid
 *   Copy     720 column at y=267, 24px stack, body held to 600
 *   Title    Albert Sans 700 · 57/74 · #FFFFFF
 *   Bar      53px strip across the foot, five marks, 39px apart
 * ---------------------------------------------------------------------- */

.zouma-ptn-hero {
  position: relative;
  display: flex;
  flex-direction: column;
  /* One screen exactly, so #ptn-intro starts at the fold.
   *
   * No --zouma-header-h subtracted, and that is the part worth stating: the
   * header is sticky, so it stays in flow and the negative margin below only
   * cancels the 76px it occupies. The section's top edge lands at y=0, level
   * with the viewport top — measured, not assumed. Taking the header off this
   * 100 as well would end the band 76px short of the fold and show a strip of
   * the intro above it.
   *
   * min-height, never height: at 390 the copy, the CTAs and the foot bar
   * already need 1385px, so the band has to be free to grow past a screen
   * rather than clip them.
   *
   * svh after vh: 100vh on a phone measures the viewport with the browser
   * chrome retracted, so it runs taller than what the visitor can see. vh
   * stays first as the fallback. */
  min-height: 100vh;
  min-height: 100svh;
  /* The header floats over this hero rather than sitting above it, so the
   * section is pulled up under it and the copy is placed from the section's
   * own top edge — 267px, which is where the design puts it with the nav
   * overlaying the first 76. */
  margin-top: calc(-1 * var(--zouma-header-h));
  padding-top: 267px;
  background-color: var(--zouma-dark);
  color: #fff;
  /* clip, not hidden: hidden would force the other axis to auto and make this
   * a scroll container, which kills the sticky header above it. */
  overflow: clip;
}

.zouma-ptn-hero__bg {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

/* The right half of the band, and no wider.
 *
 * This used to carry the Figma layer's own 1350 x 932 box anchored on the
 * centre line, which is what the layer measures — but a 1350 box starting at
 * 864 runs to 2214 on a 1728 frame, so a third of the picture sat outside the
 * viewport. That third is the half the subject is standing in: all that
 * survived on screen was her hand at the right edge. Bounding the box to the
 * frame keeps the crop inside the space it actually has. */
.zouma-ptn-hero__photo {
  position: absolute;
  top: 0;
  inset-inline-start: 50%;
  inset-inline-end: 0;
  height: 100%;
}

.zouma-ptn-hero__photo img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Framed on the subject rather than on an edge. The box is now narrower than
   * the picture's own proportions, so cover crops horizontally; left-anchoring
   * would keep the dark audience silhouettes and lose the presenter, which is
   * the only part of the shot that carries the section. */
  object-position: 62% center;
}

/* "Rectangle 11": a radial wash on the bottom edge, 656 across and 393 tall,
 * #0E85B6 at 60% fading into the section's own black. */
.zouma-ptn-hero__glow {
  position: absolute;
  inset: 0;
  background: radial-gradient(
    ellipse 656px 393px at 50% 100%,
    rgba(14, 133, 182, 0.6) 0%,
    rgba(18, 18, 18, 0) 100%
  );
}

.zouma-ptn-hero__dots {
  position: absolute;
  inset: 0;
  background-image: radial-gradient(circle, rgba(173, 219, 243, 0.1) 1.4px, transparent 1.6px);
  background-size: 30.5px 29.5px;
}

.zouma-ptn-hero__inner {
  position: relative;
  /* Basis auto rather than the 0 a plain `flex: 1` sets: with a 0 basis the
   * section's min-height counts as a definite height, and anything the copy
   * needs beyond it spills past the bottom where the clip eats it. */
  flex: 1 1 auto;
  /* Load-bearing. The shared .zouma-ptn__inner centres itself with
   * margin-inline: auto, and an auto cross-axis margin on a flex item makes it
   * shrink to fit instead of stretching — so inside this column flex the
   * container collapsed to its widest child (the badge row, 1028px) rather
   * than the 1280 it is meant to be, and everything in it sat 126px too far
   * right. An explicit width restores the stretch the auto margins cancel. */
  width: 100%;
}

.zouma-ptn-hero__copy {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 24px;
  /* Bounded so the copy cannot reach the photograph.
   *
   * The picture starts at the halfway line and the container is 1280 centred,
   * so there are exactly 640px between the copy's left edge and the photo's at
   * every width the two-column hero applies to. 600 leaves a 40px gutter; more
   * than that and the last line of the paragraph runs onto the image, which is
   * dark at the design width and bright at 1440, so it hid until someone
   * resized. */
  width: min(600px, calc(50vw - 60px), 100%);
}

.zouma-ptn-hero__title {
  margin: 0;
  color: #fff;
  font-family: var(--zouma-font-heading);
  font-size: var(--zouma-size-hero);
  font-weight: 700;
  line-height: 74px;
  letter-spacing: 0;
}

.zouma-ptn-hero__text {
  max-width: 600px;
  margin: 0;
  color: #fff;
  font-family: var(--zouma-font-body);
  font-size: 16px;
  font-weight: 500;
  line-height: 29px;
}

.zouma-ptn-hero__ctas {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
}

.zouma-ptn-hero__bar {
  position: relative;
  display: flex;
  align-items: center;
  /* min-height rather than height, and it still resolves to the design's 53:
   * one 21px row centred in a 53px box is what the flex above produces either
   * way. What the floor adds is somewhere for a second row to go — the five
   * marks wrap below 1180 in English and at 1440 in Arabic, and a fixed 53
   * left that row hanging outside the strip it belongs to. */
  min-height: 53px;
  background: rgba(255, 255, 255, 0.1);
  /* Tinted from the bar's own fill rather than the pale divider used elsewhere
   * on this page. #e4e9ee is a light-background colour, and over the dark hero
   * photograph it read as a hard white rule across the full width. */
  border-top: 1px solid rgba(255, 255, 255, 0.12);
}

.zouma-ptn-hero__badges {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: 39px;
  width: 100%;
  margin: 0;
  padding-inline: clamp(1rem, calc(3 * var(--zouma-vw)), 2.5rem);
  list-style: none;
}

.zouma-ptn-hero__badge {
  display: flex;
  align-items: center;
  gap: 4px;
  color: #fff;
  font-family: var(--zouma-font-body);
  font-size: 14px;
  font-weight: 500;
  line-height: 21px;
  letter-spacing: -0.01em;
}

/* An 11px disc centred in the 16px box the design gives it, so the 4px gap to
 * the label measures from the box and not from the circle. */
.zouma-ptn-hero__dot {
  flex: none;
  width: 16px;
  height: 16px;
  background: radial-gradient(circle, var(--zouma-cyan-soft) 0 5.5px, transparent 5.5px);
}

/* -------------------------------------------------------------------------
 * 02 · Intro — 566px
 *
 *   Section  white under a texture at 30%, hairline across the top
 *   Left     670 column · eyebrow, H2, Albert Sans 500 19/29 body
 *   Right    546 window, 250 tall, holding a four-figure track at a 303 pitch
 * ---------------------------------------------------------------------- */

.zouma-ptn-intro {
  position: relative;
  padding-block: 120px;
  background-color: #fff;
  border-top: 1px solid #e4e9ee;
  overflow: clip;
}

.zouma-ptn-intro__texture {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0.3;
  pointer-events: none;
}

.zouma-ptn-intro__grid {
  position: relative;
  display: grid;
  /* Fixed at the design width, and free to shrink under it — a bare 670px
   * track would hold its width and push the column out instead. */
  grid-template-columns: minmax(0, 670px) minmax(0, 546px);
  gap: 64px;
  align-items: start;
}

.zouma-ptn-intro__copy {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 16px;
  min-width: 0;
}

.zouma-ptn-intro__text {
  margin: 0;
  color: var(--zouma-color-muted);
  font-family: var(--zouma-font-heading);
  font-size: 19px;
  font-weight: 500;
  line-height: 29px;
}

/* The window. One figure is 207 tall and the next starts 303 lower, so 250
 * shows one whole figure and none of the one behind it. */
.zouma-ptn-intro__stats {
  height: 250px;
  overflow: hidden;
  min-width: 0;
}

.zouma-ptn-intro__track {
  display: flex;
  flex-direction: column;
  gap: 96px;
  margin: 0;
  padding: 0;
  list-style: none;
}

/* One figure at a time, swapped by a fade rather than by sliding the column
 * past the window — the same effect as the homepage's Results band.
 *
 * is-ready, which partners.js adds once it has taken over, moves the four
 * figures into a single grid cell and takes the ones that are out down to
 * nothing. Without the script the column is left alone and the window crops it
 * as before, so the page still shows a figure with JavaScript off. */
.zouma-ptn-intro__stats.is-ready .zouma-ptn-intro__track {
  display: grid;
}

.zouma-ptn-intro__stats.is-ready .zouma-ptn-stat {
  grid-area: 1 / 1;
  opacity: 0;
}

.zouma-ptn-intro__stats.is-ready .zouma-ptn-stat.is-active {
  opacity: 1;
}

/* The transition is on its own class, added a frame after the poses above.
 * Declared with them, the three figures that start out would animate from the
 * opacity they were painted at down to nothing, in full view of the window. */
.zouma-ptn-intro__stats.is-fading .zouma-ptn-stat {
  transition: opacity 260ms ease;
}

.zouma-ptn-stat {
  display: flex;
  flex-direction: column;
  flex: none;
  gap: 4px;
  height: 207px;
}

.zouma-ptn-stat__value {
  color: var(--zouma-blue);
  font-family: var(--zouma-font-heading);
  font-size: 160px;
  font-weight: 700;
  line-height: 168px;
}

.zouma-ptn-stat__label {
  color: var(--zouma-dark);
  font-family: var(--zouma-font-heading);
  font-size: 32px;
  font-weight: 700;
  line-height: 35px;
}

/* -------------------------------------------------------------------------
 * 03 · Pillars — 1003px
 *
 * One rail now, where each of the four blocks used to repeat the whole
 * four-cell rail above its own body — that repetition was most of the old
 * 2880px. The section is head + rail + whichever panel is open:
 * 136 + 40 + 89 + 40 + 457 = 762 inside 120/120. The rail is 89 rather than
 * its tabs' 88 because the hairline under it is the rail's own border.
 * ---------------------------------------------------------------------- */

.zouma-ptn-pillars {
  padding-block: 120px;
  background-color: #fff;
  border-top: 1px solid #e4e9ee;
}

/* The one gap does head → rail and rail → panel alike. */
.zouma-ptn-pillars__inner {
  display: flex;
  flex-direction: column;
  gap: 40px;
}

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

.zouma-ptn-pillars__rail {
  display: flex;
  margin: 0;
  padding: 0;
  border-bottom: 1px solid #e4e9ee;
  list-style: none;
  /* Flex items floor at min-content the same way grid items do, and four
   * uppercase labels that will not wrap are exactly the content that pushes
   * the column past the viewport. */
  min-width: 0;
}

button.zouma-ptn-pillars__tab {
  position: relative;
  display: flex;
  align-items: center;
  height: 88px;
  padding: 24px;
  min-width: 0;
  color: var(--zouma-color-muted);
  font-family: var(--zouma-font-body);
  font-size: 16px;
  font-weight: 500;
  line-height: 16px;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  /* style.css repaints every bare button — a filled background, a radius and a
   * border of its own. Undone at button.<class> specificity, because a plain
   * .class rule loses to button:hover. border: 0 rather than a transparent
   * one: the global 1px would take 2px out of the border-box 88px height. */
  background: none;
  border: 0;
  border-radius: 0;
  text-align: start;
  font-family: var(--zouma-font-body);
  cursor: pointer;
  transition:
    color 160ms ease,
    background-color 160ms ease;
}

/* Nothing to see on hover — partners has no hover state, and these three
 * selectors exist only to keep style.css's button:hover from filling the tab
 * with #0b6d95. :focus is named too, because it stays on a tab after a click
 * and would leave the fill behind. */
button.zouma-ptn-pillars__tab:hover,
button.zouma-ptn-pillars__tab:focus,
button.zouma-ptn-pillars__tab:focus-visible {
  background: none;
  color: var(--zouma-dark);
}

button.zouma-ptn-pillars__tab:focus-visible {
  outline: 2px solid var(--zouma-blue);
  outline-offset: 3px;
}

/* After the hover rule, and at the same specificity, so pointing at the open
 * tab cannot wash its gradient off. */
button.zouma-ptn-pillars__tab.is-active {
  background: linear-gradient(180deg, rgba(225, 237, 249, 0) 0%, var(--zouma-blue-pale) 100%);
  color: var(--zouma-dark);
  font-weight: 600;
}

/* The active mark sits below the tab and over the rail's own hairline, as an
 * outside stroke does in the design. A border here would have made the lit
 * tab 3px taller than its four neighbours and bent the rail.
 *
 * Carried by every tab and scaled to nothing, so moving the mark is a
 * compositor transform rather than a stroke blinking on at full width. */
button.zouma-ptn-pillars__tab::after {
  content: "";
  position: absolute;
  inset-inline: 0;
  top: 100%;
  height: 3px;
  background: var(--zouma-blue);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 240ms cubic-bezier(0.33, 0, 0.2, 1);
}

button.zouma-ptn-pillars__tab.is-active::after {
  transform: scaleX(1);
}

/* [hidden] is only a display:none in the UA sheet. The panel deliberately
 * declares no display of its own — any author display here would outrank the
 * UA rule and leave all four panels open, which is indistinguishable from the
 * section before this change. */
.zouma-ptn-pillars__panel[hidden] {
  display: none;
}

/* An animation rather than a transition, and the same one the homepage rail
 * uses: a display:none element has no state to transition from, and a from-pose
 * applied with its own transition animates into the pose instead of out of it.
 * An animation is cancelled when display goes to none and restarts from zero
 * when the panel is shown again, so initTablist()'s plain `panel.hidden = false`
 * is the entire trigger. Keyframes are document-global and live in main.css,
 * which this sheet is enqueued after. */
.zouma-ptn-pillars__panel:not([hidden]) {
  animation: zouma-tabpanel-in 420ms cubic-bezier(0.22, 1, 0.36, 1) both;
}

.zouma-ptn-pillar__body {
  display: grid;
  grid-template-columns: minmax(0, 608px) minmax(0, 608px);
  gap: 64px;
  align-items: start;
}

.zouma-ptn-pillar__copy {
  display: flex;
  flex-direction: column;
  gap: 24px;
  min-width: 0;
}

.zouma-ptn-pillar__title {
  margin: 0;
  color: var(--zouma-dark);
  font-family: var(--zouma-font-heading);
  font-size: 48px;
  font-weight: 700;
  line-height: 50px;
}

.zouma-ptn-pillar__text {
  margin: 0;
  color: var(--zouma-color-muted);
  font-family: var(--zouma-font-body);
  font-size: 16px;
  font-weight: 500;
  line-height: 29px;
}

/* The sky backing is what shows while the photograph is still being fitted,
 * and what the picture sits on where its own edges fall short. */
.zouma-ptn-pillar__media {
  height: 457px;
  background-color: var(--zouma-sky);
  border-radius: 8px;
  overflow: hidden;
}

.zouma-ptn-pillar__media img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* -------------------------------------------------------------------------
 * 04 · Routes — 846px
 *
 * #042634 under the same radial wash the hero carries. Both columns start
 * their own 120 in from the top of the band; only the bottom padding is the
 * section's.
 * ---------------------------------------------------------------------- */

.zouma-ptn-routes {
  /* clip, not hidden: the head column is sticky, and `overflow: hidden` would
   * make this section a scroll container, penning the sticky child inside a box
   * that never scrolls — it would simply stop holding. `clip` clips the
   * sideways reveal travel the same way without creating one. */
  overflow: clip;
  padding-bottom: 120px;
  background-color: var(--zouma-teal);
  background-image: radial-gradient(
    ellipse 656px 357px at 50% 100%,
    rgba(14, 133, 182, 0.6) 0%,
    rgba(4, 38, 52, 0) 100%
  );
  color: #fff;
}

.zouma-ptn-routes__grid {
  display: grid;
  grid-template-columns: minmax(0, 470px) minmax(0, 714px);
  gap: 96px;
  align-items: start;
}

/* The head rides down with the reader, as the copy beside the commitments does
 * on the homepage. The four routes opposite run to roughly three times its
 * height, so left alone the question scrolls away from its own answers. Sticky
 * travels only inside its own grid area, which is the full height of the row,
 * so it releases again at the foot of the list rather than escaping the band.
 * Switched off below where the grid collapses to one column. */
.zouma-ptn-routes__head {
  position: sticky;
  /* The same expression the homepage pins at, so the two stay in step if the
   * header is ever resized. It clears the header's scrim rather than the header
   * box: .zouma-header::before hangs 2.25rem past the bar carrying the fill and
   * the backdrop blur, so the band that obscures the page reaches ~112px, not
   * the 76px the bar measures. Pinning inside it washes the eyebrow out. */
  top: calc(var(--zouma-header-h, 76px) + 3.5rem);
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 16px;
  padding-top: 120px;
  min-width: 0;
}

h2.zouma-ptn-routes__title {
  color: #fff;
}

.zouma-ptn-routes__text {
  margin: 0;
  color: #fff;
  font-family: var(--zouma-font-body);
  font-size: 14px;
  font-weight: 500;
  line-height: 21px;
  letter-spacing: -0.02em;
}

.zouma-ptn-routes__list {
  display: flex;
  flex-direction: column;
  gap: 64px;
  padding-top: 120px;
  min-width: 0;
}

.zouma-ptn-route {
  /* Positioning context for the sweep below. */
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 270px) minmax(0, 420px);
  gap: 24px;
  padding-top: 24px;
  border-top: 2px solid var(--zouma-color-muted);
}

/* The sweep, as the commitments rows carry on the homepage.
 *
 * A second line laid over the border rather than the border itself animating:
 * a border cannot be drawn progressively, and animating its width would move
 * the row. This one scales from nothing on the left edge to full width, which
 * runs on the compositor and costs no layout.
 *
 * 2px and top: -2px, not the homepage's 1px — this row's rule is 2px, and a
 * thinner sweep would leave the muted border showing along one edge of the
 * travelling line instead of being covered by it. */
.zouma-ptn-route::before {
  content: "";
  position: absolute;
  top: -2px;
  left: 0;
  right: 0;
  height: 2px;
  background: rgba(255, 255, 255, 0.62);
  transform: scaleX(0);
  transform-origin: left center;
  /* 520ms, not 240. At the shorter time the line was already full width by the
   * time the eye reached it, so it read as switching on rather than as
   * travelling — the direction, which is the whole point of the gesture, was
   * invisible. This is still quick, just long enough to see it cross. */
  transition: transform 520ms cubic-bezier(0.33, 0.1, 0.25, 1);
}

.zouma-ptn-route:hover::before {
  transform: scaleX(1);
}

.zouma-ptn-route__title {
  margin: 0;
  /* Held back from white at rest, so hovering has somewhere to go. Both of
   * these were #fff, which left the lift with nowhere to travel; the rest
   * state is dimmer than it was on purpose. */
  color: rgba(255, 255, 255, 0.74);
  font-family: var(--zouma-font-heading);
  font-size: 20px;
  font-weight: 600;
  line-height: 24px;
  transition: color 220ms ease;
}

.zouma-ptn-route__text {
  margin: 0;
  color: rgba(255, 255, 255, 0.44);
  font-family: var(--zouma-font-body);
  font-size: 16px;
  font-weight: 400;
  line-height: 26px;
  transition: color 220ms ease;
}

.zouma-ptn-route:hover .zouma-ptn-route__title {
  color: #fff;
}

.zouma-ptn-route:hover .zouma-ptn-route__text {
  color: rgba(255, 255, 255, 0.86);
}

/* -------------------------------------------------------------------------
 * 05 · Journey — 702px
 *
 * Five 256px columns under a dotted rule whose ends fade out past the 1280
 * container on both sides.
 * ---------------------------------------------------------------------- */

.zouma-ptn-journey {
  padding-block: 96px;
  background-color: #fff;
}

.zouma-ptn-journey__inner {
  display: flex;
  flex-direction: column;
  gap: 64px;
}

.zouma-ptn-journey__head {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 16px;
}

.zouma-ptn-journey__text {
  margin: 0;
  color: var(--zouma-color-muted);
  font-family: var(--zouma-font-body);
  font-size: 14px;
  font-weight: 400;
  line-height: 21px;
  letter-spacing: -0.02em;
}

.zouma-ptn-journey__rail {
  position: relative;
  display: flex;
  height: 10px;
}

/* The tails bleed out of the container and fade as they go. Sized from the
 * gutter the viewport is currently giving the column — (100vw - 100%) / 2 —
 * plus the 20px the design runs past the frame edge, and floored at 0 so a
 * narrow window simply has no tail rather than a negative one. */
.zouma-ptn-journey__rail::before,
.zouma-ptn-journey__rail::after {
  content: "";
  position: absolute;
  top: 4px;
  height: 2px;
  width: max(0px, calc((100vw - 100%) / 2 + 20px));
}

.zouma-ptn-journey__rail::before {
  inset-inline-end: 100%;
  background: linear-gradient(to left, var(--zouma-sky-soft), rgba(199, 228, 246, 0));
}

.zouma-ptn-journey__rail::after {
  inset-inline-start: 100%;
  background: linear-gradient(to right, var(--zouma-sky-soft), rgba(199, 228, 246, 0));
}

.zouma-ptn-journey__mark {
  position: relative;
  flex: 1 1 0;
  min-width: 0;
}

/* Pulled half its own width to the left so the disc is centred on the column
 * boundary rather than sitting inside the column. */
.zouma-ptn-journey__mark::before {
  content: "";
  position: absolute;
  top: 0;
  inset-inline-start: -5px;
  width: 10px;
  height: 10px;
  background: var(--zouma-cyan-soft);
  border-radius: 50%;
}

.zouma-ptn-journey__mark.is-first::before {
  background: var(--zouma-blue);
}

.zouma-ptn-journey__mark::after {
  content: "";
  position: absolute;
  top: 4px;
  inset-inline-start: 5px;
  inset-inline-end: 0;
  height: 2px;
  background: var(--zouma-sky-soft);
}

.zouma-ptn-journey__phases {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  margin: 0;
  padding: 0;
  list-style: none;
  min-width: 0;
}

.zouma-ptn-phase {
  display: flex;
  flex-direction: column;
  gap: 16px;
  padding: 40px 24px;
  min-width: 0;
  /* A gradient divider, so border-image rather than border-color — it fades
   * out down the column the way the rule above it fades out sideways. */
  border-style: solid;
  border-width: 0;
  border-inline-end-width: 2px;
  border-image: linear-gradient(180deg, var(--zouma-sky-soft) 0%, rgba(199, 228, 246, 0) 100%) 1;
}

.zouma-ptn-phase:last-child {
  border-inline-end-width: 0;
}

.zouma-ptn-phase__num {
  color: var(--zouma-blue);
  font-family: var(--zouma-font-body);
  font-size: 16px;
  font-weight: 400;
  line-height: 26px;
}

.zouma-ptn-phase__title {
  margin: 0;
  color: var(--zouma-dark);
  font-family: var(--zouma-font-heading);
  font-size: 32px;
  font-weight: 700;
  line-height: 35px;
}

.zouma-ptn-phase__text {
  margin: 0;
  color: var(--zouma-color-muted);
  font-family: var(--zouma-font-body);
  font-size: 14px;
  font-weight: 500;
  line-height: 21px;
  letter-spacing: -0.01em;
}

/* -------------------------------------------------------------------------
 * 06 · Tiers — 694px
 * ---------------------------------------------------------------------- */

.zouma-ptn-tiers {
  padding-block: 96px;
  background-color: var(--zouma-blue-pale);
}

.zouma-ptn-tiers__inner {
  display: flex;
  flex-direction: column;
  gap: 40px;
}

.zouma-ptn-tiers__head {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 16px;
}

.zouma-ptn-tiers__text {
  margin: 0;
  color: var(--zouma-color-muted);
  font-family: var(--zouma-font-body);
  font-size: 14px;
  font-weight: 500;
  line-height: 21px;
  letter-spacing: -0.01em;
}

.zouma-ptn-tiers__cards {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 8px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.zouma-ptn-tier {
  display: flex;
  flex-direction: column;
  gap: 16px;
  padding: 24px;
  min-width: 0;
  background: #fff;
  border: 1px solid var(--zouma-blue-pale);
  border-radius: 8px;
}

.zouma-ptn-tier__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 24px;
  min-height: 74px;
}

.zouma-ptn-tier__icon {
  flex: none;
  display: block;
  width: 74px;
  height: 74px;
  object-fit: contain;
}

/* Pushed to the trailing edge by its own margin rather than by the row's
 * space-between, so it stays there on a card whose mark has not been drawn
 * yet — a lone child under space-between falls back to the leading edge. */
.zouma-ptn-tier__tag {
  flex: none;
  margin-inline-start: auto;
  padding: 8px 16px;
  background: #fff;
  border: 1px solid #e4e9ee;
  border-radius: 4px;
  color: var(--zouma-blue);
  font-family: var(--zouma-font-body);
  font-size: 10px;
  font-weight: 600;
  /* The design draws this in caps. Uppercasing here rather than storing
     "TIER 01" keeps the stored value readable in wp-admin, which is the same
     reason .zouma-eyebrow does it. */
  text-transform: uppercase;
  line-height: 13px;
  white-space: nowrap;
}

.zouma-ptn-tier__body {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.zouma-ptn-tier__name {
  margin: 0;
  color: var(--zouma-dark);
  font-family: var(--zouma-font-heading);
  font-size: 30px;
  font-weight: 700;
  line-height: 39px;
}

.zouma-ptn-tier__tagline {
  margin: 0;
  color: var(--zouma-color-muted);
  font-family: var(--zouma-font-body);
  font-size: 16px;
  font-weight: 600;
  line-height: 26px;
}

.zouma-ptn-tier__text {
  margin: 0;
  color: var(--zouma-color-muted);
  font-family: var(--zouma-font-body);
  font-size: 16px;
  font-weight: 400;
  line-height: 26px;
}

/* -------------------------------------------------------------------------
 * 07 · Stories — 978px
 *
 * A 670 column centred in the band, and a track of 670-wide cards that starts
 * at that column's left edge and runs off the right of the screen. Nothing
 * here clips it — that overhang is the design. .zouma-site's overflow-x: clip
 * is what stops it becoming a scrollbar.
 * ---------------------------------------------------------------------- */

.zouma-ptn-stories {
  padding-block: 120px;
  background-color: var(--zouma-dark);
  background-image: radial-gradient(
    ellipse 656px 413px at 50% 100%,
    rgba(14, 133, 182, 0.6) 0%,
    rgba(18, 18, 18, 0) 100%
  );
  border-top: 1px solid var(--zouma-sky);
  color: #fff;
}

.zouma-ptn-stories__inner {
  display: flex;
  flex-direction: column;
  gap: 40px;
  width: min(670px, 100%);
  margin-inline: auto;
  min-width: 0;
}

.zouma-ptn-stories__head {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
  text-align: center;
}

h2.zouma-ptn-stories__title {
  color: #fff;
}

.zouma-ptn-stories__text {
  margin: 0;
  color: var(--zouma-blue-pale);
  font-family: var(--zouma-font-body);
  font-size: 14px;
  font-weight: 400;
  line-height: 21px;
  letter-spacing: -0.02em;
}

.zouma-ptn-stories__viewport {
  position: relative;
  min-width: 0;
}

.zouma-ptn-stories__track {
  display: flex;
  gap: 24px;
  width: max-content;
  margin: 0;
  padding: 0;
  list-style: none;
}

.zouma-ptn-stories__viewport.is-ready .zouma-ptn-stories__track {
  transition: transform 520ms cubic-bezier(0.4, 0, 0.2, 1);
}

.zouma-ptn-story {
  display: flex;
  flex-direction: column;
  flex: none;
  width: min(670px, 100vw - 2rem);
  min-height: 403px;
  padding: 40px;
  background: #fff;
  border-radius: 16px;
  color: var(--zouma-dark);
}

/* Margins rather than a gap: the kicker, title and meta sit 4px apart and the
 * quote and attribution 24px, which one gap cannot say. */
.zouma-ptn-story > * {
  margin: 0;
}

.zouma-ptn-story__kicker {
  color: var(--zouma-color-muted);
  font-family: var(--zouma-font-body);
  font-size: 12px;
  font-weight: 500;
  line-height: 17px;
}

.zouma-ptn-story__title {
  margin-top: 4px;
  color: var(--zouma-blue);
  font-family: var(--zouma-font-heading);
  font-size: 19px;
  font-weight: 500;
  line-height: 29px;
}

.zouma-ptn-story__meta {
  margin-top: 4px;
  color: var(--zouma-blue);
  font-family: var(--zouma-font-body);
  font-size: 14px;
  font-weight: 500;
  line-height: 21px;
  letter-spacing: -0.01em;
}

/* The padding, rule and italic are style.css's blockquote treatment, and none
 * of the three is in the design — the quote is set upright in the card's own
 * column. */
.zouma-ptn-story__quote {
  margin-top: 24px;
  padding: 0;
  border: 0;
  color: var(--zouma-dark);
  font-family: var(--zouma-font-heading);
  font-size: 24px;
  font-weight: 600;
  font-style: normal;
  line-height: 29px;
}

.zouma-ptn-story__by {
  margin-top: 24px;
  color: var(--zouma-dark);
  font-family: var(--zouma-font-body);
  font-size: 16px;
  font-weight: 600;
  line-height: 26px;
}

.zouma-ptn-stories__nav {
  display: flex;
  justify-content: center;
  gap: 8px;
}

/* Same reset as the page's links-as-buttons, and needed more here because
 * these genuinely are <button> elements: style.css fills every bare button
 * and repaints it again at `button:hover`, which a plain class cannot beat. */
button.zouma-ptn-stories__arrow {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  padding: 0;
  background: transparent;
  border: 1px solid rgba(255, 255, 255, 0.9);
  border-radius: 8px;
  color: #fff;
  cursor: pointer;
  transition: background var(--zouma-transition), color var(--zouma-transition);
}

button.zouma-ptn-stories__arrow:hover,
button.zouma-ptn-stories__arrow:focus-visible {
  background: #fff;
  color: var(--zouma-dark);
}

button.zouma-ptn-stories__arrow:focus-visible {
  outline: 2px solid var(--zouma-cyan);
  outline-offset: 3px;
}

button.zouma-ptn-stories__arrow[disabled] {
  opacity: 0.4;
  cursor: default;
}

button.zouma-ptn-stories__arrow[disabled]:hover {
  background: transparent;
  color: #fff;
}

button.zouma-ptn-stories__arrow .zouma-icon {
  width: 20px;
  height: 20px;
}

/* -------------------------------------------------------------------------
 * 08 · Closing CTA — 365px
 * ---------------------------------------------------------------------- */

.zouma-ptn-cta {
  padding-block: 96px;
  background-color: #fff;
}

.zouma-ptn-cta__inner {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 64px;
}

.zouma-ptn-cta__copy {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 16px;
  max-width: 959px;
  min-width: 0;
}

.zouma-ptn-cta__text {
  margin: 0;
  color: var(--zouma-color-muted);
  font-family: var(--zouma-font-body);
  font-size: 14px;
  font-weight: 500;
  line-height: 21px;
  letter-spacing: -0.01em;
}

.zouma-ptn-cta__actions {
  flex: none;
}

/* -------------------------------------------------------------------------
 * Narrower than the design
 *
 * The literals above are 1:1 with a 1728 frame. Below that the fixed tracks
 * shrink on their own; these are the points where a layout has to change
 * shape rather than scale.
 * ---------------------------------------------------------------------- */

@media (max-width: 1180px) {
  /* 44px of touch. Taken out of the block padding and not the line-height:
   * 26px is the label's own metric and the desktop button is set from it, so
   * moving it would reset the type rather than the target. Element in front of
   * the class for the same reason the base rule is written that way — style.css
   * repaints every bare button and does it again at button:hover. */
  a.zouma-ptn-btn,
  button.zouma-ptn-btn {
    padding-block: 9px;
  }

  button.zouma-ptn-stories__arrow {
    width: 44px;
    height: 44px;
  }

  .zouma-ptn-hero {
    padding-top: calc(var(--zouma-header-h) + 88px);
    padding-bottom: 64px;
  }

  /* Off the bound the base rule sets.
   *
   * That width's 50vw - 60px term is there to keep the copy clear of a
   * photograph standing in the right half of the band — and the rule below has
   * already moved that photograph behind the whole band, so from here down the
   * term guards a layout that does not exist. Left in, it was the whole reason
   * the column measured 135px at 390 and ran the paragraph to nineteen lines.
   * The base rule stays as it is: above 1180 the two columns are real. */
  .zouma-ptn-hero__copy {
    width: 100%;
  }

  .zouma-ptn-hero__title {
    line-height: 1.15;
  }

  /* The photograph goes behind the copy rather than beside it once there is no
   * room for two, and it is carried at close to full strength: the flat 0.45
   * that used to knock it back was doing two jobs badly, flattening the picture
   * everywhere and still leaving the blown-out chart in it at rgb(120,120,120),
   * where white body copy measures 3.9:1. The darkening is the gradient below
   * instead, which can put it where the type is. */
  .zouma-ptn-hero__photo {
    inset-inline-start: 0;
    width: 100%;
    height: 100%;
    aspect-ratio: auto;
    opacity: 0.85;
  }

  /* Weighted down the band rather than flat.
   *
   * Measured, the copy runs from 18% of the band to 58% of it and the badge
   * strip starts at 83%; the stops follow those two. Heavy from 12 to 58 where
   * the type is, off almost entirely from 64 to 80 where nothing is written,
   * and back on under the strip. That gap is the point of the gradient: a flat
   * scrim dark enough for the type measured a lower luminance spread across
   * the picture than the 0.45 it replaced, which is the photograph reading as
   * a grey wash rather than as a photograph.
   *
   * The numbers are sampled, not judged: the brightest background pixel inside
   * every hero text box has to sit at or under luminance 0.16, which is 5:1
   * against white and leaves headroom over the 4.5 bar.
   *
   * On the photo and not over the whole backdrop, so the glow and the dot grid
   * still paint above it. A scrim rather than filter: brightness(), which
   * would take the picture's own contrast down with the highlight. */
  .zouma-ptn-hero__photo::after {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(
      180deg,
      rgba(18, 18, 18, 0.5) 0%,
      rgba(18, 18, 18, 0.58) 12%,
      rgba(18, 18, 18, 0.58) 58%,
      rgba(18, 18, 18, 0.05) 64%,
      rgba(18, 18, 18, 0.05) 80%,
      rgba(18, 18, 18, 0.55) 85%,
      rgba(18, 18, 18, 0.55) 100%
    );
  }

  /* Wrapped now, so the marks have to read as rows of a list rather than as
   * one centred line that happened to break: aligned to the page gutter, with
   * a row gap the single-row strip never needed and a column gap short enough
   * that the rows do not read as columns. flex-start rather than left, so
   * Arabic aligns to its own start edge without a second rule. */
  .zouma-ptn-hero__badges {
    justify-content: flex-start;
    gap: 12px 24px;
  }

  .zouma-ptn-intro__grid,
  .zouma-ptn-routes__grid,
  .zouma-ptn-pillar__body {
    grid-template-columns: minmax(0, 1fr);
  }

  .zouma-ptn-routes {
    padding-bottom: 80px;
  }

  /* One column now — the head sits above the routes it introduces, with a row
   * exactly its own height and nothing to ride alongside, so sticky has
   * nowhere to travel and would only hold the copy down as the list arrives. */
  .zouma-ptn-routes__head {
    position: static;
    padding-top: 80px;
  }

  .zouma-ptn-routes__list {
    padding-top: 0;
    gap: 40px;
  }

  .zouma-ptn-intro__stats {
    height: auto;
    overflow: visible;
  }

  /* Out of the window and into a plain stack: at this width the copy above it
   * has already grown taller than the rotation was worth. Every figure is on
   * show, so the ready state's cell and its fade are handed back — the script
   * keeps moving is-active, and nothing here listens to it. */
  .zouma-ptn-intro__track,
  .zouma-ptn-intro__stats.is-ready .zouma-ptn-intro__track {
    display: flex;
    gap: 40px;
  }

  .zouma-ptn-intro__stats.is-ready .zouma-ptn-stat {
    opacity: 1;
  }

  .zouma-ptn-stat {
    height: auto;
  }

  .zouma-ptn-stat__value {
    font-size: 96px;
    line-height: 104px;
  }

  .zouma-ptn-journey__phases {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  /* The rule only reads as a timeline while the five phases are one row. */
  .zouma-ptn-journey__rail {
    display: none;
  }

  .zouma-ptn-phase {
    border-inline-end-width: 0;
  }

  .zouma-ptn-tiers__cards {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .zouma-ptn-cta__inner {
    flex-direction: column;
    align-items: flex-start;
  }
}

@media (max-width: 900px) {
  .zouma-ptn-intro,
  .zouma-ptn-pillars,
  .zouma-ptn-stories {
    padding-block: 72px;
  }

  .zouma-ptn-journey,
  .zouma-ptn-tiers,
  .zouma-ptn-cta {
    padding-block: 64px;
  }

  h2.zouma-ptn-intro__title,
  h2.zouma-ptn-pillars__title,
  h2.zouma-ptn-routes__title,
  h2.zouma-ptn-journey__title,
  h2.zouma-ptn-tiers__title,
  h2.zouma-ptn-stories__title,
  h2.zouma-ptn-cta__title,
  .zouma-ptn-pillar__title {
    font-size: 32px;
    line-height: 1.15;
  }

  /* Wide enough to still read, short enough that four of them fit across. */
  .zouma-ptn-pillar__media {
    height: 280px;
  }

  .zouma-ptn-route {
    grid-template-columns: minmax(0, 1fr);
    gap: 12px;
  }

  .zouma-ptn-journey__phases,
  .zouma-ptn-tiers__cards {
    grid-template-columns: minmax(0, 1fr);
  }

  .zouma-ptn-phase {
    padding: 24px 0;
  }

  .zouma-ptn-story {
    min-height: 0;
    padding: 24px;
  }

  .zouma-ptn-stat__value {
    font-size: 72px;
    line-height: 78px;
  }

  .zouma-ptn-stat__label {
    font-size: 24px;
    line-height: 28px;
  }
}

/* The point the story card stops fitting.
 *
 * Stories is the one band on the page that is not a .zouma-ptn__inner: it takes
 * its width from the card rather than from the content column, so it never had
 * a gutter of its own. Above 670 it does not need one — the 670 column is
 * narrower than the viewport and the leftover centres it. Below, the column is
 * the viewport, and the head and the heading sat hard against both edges while
 * the tiers and the phases in the bands above them sat at 16. */
@media (max-width: 670px) {
  .zouma-ptn-stories__inner {
    padding-inline: clamp(1rem, calc(3 * var(--zouma-vw)), 2.5rem);
  }
}

@media (max-width: 620px) {
  /* Full width on a phone. Side by side at 320 the two hero calls to action
   * have 136px each, which is narrower than either label.
   *
   * The wrappers have to be released first, and that is the part that is not
   * obvious: .zouma-ptn-hero__copy and .zouma-ptn-cta__inner both align their
   * children to flex-start, so each wrapper is already shrink-to-fit — and a
   * percentage width inside a box the content sized resolves against that same
   * content, so width: 100% on its own reads as doing nothing at all. */
  .zouma-ptn-hero__ctas {
    flex-direction: column;
    align-self: stretch;
  }

  .zouma-ptn-cta__actions {
    align-self: stretch;
  }

  /* Element in front of the class for the reason the base rule gives: a bare
   * .class loses to style.css's button:hover. min-height restates the 44 the
   * block padding above already produces, so a label that ever carried its own
   * line-height cannot take a full-width button back under the touch floor. */
  a.zouma-ptn-btn,
  button.zouma-ptn-btn {
    justify-content: center;
    width: 100%;
    min-height: 44px;
  }

  /* The same scrim, re-weighted for a band with no room in it.
   *
   * On a phone the copy runs to 62% of the hero and the badge strip starts at
   * 69, so the clear stretch the rule above opens between 64 and 80 lands under
   * the badges instead — measured, their contrast fell to 2.3:1. What is left
   * is a short release just under the last line of copy, which is enough to
   * keep the picture's luminance spread above what the flat 0.45 gave it. */
  .zouma-ptn-hero__photo::after {
    background: linear-gradient(
      180deg,
      rgba(18, 18, 18, 0.48) 0%,
      rgba(18, 18, 18, 0.55) 12%,
      rgba(18, 18, 18, 0.55) 58%,
      rgba(18, 18, 18, 0.3) 64%,
      rgba(18, 18, 18, 0.55) 68%,
      rgba(18, 18, 18, 0.55) 100%
    );
  }

  .zouma-ptn-hero__badges {
    gap: 16px;
  }

  .zouma-ptn-hero__bar {
    height: auto;
    padding-block: 12px;
  }

  /* The rail scrolls rather than crushing four labels into a phone's width.
   * The gutter lives in the width, not in padding: padding on a scroll
   * container is inside the scrollport and clips nothing. */
  .zouma-ptn-pillars__rail {
    width: 100%;
    overflow-x: auto;
    scrollbar-width: none;
    /* Tabs three and four start off screen, so a drag that stops between two
     * labels leaves a half word at the edge. proximity rather than mandatory:
     * it tidies a scroll that has already come to rest near a tab and lets a
     * long flick through the rail alone. */
    scroll-snap-type: x proximity;
  }

  button.zouma-ptn-pillars__tab {
    flex: none;
    height: 64px;
    padding: 16px;
    /* start, not left: it is the rail's own start edge that the label should
     * meet, which is the right-hand one in Arabic. */
    scroll-snap-align: start;
  }

  /* Inside the scrollport rather than under it.
   *
   * overflow-x: auto on the rail forces the other axis to auto as well, which
   * makes the rail a scroll container — and the mark, sitting at top: 100%,
   * lands 3px past the bottom of the 64px content box and is clipped away.
   * Nothing painted under the lit tab on a phone. Moved to the inside edge of
   * the same box; the shared rule keeps the mark where the design has it at
   * every width above this one. */
  button.zouma-ptn-pillars__tab::after {
    top: auto;
    bottom: 0;
  }

  /* The card still overhangs so the next one is visible, but it now starts at
   * the gutter its container has rather than at the viewport edge.
   *
   * The gutter is restated rather than written as a percentage of that
   * container: the track the card sits in is width: max-content, and a
   * percentage resolved against an intrinsic containing block comes back as
   * the width of the whole track — measured, the card came out 8890px wide and
   * took the track with it. */
  .zouma-ptn-story {
    width: calc(100vw - 2 * clamp(1rem, calc(3 * var(--zouma-vw)), 2.5rem));
  }
}

/* -------------------------------------------------------------------------
 * Reduced motion
 *
 * partners.js declines to animate the story track and never adds its is-ready.
 * The stat rotator does keep rotating, because stopping it would leave three of
 * the four figures unread; what it drops is the fade, so the swap is a straight
 * replacement. The rule below is what takes that fade out.
 * ---------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  .zouma-ptn-intro__stats.is-fading .zouma-ptn-stat,
  .zouma-ptn-stories__viewport.is-ready .zouma-ptn-stories__track,
  a.zouma-ptn-btn,
  button.zouma-ptn-btn,
  button.zouma-ptn-stories__arrow,
  button.zouma-ptn-pillars__tab,
  button.zouma-ptn-pillars__tab::after,
  .zouma-ptn-route::before {
    transition: none;
  }

  /* The panel still swaps; what goes is the travel it arrives on. */
  .zouma-ptn-pillars__panel:not([hidden]) {
    animation: none;
  }

  a.zouma-ptn-btn:hover,
  button.zouma-ptn-btn:hover,
  a.zouma-ptn-btn:focus-visible,
  button.zouma-ptn-btn:focus-visible {
    transform: none;
  }
}
