/* ============================================================================
   ARIBA — Corporate Website Prototype
   Phase 1: foundation, navigation, hero, about, impact.

   Visual system is derived from the ARIBA identity: a folded two-tone green
   ribbon chevron above a warm near-black wordmark. Colours below are sampled
   directly from assets/logos/Ariba_logo.png.

   Green is treated as an accent and as a single bold surface (Impact), never
   as a wash. Most of the page is warm paper and near-black ink.
   ========================================================================= */

/* ---------------------------------------------------------------- TOKENS  */
:root {
  /* Brand — sampled from the logo */
  --green-900: #003527;
  --green-800: #004D3D;   /* logo dark green */
  --green-700: #0A6249;
  --green-500: #2DB25F;   /* logo bright green */
  --green-400: #4CC47A;

  /* Ink & paper */
  --ink-900: #241D1F;     /* logo wordmark — warm near-black */
  --ink-700: #4A4447;
  --ink-500: #6E6669;
  --ink-300: #A9A2A4;

  --paper:      #FBFAF8;
  --paper-alt:  #F4F1EC;
  --paper-line: #E4DFD7;

  /* ---------------------------------------------------------- THEME TOKENS
     One semantic layer, two value sets (light here, dark in the
     [data-theme="dark"] block below) — components consume ONLY these,
     never the raw palette above, so a theme switch is a variable swap,
     not a second stylesheet. Light values preserve the current design
     as closely as possible; they are the same raw palette colours the
     site already used, just given a semantic name. */
  --bg-primary:        var(--paper);
  --bg-secondary:      var(--paper-alt);
  --surface:            #FFFFFF;
  --surface-elevated:   #FFFFFF;
  --text-primary:      var(--ink-900);
  --text-secondary:    var(--ink-700);
  --text-muted:        var(--ink-500);
  --text-faint:        var(--ink-300);
  --border:            var(--paper-line);
  --brand-primary:     var(--green-800);
  --brand-primary-hover:var(--green-900);
  --brand-bright:      var(--green-500);
  --shadow-rgb:         36, 29, 31;   /* consumed inside rgba() so alpha stays per-use */

  /* Back-compat aliases: a handful of existing rules already reference the
     old shorter names — point them at the same tokens instead of keeping
     two independent copies of the same value. */
  --bg:        var(--bg-primary);
  --text:      var(--text-primary);
  --accent:    var(--brand-bright);
  --hairline:  var(--border);

  /* Component-scoped tokens that need more than a single swap between
     themes (surface + border + shadow moving together). */
  --nav-surface:            rgba(255, 255, 255, 0.6);
  --nav-surface-scrolled:   rgba(255, 255, 255, 0.78);
  --nav-surface-fallback:   rgba(255, 255, 255, 0.92);
  --nav-surface-fallback-scrolled: rgba(255, 255, 255, 0.96);
  --nav-surface-mobile:     rgba(255, 255, 255, 0.72);
  --nav-surface-mobile-scrolled: rgba(255, 255, 255, 0.85);
  --nav-border:             rgba(255, 255, 255, 0.5);
  --nav-link:               var(--ink-700);
  --nav-link-active:        var(--ink-900);
  --nav-toggle-bar:         var(--ink-900);
  --nav-scrim:              rgba(36, 29, 31, 0.4);

  --journey-track:          rgba(0, 77, 61, 0.10);
  --journey-stages-track:   rgba(0, 77, 61, 0.12);

  --constellation-line:     var(--ink-500);
  --constellation-logo-backing: transparent;
  --constellation-logo-shadow: transparent;

  --input-bottom-line:      var(--paper-line);

  --stat-divider:           var(--paper-line);

  /* Footer: a deep dark-green/near-black closing surface that stays dark
     in BOTH site themes — it is not "the page background", it's the
     page's own conclusion, styled independently of --bg-primary. Only
     these two tokens move between Light/Dark site mode (see the
     [data-theme="dark"] block below); the text/link tokens under it stay
     fixed because the footer surface itself never becomes light. */
  --footer-bg:              #0B1613;
  --footer-border:          rgba(255, 255, 255, 0.08);
  --footer-shape:           rgba(45, 178, 95, 0.05);
  --footer-text:            #F3EFE9;
  --footer-text-secondary:  #C9C2BA;
  --footer-text-muted:      rgba(255, 255, 255, 0.55);
  --footer-link:            rgba(255, 255, 255, 0.72);
  --footer-logo-backing:    rgba(255, 255, 255, 0.94);

  /* Colour-only theme switch — never layout/dimensions/images/SVG geometry. */
  --theme-t: 240ms var(--ease);

  /* Typography */
  --font-head: 'Archivo', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --font-body: 'Inter', system-ui, -apple-system, 'Segoe UI', sans-serif;

  /* Five-size system. Components may change weight and line-height, not size. */
  --fs-caption: 0.8125rem;
  --fs-body:    0.9375rem;
  --fs-lede:    1.125rem;
  --fs-heading: clamp(1.5rem, 1rem + 1.8vw, 2.25rem);
  --fs-display: clamp(2rem, 1rem + 2.5vw, 3rem);

  --lh-tight: 1.04;
  --lh-snug:  1.18;
  --lh-body:  1.7;

  --tracking-display: -0.032em;
  --tracking-label:    0.16em;

  /* Spacing */
  --space-2:  0.5rem;
  --space-3:  0.75rem;
  --space-4:  1rem;
  --space-6:  1.5rem;
  --space-8:  2rem;
  --space-12: 3rem;
  --space-16: 4rem;
  --space-24: 6rem;
  --section-y: clamp(4rem, 2.5rem + 6vw, 7.5rem);

  /* Layout */
  --container: 1180px;
  --gutter: clamp(1.25rem, 0.75rem + 2.4vw, 3rem);

  /* Floating navbar: height of the pill itself, the breathing gap above it
     (viewport edge -> pill), and how wide the pill is allowed to grow. */
  --nav-h: 66px;
  --nav-h-scrolled: 56px;
  --nav-top-gap: clamp(1rem, 0.7rem + 1vw, 1.5rem);
  --nav-max-w: 1120px;

  /* Radii — kept small; the identity is angular, not rounded. --radius-lg
     is the one deliberate exception, used only where a soft, floating or
     editorial surface (the nav pill's logo chip, the About note panel)
     needs it. */
  --radius-sm: 2px;
  --radius-md: 4px;
  --radius-lg: 10px;

  /* Motion */
  --ease: cubic-bezier(0.22, 0.72, 0.26, 1);
  --t-fast: 180ms var(--ease);
  --t-base: 320ms var(--ease);
  --reveal-dur: 700ms;
  --reveal-step: 90ms;
}

/* Arabic typography is designed, not inherited: different family, looser
   leading, no negative tracking, no letterspaced smallcaps. */
:root:lang(ar) {
  --font-head: 'IBM Plex Sans Arabic', system-ui, sans-serif;
  --font-body: 'IBM Plex Sans Arabic', system-ui, sans-serif;
  --lh-tight: 1.24;
  --lh-snug:  1.35;
  --lh-body:  1.95;
  --tracking-display: 0;
  --tracking-label: 0;
}

/* ---------------------------------------------------------------- DARK THEME
   Same tokens, different values — nothing below this block is aware a
   theme switch even happened. Backgrounds are a warm, near-black charcoal
   (never pure #000) with a faint green undertone; two tiers (--bg-primary /
   --bg-secondary) give neighbouring sections gentle separation the same
   way --paper / --paper-alt do in light mode. ARIBA green stays the one
   controlled accent — most surfaces are charcoal/off-white, not green. */
:root[data-theme="dark"] {
  --bg-primary:        #171A19;
  --bg-secondary:      #1D2120;
  --surface:            #1F2422;
  --surface-elevated:   #262B29;
  --text-primary:      #F3EFE9;
  --text-secondary:    #C9C2BA;
  --text-muted:        #948C86;
  --text-faint:        #6B6560;
  --border:            rgba(255, 255, 255, 0.10);
  --brand-primary:     var(--green-500);
  --brand-primary-hover:var(--green-400);
  --brand-bright:      var(--green-400);
  --shadow-rgb:         0, 0, 0;

  --nav-surface:            rgba(23, 26, 25, 0.6);
  --nav-surface-scrolled:   rgba(23, 26, 25, 0.82);
  --nav-surface-fallback:   rgba(23, 26, 25, 0.92);
  --nav-surface-fallback-scrolled: rgba(23, 26, 25, 0.96);
  --nav-surface-mobile:     rgba(23, 26, 25, 0.82);
  --nav-surface-mobile-scrolled: rgba(23, 26, 25, 0.92);
  --nav-border:             rgba(255, 255, 255, 0.08);
  --nav-link:               var(--text-secondary);
  --nav-link-active:        var(--text-primary);
  --nav-toggle-bar:         var(--text-primary);
  --nav-scrim:              rgba(0, 0, 0, 0.6);

  --journey-track:          rgba(255, 255, 255, 0.10);
  --journey-stages-track:   rgba(255, 255, 255, 0.12);

  --constellation-line:     rgba(255, 255, 255, 0.28);
  /* Solid, not a faint wash: client marks are never recoloured/inverted, so
     dark logos on transparent PNGs need a real light surface under them to
     stay readable — see the .constellation__btn dark-mode rule below. */
  --constellation-logo-backing: #FFFFFF;
  --constellation-logo-shadow: rgba(0, 0, 0, 0.4);

  --input-bottom-line:      rgba(255, 255, 255, 0.16);

  --stat-divider:           rgba(255, 255, 255, 0.12);

  /* Dark Mode's own page background (--bg-primary) is already a dark
     charcoal, so the Footer has to go a step further to still read as a
     distinct closing surface rather than fading into it: a touch deeper,
     a more visible border, and a slightly stronger green undertone in its
     background shape. */
  --footer-bg:              #080D0C;
  --footer-border:          rgba(255, 255, 255, 0.12);
  --footer-shape:           rgba(45, 178, 95, 0.08);
}

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

[hidden] { display: none !important; }

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

body {
  margin: 0;
  background: var(--bg-primary);
  color: var(--text-primary);
  font-family: var(--font-body);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
  transition: background-color var(--theme-t), color var(--theme-t);
}

::selection { background: rgba(45, 178, 95, 0.28); color: var(--text-primary); }

html { scrollbar-color: var(--border) var(--bg-primary); }
::-webkit-scrollbar { width: 12px; height: 12px; }
::-webkit-scrollbar-track { background: var(--bg-primary); }
::-webkit-scrollbar-thumb {
  background: var(--border);
  border-radius: 8px;
  border: 3px solid var(--bg-primary);
}
::-webkit-scrollbar-thumb:hover { background: rgba(45, 178, 95, 0.35); }

h1, h2, h3 {
  margin: 0;
  font-family: var(--font-head);
  font-weight: 600;
  line-height: var(--lh-tight);
  letter-spacing: var(--tracking-display);
  text-wrap: balance;
}

p { margin: 0; }
ul { margin: 0; padding: 0; list-style: none; }
img { max-width: 100%; height: auto; display: block; }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; }

:focus-visible {
  outline: 2px solid var(--green-500);
  outline-offset: 3px;
  border-radius: var(--radius-sm);
}

.skip-link {
  position: absolute;
  inset-inline-start: var(--gutter);
  top: -100px;
  z-index: 200;
  padding: var(--space-3) var(--space-6);
  background: var(--green-800);
  color: #fff;
  border-radius: var(--radius-md);
  transition: top var(--t-fast);
}
.skip-link:focus-visible { top: var(--space-4); }

/* ---------------------------------------------------------------- LAYOUT  */
.container {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

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

/* ------------------------------------------------------- SHARED ELEMENTS  */

/* Gradient tick derived from the logo's dark→bright ribbon fold. */
.rule {
  display: inline-block;
  inline-size: 34px;
  block-size: 2px;
  flex: none;
  background: linear-gradient(90deg, var(--green-800), var(--green-500));
}
[dir="rtl"] .rule { background: linear-gradient(270deg, var(--green-800), var(--green-500)); }
.rule--onDark { background: linear-gradient(90deg, var(--green-400), rgba(255,255,255,0.35)); }
[dir="rtl"] .rule--onDark { background: linear-gradient(270deg, var(--green-400), rgba(255,255,255,0.35)); }

.eyebrow,
.section-label {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  font-family: var(--font-body);
  font-size: var(--fs-caption);
  font-weight: 500;
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--text-muted);
}
:lang(ar) .eyebrow,
:lang(ar) .section-label { text-transform: none; }

.section-label--onDark { color: rgba(255,255,255,0.62); }

/* Reusable label treatment: text sits above a short gradient rule instead
   of beside it. Reuses .rule as-is (including its RTL gradient flip), just
   restacks the flex container — align-items: start keeps it pinned to the
   reading-start edge in both directions with no extra dir-specific rules.
   Used by the Hero eyebrow and the About section label today; intended for
   any future section label that wants the same treatment. */
.label--underline {
  flex-direction: column;
  align-items: start;
  gap: var(--space-3);
}

.lede {
  font-size: var(--fs-lede);
  line-height: var(--lh-body);
  color: var(--text-secondary);
  max-inline-size: 54ch;
}

/* The full stop set in brand green — a small, repeated identity signal. */
.accent { color: var(--green-500); }

/* --------------------------------------------------------------- BUTTONS  */
.btn {
  --btn-py: 0.95rem;
  --btn-px: 1.75rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  padding: var(--btn-py) var(--btn-px);
  font-family: var(--font-body);
  font-size: var(--fs-body);
  font-weight: 500;
  letter-spacing: 0.01em;
  border: 1px solid transparent;
  border-radius: var(--radius-md);
  cursor: pointer;
  white-space: nowrap;
  transition: background-color var(--t-base), color var(--t-base),
              border-color var(--t-base), transform var(--t-fast);
}
:lang(ar) .btn { letter-spacing: 0; }

.btn--sm { --btn-py: 0.6rem; --btn-px: 1.15rem; font-size: var(--fs-body); }

.btn--primary { background: var(--green-800); color: #fff; }
.btn--primary:hover { background: var(--green-900); }

.btn--ghost { background: transparent; color: var(--text); border-color: var(--border); }
.btn--ghost:hover { border-color: var(--text-primary); background: rgba(var(--shadow-rgb), 0.03); }

/* Footer-only: the Footer surface is always dark in both site themes (see
   --footer-* tokens), so the usual dark-green .btn--primary would sit
   dark-on-dark with too little contrast. Bright green fill + near-black
   text is the same "strong, controlled accent on a dark surface" idea the
   Nav CTA and Why ARIBA already use, just inverted for this surface. */
.btn--footer { background: var(--green-500); color: #04140F; }
.btn--footer:hover { background: var(--green-400); }

.btn:active { transform: translateY(1px); }

/* ============================================================ NAVIGATION  */
/* Floating pill, not an edge-to-edge header bar: .nav is a full-width,
   invisible positioning shell (fixed, centred content, side gutters) and
   .nav__inner is the actual surface — sized, padded, rounded, and
   shadowed on its own, capped at --nav-max-w so it never spans the
   viewport. Scrolling only compacts its height/shadow/opacity; the
   floating shape and side margins never change.

   GLASS NAVBAR — paired with the full-screen photo Hero experiment.
   .nav__inner used to be a flat var(--green-800) fill; it's now a
   translucent glass surface (semi-transparent white + backdrop-filter)
   so the Hero photo stays visible through it instead of being hidden
   behind a solid bar. Because the surface itself is no longer dark, every
   child that used to be styled light-on-dark (links, brand chip, lang
   switch, CTA, toggle bars) is repainted dark-on-glass below — this is a
   surface-colour change only, no structural change. */
.nav {
  position: fixed;
  inset-block-start: var(--nav-top-gap);
  inset-inline: 0;
  z-index: 100;
  display: flex;
  justify-content: center;
  padding-inline: var(--gutter);
  pointer-events: none;
}
.nav__inner {
  pointer-events: auto;
  inline-size: 100%;
  max-inline-size: var(--nav-max-w);
  block-size: var(--nav-h);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-8);
  padding-inline: clamp(1.25rem, 1.6vw, 1.75rem);
  background: var(--nav-surface);
  backdrop-filter: blur(20px) saturate(160%);
  -webkit-backdrop-filter: blur(20px) saturate(160%);
  border: 1px solid var(--nav-border);
  border-radius: 999px;
  box-shadow: 0 12px 32px -18px rgba(var(--shadow-rgb), 0.28), 0 2px 10px -4px rgba(var(--shadow-rgb), 0.1);
  transition: block-size var(--t-base), box-shadow var(--t-base), padding var(--t-base),
              background-color var(--theme-t), border-color var(--theme-t);
}
/* Sensible fallback where backdrop-filter isn't supported: lean on opacity
   alone (higher, since there's no blur softening the image behind it) —
   still visibly a light (or, in dark mode, dark) surface, never back to
   solid green. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .nav__inner { background: var(--nav-surface-fallback); }
  .nav.is-scrolled .nav__inner { background: var(--nav-surface-fallback-scrolled); }
}

/* The mark no longer needs its own contrast-boosting chip: on flat dark
   green the near-black wordmark and dark ribbon fold were unreadable, but
   directly on light glass they already have plenty of contrast. Structure
   (padding, tap target) stays — only the visible chip surface is gone. */
.nav__brand {
  display: inline-flex;
  align-items: center;
  padding: 0.5rem 0.75rem;
  transition: padding var(--t-base);
}

.nav__logo {
  block-size: 30px;
  inline-size: auto;
  transition: block-size var(--t-base);
}

/* Scrolled state: a little more opaque + a little more shadow so the pill
   stays legible over the paper-coloured content sections below the Hero —
   still clearly glass, just a subtle step up, not a jump to solid. */
.nav.is-scrolled .nav__inner {
  block-size: var(--nav-h-scrolled);
  background: var(--nav-surface-scrolled);
  box-shadow: 0 14px 34px -18px rgba(var(--shadow-rgb), 0.32), 0 2px 12px -4px rgba(var(--shadow-rgb), 0.12);
}
.nav.is-scrolled .nav__brand { padding-block: 0.375rem; }
.nav.is-scrolled .nav__logo { block-size: 25px; }

.nav__menu {
  display: flex;
  flex: 1;
  align-items: center;
  justify-content: space-between;
  gap: clamp(1.5rem, 2.4vw, 3rem);
}
.nav__list {
  display: flex;
  align-items: center;
  gap: clamp(1.25rem, 1.9vw, 2.25rem);
}
.nav__link {
  position: relative;
  font-size: var(--fs-caption);
  color: var(--nav-link);
  padding-block: 0.35rem;
  transition: color var(--t-base);
}
.nav__link::after {
  content: "";
  position: absolute;
  inset-block-end: 0;
  inset-inline-start: 0;
  inline-size: 0;
  block-size: 1.5px;
  background: var(--brand-bright);
  transition: inline-size var(--t-base);
}
.nav__link:hover { color: var(--nav-link-active); }
.nav__link:hover::after { inline-size: 100%; }
.nav__link.is-active { color: var(--nav-link-active); }
.nav__link.is-active::after { inline-size: 100%; }

.nav__actions {
  display: flex;
  align-items: center;
  gap: var(--space-4);
}

.lang-switch {
  padding: 0.45rem 0.75rem;
  min-inline-size: 46px;
  font-size: var(--fs-caption);
  font-weight: 500;
  letter-spacing: 0.08em;
  color: var(--nav-link);
  background: rgba(var(--shadow-rgb), 0.06);
  border: 1px solid rgba(var(--shadow-rgb), 0.14);
  border-radius: var(--radius-md);
  cursor: pointer;
  transition: color var(--t-base), border-color var(--t-base), background-color var(--t-base);
}
.lang-switch:hover { color: var(--nav-link-active); border-color: rgba(var(--shadow-rgb), 0.28); background: rgba(var(--shadow-rgb), 0.1); }

/* Theme toggle: visually belongs with the language switch — same compact
   pill footprint as .lang-switch's tap target, but round and icon-only.
   Sun/moon are both always in the markup; CSS alone decides which shows
   via [data-theme], so JS only ever flips the attribute + persists it. */
.theme-toggle {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  inline-size: 38px;
  block-size: 38px;
  padding: 0;
  color: var(--nav-link);
  background: rgba(var(--shadow-rgb), 0.06);
  border: 1px solid rgba(var(--shadow-rgb), 0.14);
  border-radius: 50%;
  cursor: pointer;
  transition: color var(--t-base), border-color var(--t-base), background-color var(--t-base);
}
.theme-toggle:hover { color: var(--nav-link-active); border-color: rgba(var(--shadow-rgb), 0.28); background: rgba(var(--shadow-rgb), 0.1); }

.theme-toggle__icon {
  position: absolute;
  inset: 0;
  margin: auto;
  inline-size: 18px;
  block-size: 18px;
  transition: opacity var(--t-base), transform var(--t-base);
}
/* Light mode: sun visible (the switch is offered to go *to* dark).
   Dark mode: moon visible. Icons cross-fade with a tiny rotate, never a
   layout shift — both are always painted, only opacity/transform move. */
.theme-toggle__icon--moon { opacity: 0; transform: rotate(-40deg) scale(0.7); }
:root[data-theme="dark"] .theme-toggle__icon--sun { opacity: 0; transform: rotate(40deg) scale(0.7); }
:root[data-theme="dark"] .theme-toggle__icon--moon { opacity: 1; transform: none; }

/* Nav CTA: now that the surface itself is light glass, the CTA is the one
   deliberately strong-green element in the pill — just the ordinary
   .btn--primary (dark-green fill, white text) used everywhere else, no
   inverse pairing needed anymore. */

/* Mobile toggle */
.nav__toggle {
  display: none;
  padding: var(--space-3);
  margin-inline-end: -0.5rem;
  background: transparent;
  border: 0;
  cursor: pointer;
}
.nav__toggle-bars { display: block; inline-size: 24px; }
.nav__toggle-bars i {
  display: block;
  block-size: 1.5px;
  background: var(--nav-toggle-bar);
  transition: transform var(--t-base), opacity var(--t-fast), background-color var(--theme-t);
}
.nav__toggle-bars i:first-child { inline-size: 24px; }
.nav__toggle-bars i:last-child  { inline-size: 16px; margin-block-start: 6px; }
[dir="rtl"] .nav__toggle-bars i:last-child { margin-inline-start: auto; }
.nav__toggle[aria-expanded="true"] i:first-child { transform: translateY(3.75px) rotate(45deg); }
.nav__toggle[aria-expanded="true"] i:last-child  { inline-size: 24px; transform: translateY(-3.75px) rotate(-45deg); }

.nav__scrim {
  position: fixed;
  inset: 0;
  z-index: 90;
  background: var(--nav-scrim);
  opacity: 0;
  transition: opacity var(--t-base);
}
.nav__scrim.is-visible { opacity: 1; }

/* ================================================================== HERO  */
/* Top offset clears the floating pill (its own top gap + height) plus one
   small, fixed buffer — not a viewport-height calculation — so the Hero
   starts right under the navbar instead of being pushed down by leftover
   centering space. No min-block-size/100svh here on purpose: the row's
   height is simply whatever its content needs. */
.hero {
  position: relative;
  padding-block-start: calc(var(--nav-top-gap) + var(--nav-h) + clamp(5rem, 10vh, 8rem));
}
.hero__inner {
  display: grid;
  /* Image column runs slightly larger than content — ~55% of the row on
     desktop — so the photograph reads as part of the composition rather
     than an inset illustration. */
  grid-template-columns: minmax(0, 0.88fr) minmax(0, 1.12fr);
  column-gap: clamp(2rem, 3.5vw, 4rem);
  align-items: center;
  padding-block-end: clamp(2rem, 4vh, 3rem);
}

.hero__content { max-inline-size: 44rem; }

.hero__headline {
  font-size: var(--fs-display);
  font-weight: 600;
  margin-block: var(--space-6);
  /* Explicit <br> controls the break; balancing would fight it. */
  text-wrap: normal;
}

.hero__copy { margin-block-end: var(--space-12); }

.hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-4);
}

/* Media bleeds to the true viewport edge — LTR right, RTL left.
   `-1 * gutter` alone only cancels the container's own padding, so past
   the container's max-width (on wide screens) its centering margin was
   still left showing as a gap. Pulling by that centering margin *and* the
   gutter reaches the real edge at every viewport width; max(0px, …) keeps
   it a no-op below the max-width, where auto-centering doesn't apply.
   align-items: center (not stretch) so the image keeps its own aspect
   ratio inside the tall hero row rather than being force-stretched. */
.hero__media {
  margin: 0;
  margin-inline-end: calc(-1 * (max(0px, (100vw - var(--container)) / 2) + var(--gutter)));
  align-self: stretch;
  display: flex;
  align-items: center;
}

/* --------------------------------------------------- HERO VISUAL (image) */
/* The source asset already contains the final design — its own angled cut
   and brand-green edge are baked into the pixels. This wrapper only sizes
   and crops; it adds no shape, colour or chrome of its own.

   The image is wider than the space it fills (skyline + cut ≈ the first
   ~88% of its width; the rest is a plain white margin the designer left as
   fade-out room). A fixed aspect-ratio crops that trailing margin away via
   object-position: left, while keeping the full designed cut in frame at
   every breakpoint — cropping never eats into it because the ratio, not
   the viewport, decides where the visible window ends. */
.hero__visual {
  inline-size: 100%;
  overflow: hidden;
  aspect-ratio: 1649 / 839;
}

.hero__visual-img {
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
  object-position: left center;
  display: block;
}

/* ============================================================
   TEMP HERO EXPERIMENT — previous ariba_hero preserved
   ------------------------------------------------------------
   Full-bleed photo background (assets/images/home-riyadh-color.jpg) in place
   of the two-column text+image layout above. Nothing above this block
   was changed — the old .hero/.hero__inner/.hero__media/.hero__visual*
   rules are all still intact and still fully wired to their markup
   (currently commented out in index.html). This block only adds new,
   scoped rules on top; to restore the previous Hero, remove the
   "hero--bg-experiment" class from the <section class="hero"> in
   index.html, delete this block, and uncomment the old <figure
   class="hero__media">. See index.html's Hero comment for the full list.
   ============================================================ */
.hero--bg-experiment {
  display: grid;
  align-items: center;
  min-block-size: min(92svh, 860px);
  overflow: hidden;
  /* More top clearance than bottom (beyond the mandatory nav clearance)
     biases the vertically-centered content slightly below true centre —
     an editorial placement, not a mechanical middle. */
  padding-block-start: calc(var(--nav-top-gap) + var(--nav-h) + clamp(2.5rem, 7vh, 4.5rem));
  padding-block-end: clamp(3rem, 6vh, 4.5rem);
}

/* Full-bleed layer behind .hero__inner. An <img>, not background-image,
   to match how every other photo on this site is marked up (.hero__visual
   -img, .about__media-img, …) — same object-fit: cover mechanics, just
   sized to the full section instead of a column. */
.hero__bg {
  position: absolute;
  inset: 0;
  z-index: 0;
  overflow: hidden;
}
.hero__bg-img {
  position: absolute;
  inset: 0;
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
  object-position: center;
  display: block;
}

/* Directional readability scrim — brand dark-green rather than flat black,
   so the photo keeps its own colour temperature instead of reading as
   "photo + generic dark layer". Strongest on whichever edge the text sits
   (reading-start), fading out well before the image's opposite edge so
   most of the photograph stays visibly rich. LTR content sits left, so
   the scrim reads left→right; [dir="rtl"] mirrors it to read right→left,
   matching where the Arabic content column actually is — the photo asset
   itself is never flipped. */
.hero__bg-scrim {
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg,
    rgba(0, 25, 19, 0.62) 0%,
    rgba(0, 25, 19, 0.36) 40%,
    rgba(0, 25, 19, 0.10) 68%,
    rgba(0, 25, 19, 0) 92%);
}
[dir="rtl"] .hero__bg-scrim {
  background: linear-gradient(270deg,
    rgba(0, 25, 19, 0.62) 0%,
    rgba(0, 25, 19, 0.36) 40%,
    rgba(0, 25, 19, 0.10) 68%,
    rgba(0, 25, 19, 0) 92%);
}

.hero--bg-experiment .hero__inner {
  position: relative;
  z-index: 1;
  grid-template-columns: 1fr;
}

/* Text colours, scoped to the experiment only — nothing global changed. */
.hero--bg-experiment .eyebrow { color: rgba(255, 255, 255, 0.8); }
.hero--bg-experiment .hero__headline { color: #fff; }
.hero--bg-experiment .hero__copy { color: rgba(255, 255, 255, 0.86); }
.hero--bg-experiment .rule { background: linear-gradient(90deg, var(--green-400), rgba(255, 255, 255, 0.4)); }
[dir="rtl"] .hero--bg-experiment .rule { background: linear-gradient(270deg, var(--green-400), rgba(255, 255, 255, 0.4)); }

/* .btn--primary (solid dark-green fill) already has enough contrast over
   the photo unchanged. .btn--ghost's default ink text/paper-line border
   would nearly disappear over a dark image, so only that variant is
   adjusted here. */
.hero--bg-experiment .btn--ghost {
  color: #fff;
  border-color: rgba(255, 255, 255, 0.55);
}
.hero--bg-experiment .btn--ghost:hover {
  background: rgba(255, 255, 255, 0.1);
  border-color: #fff;
}

@media (max-width: 900px) {
  /* Same full-height background; a fuller-width scrim since the content
     column now spans nearly the full viewport instead of ~44rem beside an
     untouched photo half. */
  .hero__bg-scrim,
  [dir="rtl"] .hero__bg-scrim {
    background: linear-gradient(180deg,
      rgba(0, 25, 19, 0.42) 0%,
      rgba(0, 25, 19, 0.56) 55%,
      rgba(0, 25, 19, 0.66) 100%);
  }
}

/* ================================================================= ABOUT  */
.about {
  position: relative;
  background: var(--bg-primary);
  overflow: hidden;
  /* Tighter than the shared .section top padding — the Hero no longer ends
     in a closing rule/microcopy line, so this is now the only thing setting
     the Hero → About distance. Bottom padding is zeroed (overriding the
     shared .section rule's --section-y) rather than inheriting it: with
     Capabilities now directly after Journey, that generic full-size
     section-boundary padding just stacked with Journey's own trailing
     space and Capabilities' own leading space, producing a huge triple
     gap. Capabilities' padding-block-start is the section boundary now;
     About ends the moment Journey's own content does. */
  padding-block-start: clamp(3rem, 6vw, 5rem);
  padding-block-end: 0;
}

/* The image is always the visual-outer column — right in Arabic, left in
   English — with the heading beside it, closer to page centre. This is a
   flat swap (not a [dir="rtl"] override): combined with how CSS Grid
   itself already flips track1's physical side with `direction` (track1 =
   left in LTR, right in RTL), putting media in track1 unconditionally
   lands it on the right for Arabic and the left for English — exactly
   the mirrored composition both languages ask for.

   Desktop only (see the >=901px block below): the row breaks out of
   .container to the full 100vw viewport width via the standard
   left:50%/-50vw idiom, so a genuine 1fr/1fr split gives each column a
   *true* 50vw — not 50% of the 1280px container — with the image column
   already flush against the viewport edge with no extra bleed margin
   needed. Below 901px the row stays inside .container and stacks to a
   single column (see the mobile block). */
.about__grid {
  display: grid;
  grid-template-columns: 1fr;
  align-items: center;
  margin-block-start: clamp(1.75rem, 3.5vw, 2.75rem);
}

/* grid-row: 1 on both is load-bearing, not decorative: auto-placement's
   sparse packing only searches *forward* from the previous item's
   column, so media (column 1, placed after lead which already claimed
   column 2) would otherwise get pushed to row 2 instead of back-filling
   row 1 — silently splitting the "row" into two stacked rows and
   producing exactly the floating-heading / cramped-image misalignment
   this markup used to have. */
.about__lead  { grid-column: 1; grid-row: 1; }
.about__media { grid-column: 1; grid-row: 1; }

@media (min-width: 901px) {
  .about__grid {
    grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr);
    column-gap: clamp(2rem, 4vw, 4.5rem);
    width: auto;
    position: static;
    margin-inline: 0;
  }

  .about__lead  { grid-column: 2; }
  .about__media { grid-column: 1; }

  /* Both edges get the standard page gutter, same as .container's own
     padding — not the wider "match the 1280px container's edge" offset
     that an earlier version used here, which capped this column's width
     at a fixed ~530px on any screen beyond ~1600px wide and forced the
     headline to wrap mid-phrase at larger sizes. With just the gutter,
     the column keeps growing with the viewport, which is what actually
     lets the bigger clamp() below stay on two lines instead of three.
     padding-inline-end is the *outer* edge on both sides: track2 (lead)
     sits physically right in LTR (end=right ✓) and physically left in
     RTL (end=left ✓), so this needs no [dir] override either. */
  .about__lead {
    padding-inline-start: clamp(1rem, 2vw, 2rem);
  }

  /* Arabic: centre the heading *block* within the full 50% column
     instead of padding it away from the image edge — a fixed padding
     was still visually anchoring it to the image side rather than
     balancing it in the available space, so it's replaced here rather
     than layered under the centering. .about__headline has no explicit
     width and its two lines are a hard <br> (not natural wrapping), so
     as a flex item it sizes to its own longest line — that fit-content
     box is what justify-content:center centres, while the shorter line
     stays right-aligned *within that box* by the normal RTL default,
     preserving the current two-line relationship instead of forcing
     each line to its own centre (which is what plain text-align:center
     on the full column would have done). English is untouched: .about
     __lead there stays a plain block, not a flex container. */
  :root[dir="rtl"] .about__lead { padding-inline-start: clamp(1rem, 2vw, 2rem); }
}

.about__headline {
  font-size: var(--fs-heading);
  font-weight: 600;
}

:lang(en) .about__headline {
  max-inline-size: 25ch;
}
/* Arabic-only bump: was reading visually lighter than the image's 50vw
   presence warranted. Keeps the same 2.125rem floor for mobile widths
   (where this clamp still applies) and stays comfortably inside the
   ~2-line budget the extra inner gap above just tightened slightly —
   Arabic's short two phrases ("نقود التحول." / "ونصنع الأثر.") have far
   more room to grow than English's longer lines did. */
:lang(ar) .about__headline { max-inline-size: 25ch; }

/* --------------------------------------------------- ABOUT / MEDIA  */
.about__media {
  position: relative;
  align-self: stretch;
  display: flex;
  align-items: center;
}

/* The source asset already contains the final design — its own angled
   chevron cut and green edge are baked into the pixels, matching the
   Hero visual's treatment. Aspect-ratio matches the asset exactly (no
   crop at most desktop widths, since the column is now a true 50vw and
   its natural aspect-ratio height is already substantial); min-block-size
   is only a floor for narrower desktop/tablet widths where 50vw alone
   would leave too little room for the overlaid paragraphs — object-fit
   then crops top/bottom only, the asset itself is never edited. */
.about__media-frame {
  --flip: -1; /* default = LTR/English: mirrored so the cut faces the
                 heading on the right, per the Hero-style bleed-left
                 composition. */
  inline-size: 100%;
  overflow: hidden;
  aspect-ratio: 1536 / 1024;
  min-block-size: clamp(460px, 31vw, 580px);
}
:root[dir="rtl"] .about__media-frame { --flip: 1; } /* Arabic: unmirrored, cut faces the heading on the left. */

/* brightness(), not a black ::after overlay: the asset's chevron cut is
   real transparency (the frame is wider than the visible photo shape),
   so a rectangular overlay box painted a flat gray slab across the cut-
   away area instead of just darkening the photo. Filtering the <img>
   itself only ever touches its own pixels — transparent stays
   transparent — and darkens for the white paragraph text's contrast
   without needing a separate layer. Order matters: scaleX flips first,
   then brightness applies to the (already-flipped) pixels either way,
   so English mirroring is unaffected. */
.about__media-img {
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
  display: block;
  transform: scaleX(var(--flip));
  filter: brightness(0.8);
  transition: transform 600ms cubic-bezier(0.2, 0.8, 0.2, 1);
}

/* Hover: a very subtle zoom on the photo only — the overlaid text stays
   fixed. Restates the same brightness() alongside the added scale()
   since this replaces the base transform/filter declaration rather than
   layering on top of it. Guarded to devices with a real hover-capable
   pointer. */
@media (hover: hover) and (pointer: fine) {
  .about__media:hover .about__media-img { transform: scaleX(var(--flip)) scale(1.02); filter: brightness(0.8); }
}

/* The two About paragraphs, laid directly over the photo, inside the
   clear/dark patch beside the chevron. Anchored with a physical offset
   from the *outer* edge (right in English, left in Arabic) because that
   patch mirrors along with the image itself — see --flip above — so the
   text has to mirror with it to stay over the same part of the photo. */
.about__media-text {
  position: absolute;
  left: clamp(1.25rem, 3vw, 2rem);
  right: 28%;
  /* Nudged up from a tighter bottom-corner offset now that the eyebrow
     label is gone — with only the two paragraphs left, sitting this
     much closer to centre reads as balanced instead of bottom-heavy. */
  bottom: clamp(2rem, 5vw, 3.5rem);
  max-inline-size: 680px;
  padding: clamp(1.25rem, 2.5vw, 2rem);
  z-index: 2;
}
:root[dir="rtl"] .about__media-text { left: 28%; right: clamp(1.25rem, 3vw, 2rem); }

/* A soft, blurred glow behind the text rather than a hard-edged panel —
   it reads as light falling on the photo, not a card. Sized and blurred
   well past the text's own box so no rectangle edge is ever visible;
   "don't darken the whole image" is enforced by keeping the glow local
   to the text and letting it fall fully to transparent inside its own
   bounds. Colour is --green-800 (0,77,61) rather than the darker
   --green-900 used elsewhere, so it reads as a warm wash, not a shadow. */
.about__media-text::before {
  content: '';
  position: absolute;
  inset: -3rem -3.5rem -3.5rem -3.5rem;
  background: radial-gradient(closest-side at 72% 72%,
              rgba(0, 77, 61, 0.65) 0%,
              rgba(0, 77, 61, 0.3) 50%,
              rgba(0, 77, 61, 0) 80%);
  filter: blur(24px);
  z-index: -1;
  pointer-events: none;
}
/* Arabic reads fine over its own patch of the photo already — a lighter
   touch than the English side, just enough to guard against the
   brighter marble reflections at the very bottom. */
:root[dir="rtl"] .about__media-text::before {
  background: radial-gradient(closest-side at 28% 72%,
              rgba(0, 77, 61, 0.5) 0%,
              rgba(0, 77, 61, 0.22) 50%,
              rgba(0, 77, 61, 0) 80%);
}

.about__media-body {
  display: grid;
  gap: var(--space-4);
  font-size: var(--fs-lede);
  line-height: var(--lh-body);
  color: rgba(255, 255, 255, 0.94);
  text-shadow: 0 1px 6px rgba(0, 0, 0, 0.4);
}

/* Keep the approved profile paragraphs in the same dedicated reading panel
   in both languages. Direction changes the copy flow, not the composition. */
.about__media {
  display: grid;
  grid-template-rows: clamp(260px, 20vw, 340px) auto;
  align-items: stretch;
  background: var(--green-900);
}

.about__media-frame {
  min-block-size: 0;
  block-size: 100%;
  aspect-ratio: auto;
}

.about__media-text,
:root[dir="rtl"] .about__media-text {
  position: relative;
  inset: auto;
  align-self: stretch;
  max-inline-size: none;
  padding: clamp(1.5rem, 3vw, 2.25rem);
  background: var(--green-900);
}

.about__media-text::before { display: none; }

.about__media-body {
  gap: var(--space-3);
  font-size: var(--fs-body);
  line-height: 1.62;
  text-shadow: none;
}

/* The narrowest desktop tier: a true 50vw column is only ~450–620px
   here, so the overlaid paragraphs need a smaller, tighter-set size to
   stay inside the frame's min-block-size floor instead of spilling
   above it (English needs it more; Arabic already clears at this
   width, but the tighter set doesn't hurt it either). Placed after the
   unconditional rules above so the cascade actually picks it up at
   this width — same specificity, later wins. */
@media (min-width: 901px) and (max-width: 1199px) {
  .about__media-body { font-size: var(--fs-body); gap: var(--space-3); }
  .about__media-text { padding: 1.25rem; }
}

/* Reveal: the image slides in from the right (translateX) while the text
   uses the shared vertical fade — see data-reveal-delay in the markup for
   the image-then-text stagger. */
.js .about__media-frame[data-reveal] { transform: translateX(30px); }

.about .container { position: relative; z-index: 1; }

/* --------------------------------------------- ABOUT / JOURNEY  */
/* Scroll arms one coordinated reveal. English draws toward the mark from
   left to right; the existing RTL mirror makes Arabic draw from right to
   left toward its mark. The brand mark appears only after the route ends. */
.journey {
  position: relative;
  margin-block-start: clamp(1.75rem, 3.5vw, 3rem);
  /* No padding-block-end: this used to add its own trailing space before
     Impact came right after About, on top of About's own bottom padding.
     Now that Capabilities sits here instead, its padding-block-start is
     the single source of that gap — see .about and .capabilities. */
}

.journey__viz { position: relative; }

/* preserveAspectRatio="none" lets the drawing stretch to any width while
   non-scaling-stroke keeps the line weight constant. */
.journey__svg {
  display: block;
  inline-size: 100%;
  block-size: clamp(320px, 32vw, 460px);
}

.journey__track,
.journey__path {
  fill: none;
  stroke-width: 12;
  stroke-linecap: round;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
  transition: stroke var(--theme-t);
}

/* The undrawn route stays faintly present, so the section never reads empty.
   Dark mode swaps the tint from a faint brand-green to a faint light-gray-
   green so it stays visible against the dark charcoal page — see
   --journey-track in the theme token blocks. */
.journey__track { stroke: var(--journey-track); }
.journey__path {
  stroke: url(#journeyStroke);
  stroke-dasharray: none;
  stroke-dashoffset: 0;
}

/* The route stays undashed. A rectangular SVG curtain is moved by changing
   its numeric x attribute, avoiding cross-browser path-length calculations. */
.js .journey__path {
  stroke-dasharray: none;
  stroke-dashoffset: 0;
}

.journey__curtain { display: none; }
.js .journey__curtain {
  display: block;
  fill: var(--bg-primary);
  transition: fill var(--theme-t);
}

.journey__track--foreground { pointer-events: none; }

.journey__stages {
  position: absolute;
  inset: 0;
  margin: 0;
  padding: 0;
  list-style: none;
}

/* --x / --y are the node's position on the path, set in markup. Centring is
   done with left/inline-size rather than a transform, so transform stays
   free for the reveal (and can be safely cancelled for reduced motion). */
.journey__stage {
  position: absolute;
  top: var(--y);
  left: calc(var(--x) - min(120px, 11%));
  inline-size: min(240px, 22%);
  padding-block-start: 1.75rem;
  text-align: start;
}

/* The real cause of the English stage-03 overlap wasn't horizontal — its
   text column already sits (like every stage's) with its left edge under
   the path, and stage 02 -> 03 is exactly where the path is NOT flat: it
   rises diagonally from y=190 (stage 02's plateau) to y=90 (stage 03's) in
   SVG-unit terms, i.e. across 21.74% of the drawing's height. A modest
   padding bump (tried previously) doesn't clear that; a left-shift makes
   it worse by moving the column deeper under the rising diagonal. The fix
   is to push stage 03's text down past where that diagonal ends, scaled to
   match .journey__svg's own clamp(320px, 32vw, 460px) so the clearance
   holds proportionally at every width instead of only at one screenshot's.
   Arabic reads shorter and already clears it, so it's untouched; stages
   01/02 sit on flat stretches and are untouched. */
@media (min-width: 901px) {
  :lang(en) .journey__stage--end {
    padding-block-start: clamp(5.5rem, calc(7vw + 1.125rem), 7.5rem);
  }
}

.js .journey__stage {
  opacity: 0;
  transform: translateY(14px);
  transition: opacity 560ms var(--ease), transform 560ms var(--ease);
}
.js .journey__stage.is-reached {
  opacity: 1;
  transform: none;
}

/* Sits on the line: paper fill so the stroke reads through the ring. */
.journey__dot {
  position: absolute;
  top: 0;
  left: 50%;
  inline-size: 14px;
  block-size: 14px;
  margin: -7px 0 0 -7px;
  border-radius: 50%;
  background: var(--bg-primary);
  box-shadow: inset 0 0 0 3px var(--dot, var(--green-800));
  transition: background-color var(--theme-t);
}

/* One-shot pulse when the line arrives. Never loops. */
.journey__dot::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: 50%;
  border: 2px solid var(--dot, var(--green-500));
  opacity: 0;
}
.journey__stage.is-reached .journey__dot::after {
  animation: journey-pulse 900ms var(--ease) 1 both;
}
@keyframes journey-pulse {
  from { transform: scale(1);   opacity: 0.5; }
  to   { transform: scale(2.8); opacity: 0; }
}

.journey__num {
  position: absolute;
  top: 0;
  left: 50%;
  transform: translate(-50%, calc(-100% - 1.25rem));
  font-family: var(--font-head);
  font-size: var(--fs-heading);
  font-weight: 600;
  line-height: 1;
  letter-spacing: -0.02em;
  color: var(--text-faint);
}

.journey__title {
  font-size: var(--fs-lede);
  font-weight: 600;
  line-height: var(--lh-snug);
  margin-block-end: var(--space-3);
}

.journey__text {
  margin: 0;
  font-size: var(--fs-body);
  line-height: 1.7;
  color: var(--text-muted);
}

/* Destination of the line, sitting on the final plateau. It is part of the
   permanently complete route and is never mirrored in either direction. */
.journey__mark {
  position: absolute;
  right: 0;
  top: 19.565%;
  inline-size: clamp(64px, 11%, 132px);
  transform: translateY(-50%);
}

/* The English profile journey carries five verified approach stages. Its
   taller drawing and narrower copy columns preserve the same stepped-route
   signature without forcing five stages into the old three-stage geometry. */
.journey--profile .journey__svg {
  block-size: clamp(430px, 39vw, 560px);
}

.journey--profile .journey__path {
  stroke: url(#journeyStrokeProfile);
}

.journey--profile .journey__stage {
  left: calc(var(--x) - 6.5%);
  inline-size: 13%;
  padding-block-start: 1.5rem;
}

@media (min-width: 901px) {
  .journey--profile .journey__dot,
  .journey--profile .journey__num {
    left: 50%;
  }

  .journey--profile .journey__num {
    transform: translate(-50%, calc(-100% - 1.25rem));
  }

  .journey--profile .journey__stage:last-child {
    left: calc(var(--x) - 7.5%);
    inline-size: 15%;
  }
}

.journey--profile .journey__title {
  font-size: var(--fs-body);
}

.journey--profile .journey__text {
  font-size: var(--fs-caption);
  line-height: 1.58;
}

.journey--profile .journey__mark { top: 12.5%; }

.js .journey__mark {
  opacity: 0;
  transition: opacity 420ms var(--ease);
}

.js .journey.is-complete .journey__mark { opacity: 1; }

/* ============================================================ CAPABILITIES */
.capabilities {
  position: relative;
  background: var(--bg-primary);
  /* The sole source of the About -> Capabilities gap: About's own bottom
     padding and Journey's own trailing padding are both zeroed (see
     .about and .journey) specifically so this is the only spacing rule
     governing that transition, instead of three separate section-boundary
     paddings stacking into one huge gap. Ceiling raised slightly past the
     shared clamp(3rem,6vw,5rem) pattern (48-80px) to 6.5rem (104px) so it
     reads as a full, deliberate gap on wide screens now that it's carrying
     the whole distance alone. Bottom padding stays the standard
     --section-y (set by the shared .section class) since the next
     section isn't built yet. */
  padding-block-start: clamp(3rem, 6vw, 6.5rem);
}

.cap__head {
  display: grid;
  gap: var(--space-6);
  max-inline-size: 46rem;
}

.cap__headline {
  font-size: var(--fs-heading);
  font-weight: 600;
  max-inline-size: 26ch;
}

.cap__copy {
  display: grid;
  gap: var(--space-2);
  margin: 0;
}

.cap-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(1.25rem, 2.5vw, 2rem);
  margin-block-start: clamp(2rem, 4vw, 3rem);
}

/* Card state is expressed as custom properties set on .cap-card (the <li>)
   and consumed by its descendants — one source of truth per interaction
   state (hover / keyboard focus-within / the JS-driven .is-expanded tap
   state on touch) instead of repeating the same declarations three times.
   Mirrors the --flip pattern already used for the About image. */
.cap-card {
  --cap-tint: linear-gradient(180deg,
              rgba(20, 16, 17, 0.16) 0%,
              rgba(20, 16, 17, 0.32) 55%,
              rgba(10, 8, 9, 0.78) 100%);
  --cap-img-scale: 1;
  --cap-desc-row: 0fr;
  --cap-desc-op: 0;
  --cap-desc-y: 8px;
  --cap-arrow: none;
  --cap-lift: 0px;
  --cap-shadow: 0 1px 2px rgba(var(--shadow-rgb), 0.05);
}

/* Richer ARIBA-green tint + description reveal, shared by keyboard focus
   and the touch/tap toggle. Hover (desktop-only) sets the same variables
   further down, gated to real pointer devices. */
.cap-card:focus-within,
.cap-card.is-expanded {
  --cap-tint: linear-gradient(180deg,
              rgba(0, 77, 61, 0.4) 0%,
              rgba(0, 77, 61, 0.52) 55%,
              rgba(0, 42, 33, 0.86) 100%);
  --cap-desc-row: 1fr;
  --cap-desc-op: 1;
  --cap-desc-y: 0px;
  --cap-lift: -5px;
  --cap-shadow: 0 18px 34px -18px rgba(0, 53, 39, 0.32);
}
/* Rotate (not translate) marks the tap-expanded state specifically — it
   reads as "tap again to collapse" rather than the hover-only nudge. */
.cap-card.is-expanded { --cap-arrow: rotate(180deg); }
.cap-card:focus-within { --cap-arrow: translateY(-5px); }

@media (hover: hover) and (pointer: fine) {
  .cap-card:hover {
    --cap-tint: linear-gradient(180deg,
                rgba(0, 77, 61, 0.4) 0%,
                rgba(0, 77, 61, 0.52) 55%,
                rgba(0, 42, 33, 0.86) 100%);
    --cap-img-scale: 1.02;
    --cap-desc-row: 1fr;
    --cap-desc-op: 1;
    --cap-desc-y: 0px;
    --cap-arrow: translateY(-5px);
    --cap-lift: -5px;
    --cap-shadow: 0 18px 34px -18px rgba(0, 53, 39, 0.32);
  }
}

.cap-card__inner {
  position: relative;
  aspect-ratio: 3 / 4;
  overflow: hidden;
  border-radius: var(--radius-lg);
  box-shadow: var(--cap-shadow);
  transform: translateY(var(--cap-lift));
  transition: transform 380ms var(--ease), box-shadow 380ms var(--ease);
}

.cap-card__media { position: absolute; inset: 0; }

.cap-card__img {
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
  display: block;
  transform: scale(var(--cap-img-scale));
  transition: transform 380ms var(--ease);
}

/* Doubles as the default readability gradient (darker toward the bottom,
   where the title/CTA sit) and the hover-state green tint — same layer,
   just a different --cap-tint value, so there's only ever one darkening
   pass over the photo rather than a base overlay plus a separate tint. */
.cap-card__media::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 1;
  background: var(--cap-tint);
  transition: background 380ms var(--ease);
}

.cap-card__content {
  position: absolute;
  inset-inline: 0;
  inset-block-end: 0;
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: start;
  text-align: start;
  padding: clamp(1.25rem, 2.2vw, 1.75rem);
  color: #fff;
}

.cap-card__number {
  font-family: var(--font-head);
  font-size: var(--fs-body);
  font-weight: 600;
  letter-spacing: 0.04em;
  color: rgba(255, 255, 255, 0.6);
  margin-block-end: var(--space-2);
}
:lang(ar) .cap-card__number { letter-spacing: 0; }

.cap-card__title {
  font-size: var(--fs-lede);
  font-weight: 600;
  line-height: var(--lh-snug);
  color: #fff;
}

/* The 0fr -> 1fr grid-rows trick: a single-track grid with no explicit
   height animates smoothly to its content's natural height without JS
   measuring anything, and min-block-size: 0 on the child lets the track
   actually collapse to zero instead of being floored by the paragraph's
   own intrinsic minimum. */
.cap-card__desc-wrap {
  display: grid;
  grid-template-rows: var(--cap-desc-row);
  transition: grid-template-rows 380ms var(--ease);
}
.cap-card__desc-content {
  overflow: hidden;
  min-block-size: 0;
  opacity: var(--cap-desc-op);
  transform: translateY(var(--cap-desc-y));
  transition: opacity 320ms var(--ease), transform 320ms var(--ease);
}

.cap-card__desc {
  margin: 0;
  padding-block-start: var(--space-3);
  font-size: var(--fs-body);
  line-height: 1.6;
  color: rgba(255, 255, 255, 0.88);
}

.cap-card__services {
  display: grid;
  gap: var(--space-2);
  margin-block-start: var(--space-3);
  padding: 0;
  list-style: none;
  color: rgba(255, 255, 255, 0.82);
  font-size: var(--fs-caption);
  line-height: 1.45;
}

.cap-card__services li::before {
  content: '•';
  margin-inline-end: var(--space-2);
  color: var(--green-400);
}

.cap-card__more {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  margin-block-start: var(--space-3);
  padding: 0;
  background: none;
  border: 0;
  font-family: var(--font-body);
  font-size: var(--fs-caption);
  font-weight: 500;
  letter-spacing: 0.02em;
  color: #fff;
  cursor: pointer;
}
:lang(ar) .cap-card__more { letter-spacing: 0; }

.cap-card__arrow {
  inline-size: 16px;
  block-size: 16px;
  transform: var(--cap-arrow);
  transition: transform 320ms var(--ease);
}

/* ======================================================== WHY ARIBA  */
/* Explicit top/bottom padding instead of the generic .section class —
   see the About/Journey/Capabilities fix above: letting two neighbours
   each own a large, uncoordinated padding is exactly how that whitespace
   bug happened. Here Why owns both edges of its own gap outright. */
.why {
  position: relative;
  padding-block-start: clamp(3rem, 6vw, 6.5rem);
  padding-block-end: clamp(2.5rem, 5vw, 4rem);
  background: var(--bg-primary);
}

/* The green surface. A plain block (not the .section/.container pair),
   so it's edge-to-edge by default with no width override needed; the
   editorial content inside it is still wrapped in .container. */
.why__band {
  position: relative;
  padding-block: clamp(3.5rem, 7vw, 6rem) clamp(6.5rem, 11vw, 9.5rem);
  color: #fff;
  background:
    radial-gradient(130% 90% at 88% 0%, rgba(10, 98, 73, 0.55) 0%, transparent 55%),
    linear-gradient(160deg, var(--green-900) 0%, var(--green-800) 62%, var(--green-700) 100%);
  /* One straight architectural cut: full height on the reading-start
     edge, tapering to a shorter panel on the reading-end edge. No
     curves — a single diagonal line only. */
  clip-path: polygon(0 0, 100% 0, 100% 80%, 0 100%);
}
[dir="rtl"] .why__band {
  clip-path: polygon(100% 0, 0 0, 0 80%, 100% 100%);
}

.why__head {
  display: grid;
  gap: var(--space-6);
  max-inline-size: 32rem;
}

.why__headline {
  font-size: var(--fs-heading);
  font-weight: 600;
  line-height: var(--lh-snug);
  color: #fff;
  max-inline-size: 18ch;
}

.why__copy {
  margin: 0;
  font-size: var(--fs-lede);
  line-height: var(--lh-body);
  color: rgba(255, 255, 255, 0.88);
  max-inline-size: 42ch;
}

.why__supporting {
  margin: 0;
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  color: rgba(255, 255, 255, 0.64);
  max-inline-size: 42ch;
}

/* The floating panel. Pulled up over .why__band's cut with a negative
   margin — a deliberate overlap, the one place this section intentionally
   crosses its own boundary, not a leftover spacing bug. */
.why__stats {
  position: relative;
  z-index: 1;
  margin: clamp(-6.5rem, -9vw, -5rem) 0 0;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 0;
  background: var(--surface-elevated);
  border: 1px solid transparent;
  border-radius: var(--radius-lg);
  box-shadow: 0 30px 60px -28px rgba(0, 53, 39, 0.32), 0 4px 16px rgba(var(--shadow-rgb), 0.06);
  padding-block: clamp(1.75rem, 3.2vw, 2.5rem);
  padding-inline: clamp(1.5rem, 3vw, 2.75rem);
  transition: background-color var(--theme-t), border-color var(--theme-t);
}
/* Dark mode: the panel is a lifted surface, not the paper-white card it is
   in light mode, so it needs its own thin border to read as "elevated"
   against the green band's edge instead of relying on a light/paper
   contrast that no longer exists. */
:root[data-theme="dark"] .why__stats { border-color: var(--border); }

.why__stat {
  position: relative;
  padding-inline: clamp(1rem, 2.2vw, 2rem);
  text-align: center;
}
.why__stat:first-child { padding-inline-start: 0; }
.why__stat:last-child  { padding-inline-end: 0; }
.why__stat + .why__stat { border-inline-start: 1px solid var(--stat-divider); }

.why__stat-number {
  display: block;
  font-family: var(--font-head);
  font-size: var(--fs-heading);
  font-weight: 600;
  line-height: 1;
  letter-spacing: -0.02em;
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}

.why__stat-number--vision {
  font-size: var(--fs-lede);
  letter-spacing: 0.035em;
}
:lang(ar) .why__stat-number { letter-spacing: 0; }

.why__stat-label {
  display: block;
  margin-block-start: var(--space-3);
  font-size: var(--fs-caption);
  line-height: 1.5;
  color: var(--text-muted);
}

/* Prototype-only marker. Delete with the confirmed figure. */
.why__stat-tbd {
  display: inline-block;
  margin-block-start: var(--space-2);
  font-size: var(--fs-caption);
  font-weight: 500;
  letter-spacing: 0.12em;
  color: var(--green-700);
  opacity: 0.75;
}
:root[data-theme="dark"] .why__stat-tbd { color: var(--green-400); }

/* ====================================================== CLIENTS / CONSTELLATION  */
/* Editorial intro (asymmetric, reading-start aligned) followed by a hand-
   placed composition: a 12-column grid puts the ARIBA mark at the centre
   and the 15 real client logos around it in fixed, non-random positions
   (see the grid-column/grid-row rules below — each one is a deliberate
   placement, not generated). Hover/focus dimming and the connecting-line
   highlight are done with :has() only; there is no interaction JS. */
/* Tighter than the shared .section bottom padding — paired with Contact's
   own reduced top padding below, this replaces the doubled-up
   Clients-bottom + Contact-top gap (each independently near --section-y)
   with a single, smaller transition so the constellation and Contact read
   as connected rather than as two distant sections. */
.clients { padding-block-end: clamp(2.5rem, 4vw, 4rem); }

.clients__head { max-inline-size: 34rem; display: grid; gap: var(--space-4); }
.clients__headline {
  font-size: var(--fs-heading);
  font-weight: 600;
  line-height: var(--lh-snug);
  color: var(--text-primary);
  max-inline-size: 16ch;
}
.clients__copy {
  margin: 0;
  font-size: var(--fs-lede);
  line-height: var(--lh-body);
  color: var(--text-muted);
  max-inline-size: 40ch;
}

.constellation {
  position: relative;
  margin-block-start: clamp(3rem, 7vw, 5.5rem);
  isolation: isolate;
  overflow: hidden;
}

/* Oversized brand geometry, barely there. A single rotated square evokes
   the diamond/ribbon fold used across the identity (nav rule, About
   chevron) without repeating the mark itself. Physical left/top + a
   physical translate (not logical inset-inline-start) — centering math
   that must not re-derive per direction. */
.constellation__bg {
  position: absolute;
  top: 50%;
  left: 50%;
  inline-size: min(900px, 90vw);
  block-size: min(900px, 90vw);
  background: linear-gradient(135deg, var(--green-800), var(--green-500));
  opacity: 0.025;
  filter: blur(70px);
  transform: translate(-50%, -50%) rotate(45deg);
  z-index: -1;
  pointer-events: none;
}

.constellation__lines {
  position: absolute;
  inset: 0;
  inline-size: 100%;
  block-size: 100%;
  z-index: 1;
  pointer-events: none;
}
.constellation__line {
  fill: none;
  stroke: var(--constellation-line);
  stroke-width: 1.25;
  opacity: 0.1;
  vector-effect: non-scaling-stroke;
  transition: opacity var(--t-base), stroke var(--theme-t);
}
/* Each side forks near the mark into an upper and a lower branch, so
   hover/focus/auto-highlight on any logo in that quadrant lights only its
   own branch — never all four at once. */
.constellation:has(.constellation__logo[data-sector="upper-left"] .constellation__btn:hover) .constellation__line--upper-left,
.constellation:has(.constellation__logo[data-sector="upper-left"] .constellation__btn:focus-visible) .constellation__line--upper-left,
.constellation:has(.constellation__logo[data-sector="upper-left"] .constellation__btn.is-auto-active) .constellation__line--upper-left,
.constellation:has(.constellation__logo[data-sector="upper-right"] .constellation__btn:hover) .constellation__line--upper-right,
.constellation:has(.constellation__logo[data-sector="upper-right"] .constellation__btn:focus-visible) .constellation__line--upper-right,
.constellation:has(.constellation__logo[data-sector="upper-right"] .constellation__btn.is-auto-active) .constellation__line--upper-right,
.constellation:has(.constellation__logo[data-sector="lower-left"] .constellation__btn:hover) .constellation__line--lower-left,
.constellation:has(.constellation__logo[data-sector="lower-left"] .constellation__btn:focus-visible) .constellation__line--lower-left,
.constellation:has(.constellation__logo[data-sector="lower-left"] .constellation__btn.is-auto-active) .constellation__line--lower-left,
.constellation:has(.constellation__logo[data-sector="lower-right"] .constellation__btn:hover) .constellation__line--lower-right,
.constellation:has(.constellation__logo[data-sector="lower-right"] .constellation__btn:focus-visible) .constellation__line--lower-right,
.constellation:has(.constellation__logo[data-sector="lower-right"] .constellation__btn.is-auto-active) .constellation__line--lower-right,
.constellation:has(.constellation__logo[data-sector="center"] .constellation__btn:hover) .constellation__line--center,
.constellation:has(.constellation__logo[data-sector="center"] .constellation__btn:focus-visible) .constellation__line--center,
.constellation:has(.constellation__logo[data-sector="center"] .constellation__btn.is-auto-active) .constellation__line--center {
  stroke: var(--green-500);
  opacity: 0.5;
}
[dir="rtl"] .constellation__lines { transform: scaleX(-1); }

.constellation__logos {
  position: relative;
  z-index: 2;
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  grid-auto-rows: minmax(64px, auto);
  align-items: center;
  justify-items: center;
  column-gap: clamp(0.5rem, 1.4vw, 1.25rem);
  row-gap: clamp(1.25rem, 3vw, 2.25rem);
  margin: 0;
  padding-block: clamp(1.5rem, 4vw, 3rem);
  list-style: none;
}

/* ARIBA mark — the composition's fixed centre. Never resized aggressively,
   never mirrored; only its position and the faint halo around it change. */
.constellation__mark {
  grid-column: 6 / 8;
  grid-row: 3 / 4;
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  inline-size: clamp(56px, 5vw, 76px);
  block-size: clamp(56px, 5vw, 76px);
}
.constellation__mark::before {
  content: "";
  position: absolute;
  inset: -34%;
  background: radial-gradient(circle, rgba(10, 98, 73, 0.10) 0%, rgba(10, 98, 73, 0) 70%);
  border-radius: 50%;
  opacity: 0.6;
  transition: opacity var(--t-base);
}
.constellation:has(.constellation__btn:hover) .constellation__mark::before,
.constellation:has(.constellation__btn:focus-visible) .constellation__mark::before {
  opacity: 1;
}
.constellation__mark img {
  inline-size: 100%;
  block-size: 100%;
  object-fit: contain;
  transition: transform var(--t-base);
}
.constellation:has(.constellation__btn:hover) .constellation__mark img,
.constellation:has(.constellation__btn:focus-visible) .constellation__mark img {
  transform: scale(1.03);
}

.constellation__logo {
  --box-h: clamp(42px, 3.4vw, 60px);
  transform: translateY(var(--nudge, 0px));
}
.constellation__logo--tall { --box-h: clamp(60px, 5vw, 84px); }

.constellation__btn {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  inline-size: clamp(84px, 8vw, 128px);
  block-size: var(--box-h);
  padding: 0;
  background: none;
  border: 0;
  border-radius: var(--radius-md);
  cursor: pointer;
  transition: transform var(--t-base), background-color var(--theme-t), box-shadow var(--theme-t);
}
/* Dark mode only: a clean white card behind EVERY logo individually, not
   one shared backdrop behind the whole composition. Client marks are
   never edited/inverted/filtered — some are dark-on-transparent and would
   otherwise vanish into the dark section background, so each one gets its
   own small opaque "paper" surface to sit on instead. The button's own box
   (already sized per logo via --box-h / --tall, and consistent with the
   grid the constellation is built on) IS the logo's bounding box, so
   giving it padding + a solid background here makes the white card hug
   that box tightly rather than introducing a second, differently-sized
   surface. Sits behind the img (paint order: background, then ::before
   glow, then img — see the img rule below) so the green highlight glow and
   the logo itself both still render on top of it. Light mode is
   completely untouched (--constellation-logo-backing is transparent
   there, see the root token block). */
:root[data-theme="dark"] .constellation__btn {
  padding: clamp(0.4rem, 1.1vw, 0.65rem);
  background: var(--constellation-logo-backing);
  border-radius: var(--radius-lg);
  box-shadow: 0 6px 16px -8px var(--constellation-logo-shadow);
}
.constellation__btn:focus-visible {
  outline: 2px solid var(--green-500);
  outline-offset: 4px;
}

/* Soft green presence behind the logo — brand emphasis, not a neon glow.
   Painted before the img in source order, so it always sits behind it. */
.constellation__btn::before {
  content: "";
  position: absolute;
  inset: -26%;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(45, 178, 95, 0.16) 0%, rgba(45, 178, 95, 0) 72%);
  opacity: 0;
  transition: opacity var(--t-base);
  pointer-events: none;
}
/* A hair quieter on dark surfaces, where the same alpha reads brighter
   against charcoal than it does against paper — keeps the highlight
   sophisticated rather than glowing. */
:root[data-theme="dark"] .constellation__btn::before {
  background: radial-gradient(circle, rgba(45, 178, 95, 0.12) 0%, rgba(45, 178, 95, 0) 72%);
}
.constellation__btn:hover::before,
.constellation__btn:focus-visible::before,
.constellation__btn.is-auto-active::before {
  opacity: 1;
}

.constellation__btn img {
  position: relative;
  max-inline-size: 100%;
  max-block-size: 100%;
  inline-size: auto;
  block-size: auto;
  object-fit: contain;
  opacity: 0.8;
  filter: grayscale(20%);
  transition: opacity var(--t-base), filter var(--t-base);
}
.constellation__btn:hover img,
.constellation__btn:focus-visible img,
.constellation__btn.is-auto-active img {
  opacity: 1;
  filter: grayscale(0%);
}
.constellation__btn:hover,
.constellation__btn:focus-visible {
  transform: scale(1.03);
}
.constellation__btn.is-auto-active {
  transform: scale(1.02);
}

/* Any hover/focus dims the rest of the field slightly — never to the
   point of disappearing — so the highlighted logo reads as figure against
   a calmer ground. */
.constellation__logos:has(.constellation__btn:hover) .constellation__logo:not(:has(.constellation__btn:hover)) .constellation__btn img,
.constellation__logos:has(.constellation__btn:focus-visible) .constellation__logo:not(:has(.constellation__btn:focus-visible)) .constellation__btn img {
  opacity: 0.65;
}

/* Fixed, hand-placed positions — a deliberate composition, not a repeating
   grid. Balanced 7 left / 7 right / 1 centre-top, diamond silhouette
   around the mark (3 / 4 / 2+mark / 2 / 4 across five rows). data-sector
   on each <li> (upper-left/upper-right/lower-left/lower-right/center)
   groups these same 15 positions into the 5 path branches above. */
.constellation__logo[data-pos="1"]  { grid-column: 2 / 4;   grid-row: 1 / 2; --nudge: -8px; }
.constellation__logo[data-pos="2"]  { grid-column: 5 / 8;   grid-row: 1 / 2; }
.constellation__logo[data-pos="3"]  { grid-column: 9 / 11;  grid-row: 1 / 2; --nudge: 8px; }
.constellation__logo[data-pos="4"]  { grid-column: 1 / 3;   grid-row: 2 / 3; }
.constellation__logo[data-pos="5"]  { grid-column: 11 / 13; grid-row: 2 / 3; }
.constellation__logo[data-pos="6"]  { grid-column: 4 / 6;   grid-row: 2 / 3; --nudge: -10px; }
.constellation__logo[data-pos="7"]  { grid-column: 8 / 10;  grid-row: 2 / 3; }
.constellation__logo[data-pos="8"]  { grid-column: 1 / 3;   grid-row: 3 / 4; }
.constellation__logo[data-pos="9"]  { grid-column: 11 / 13; grid-row: 3 / 4; --nudge: 8px; }
.constellation__logo[data-pos="10"] { grid-column: 3 / 5;   grid-row: 4 / 5; }
.constellation__logo[data-pos="11"] { grid-column: 9 / 11;  grid-row: 4 / 5; }
.constellation__logo[data-pos="12"] { grid-column: 1 / 3;   grid-row: 5 / 6; --nudge: -8px; }
.constellation__logo[data-pos="13"] { grid-column: 5 / 7;   grid-row: 5 / 6; }
.constellation__logo[data-pos="14"] { grid-column: 8 / 10;  grid-row: 5 / 6; --nudge: 10px; }
.constellation__logo[data-pos="15"] { grid-column: 11 / 13; grid-row: 5 / 6; }

/* ================================================= CLIENT MARQUEE  */
/* A single proof line adapted from the approved ARIBA_Website - 1
   treatment. The logo field stays white in both themes so every approved
   mark keeps its original colour and contrast. */
.clients {
  padding-block: clamp(3rem, 6vw, 5.5rem);
  background: var(--bg-primary);
  border-block: 1px solid var(--border);
  overflow: hidden;
  scroll-margin-block-start: calc(var(--nav-top-gap) + var(--nav-h-scrolled) + 1.5rem);
}

.client-marquee__heading {
  display: block;
  max-inline-size: 60rem;
  margin-inline: auto;
  margin-block-end: clamp(2rem, 4vw, 3rem);
}

.client-marquee__heading h2 {
  margin-block-start: var(--space-5, 1.25rem);
  font-size: var(--fs-heading);
  font-weight: 600;
  line-height: var(--lh-snug);
}

.client-marquee__copy {
  max-inline-size: 60ch;
  margin-block-start: var(--space-4);
  color: var(--text-muted);
  line-height: var(--lh-body);
}

.client-marquee {
  --marquee-width: min(calc(100vw - (2 * var(--gutter))), 80rem);
  direction: ltr;
  inline-size: var(--marquee-width);
  min-inline-size: 0;
  max-inline-size: none;
  margin-inline: calc((100% - var(--marquee-width)) / 2);
  contain: inline-size;
  overflow-x: auto;
  padding-block: clamp(1.5rem, 3vw, 2.25rem);
  padding-inline: var(--space-4);
  background: #fff;
  border-block: 1px solid rgba(0, 77, 61, 0.18);
  scrollbar-color: var(--green-500) transparent;
  scrollbar-width: thin;
}

.client-marquee.is-enhanced {
  overflow: hidden;
  cursor: grab;
  touch-action: pan-y;
  user-select: none;
}

.client-marquee.is-dragging { cursor: grabbing; }

.client-marquee__track {
  direction: ltr;
  display: flex;
  inline-size: max-content;
}

.client-marquee.is-enhanced .client-marquee__track { will-change: transform; }

.client-marquee__group {
  --client-gap: clamp(2.5rem, 5vw, 5rem);
  flex: none;
  display: flex;
  align-items: center;
  gap: var(--client-gap);
  margin: 0;
  padding: 0 var(--client-gap) 0 0;
}

.client-marquee__group li {
  flex: none;
  display: grid;
  place-items: center;
  inline-size: clamp(8rem, 15vw, 12rem);
  block-size: clamp(4.5rem, 8vw, 6.25rem);
}

.client-marquee__group img {
  inline-size: auto;
  block-size: auto;
  max-inline-size: 100%;
  max-block-size: clamp(3.5rem, 5.5vw, 4.75rem);
  opacity: 1;
  filter: none;
  pointer-events: none;
}

.client-marquee:focus-visible {
  outline: 2px solid var(--green-500);
  outline-offset: 4px;
}

@media (min-width: 901px) {
  .client-marquee__heading h2 { max-inline-size: 28ch; }
}

@media (max-width: 560px) {
  .client-marquee {
    margin-inline: calc(-1 * var(--gutter));
    inline-size: calc(100% + (2 * var(--gutter)));
    max-inline-size: none;
    padding-inline: var(--gutter);
  }
  .client-marquee__group { --client-gap: 2rem; }
  .client-marquee__group li { inline-size: 7rem; }
}

@media (prefers-reduced-motion: reduce) {
  .client-marquee.is-enhanced .client-marquee__track { will-change: auto; }
}

/* ====================================================== CONTACT  */
/* Split editorial layout — intro, details, and an unboxed form as three
   grid siblings, closing the homepage. Mobile-first base is a single
   stacked column: with no explicit placement, each sibling auto-flows
   into its own row in source order (intro -> details -> form), which is
   exactly the required mobile reading order — no [dir] override, no
   extra markup for it. The >=901px block re-places the same three
   siblings onto two columns and two explicit rows: intro alone in row 1
   (column 1), details and the form sharing row 2 (columns 1 and 2). The
   form's top edge is therefore never a hand-tuned margin — it falls out
   of the intro's own content height plus the one shared .contact__grid
   row-gap, landing level with where the details list starts. */
.contact {
  /* Top padding tightened to match Clients' own reduced bottom padding
     above — see the .clients rule for why. Bottom padding is untouched,
     since that boundary (Contact -> footer) isn't part of this gap. */
  padding-block-start: clamp(2.5rem, 4vw, 4rem);
  padding-block-end: clamp(4rem, 5vw, 6rem);
}

.contact__grid {
  display: grid;
  grid-template-columns: 1fr;
  row-gap: clamp(2rem, 5vw, 3rem);
}

.contact__headline {
  margin-block-start: var(--space-6);
  font-size: var(--fs-heading);
  font-weight: 600;
  line-height: var(--lh-snug);
  color: var(--text-primary);
  max-inline-size: 14ch;
}

.contact__lede {
  margin-block-start: var(--space-4);
}

@media (min-width: 901px) {
  .contact__grid {
    grid-template-columns: minmax(0, 4fr) minmax(0, 5fr);
    column-gap: clamp(3rem, 6vw, 6rem);
    align-items: start;
  }
  .contact__intro      { grid-column: 1; grid-row: 1; }
  .contact__details    { grid-column: 1; grid-row: 2; }
  .contact__form-wrap  { grid-column: 2; grid-row: 2; }
}

/* ---------------------------------------------------------- details  */
/* A definition list, not individual cards: each row stacks its label
   tight above its value (when one exists) and closes with a hairline —
   matching "avoid boxed cards / per-field icons" while reading label and
   value as one connected unit rather than two ends of a spaced-out row.
   Email/Phone/LinkedIn have no <dd> yet (unconfirmed — no invented value,
   no placeholder dash): the label alone before the hairline is the
   intentional empty state. */
.contact__details {
  display: grid;
}
.contact__detail {
  display: grid;
  gap: 0.25rem;
  padding-block: var(--space-3);
  border-block-end: 1px solid var(--border);
}
.contact__detail:first-child { padding-block-start: 0; }
.contact__detail:last-child  { border-block-end: 0; padding-block-end: 0; }

.contact__detail dt {
  font-size: var(--fs-caption);
  color: var(--text-muted);
}
.contact__detail dd {
  margin: 0;
  font-family: var(--font-head);
  font-size: var(--fs-body);
  font-weight: 500;
  color: var(--text-primary);
}

/* ------------------------------------------------------------- form  */
/* No card shell: transparent fields on the section's own paper
   background, a hairline "bottom border" painted as a box-shadow (so the
   focus-state colour/weight change never shifts layout). Single-line
   fields get a consistent, comfortable min-height instead of relying on
   padding alone; the textarea gets more room to actually feel writable. */
.contact__form {
  display: grid;
  gap: var(--space-6);
}

.contact__field {
  display: grid;
  gap: var(--space-2);
}
.contact__field label {
  font-size: var(--fs-caption);
  color: var(--text-muted);
}
.contact__field input,
.contact__field textarea {
  display: block;
  inline-size: 100%;
  padding-block: 0.625rem;
  background: transparent;
  border: 0;
  border-radius: 0;
  font: inherit;
  font-size: var(--fs-body);
  color: var(--text-primary);
  box-shadow: inset 0 -1px 0 0 var(--input-bottom-line);
  transition: box-shadow var(--t-base), color var(--theme-t);
}
/* Neutralise the browser's own bright yellow/white autofill fill so a
   filled field still reads as "transparent field on the page background"
   in both themes, not a mismatched opaque patch. The absurdly long
   transition-delay is the standard trick for suppressing the animation
   Chromium uses to apply its autofill styles. */
.contact__field input:-webkit-autofill,
.contact__field input:-webkit-autofill:hover,
.contact__field input:-webkit-autofill:focus {
  -webkit-text-fill-color: var(--text-primary);
  -webkit-box-shadow: 0 0 0 1000px var(--bg-primary) inset,
                      inset 0 -1px 0 0 var(--input-bottom-line);
  caret-color: var(--text-primary);
  transition: background-color 5000s ease-in-out 0s;
}
.contact__field input {
  min-block-size: 2.75rem;
}
.contact__field textarea {
  min-block-size: 8.5rem;
  resize: none;
  line-height: var(--lh-body);
}
.contact__field input:focus,
.contact__field textarea:focus {
  outline: none;
  box-shadow: inset 0 -2px 0 0 var(--green-500);
}
.contact__field input:focus-visible,
.contact__field textarea:focus-visible {
  outline: none;
}

.contact__submit {
  justify-self: start;
}

/* Prototype confirmation — never worded to imply real delivery. Hidden by
   default; JS flips [hidden] off then adds .is-visible a frame later so
   the opacity transition actually runs (same pattern as .nav__scrim). */
.contact__note {
  margin: 0;
  font-size: var(--fs-caption);
  color: var(--green-700);
  opacity: 0;
  transition: opacity var(--t-base);
}
/* --green-700 is calibrated for contrast against paper; against the dark
   charcoal background it needs the brighter end of the brand ramp instead
   to stay readable. */
:root[data-theme="dark"] .contact__note { color: var(--green-400); }
.contact__note.is-visible { opacity: 1; }

/* Direct-contact cards imported from ARIBA_Website - 1 and expressed through
   this site's paper, ink, spacing, and five-size type system. */
.contact__intro {
  display: grid;
  gap: var(--space-6);
  align-items: end;
  margin-block-end: clamp(2.5rem, 5vw, 4rem);
}

.contact__headline {
  max-inline-size: 13ch;
  margin-block-start: var(--space-6);
  font-size: var(--fs-display);
  font-weight: 600;
  line-height: var(--lh-snug);
  color: var(--text-primary);
}

.contact__lede {
  max-inline-size: 54ch;
  margin: 0;
  color: var(--text-muted);
  font-size: var(--fs-lede);
  line-height: var(--lh-body);
}

.contact__cards {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-4);
}

.contact__card {
  display: flex;
  flex-direction: column;
  min-inline-size: 0;
  min-block-size: 15rem;
  padding: clamp(1.5rem, 3vw, 2rem);
  background: var(--surface-elevated);
  border: 1px solid var(--border);
  border-block-start: 3px solid var(--green-500);
  border-radius: var(--radius-lg);
  box-shadow: 0 18px 40px -28px rgba(var(--shadow-rgb), 0.28);
  transition: transform var(--t-fast), border-color var(--t-fast), background-color var(--theme-t);
}

.contact__icon {
  display: grid;
  place-items: center;
  inline-size: 3.5rem;
  block-size: 3.5rem;
  margin-block-end: var(--space-6);
  color: var(--green-900);
  background: rgba(45, 178, 95, 0.14);
  border: 1px solid rgba(0, 77, 61, 0.12);
  border-radius: var(--radius-lg);
  box-shadow: 5px 5px 0 rgba(0, 77, 61, 0.08);
}

.contact__card:nth-child(2) .contact__icon { background: rgba(218, 196, 89, 0.28); }
.contact__card:nth-child(3) .contact__icon { background: rgba(76, 196, 122, 0.42); }

.contact__icon svg {
  inline-size: 1.5rem;
  block-size: 1.5rem;
}

.contact__card-label {
  margin: 0 0 var(--space-4);
  color: var(--green-700);
  font-size: var(--fs-caption);
  font-weight: 600;
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
}

:lang(ar) .contact__card-label { text-transform: none; }

.contact__card h3 {
  margin: 0 0 var(--space-3);
  color: var(--text-primary);
  font-size: var(--fs-lede);
  font-weight: 600;
  line-height: var(--lh-snug);
}

.contact__card a {
  inline-size: fit-content;
  max-inline-size: 100%;
  margin-block-start: auto;
  color: var(--green-800);
  font-family: var(--font-head);
  font-size: var(--fs-lede);
  font-weight: 600;
  line-height: var(--lh-snug);
  text-decoration-line: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.3em;
  overflow-wrap: anywhere;
}

.contact__card a:hover,
.contact__card a:focus-visible { color: var(--green-500); }

:root[data-theme="dark"] .contact__card a { color: var(--green-400); }

@media (hover: hover) and (pointer: fine) {
  .contact__card:hover {
    transform: translateY(-3px);
    border-block-start-color: var(--green-400);
  }
}

@media (min-width: 640px) {
  .contact__cards { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .contact__card:last-child { grid-column: 1 / -1; }
}

@media (min-width: 901px) {
  .contact__intro {
    grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
    gap: clamp(3rem, 6vw, 6rem);
  }

  .contact__cards { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .contact__card:last-child { grid-column: auto; }
}

/* ====================================================== FOOTER  */
/* Always a deep dark-green/near-black closing surface — in both Light and
   Dark site mode (see --footer-* tokens at the top of the file). Three
   stacked levels: a closing CTA, a brand/nav/contact grid, and a compact
   legal bar, each separated by a hairline rather than a background
   change, since the surface itself never changes tone internally. */
.footer {
  position: relative;
  overflow: hidden;
  background: var(--footer-bg);
  color: var(--footer-text);
  transition: background-color var(--theme-t);
}

/* Same "oversized, barely-there rotated square" idiom as .constellation__bg
   — brand geometry (the ribbon-fold diamond), not a literal logo, and low
   enough opacity that it never competes with the text over it. */
.footer__shape {
  position: absolute;
  top: 10%;
  inset-inline-end: -12%;
  inline-size: min(640px, 60vw);
  block-size: min(640px, 60vw);
  background: var(--footer-shape);
  filter: blur(90px);
  transform: rotate(45deg);
  pointer-events: none;
  z-index: 0;
}

/* --------------------------------------------------------- LEVEL 1 — CTA */
.footer__cta {
  position: relative;
  z-index: 1;
  padding-block: clamp(3.5rem, 6vw, 5.5rem) clamp(2.5rem, 4.5vw, 3.5rem);
}
.footer__cta-inner {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: clamp(1.75rem, 4vw, 3rem);
}
.footer__cta-text { max-inline-size: 42rem; }
.footer__cta-headline {
  margin-block: var(--space-4);
  font-size: var(--fs-heading);
  font-weight: 600;
  line-height: var(--lh-snug);
  color: #fff;
  max-inline-size: 18ch;
}
.footer__cta-copy {
  margin: 0;
  font-size: var(--fs-lede);
  line-height: var(--lh-body);
  color: var(--footer-text-secondary);
  max-inline-size: 46ch;
}
.footer__cta-btn { flex: none; }

.footer__divider {
  position: relative;
  z-index: 1;
  border-block-start: 1px solid var(--footer-border);
  transition: border-color var(--theme-t);
}

/* -------------------------------------------------------- LEVEL 2 — MAIN */
.footer__main {
  position: relative;
  z-index: 1;
  padding-block: clamp(2.75rem, 5vw, 4rem);
}
.footer__grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: clamp(2.25rem, 6vw, 3rem);
}
@media (min-width: 901px) {
  .footer__grid {
    grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr) minmax(0, 1fr);
    gap: clamp(2rem, 4vw, 4rem);
  }
}

.footer__brand { display: grid; gap: var(--space-3); align-content: start; }

/* The ARIBA lockup itself is never recoloured or filtered — same asset the
   Navbar uses. Its dark wordmark just needs a small light surface under
   it to stay readable here, exactly like the client logos' backing plate
   in the Dark Mode constellation: the fix lives in the surface behind the
   asset, never in the asset. */
.footer__logo-wrap {
  display: inline-flex;
  align-items: center;
  inline-size: fit-content;
  padding: 0.5rem 0.75rem;
  background: var(--footer-logo-backing);
  border-radius: var(--radius-md);
}
.footer__logo { display: block; block-size: 26px; inline-size: auto; }

.footer__brand-name {
  margin: var(--space-2) 0 0;
  font-family: var(--font-head);
  font-size: var(--fs-body);
  font-weight: 600;
  color: var(--footer-text);
}
.footer__brand-desc {
  margin: 0;
  font-size: var(--fs-caption);
  line-height: var(--lh-body);
  color: var(--footer-text-secondary);
  max-inline-size: 32ch;
}

.footer__col-label {
  margin: 0 0 var(--space-4);
  font-size: var(--fs-caption);
  font-weight: 500;
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--footer-text-muted);
}
:lang(ar) .footer__col-label { text-transform: none; }

.footer__nav-list {
  display: grid;
  gap: var(--space-3);
  margin: 0;
  padding: 0;
  list-style: none;
}
.footer__nav-list a {
  font-size: var(--fs-body);
  color: var(--footer-link);
  transition: color var(--t-base);
}
.footer__nav-list a:hover,
.footer__nav-list a:focus-visible { color: var(--green-400); }

.footer__contact-list { display: grid; gap: var(--space-3); margin: 0; }
.footer__contact-row { display: grid; gap: 0.25rem; }
.footer__contact-row dt { font-size: var(--fs-caption); color: var(--footer-text-muted); }
.footer__contact-row dd {
  margin: 0;
  font-family: var(--font-head);
  font-size: var(--fs-body);
  font-weight: 500;
  color: var(--footer-text);
}

/* ------------------------------------------------------- LEVEL 3 — LEGAL */
.footer__legal {
  position: relative;
  z-index: 1;
  border-block-start: 1px solid var(--footer-border);
  transition: border-color var(--theme-t);
}
.footer__legal-inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  padding-block: clamp(1.25rem, 2.5vw, 1.75rem);
}
.footer__copyright { margin: 0; font-size: var(--fs-caption); color: var(--footer-text-muted); }
.footer__legal-links { display: flex; gap: var(--space-6); }
.footer__legal-links a {
  font-size: var(--fs-caption);
  color: var(--footer-link);
  transition: color var(--t-base);
}
.footer__legal-links a:hover,
.footer__legal-links a:focus-visible { color: var(--green-400); }

/* ============================================================== REVEALS  */
/* One system. Opacity + a short vertical translate, staggered by index. */
.js [data-reveal] {
  opacity: 0;
  transform: translateY(20px);
  transition: opacity var(--reveal-dur) var(--ease),
              transform var(--reveal-dur) var(--ease);
  transition-delay: calc(var(--reveal-delay, 0) * var(--reveal-step));
}
.js [data-reveal].is-revealed {
  opacity: 1;
  transform: none;
}

/* ========================================================== RESPONSIVE  */

/* Tablet / small laptop — collapse to the mobile menu before links crowd. */
@media (max-width: 1024px) {
  :root {
    --nav-h: 64px;
    --nav-h-scrolled: 56px;
    --nav-top-gap: clamp(0.75rem, 1.6vw, 1.125rem);
  }

  .nav__toggle { display: block; }

  .nav__menu {
    position: fixed;
    inset-block-start: 0;
    inset-inline-end: 0;
    z-index: 95;
    block-size: 100svh;
    inline-size: min(420px, 88vw);
    padding: calc(var(--nav-h) + var(--space-8)) var(--gutter) var(--space-12);
    flex-direction: column;
    align-items: stretch;
    justify-content: flex-start;
    gap: 0;
    background: var(--bg-primary);
    border-inline-start: 1px solid var(--hairline);
    transform: translateX(100%);
    visibility: hidden;
    transition: transform 380ms var(--ease), visibility 380ms, background-color var(--theme-t);
    overflow-y: auto;
  }
  [dir="rtl"] .nav__menu { transform: translateX(-100%); }
  .nav__menu.is-open { transform: translateX(0); visibility: visible; }

  .nav__list {
    flex-direction: column;
    align-items: stretch;
    gap: 0;
  }
  .nav__list li + li { border-block-start: 1px solid var(--hairline); }
  .nav__link {
    display: block;
    padding-block: var(--space-4);
    font-family: var(--font-head);
    font-size: var(--fs-lede);
    font-weight: 500;
    letter-spacing: -0.01em;
    color: var(--text-primary);
  }
  :lang(ar) .nav__link { letter-spacing: 0; }
  .nav__link::after { display: none; }

  .nav__actions {
    margin-block-start: var(--space-8);
    flex-direction: column;
    align-items: stretch;
    gap: var(--space-4);
  }
  .lang-switch { padding-block: 0.75rem; }
  .nav__cta { --btn-py: 0.95rem; inline-size: 100%; }

  /* Journey keeps the horizontal sequence; only the copy tightens. */
  .journey__num   { font-size: var(--fs-lede); }
  .journey__title { font-size: var(--fs-body); }
  .journey__text  { font-size: var(--fs-caption); }
  .journey__track,
  .journey__path  { stroke-width: 10; }
}

/* Hero stacks — media becomes a wide band under the copy. */
@media (max-width: 900px) {
  .hero__inner {
    grid-template-columns: 1fr;
    row-gap: clamp(2.5rem, 6vw, 4rem);
    align-items: start;
    padding-block-end: clamp(2.5rem, 6vh, 3.5rem);
  }
  .hero__content { max-inline-size: 34rem; }

  /* Stacked layout: the image becomes a full-bleed band under the copy.
     Bleeding both sides (rather than one) keeps it edge-to-edge now that
     it's no longer sharing a row with the text. Sizing stays governed by
     the same aspect-ratio as desktop — no extra rules needed. */
  .hero__media { margin-inline: calc(-1 * var(--gutter)); }

  .about__grid { grid-template-columns: 1fr; row-gap: clamp(2rem, 5vw, 2.75rem); align-items: stretch; }
  /* Undo the desktop grid-row:1 pairing — at one column, both items
     forced onto row 1 would stack in the same cell (image painting over
     the heading) instead of flowing heading-then-image down the page. */
  .about__lead, .about__media { grid-column: 1 / -1; grid-row: auto; }

  /* Preserve the same image-above-copy composition on narrow screens. */
  .about__media {
    grid-template-rows: auto auto;
    margin-inline: 0;
  }
  .about__media-frame { aspect-ratio: auto; block-size: clamp(260px, 70vw, 360px); }
  .about__media-text,
  :root[dir="rtl"] .about__media-text {
    position: relative;
    inset: auto;
    max-inline-size: none;
  }

  .about__media-body { font-size: var(--fs-body); }

  /* Capabilities: single column, full width. Cards keep the same
     aspect-ratio and hover-state custom properties as desktop — only
     .is-expanded (set by main.js on tap, since there's no hover here)
     ever actually flips them at this width, the :hover block above is
     already gated out by (hover: hover) and (pointer: fine). */
  .cap-grid { grid-template-columns: 1fr; gap: clamp(1.25rem, 5vw, 1.75rem); }

  /* Journey becomes a vertical stepped path. The complete rule is rendered
     directly while the three pieces of copy retain their staged reveal. */
  .journey { margin-block-start: clamp(1.5rem, 5vw, 2.25rem); }
  .journey__svg { display: none; }
  .journey__viz { position: static; }

  .journey__stages {
    position: relative;
    inset: auto;
    padding-inline-start: 2.75rem;
    display: grid;
    gap: clamp(2.25rem, 7vw, 3rem);
  }
  .journey__stages::before,
  .journey__stages::after {
    content: '';
    position: absolute;
    inset-block: 0.45rem 1.25rem;
    inset-inline-start: 5px;
    inline-size: 3px;
    border-radius: 2px;
  }
  .journey__stages::before { background: var(--journey-stages-track); }
  .journey__stages::after {
    background: linear-gradient(180deg, var(--green-800), var(--green-500));
    transform-origin: top;
  }
  .js .journey__stages::after {
    transform: scaleY(0);
    transition: transform 3000ms linear 140ms;
  }
  .js .journey.is-playing .journey__stages::after,
  .js .journey.is-complete .journey__stages::after { transform: scaleY(1); }
  .journey__stage {
    position: relative;
    top: auto;
    left: auto;
    inline-size: auto;
    max-inline-size: 46ch;
    padding-block-start: 0;
  }

  .journey--profile .journey__stage {
    left: auto;
    inline-size: auto;
    padding-block-start: 0;
  }

  .journey__dot {
    top: 0.45rem;
    left: auto;
    margin: 0;
    inset-inline-start: -2.75rem;
  }

  .journey__num {
    position: static;
    transform: none;
    display: block;
    font-size: var(--fs-lede);
    margin-block-end: var(--space-2);
  }

  .journey__mark {
    position: relative;
    right: auto;
    top: auto;
    transform: none;
    display: block;
    inline-size: 64px;
    margin-block-start: var(--space-12);
  }

  .journey--profile .journey__mark { top: auto; }

  /* Why ARIBA: the cut simplifies to a shallower single diagonal (less
     vertical travel looks calmer at narrower widths) and the floating
     panel becomes 2x2, still overlapping the band below it. */
  .why__band { clip-path: polygon(0 0, 100% 0, 100% 88%, 0 100%); }
  [dir="rtl"] .why__band { clip-path: polygon(100% 0, 0 0, 0 88%, 100% 100%); }

  .why__stats { grid-template-columns: repeat(2, 1fr); row-gap: var(--space-8); }
  .why__stat { padding-inline: clamp(1rem, 3vw, 2rem); }
  .why__stat:nth-child(odd)  { padding-inline-start: 0; }
  .why__stat:nth-child(even) { padding-inline-end: 0; }
  .why__stat:nth-child(even) { border-inline-start: 1px solid var(--stat-divider); }
  .why__stat:nth-child(odd)  { border-inline-start: 0; }
  .why__stat:nth-child(n+3)  { padding-block-start: var(--space-6); }

  /* Clients: keep the same 12-column composition (it scales fluidly) but
     drop the connecting lines and quiet the background shape further —
     at this width the geometry read as busier than it added. */
  .constellation__lines { display: none; }
  .constellation__bg { opacity: 0.025; }
  .constellation__logos { column-gap: clamp(0.5rem, 2vw, 1rem); row-gap: clamp(1rem, 3vw, 1.75rem); }
  .constellation__btn { inline-size: clamp(72px, 12vw, 112px); }
  .constellation__logo { --box-h: clamp(40px, 5.6vw, 58px); }
  .constellation__logo--tall { --box-h: clamp(54px, 7.6vw, 78px); }
}

/* Phones */
@media (max-width: 560px) {
  :root { --nav-h: 58px; --nav-top-gap: clamp(0.75rem, 3vw, 1rem); }
  .nav__inner { padding-inline: 1rem; }
  .nav__brand { padding: 0.4rem 0.6rem; }
  .nav__logo  { block-size: 26px; }

  /* Smaller pill, smaller margin for error: a touch more opaque than the
     desktop default so the (collapsed, logo + toggle only) pill stays
     unambiguously legible against any part of the Hero photo. */
  .nav__inner { background: var(--nav-surface-mobile); }
  .nav.is-scrolled .nav__inner { background: var(--nav-surface-mobile-scrolled); }

  .hero__actions { flex-direction: column; align-items: stretch; }
  .hero__actions .btn { inline-size: 100%; }

  .why__stats { row-gap: var(--space-6); margin-block-start: clamp(-4.5rem, -12vw, -3rem); }
  .why__stat-label { margin-block-start: var(--space-2); }

  /* Clients: the constellation gives way to a refined editorial grid —
     the mark on its own row, then two logos per row with a light
     alternating offset. No absolute grid placement, no lines, no
     horizontal scroll; every logo stays reachable in document order. */
  .constellation__bg { opacity: 0.03; }
  .constellation__lines { display: none; }

  .constellation__logos {
    grid-template-columns: repeat(2, 1fr);
    grid-auto-rows: auto;
    column-gap: var(--space-6);
    row-gap: var(--space-8);
    padding-block: var(--space-6);
  }

  .constellation__mark {
    grid-column: 1 / -1;
    grid-row: auto;
    inline-size: 52px;
    block-size: 52px;
    margin-block-end: var(--space-2);
  }

  .constellation__logo[data-pos] {
    grid-column: auto;
    grid-row: auto;
    transform: none;
    --box-h: clamp(44px, 13vw, 60px);
  }
  .constellation__logo:nth-child(even) { margin-block-start: clamp(0.75rem, 6vw, 1.5rem); }

  .constellation__btn { inline-size: clamp(96px, 34vw, 140px); }

  /* Footer: CTA button goes full-width under the closing copy (same
     pattern as .hero__actions .btn at this width) and the legal row
     stacks copyright above the links instead of trying to fit both on
     one line. */
  .footer__cta-btn { inline-size: 100%; }
  .footer__legal-inner { flex-direction: column; align-items: flex-start; }
}

/* =============================================== CONTENT EXPANSION  */
.about-purpose {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1px;
  margin-block-start: clamp(2.5rem, 5vw, 4.5rem);
  background: var(--border);
  border-block: 1px solid var(--border);
}

.purpose-card {
  padding: clamp(1.5rem, 3.5vw, 3rem);
  background: var(--bg-primary);
}

.purpose-card__kicker,
.impact-card__sector,
.careers__network-label {
  margin: 0 0 var(--space-3);
  font-family: var(--font-head);
  font-size: var(--fs-caption);
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--green-700);
}

:lang(ar) .purpose-card__kicker,
:lang(ar) .impact-card__sector,
:lang(ar) .careers__network-label {
  letter-spacing: 0;
  text-transform: none;
}

.purpose-card__values {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-4);
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: var(--fs-lede);
  font-weight: 600;
  line-height: var(--lh-snug);
}

.purpose-card__values li + li::before {
  content: '•';
  margin-inline-end: var(--space-4);
  color: var(--green-500);
}

.purpose-card__copy {
  max-inline-size: 58ch;
  margin-block-start: var(--space-4);
  color: var(--text-muted);
  line-height: var(--lh-body);
}

.journey__intro {
  display: grid;
  grid-template-columns: minmax(0, 0.8fr) minmax(0, 1.3fr) minmax(0, 1fr);
  gap: clamp(1.5rem, 4vw, 4rem);
  align-items: start;
  margin-block-end: var(--space-4);
}

.journey__intro h2 {
  font-size: var(--fs-heading);
  line-height: var(--lh-snug);
  font-weight: 600;
}

.journey__intro > p:last-child {
  color: var(--text-muted);
  line-height: var(--lh-body);
}

@media (min-width: 901px) {
  [dir="rtl"] .journey__svg {
    transform: scaleX(-1);
    transform-origin: center;
  }

  [dir="rtl"] .journey__stage {
    left: calc(var(--x-rtl) - min(120px, 11%));
  }

  /* The five-stage profile anchors and copy columns share the midpoint of
     each plateau. This mirrors the English half-column shift so Arabic copy
     moves inward by the same amount in the opposite direction. */
  [dir="rtl"] .journey--profile .journey__stage {
    left: calc(var(--x-rtl) - 6.5%);
  }

  [dir="rtl"] .journey--profile .journey__stage:last-child {
    left: calc(var(--x-rtl) - 7.5%);
  }

  [dir="rtl"] .journey--profile .journey__dot,
  [dir="rtl"] .journey--profile .journey__num {
    right: auto;
    left: 50%;
  }

  [dir="rtl"] .journey__mark {
    right: auto;
    left: 0;
  }
}

.why__values {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 1px;
  margin: clamp(2rem, 4vw, 3.5rem) 0 0;
  padding: 1px;
  list-style: none;
  background: rgba(255, 255, 255, 0.14);
}

.why__head { max-inline-size: none; }

.why__values li {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-3);
  min-block-size: 7rem;
  padding: 1.25rem 1rem;
  background: rgba(0, 42, 33, 0.72);
  color: rgba(255, 255, 255, 0.9);
  font-size: var(--fs-caption);
  line-height: 1.55;
  text-align: center;
}

[dir="rtl"] .why__values li { padding: 1.25rem 1rem; }

.why__values li::before {
  content: '';
  position: static;
  flex: 0 0 0.45rem;
  inline-size: 0.45rem;
  block-size: 0.45rem;
  border-radius: 50%;
  background: var(--green-400);
}

.impact {
  position: relative;
  background: var(--bg-secondary);
}

.impact__head {
  display: grid;
  grid-template-columns: minmax(0, 0.75fr) minmax(0, 1.35fr) minmax(0, 1fr);
  gap: clamp(1.5rem, 4vw, 4rem);
  align-items: start;
}

.impact__headline {
  font-size: var(--fs-heading);
  font-weight: 600;
  line-height: var(--lh-snug);
}

.impact-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--space-5);
  margin-block-start: clamp(2.5rem, 5vw, 4rem);
}

/* Profile-backed program register. Sector labels act as the organizing
   structure; the program names remain unembellished evidence beneath them. */
.program-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 1px;
  margin-block-start: clamp(2.5rem, 5vw, 4rem);
  padding: 1px;
  background: var(--border);
}

.program-card {
  min-block-size: 12rem;
  padding: clamp(1.35rem, 2.5vw, 2rem);
  background: var(--bg-primary);
  border-block-start: 3px solid var(--green-700);
  transition: background-color var(--theme-t), border-color var(--t-base);
}

.program-card--wide {
  grid-column: 1 / -1;
  min-block-size: auto;
  display: grid;
  grid-template-columns: minmax(0, 0.7fr) minmax(0, 1.3fr);
  gap: clamp(1.5rem, 4vw, 4rem);
}

.program-card__sector {
  font-family: var(--font-head);
  font-size: var(--fs-lede);
  font-weight: 600;
  line-height: var(--lh-snug);
  color: var(--text-primary);
}

.program-card__list {
  display: grid;
  gap: var(--space-3);
  margin-block-start: var(--space-6);
}

.program-card--wide .program-card__list {
  grid-template-columns: repeat(2, minmax(0, 1fr));
  margin-block-start: 0;
}

/* In Arabic, GEOSA belongs in its dedicated geospatial section. Hide only
   the repeated entry under Government Transformation; English is unchanged. */
html[lang='ar'] [data-arabic-duplicate] {
  display: none;
}

.program-card__list li {
  position: relative;
  padding-inline-start: 1.15rem;
  color: var(--text-muted);
  line-height: 1.6;
}

.program-card__list li::before {
  content: '';
  position: absolute;
  inset-inline-start: 0;
  inset-block-start: 0.65em;
  inline-size: 0.42rem;
  block-size: 0.42rem;
  background: var(--green-500);
  transform: rotate(45deg);
}

@media (hover: hover) and (pointer: fine) {
  .program-card:hover { border-block-start-color: var(--green-500); }
}

.impact-card {
  display: flex;
  flex-direction: column;
  min-block-size: 100%;
  padding: clamp(1.35rem, 2.5vw, 2rem);
  border: 1px solid var(--border);
  background: var(--bg-primary);
  transition: border-color var(--t-base), transform var(--t-base), background-color var(--theme-t);
}

@media (hover: hover) and (pointer: fine) {
  .impact-card:hover { transform: translateY(-4px); border-color: var(--green-500); }
}

.impact-card h3 {
  min-block-size: 3.2em;
  font-size: var(--fs-lede);
  font-weight: 600;
  line-height: var(--lh-snug);
}

.impact-card dl {
  display: grid;
  gap: var(--space-5);
  margin: var(--space-6) 0;
}

.impact-card dl > div {
  padding-block-start: var(--space-4);
  border-block-start: 1px solid var(--border);
}

.impact-card dt {
  margin-block-end: var(--space-2);
  font-size: var(--fs-caption);
  font-weight: 600;
  color: var(--green-700);
}

.impact-card dd {
  margin: 0;
  color: var(--text-muted);
  font-size: var(--fs-body);
  line-height: 1.65;
}

.impact-card__link {
  margin-block-start: auto;
  color: var(--green-700);
  font-family: var(--font-head);
  font-size: var(--fs-caption);
  font-weight: 600;
  text-decoration: underline;
  text-decoration-color: rgba(45, 178, 95, 0.45);
  text-underline-offset: 0.25em;
}

:root[data-theme="dark"] .impact-card__link { color: var(--green-400); }

.careers {
  padding-block: clamp(3rem, 6vw, 5rem);
  background: var(--green-900);
  color: #fff;
}

.careers__inner {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(2rem, 7vw, 7rem);
  align-items: center;
}

.careers h2 {
  margin-block-start: var(--space-5);
  font-size: var(--fs-heading);
  font-weight: 600;
}

.careers__copy > p:last-child,
.careers__network > p:not(.careers__network-label) {
  max-inline-size: 55ch;
  margin-block-start: var(--space-4);
  color: rgba(255, 255, 255, 0.76);
  line-height: var(--lh-body);
}

.careers__network {
  padding-inline-start: clamp(1.5rem, 4vw, 3.5rem);
  border-inline-start: 1px solid rgba(255, 255, 255, 0.2);
}

.careers__instruction { font-size: var(--fs-caption); }
.careers__network .btn { margin-block-start: var(--space-6); }

.contact__detail a,
.footer__contact-row a {
  color: inherit;
  text-decoration: none;
}

.contact__detail a:hover,
.contact__detail a:focus-visible,
.footer__contact-row a:hover,
.footer__contact-row a:focus-visible { color: var(--green-500); }

.contact__field select {
  display: block;
  inline-size: 100%;
  min-block-size: 2.75rem;
  padding-block: 0.625rem;
  padding-inline: 0 2rem;
  background: transparent;
  border: 0;
  border-radius: 0;
  color: var(--text-primary);
  font: inherit;
  font-size: var(--fs-body);
  box-shadow: inset 0 -1px 0 0 var(--input-bottom-line);
}

.contact__field select:focus,
.contact__field select:focus-visible {
  outline: none;
  box-shadow: inset 0 -2px 0 0 var(--green-500);
}

.contact__field select option { color: #1d2522; background: #fff; }

@media (max-width: 1024px) {
  .impact-grid { grid-template-columns: 1fr; }
  .program-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .program-card--wide { grid-column: 1 / -1; }
  .impact-card h3 { min-block-size: auto; }
  .why__values { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

@media (max-width: 900px) {
  .about-purpose,
  .careers__inner { grid-template-columns: 1fr; }
  .journey__intro,
  .impact__head { grid-template-columns: 1fr; gap: var(--space-4); }
  .journey__intro > p:last-child,
  .impact__copy { max-inline-size: 58ch; }
  .careers__network { padding-inline-start: 0; padding-block-start: var(--space-7); border-inline-start: 0; border-block-start: 1px solid rgba(255, 255, 255, 0.2); }
}

@media (max-width: 560px) {
  .about-purpose { grid-template-columns: 1fr; }
  .why__values { grid-template-columns: 1fr; }
  .why__values li { min-block-size: auto; }
  .program-grid { grid-template-columns: 1fr; }
  .program-card,
  .program-card--wide { grid-column: auto; min-block-size: auto; }
  .program-card--wide { grid-template-columns: 1fr; gap: var(--space-4); }
  .program-card--wide .program-card__list { grid-template-columns: 1fr; margin-block-start: var(--space-4); }
  .impact-card { padding: 1.25rem; }
}

/* ==================================================== REDUCED MOTION  */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }

  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    transition-delay: 0ms !important;
  }

  .js [data-reveal] { opacity: 1; transform: none; }

  /* The journey shows all stage copy with no scroll dependency. Its route
     and destination mark are already complete in the base styles. */
  .js .journey__stage { opacity: 1; transform: none; }
  .journey__dot::after { animation: none; }

  /* The card's only motion is the shared [data-reveal] fade/translate
     (handled by the rule above) and its hover lift, which is already a
     one-off, non-repeating transition — nothing else to neutralize here. */
}
