/* =========================================================
   Creative Marketing Agency — clone
   Static HTML/CSS/JS · CSS-rendered glass visuals
   ========================================================= */

/* ---------- fonts ----------
   General Sans (ITF Free Font License), self-hosted: fetching it from
   Fontshare cost two extra server hops before first paint on mobile. */
@font-face {
  font-family: 'General Sans';
  src: url('assets/fonts/general-sans-400.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'General Sans';
  src: url('assets/fonts/general-sans-500.woff2') format('woff2');
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'General Sans';
  src: url('assets/fonts/general-sans-600.woff2') format('woff2');
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}

:root {
  /* palette — azure blue system */
  --brand-50:      #eaf6fe;
  --brand-100:     #d6eefd;
  --brand-200:     #a9d8f5;   /* tags / chips */
  --brand-300:     #5bb8f0;   /* accent: icons, numbers, glow, links, highlighted words */
  --brand:         #1899e8;   /* PRIMARY */
  --brand-600:     #0f5f9c;
  --brand-700:     #0a4470;
  /* deep blues — background field */
  --blue-navy:     #123f5e;
  --blue-deep:     #0d2c44;
  --blue-night:    #082033;
  --blue-black:    #04101a;

  --black:         #000000;
  --ink:           #050a10;
  --ink-2:         #0a1017;
  --white:         #ffffff;
  --muted:         rgba(255, 255, 255, 0.62);
  --muted-dim:     rgba(255, 255, 255, 0.40);
  --line:          rgba(255, 255, 255, 0.10);
  --green:         #3ecf8e;
  --red:           #e5613f;

  --container: 1280px;
  --pad: 40px;
  --radius-lg: 18px;
  --radius-md: 13px;
  --radius-sm: 9px;

  --font: 'General Sans', ui-sans-serif, system-ui, sans-serif;
  /* Arabic pages: General Sans stays FIRST so Latin runs -- brand names, the
     phone number, figures like 480,000+ -- keep the brand face. It carries no
     Arabic glyphs, so Arabic falls through to IBM Plex Sans Arabic per-glyph. */
  --font-ar: 'General Sans', 'IBM Plex Sans Arabic', ui-sans-serif, system-ui, sans-serif;
  --ease: cubic-bezier(0.22, 1, 0.36, 1);
}

* { box-sizing: border-box; margin: 0; padding: 0; }

/* smooth scrolling is opt-in via .smooth-scroll (added by script.js after load) —
   with it on <html> directly, Chrome also animates scroll RESTORATION on refresh,
   scrolling from the hero down to wherever the visitor was */
html.smooth-scroll { scroll-behavior: smooth; }

body {
  font-family: var(--font);
  background: var(--black);
  color: var(--white);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}

a { color: inherit; text-decoration: none; }

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

/* ---------- shared type ---------- */
.eyebrow {
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.75);
  margin-bottom: 26px;
}
.eyebrow b { color: var(--brand-300); font-weight: 500; }
.eyebrow--center { text-align: center; }
.eyebrow--sm { margin-bottom: 22px; font-size: 12px; }

.section-title {
  font-size: clamp(34px, 4.1vw, 56px);
  font-weight: 500;
  line-height: 1.02;
  letter-spacing: -0.02em;
}
.section-title--center { text-align: center; }
.section-title b { color: var(--brand-300); font-weight: 500; }

/* ---------- grain overlay ---------- */
.grain {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 2;
  opacity: 0.5;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}
.grain--soft { opacity: 0.32; }

/* ---------- rendering stability ----------
   Frosted-glass elements (backdrop-filter) re-sample the backdrop every frame
   while they animate (scroll reveals, hover lifts, the logo marquee). Chromium
   can transiently show a diagonal seam / smearing while that happens. Keeping
   each glass element on its own compositor layer prevents it. */
.pstep, .scard, .stat--dark, .about__panel, .plogo,
.nav__pill, .nav__lang, .nav__burger, .btn--glass, .btn--glass-dark,
.hdash__panel {
  will-change: transform;
}

/* decorative infinite animations pause while their section is offscreen
   (script.js toggles .is-offscreen) — stops permanent per-frame paint work
   (conic border ring, hero word shine) and compositor churn (floats, marquee)
   for content the visitor can't currently see. Zero visual change in-view. */
.hero.is-offscreen .hdash__panel,
.hero.is-offscreen .hero__word,
.about__panel.is-offscreen::after,
.partners.is-offscreen .partners__track {
  animation-play-state: paused;
}

/* =========================================================
   BUTTONS
   ========================================================= */
.btn {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-size: 16px;
  font-weight: 500;
  line-height: 1;
  padding: 15px 22px;
  border-radius: 999px;
  cursor: pointer;
  border: 0;
  white-space: nowrap;
  transition: transform 0.35s var(--ease), background 0.3s var(--ease),
    box-shadow 0.35s var(--ease), color 0.3s var(--ease);
}
.btn:hover { transform: translateY(-2px); }

.btn--dark  { background: #0b0b0c; color: #fff; }
.btn--dark:hover  { background: #000; box-shadow: 0 12px 30px rgba(0,0,0,.4); }

.btn--light { background: #fff; color: #0b0b0c; }
.btn--light:hover { box-shadow: 0 12px 30px rgba(0,0,0,.25); }

/* gradient text — same wash as .hero__word, for section titles on dark bg */
.text-gradient {
  background: linear-gradient(100deg, #7cc6fb 0%, #35a8f4 40%, #8fd4ff 60%, #7cc6fb 100%);
  background-size: 220% 100%;
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent; color: transparent;
  filter: drop-shadow(0 0 14px rgba(90,184,240,0.5));
}
.cs-cta__title {
  background: linear-gradient(100deg, #7cc6fb 0%, #35a8f4 40%, #8fd4ff 60%, #7cc6fb 100%);
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent; color: transparent;
  filter: drop-shadow(0 0 14px rgba(90,184,240,0.5));
}

.btn--glass {
  background: rgba(255,255,255,0.16);
  color: #fff;
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border: 1px solid rgba(255,255,255,0.18);
}
.btn--glass:hover { background: rgba(255,255,255,0.26); }

.btn--glass-dark {
  background: rgba(20,14,10,0.45);
  color: #fff;
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border: 1px solid rgba(255,255,255,0.10);
}
.btn--glass-dark:hover { background: rgba(20,14,10,0.65); }

.btn--wide { padding-inline: 40px; justify-content: center; }

/* circular arrow badge — CSS chevron, always crisp + centered */
.arrow {
  display: inline-grid;
  place-items: center;   /* centers the ::before; keep the span EMPTY */
  width: 22px; height: 22px;
  border-radius: 50%;
  background: #fff;
  color: #0b0b0c;
  font-size: 0;
  line-height: 1;
  overflow: visible;
  flex: 0 0 auto;
  transition: transform 0.35s var(--ease);
}
.arrow::before {
  content: "";
  display: block;
  width: 12px; height: 12px;
  margin: 0; padding: 0;
  background: currentColor;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M8 5l7 7-7 7'/%3E%3C/svg%3E") center / contain no-repeat;
          mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M8 5l7 7-7 7'/%3E%3C/svg%3E") center / contain no-repeat;
}
.arrow--dark { background: #0b0b0c; color: #fff; }
.btn:hover .arrow { transform: translateX(2px); }
.arrow-sm { font-weight: 600; margin-inline-start: 4px; }

/* =========================================================
   NAVBAR
   ========================================================= */
.nav {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 100;
  padding: 20px 0;
  padding-top: calc(20px + env(safe-area-inset-top));
  transition: padding 0.3s var(--ease);
}
.nav.is-scrolled { padding: 12px 0; padding-top: calc(12px + env(safe-area-inset-top)); }
/* lock the page while the mobile menu is open so it can't scroll underneath */
body.nav-open { overflow: hidden; }
.nav__inner {
  max-width: calc(var(--container) + var(--pad) * 2);
  margin-inline: auto;
  padding-inline: var(--pad);
  display: flex;
  align-items: center;
  gap: 18px;
}
.nav__logo {
  display: inline-flex;
  align-items: center;
  margin-inline-end: auto;
}
.nav__logo img { height: 30px; width: auto; display: block; }
.nav__pill {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 8px;
  border-radius: 999px;
  /* liquid glass: brighter translucent fill with a top-to-bottom sheen */
  background: linear-gradient(180deg, rgba(255,255,255,0.26) 0%, rgba(255,255,255,0.10) 100%);
  backdrop-filter: blur(18px) saturate(1.7);
  -webkit-backdrop-filter: blur(18px) saturate(1.7);
  border: 1px solid rgba(255,255,255,0.30);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.6),
    inset 0 -8px 14px rgba(255,255,255,0.04),
    0 8px 22px rgba(4,16,26,0.20);
}
.nav__pill a {
  font-size: 15px;
  font-weight: 500;
  color: rgba(255,255,255,0.94);
  padding: 9px 16px;
  border-radius: 999px;
  transition: background 0.25s var(--ease), color 0.25s var(--ease);
}
.nav__pill a:hover { background: rgba(255,255,255,0.20); }
.nav__cta { padding-block: 12px; padding-inline: 20px 16px; font-size: 15px; }
/* a nav label is a phrase, not a paragraph -- never let one break onto a
   second line inside its own pill */
.nav__pill a, .nav__cta, .nav__lang { white-space: nowrap; }

.nav__burger {
  display: none;
  flex-direction: column;
  gap: 5px;
  width: 44px; height: 44px;
  align-items: center; justify-content: center;
  /* liquid glass to match the pill / FR toggle */
  background: linear-gradient(180deg, rgba(255,255,255,0.26) 0%, rgba(255,255,255,0.10) 100%);
  backdrop-filter: blur(18px) saturate(1.7);
  -webkit-backdrop-filter: blur(18px) saturate(1.7);
  border: 1px solid rgba(255,255,255,0.30);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.6),
    0 8px 22px rgba(4,16,26,0.20);
  border-radius: 12px;
  cursor: pointer;
}
.nav__burger span {
  width: 18px; height: 2px; background: #fff; border-radius: 2px;
  transition: transform .3s var(--ease), opacity .3s var(--ease);
}

/* =========================================================
   HERO
   ========================================================= */
/* one connected warm background spanning hero + about + partners, then
   flowing seamlessly into .warm-zone (services + process): both end/begin
   on the same blue (#167ecf) so there is no seam between them. */
.warm-stack { position: relative; }
/* the gradient sits BEHIND the fixed disc canvas (z-index:-1) so the discs
   render over it, while section content stays in front (z-index:auto/positive). */
.warm-stack::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -2;
  pointer-events: none;
  background:
    radial-gradient(110% 45% at 80% 4%, rgba(49,156,239,0.45), transparent 46%),
    linear-gradient(180deg,
      #1c90ef 0%,
      #1689ea 12%,
      #1581de 27%,
      #147bce 34%,
      #147cd0 40%,
      #1584de 55%,
      #188ae8 72%,
      #2090e8 78%,
      #1d8ee6 87%,
      #1986de 94%,
      #167ecf 100%
    );
}
.hero {
  position: relative;
  min-height: 100vh;
  display: flex;
  align-items: center;
  overflow: hidden;
  padding: 140px 0 60px;
}
.hero__bg {
  position: absolute; inset: 0; z-index: 0;
  /* overlays only now — the connected .warm-stack gradient shows through */
  background:
    radial-gradient(120% 130% at 78% 8%, rgba(39,142,226,0.35) 0%, rgba(0,0,0,0) 42%),
    radial-gradient(150% 120% at 10% 98%, rgba(0,0,0,0.42) 6%, rgba(0,0,0,0) 46%);
  /* fade the hero overlays (radials + grain) out before the section's bottom
     edge so overflow:hidden doesn't clip them into a hard line — lets the hero
     dissolve into the shared .warm-stack gradient with no visible seam */
  -webkit-mask-image: linear-gradient(to bottom, #000 70%, transparent 100%);
  mask-image: linear-gradient(to bottom, #000 70%, transparent 100%);
}
/* the grain uses mix-blend-mode, so fade it explicitly too (belt & suspenders) */
.hero__bg .grain {
  -webkit-mask-image: linear-gradient(to bottom, #000 70%, transparent 100%);
  mask-image: linear-gradient(to bottom, #000 70%, transparent 100%);
}
.hero__content {
  position: relative; z-index: 5;
  display: grid;
  grid-template-columns: 1fr 1fr;
  align-items: end;
  gap: 40px;
  width: 100%;
}
.hero__title {
  font-size: clamp(46px, 6.4vw, 88px);
  font-weight: 500;
  line-height: 0.96;
  letter-spacing: -0.03em;
}
/* animated hero brand word */
.hero__word {
  background: linear-gradient(100deg, #7cc6fb 0%, #35a8f4 40%, #8fd4ff 60%, #7cc6fb 100%);
  background-size: 220% 100%;
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent; color: transparent;
  filter: drop-shadow(0 0 14px rgba(90,184,240,0.5));
  animation: heroWordShine 5.5s ease-in-out infinite;
}
@keyframes heroWordShine {
  0%, 100% { background-position: 0% 0; }
  50%      { background-position: 100% 0; }
}
.hero__subtitle {
  margin-top: 24px;
  font-size: clamp(17px, 1.5vw, 21px);
  font-weight: 400;
  line-height: 1.45;
  color: rgba(255, 255, 255, 0.9);
  max-width: 440px;
}
@media (prefers-reduced-motion: reduce) { .hero__word { animation: none; } }

/* nav language toggle (decorative for now — TODO: wire real i18n) */
.nav__lang {
  font-family: inherit;
  /* centre the label with flex, not with padding: the mobile/tablet bar zeroes
     the padding and forces a 44px circle, and a padding-centred label would
     fall out of it to the top-left (the burger and WhatsApp buttons already
     centre this way) */
  display: inline-flex; align-items: center; justify-content: center;
  flex: 0 0 auto;
  font-size: 14px; font-weight: 500; line-height: 1;
  color: rgba(255, 255, 255, 0.94);
  /* liquid glass to match the pill / burger */
  background: linear-gradient(180deg, rgba(255,255,255,0.26) 0%, rgba(255,255,255,0.10) 100%);
  backdrop-filter: blur(18px) saturate(1.7);
  -webkit-backdrop-filter: blur(18px) saturate(1.7);
  border: 1px solid rgba(255, 255, 255, 0.30);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.6),
    0 8px 22px rgba(4,16,26,0.20);
  border-radius: 999px;
  padding: 10px 14px;
  cursor: pointer;
  transition: background 0.25s var(--ease), color 0.25s var(--ease);
}
.nav__lang:hover { background: linear-gradient(180deg, rgba(255,255,255,0.34) 0%, rgba(255,255,255,0.16) 100%); }

/* ---- language switcher ----------------------------------------------------
   Three languages no longer fit the old two-way toggle. The pill is now the
   <summary> of a <details>, which carries the open/closed state, keyboard
   support and aria-expanded natively -- so the menu still opens with JS
   disabled. script.js only layers outside-click and Escape on top.
   The pill keeps .nav__lang, so every existing size rule (the 44px and 40px
   circles in the phone tiers) still applies to it unchanged. */
.nav__langwrap { position: relative; flex: 0 0 auto; }
/* strip the native disclosure triangle in every engine */
.nav__lang { list-style: none; }
.nav__lang::-webkit-details-marker { display: none; }
.nav__lang::marker { content: ""; }

.nav__langmenu {
  position: absolute;
  inset-block-start: calc(100% + 10px);
  inset-inline-end: 0;
  z-index: 60;
  min-width: 150px;
  padding: 6px;
  list-style: none;
  background: linear-gradient(180deg, rgba(13,44,68,0.96) 0%, rgba(8,32,51,0.96) 100%);
  backdrop-filter: blur(18px) saturate(1.7);
  -webkit-backdrop-filter: blur(18px) saturate(1.7);
  border: 1px solid rgba(255,255,255,0.20);
  border-radius: var(--radius-md);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.14), 0 18px 40px rgba(4,16,26,0.45);
}
.nav__langmenu a {
  display: block;
  padding: 10px 12px;
  border-radius: var(--radius-sm);
  font-size: 14px; font-weight: 500; line-height: 1;
  color: rgba(255,255,255,0.86);
  text-decoration: none;
  white-space: nowrap;
  transition: background 0.2s var(--ease), color 0.2s var(--ease);
}
.nav__langmenu a:hover { background: rgba(255,255,255,0.10); color: var(--white); }
/* the page you are already on */
.nav__langmenu a[aria-current="true"] { color: var(--brand-300); }
/* each label is written in its own language, so it sets its own direction */
.nav__langmenu a[lang="ar"] { font-family: var(--font-ar); direction: rtl; }

.hero__right { position: relative; align-self: end; padding-bottom: 6px; max-width: 520px; margin-inline-start: auto; }
/* soft scrim so the copy stays legible over the glass orb */
.hero__right::before {
  content: "";
  display: none;   /* scrim hidden — the "At Athar Creatives" copy card is removed */
  position: absolute;
  inset: -24px -34px -24px -44px;
  z-index: -1;
  border-radius: 30px;
  background: radial-gradient(120% 110% at 62% 62%, rgba(8,5,3,0.55), rgba(8,5,3,0) 72%);
}
.hero__desc {
  display: none;   /* "At Athar Creatives…" paragraph hidden */
  font-size: 20px;
  line-height: 1.5;
  color: rgba(255,255,255,0.86);
  margin-bottom: 26px;
}
.hero__actions { display: none; } /* hero CTA buttons hidden */

/* ===== hero glass dashboard — pure CSS (replaces hero data.png) ===== */
.hero-dash {
  position: absolute;
  z-index: 4;
  top: 20%;
  inset-inline-end: max(var(--pad), calc((100% - (var(--container) + var(--pad) * 2)) / 2 + var(--pad)));
  width: clamp(380px, 50vw, 720px);
  aspect-ratio: 1 / 0.78;
  pointer-events: none;
}
.hdash__panel {
  position: absolute;
  border-radius: 18px;
  background: linear-gradient(165deg, rgba(255,255,255,0.22), rgba(255,255,255,0.08));
  border: 1px solid rgba(255,255,255,0.38);
  -webkit-backdrop-filter: blur(14px) saturate(130%);
  backdrop-filter: blur(14px) saturate(130%);
  box-shadow:
    0 24px 50px -18px rgba(4,32,58,0.5),
    inset 0 1px 0 rgba(255,255,255,0.4);
}
.hdash__title {
  display: block;
  font-size: 12px; font-weight: 600; letter-spacing: 0.01em;
  color: rgba(255,255,255,0.95);
}

/* --- roadmap panel --- */
.hdash__roadmap {
  inset-inline-start: 0; top: 0; width: 66%;
  padding: 16px 18px 18px;
  z-index: 2;
  animation: hdFloatA 9s ease-in-out infinite;
}
.hdash__quarters {
  display: grid; grid-template-columns: repeat(4, 1fr);
  margin-block: 12px 10px; margin-inline: 76px 0;  /* aligns over the tracks (label col + gap) */
  font-size: 9.5px; font-weight: 600; letter-spacing: 0.06em;
  color: rgba(255,255,255,0.6);
}
.hdash__rows { position: relative; display: grid; gap: 13px; }
/* recessive quarter grid lines behind the bars */
.hdash__rows::before {
  content: "";
  position: absolute; top: -6px; bottom: -6px;
  inset-inline-start: 76px; inset-inline-end: 0;
  background-image: linear-gradient(to left, rgba(255,255,255,0.16) 1px, transparent 1px);
  background-size: 25% 100%;
}
.hdash__row { display: grid; grid-template-columns: 68px 1fr; align-items: center; gap: 8px; }
.hdash__label { font-size: 10px; color: rgba(255,255,255,0.85); white-space: nowrap; }
.hdash__track {
  position: relative; height: 8px; border-radius: 4px;
  background: rgba(255,255,255,0.10);
}
.hdash__bar {
  position: absolute; top: 0; bottom: 0;
  inset-inline-start: var(--o); width: var(--w);
  border-radius: 4px;
  background: linear-gradient(90deg, #0f6ec0, #5bb8f0);
  box-shadow: 0 2px 8px rgba(10,60,110,0.35);
  transform: scaleX(0); transform-origin: left center;
}
.hdash__bar--alt { background: linear-gradient(90deg, #3f9fe0, #a9d8f5); }
.hero-dash.is-in .hdash__bar { animation: hdGrow 0.9s var(--ease) var(--d, 0s) forwards; }
@keyframes hdGrow { to { transform: scaleX(1); } }
/* floating tag chips */
.hdash__tag {
  position: absolute;
  font-size: 9.5px; font-weight: 600; color: #0d3a5e;
  background: rgba(255,255,255,0.92);
  padding: 5px 9px; border-radius: 8px;
  box-shadow: 0 8px 20px rgba(6,40,70,0.35);
  opacity: 0; transform: translateY(6px);
  white-space: nowrap;
}
.hdash__tag--a { inset-inline-start: 30%; top: 38%; }
.hdash__tag--b { inset-inline-start: 48%; top: 68%; }
.hero-dash.is-in .hdash__tag--a { animation: hdPop 0.5s var(--ease) 1.05s forwards; }
.hero-dash.is-in .hdash__tag--b { animation: hdPop 0.5s var(--ease) 1.25s forwards; }
@keyframes hdPop { to { opacity: 1; transform: none; } }

/* --- KPI panel --- */
.hdash__kpi {
  inset-inline-end: 0; top: 5%; width: 32%;
  padding: 14px 16px 12px;
  z-index: 3;
  display: flex; flex-direction: column; gap: 10px;
  animation: hdFloatB 8s ease-in-out infinite 0.6s;
}
.hdash__stat { display: flex; flex-direction: column; }
@property --hdna { syntax: "<integer>"; initial-value: 0; inherits: false; }
@property --hdnb { syntax: "<integer>"; initial-value: 0; inherits: false; }
.hdash__num {
  font-size: 23px; font-weight: 600; line-height: 1.1;
  color: #fff; font-variant-numeric: tabular-nums;
}
/* count-up via animatable @property; var() fallback = final value on old browsers */
.hdash__num--a::after { counter-reset: hdna var(--hdna, 47); content: "+" counter(hdna) "%"; }
.hdash__num--b::after { counter-reset: hdnb var(--hdnb, 35); content: "+" counter(hdnb) "%"; }
.hero-dash.is-in .hdash__num--a::after { animation: hdCountA 1.7s cubic-bezier(0.16, 1, 0.3, 1) 0.7s forwards; }
.hero-dash.is-in .hdash__num--b::after { animation: hdCountB 1.7s cubic-bezier(0.16, 1, 0.3, 1) 0.9s forwards; }
@keyframes hdCountA { to { --hdna: 47; } }
@keyframes hdCountB { to { --hdnb: 35; } }
.hdash__stat-label { font-size: 10px; color: rgba(255,255,255,0.72); margin-top: 2px; }
.hdash__spark { width: 100%; height: 40px; margin-top: 2px; overflow: visible; }
.hdash__spark-line {
  fill: none; stroke: #fff; stroke-width: 2;
  stroke-linecap: round; stroke-linejoin: round;
  stroke-dasharray: 125; stroke-dashoffset: 125;
}
.hero-dash.is-in .hdash__spark-line { animation: hdDraw 1.4s var(--ease) 0.9s forwards; }
@keyframes hdDraw { to { stroke-dashoffset: 0; } }
.hdash__spark-fill { fill: url(#hdSparkGrad); opacity: 0; }
.hero-dash.is-in .hdash__spark-fill { animation: hdFade 0.8s ease 1.6s forwards; }
.hdash__spark-dot { fill: #fff; opacity: 0; }
.hero-dash.is-in .hdash__spark-dot { animation: hdFade 0.4s ease 2s forwards; }
@keyframes hdFade { to { opacity: 1; } }

/* --- audience panel --- */
.hdash__aud {
  inset-inline-start: 8%; top: 60%; width: 44%;
  padding: 14px 16px;
  z-index: 3;
  animation: hdFloatC 7.5s ease-in-out infinite 0.3s;
}
.hdash__aud-body { display: flex; align-items: center; gap: 12px; margin-top: 10px; }
.hdash__donut {
  flex: 0 0 auto;
  width: 76px; height: 76px; border-radius: 50%;
  /* transparent slivers = surface gaps between segments */
  background: conic-gradient(
    #0b4f7e 0deg 135deg,
    transparent 135deg 139deg,
    #1899e8 139deg 232deg,
    transparent 232deg 236deg,
    #bfe4fb 236deg 298deg,
    transparent 298deg 302deg,
    rgba(255,255,255,0.30) 302deg 356deg,
    transparent 356deg 360deg
  );
  -webkit-mask: radial-gradient(circle, transparent 23px, #000 24px);
          mask: radial-gradient(circle, transparent 23px, #000 24px);
  opacity: 0; transform: rotate(-70deg) scale(0.9);
}
.hero-dash.is-in .hdash__donut { animation: hdSpin 1s var(--ease) 0.6s forwards; }
@keyframes hdSpin { to { opacity: 1; transform: none; } }
.hdash__legend {
  list-style: none; margin: 0; padding: 0;
  display: grid; gap: 6px;
  font-size: 9.5px; color: rgba(255,255,255,0.88);
  flex: 1;
}
.hdash__legend li { display: flex; align-items: center; gap: 6px; white-space: nowrap; }
.hdash__legend i {
  width: 7px; height: 7px; border-radius: 50%; flex: 0 0 auto;
  background: var(--c);
  box-shadow: 0 0 0 1px rgba(255,255,255,0.25);
}
.hdash__legend b { margin-inline-start: auto; padding-inline-start: 8px; font-weight: 600; color: rgba(255,255,255,0.65); }

/* --- connector lines --- */
.hdash__link { position: absolute; z-index: 1; background: rgba(255,255,255,0.4); }
.hdash__link::after {
  content: ""; position: absolute;
  width: 5px; height: 5px; border-radius: 2px; background: #fff;
}
.hdash__link--a { inset-inline-start: 65%; top: 13%; width: 4.5%; height: 1.5px; }
.hdash__link--a::after { inset-inline-end: -2px; top: 50%; transform: translateY(-50%); }
.hdash__link--b { inset-inline-start: 20%; top: 38%; width: 1.5px; height: 21%; }
.hdash__link--b::after { inset-inline-start: 50%; bottom: -2px; transform: translateX(-50%); }
.hdash__link--c { inset-inline-start: 82%; top: 38%; width: 1.5px; height: 8%; }
.hdash__link--c::after { inset-inline-start: 50%; bottom: -2px; transform: translateX(-50%); }
.hdash__link--d { inset-inline-start: 53%; top: 70%; width: 12%; height: 1.5px; }
.hdash__link--d::after { inset-inline-end: -2px; top: 50%; transform: translateY(-50%); }

/* --- progress ring mini panel --- */
@property --hdring { syntax: "<angle>"; initial-value: 0deg; inherits: false; }
@property --hdnc { syntax: "<integer>"; initial-value: 0; inherits: false; }
.hdash__ring {
  inset-inline-start: 0; top: 44%;
  display: flex; align-items: center; gap: 10px;
  padding: 10px 14px;
  z-index: 3;
  animation: hdFloatC 8.5s ease-in-out infinite 1s;
}
.hdash__ring-viz {
  flex: 0 0 auto;
  width: 34px; height: 34px; border-radius: 50%;
  background: conic-gradient(#fff var(--hdring, 259deg), rgba(255,255,255,0.22) 0deg);
  -webkit-mask: radial-gradient(circle, transparent 11px, #000 12px);
          mask: radial-gradient(circle, transparent 11px, #000 12px);
}
.hero-dash.is-in .hdash__ring-viz { animation: hdRing 1.6s var(--ease) 1.1s forwards; }
@keyframes hdRing { to { --hdring: 259deg; } }
.hdash__ring-txt { display: flex; flex-direction: column; line-height: 1.15; }
.hdash__ring-num { font-size: 16px; font-weight: 600; color: #fff; font-variant-numeric: tabular-nums; }
.hdash__ring-num::after { counter-reset: hdnc var(--hdnc, 72); content: counter(hdnc) "%"; }
.hero-dash.is-in .hdash__ring-num::after { animation: hdCountC 1.6s cubic-bezier(0.16, 1, 0.3, 1) 1.1s forwards; }
@keyframes hdCountC { to { --hdnc: 72; } }
.hdash__ring-txt em { font-style: normal; font-size: 9px; color: rgba(255,255,255,0.72); }

/* --- content calendar panel --- */
.hdash__cal {
  inset-inline-end: 0; top: 46%; width: 34%;
  padding: 14px 16px;
  z-index: 2;
  animation: hdFloatB 9.5s ease-in-out infinite 0.9s;
}
.hdash__cal-grid { display: grid; grid-template-columns: repeat(5, 1fr); gap: 5px; margin-top: 10px; }
.hdash__cal-day { font-size: 8.5px; font-weight: 600; text-align: center; color: rgba(255,255,255,0.6); }
.hdash__cell {
  aspect-ratio: 1; border-radius: 6px;
  background: rgba(255,255,255,0.10);
  display: grid; place-items: center;
}
.hdash__cell i {
  width: 55%; height: 55%; border-radius: 4px;
  background: var(--c);
  box-shadow: 0 2px 6px rgba(6,40,70,0.3);
  transform: scale(0);
}
.hero-dash.is-in .hdash__cell i { animation: hdTile 0.45s var(--ease) var(--d, 1.2s) forwards; }
@keyframes hdTile { to { transform: scale(1); } }

/* --- floating status chip --- */
.hdash__chip {
  position: absolute; inset-inline-start: 55%; top: 82%; z-index: 4;
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 9.5px; font-weight: 600; color: #0d3a5e;
  background: rgba(255,255,255,0.92);
  padding: 6px 10px; border-radius: 999px;
  box-shadow: 0 10px 24px rgba(6,40,70,0.35);
  opacity: 0; transform: translateY(6px);
  white-space: nowrap;
}
.hdash__chip i {
  width: 12px; height: 12px; border-radius: 50%; flex: 0 0 auto;
  background: #1899e8; position: relative;
}
.hdash__chip i::after {
  content: ""; position: absolute; inset-inline-start: 3.5px; top: 2.5px;
  width: 4px; height: 6px;
  border: solid #fff; border-width: 0 1.5px 1.5px 0;
  transform: rotate(40deg);
}
.hero-dash.is-in .hdash__chip { animation: hdPop 0.5s var(--ease) 1.6s forwards; }

/* gentle float (echoes the old 3D objects) */
@keyframes hdFloatA { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-7px); } }
@keyframes hdFloatB { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-10px); } }
@keyframes hdFloatC { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-6px); } }

@media (prefers-reduced-motion: reduce) {
  .hero-dash *, .hero-dash *::after { animation: none !important; }
  .hdash__bar { transform: none; }
  .hdash__tag { opacity: 1; transform: none; }
  .hdash__spark-line { stroke-dashoffset: 0; }
  .hdash__spark-fill, .hdash__spark-dot { opacity: 1; }
  .hdash__donut { opacity: 1; transform: none; }
  .hdash__num--a::after { --hdna: 47; }
  .hdash__num--b::after { --hdnb: 35; }
  .hdash__cell i { transform: none; }
  .hdash__chip { opacity: 1; transform: none; }
  .hdash__ring-viz { --hdring: 259deg; }
  .hdash__ring-num::after { --hdnc: 72; }
}

/* =========================================================
   GLASS DISC RENDERS (CSS abstractions)
   ========================================================= */
.disc-scene { position: absolute; pointer-events: none; }

/* WebGL glass-disc scene — fixed, full-viewport background layer.
   z-index:-1 keeps it behind in-flow section backgrounds (which occlude it),
   while the transparent hero lets it show through as the hero visual. */
/* --- 3D discs temporarily hidden (re-enable: delete this rule + uncomment discs.js in index.html) --- */
.disc-canvas, .disc-scene--hero { display: none !important; }

.disc-canvas {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: -1;
  display: block;
  pointer-events: none;
  background:
    radial-gradient(120% 130% at 78% 8%, rgba(39,142,226,0.55) 0%, rgba(0,0,0,0) 42%),
    radial-gradient(150% 120% at 12% 96%, #000 8%, rgba(0,0,0,0) 55%),
    linear-gradient(150deg, #1784de 0%, #105798 34%, #07234d 66%, #060e18 100%);
}
/* when the WebGL scene is live, reveal it through the hero + drop the CSS fallback */
html.webgl-on .hero__bg { opacity: 0; }
html.webgl-on .disc-scene--hero { display: none; }

/* hero: cluster of translucent discs on the right (CSS fallback, no WebGL) */
.disc-scene--hero { top: -6%; right: -6%; width: 62%; height: 118%; }
.disc {
  position: absolute;
  border-radius: 50%;
  background:
    linear-gradient(135deg, rgba(255,255,255,0.85), rgba(170,210,240,0.25) 40%, rgba(40,90,140,0.15) 75%);
  box-shadow: inset 0 0 40px rgba(255,255,255,0.35), 0 30px 60px rgba(0,0,0,0.25);
  filter: blur(0.4px);
  mix-blend-mode: screen;
  opacity: 0.9;
}
.disc--1 { width: 46%; height: 26%; top: 6%;  right: 20%; transform: rotate(-18deg); }
.disc--2 { width: 52%; height: 30%; top: 26%; right: -4%; transform: rotate(14deg); opacity: 0.8; }
.disc--3 { width: 60%; height: 34%; top: 52%; right: 8%;  transform: rotate(-8deg); opacity: 0.85; }
.disc--4 { width: 40%; height: 22%; top: 78%; right: 30%; transform: rotate(20deg); opacity: 0.7; }

/* =========================================================
   SOLUTIONS + DASHBOARD
   ========================================================= */
.about { background: transparent; padding: 30px 0 90px; }
.about__panel {
  position: relative;
  margin: 0 var(--pad);
  padding: 56px 0 52px;   /* holds the intro, collage and value cards */
  overflow: hidden;       /* clip the grain + content to the rounded corners */
  /* frosted-glass card sitting on top of the shared .warm-stack gradient, which
     flows continuously behind it so hero + Who-We-Are read as one background */
  background: linear-gradient(180deg, rgba(22,58,86,0.42), rgba(10,34,54,0.50));
  border: 1px solid rgba(255,255,255,0.12);
  border-radius: 32px;
  backdrop-filter: blur(16px) saturate(120%);
  -webkit-backdrop-filter: blur(16px) saturate(120%);
  box-shadow:
    0 24px 60px -22px rgba(0,0,0,0.5),
    inset 0 1px 0 rgba(255,255,255,0.08);
}
/* animated white gradient border ring — a light travels around the rounded corners */
@property --about-border-angle {
  syntax: "<angle>";
  initial-value: 0deg;
  inherits: false;
}
.about__panel::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  padding: 3px;
  background: conic-gradient(from var(--about-border-angle),
    rgba(255,255,255,0.16) 0deg,
    rgba(255,255,255,1) 60deg,
    rgba(255,255,255,0.45) 130deg,
    rgba(255,255,255,0.16) 220deg,
    rgba(255,255,255,0.16) 360deg);
  -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
          mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
  -webkit-mask-composite: xor;
          mask-composite: exclude;
  pointer-events: none;
  z-index: 4;
  /* the angle animation repaints the conic every frame — isolate it on its
     own layer so it doesn't invalidate the whole frosted panel each time */
  will-change: background;
  animation: aboutBorderSpin 8s linear infinite;
}
@keyframes aboutBorderSpin {
  to { --about-border-angle: 360deg; }
}
.about__intro {
  display: grid;
  grid-template-columns: 1.1fr 0.9fr;
  gap: 40px;
  align-items: end;
  padding-block: 40px 30px;
}
.about__copy .section-title { margin: 26px 0 30px; }
.about__actions { display: flex; gap: 14px; }
/* phone-length copy variants: the short span swaps in at ≤820px */
.txt-short { display: none; }
.about__lead {
  font-size: 19px; line-height: 1.5;
  color: rgba(255,255,255,0.82);
  max-width: 440px; margin-inline-start: auto; padding-bottom: 8px;
}

/* portfolio collage (replaces the old dashboard mockup) */
.collage {
  position: relative; z-index: 3;
  margin-top: 12px;
  display: grid;
  grid-template-columns: 1.5fr 1fr 1fr;
  grid-auto-rows: 158px;
  gap: 14px;
}
.collage__item {
  position: relative;
  overflow: hidden;
  border-radius: 16px;
  border: 1px solid rgba(255,255,255,0.08);
  background: rgba(255,255,255,0.04);
}
.collage__item img {
  width: 100%; height: 100%;
  object-fit: cover; display: block;
  transition: transform .6s var(--ease);
}
.collage__item:hover img { transform: scale(1.05); }
.collage__item--tall { grid-row: span 2; }
.collage__item--wide { grid-column: span 2; }

/* value cards */
.about__values {
  position: relative; z-index: 3;
  margin-top: 24px;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 16px;
}
.vcard {
  min-height: 210px;
  padding: 34px 32px;
  border-radius: var(--radius-lg);
  background: transparent;
  border: 1px solid rgba(91,184,240,0.30);
  display: flex; flex-direction: column;
}
.vcard__title { font-size: 24px; font-weight: 600; letter-spacing: -0.01em; margin-bottom: 16px; color: #fff; }
.vcard__desc { font-size: 17px; line-height: 1.6; color: rgba(255,255,255,0.78); }

/* =========================================================
   PARTNERS
   ========================================================= */
.partners {
  position: relative;
  padding: 110px 0 90px;
  overflow: hidden;
  background: transparent;   /* uses the shared .warm-stack background */
}
/* fade the partners grain in from the top so overflow:hidden doesn't clip it
   into a hard line where the section above meets it — keeps the shared
   .warm-stack background reading as one continuous field */
.partners .grain {
  -webkit-mask-image: linear-gradient(to bottom, transparent 0%, #000 22%);
  mask-image: linear-gradient(to bottom, transparent 0%, #000 22%);
}
.partners__glow {
  position: absolute; top: 8%; left: 22%;
  width: 340px; height: 340px; border-radius: 50%;
  background: radial-gradient(circle, rgba(240,250,255,0.95), rgba(200,230,255,0) 62%);
  filter: blur(4px);
}
.partners__head { position: relative; z-index: 3; margin-bottom: 60px; }
.partners .eyebrow { color: rgba(255,255,255,0.9); }
.partners .section-title { color: #fff; }
/* the mask also clips to the marquee's box, which ended flush with the tiles
   and cut their drop shadow into a hard dark line; the padding gives the
   shadow room (22px blur + 8px offset) and the negative margins cancel it */
.partners__marquee { position: relative; z-index: 3; padding: 16px 0 36px; margin: -16px 0 -36px; -webkit-mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent); mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent); }
.partners__track { display: flex; gap: 20px; width: max-content; animation: marquee 34s linear infinite; will-change: transform; }
@keyframes marquee { to { transform: translateX(-50%); } }
.plogo {
  flex: 0 0 auto;
  width: 155px; height: 155px;
  display: grid; place-items: center;
  padding: 28px;
  border-radius: 12px;
  /* frosted-white glass. Partner logos are full-colour artwork drawn for a
     light ground; the old 14% tint left 9 of the 12 under the 3:1 contrast
     floor. The vertical gradient + bright top edge is what makes this read as
     lit glass rather than a flat white tile at this opacity — a plain fill at
     the same value reads as cardboard. Mid-range values (25–45%) are worse
     than either end: they land on the pastel logos' own luminance. */
  background: linear-gradient(180deg, rgba(255,255,255,0.76), rgba(255,255,255,0.62));
  border: 1px solid rgba(255,255,255,0.55);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.85),
    0 8px 22px rgba(4,16,26,0.18);
  backdrop-filter: blur(14px) saturate(1.4);
  -webkit-backdrop-filter: blur(14px) saturate(1.4);
}
.plogo img {
  max-width: 100%; max-height: 100%;
  object-fit: contain; display: block;
}
/* wide or detailed logos (size: "lg" in content.js) read too small inside the
   default 28px padding, so they get most of the tile */
.plogo--lg { padding: 14px 10px; }

/* =========================================================
   SERVICES — Our Expertises (sticky stacking cards)
   ========================================================= */
/* continues the .warm-stack field: starts on the same #167ecf as the section
   above ends, so hero + who-we-are + partners + expertises + approach all read
   as one uninterrupted hero-blue background — held bright through its body
   (no section-by-section darkening), fading to near-black only at the very
   end for the seam into the black Portfolio section. */
.warm-zone {
  position: relative;
  background: linear-gradient(180deg, #167ecf 0%, #1584de 34%, #188ae8 58%, #1584de 76%, #105bab 88%, #062556 96%, #04101a 100%);
}
.services {
  position: relative;
  padding: 110px 0 120px;
  /* no overflow:hidden here — it would disable position:sticky on the pinned title */
  background: transparent;
}
/* fade the services grain out at the bottom so its texture/lift doesn't end on a
   hard line where Approach begins — lets the warm-zone gradient flow through as
   one continuous field into the process section */
.services .grain {
  -webkit-mask-image: linear-gradient(to bottom, #000 58%, transparent 100%);
  mask-image: linear-gradient(to bottom, #000 58%, transparent 100%);
}
.services__disc {
  position: absolute; top: 4%; left: 30%;
  width: 360px; height: 200px; border-radius: 50%;
  background: radial-gradient(circle at 50% 40%, rgba(190,225,255,0.7), rgba(60,110,150,0.2) 70%, transparent);
  filter: blur(10px);
}
.services__inner {
  position: relative; z-index: 3;
  display: grid; grid-template-columns: 1fr 1fr; gap: 60px;
  align-items: stretch; /* left column stretches so the sticky title can pin */
}
.services__sticky { position: sticky; top: 120px; }
.services__sticky .section-title { margin: 26px 0 24px; }
.services__lead { font-size: 19px; line-height: 1.5; color: rgba(255,255,255,0.82); max-width: 400px; }

.services__right { display: flex; flex-direction: column; gap: 24px; }
.scard {
  position: relative; /* anchors .scard__art placed outside the masked grid */
  /* 420 (not 380) so the squarer websites art fits at the shared --sm size
     without crowding its title */
  min-height: 420px;
  border-radius: var(--radius-lg);
  padding: 34px 36px;
  display: flex; flex-direction: column;
  overflow: hidden;
  border: 1px solid rgba(255,255,255,0.10);
  background:
    linear-gradient(160deg, rgba(20,52,80,0.55), rgba(6,18,32,0.75)),
    rgba(12,32,52,0.6);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  box-shadow: 0 30px 60px rgba(0,0,0,0.35);
}
.scard__title { font-size: clamp(26px, 2.6vw, 34px); font-weight: 500; letter-spacing: -0.01em; }
.scard__grid {
  flex: 1; margin: 6px 0 20px; border-radius: 12px; position: relative;
  background-image:
    linear-gradient(rgba(255,255,255,0.09) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255,255,255,0.09) 1px, transparent 1px);
  background-size: 62px 62px;
  -webkit-mask-image: radial-gradient(70% 80% at 75% 55%, #000, transparent 75%);
  mask-image: radial-gradient(70% 80% at 75% 55%, #000, transparent 75%);
}
.scard__grid--alt { background-size: 74px 74px; }
/* per-service line illustration (replaces the generic +/cursor motif) */
.scard__art {
  position: absolute; inset-inline-end: 16%; top: 50%;
  transform: translateY(-50%);
  width: 140px; height: 140px;
  color: rgba(226,240,255,0.88);
  filter: drop-shadow(0 0 22px rgba(120,190,240,0.40));
  pointer-events: none;
}
/* wide "cluster" illustration (reference-style composition) */
.scard__art--wide {
  width: min(330px, 58%);
  height: auto;
  inset-inline-end: 6%;
  top: 44%;
}
.scard__art--lower { top: 52%; }
.scard__art--sm { width: min(290px, 52%); }
/* content-creation card: larger art, true vertical center of the card */
.scard__art--cc { width: min(400px, 68%); top: 46%; }.scard__desc { font-size: 18px; line-height: 1.5; color: rgba(255,255,255,0.85); max-width: 460px; }

/* =========================================================
   PROCESS — Our Approach (step strip)
   ========================================================= */
.process { background: transparent; padding: 30px 0 130px; }
.process__head { text-align: center; margin-bottom: 60px; }
.process__head .section-title { margin-top: 22px; }
.process__sub { max-width: 660px; margin: 22px auto 0; font-size: 18px; line-height: 1.55; color: rgba(255,255,255,0.78); }
.process__strip { display: grid; grid-template-columns: repeat(4, 1fr); gap: 20px; }
.pstep {
  position: relative;
  overflow: hidden;
  min-height: 460px;
  border-radius: var(--radius-lg);
  padding: 32px 30px;
  display: flex; flex-direction: column; justify-content: space-between;
  border: 1px solid rgba(150,200,240,0.18);
  /* frosted glass — matches the Who We Are card so the warm-zone gradient
     flows through and the section reads as one continuous background */
  background: linear-gradient(180deg, rgba(22,58,86,0.40), rgba(10,34,54,0.52));
  -webkit-backdrop-filter: blur(16px) saturate(120%);
  backdrop-filter: blur(16px) saturate(120%);
  box-shadow:
    0 30px 60px rgba(0,0,0,0.32),
    inset 0 1px 0 rgba(255,255,255,0.08);
  /* the hover reveal animates max-height (a layout animation) — containment
     keeps those per-frame reflows inside the card instead of the whole page */
  contain: layout paint;
  transition: transform 0.4s var(--ease), border-color 0.4s var(--ease);
}
.pstep:hover { transform: translateY(-6px); border-color: rgba(91,184,240,0.4); }

/* decorative grid, faded to the middle of the card */
.pstep__grid {
  position: absolute; z-index: 0; pointer-events: none;
  left: 0; right: 0; top: 50%; transform: translateY(-50%);
  height: 220px;
  background-image:
    linear-gradient(rgba(255,255,255,0.07) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255,255,255,0.07) 1px, transparent 1px);
  background-size: 40px 40px;
  -webkit-mask-image: radial-gradient(58% 62% at 50% 50%, #000, transparent 72%);
  mask-image: radial-gradient(58% 62% at 50% 50%, #000, transparent 72%);
}
/* cursor light — follows the pointer via --mx/--my set in JS */
.pstep__glow {
  position: absolute; z-index: 0; inset: 0; pointer-events: none;
  border-radius: inherit;
  opacity: 0; transition: opacity 0.35s var(--ease);
  background: radial-gradient(240px circle at var(--mx, 50%) var(--my, 50%), rgba(91,184,240,0.18), transparent 60%);
}
.pstep:hover .pstep__glow { opacity: 1; }

.pstep__n {
  position: relative; z-index: 1;
  font-size: clamp(58px, 5.5vw, 88px);
  font-weight: 500; line-height: 1; letter-spacing: -0.02em;
  color: rgba(210,232,255,0.16);
}
.pstep__foot { position: relative; z-index: 1; }
.pstep__ico {
  display: grid; place-items: center;
  width: 46px; height: 46px; border-radius: 12px;
  background: rgba(91,184,240,0.13); border: 1px solid rgba(91,184,240,0.28);
  color: var(--brand-300); margin-bottom: 18px;
  transition: transform 0.4s var(--ease);
}
.pstep__ico svg { width: 22px; height: 22px; }
.pstep__title { font-size: 23px; font-weight: 500; line-height: 1.15; letter-spacing: -0.01em; }
/* paragraph hidden until hover; the bottom-anchored foot lifts the icon/title as it appears */
.pstep__desc {
  max-height: 0; opacity: 0; overflow: hidden;
  margin-top: 0; font-size: 14.5px; line-height: 1.55; color: rgba(255,255,255,0.72);
  transform: translateY(6px);
  transition: max-height 0.45s var(--ease), opacity 0.35s var(--ease),
    transform 0.45s var(--ease), margin-top 0.45s var(--ease);
}
.pstep:hover .pstep__desc { max-height: 160px; opacity: 1; margin-top: 14px; transform: none; }
.pstep:hover .pstep__ico { transform: translateY(-2px); }

/* =========================================================
   PORTFOLIO — Our Portfolio (carousel)
   ========================================================= */
.portfolio { background: var(--black); padding: 110px 0 140px; overflow: hidden; }
.portfolio__head { display: flex; justify-content: space-between; align-items: flex-end; gap: 24px; margin-bottom: 44px; }
.portfolio__head .section-title { margin-top: 20px; }
.portfolio__nav { display: flex; gap: 12px; flex: 0 0 auto; }
.pf-arrow {
  width: 52px; height: 52px; border-radius: 50%;
  display: grid; place-items: center;
  background: rgba(255,255,255,0.06); border: 1px solid rgba(255,255,255,0.14);
  color: #fff; cursor: pointer; transition: background 0.25s var(--ease), transform 0.25s var(--ease);
}
.pf-arrow:hover { background: rgba(255,255,255,0.18); }
.pf-arrow:active { transform: scale(0.94); }
.pf-arrow svg { width: 20px; height: 20px; }
.portfolio__viewport {
  overflow-x: auto; scroll-behavior: smooth;
  -ms-overflow-style: none; scrollbar-width: none;
  scroll-snap-type: x mandatory;
  /* snap inset matches the track's lead-in padding so the snapped card
     lines up with the section heading (100%, not 100vw — vw includes the scrollbar) */
  scroll-padding-inline-start: max(var(--pad), calc((100% - var(--container)) / 2));
  -webkit-overflow-scrolling: touch;   /* momentum scroll on iOS */
}
.portfolio__viewport::-webkit-scrollbar { display: none; }
.portfolio__track {
  display: flex; gap: 24px; width: max-content;
  /* 100% (viewport width minus scrollbar) — 100vw would push the first card
     ~15px right of the section heading */
  padding-inline-start: max(var(--pad), calc((100% - var(--container)) / 2));
  padding-inline-end: var(--pad);
}
.pcard { flex: 0 0 auto; width: 380px; max-width: 82vw; scroll-snap-align: start; }
.pcard__media {
  position: relative; display: block;
  height: 250px; border-radius: var(--radius-md); overflow: hidden;
  border: 1px solid rgba(255,255,255,0.06);
  background: rgba(255,255,255,0.03);
}
.pcard__media img { width: 100%; height: 100%; object-fit: cover; transition: transform 0.6s var(--ease); }
/* zoom only with a real pointer: on touch, :hover fires on tap and sticks, and
   scaling a photo mid-scroll is expensive on a phone */
@media (hover: hover) and (pointer: fine) {
  .pcard__media:hover img { transform: scale(1.05); }
}
.pcard__cat {
  position: absolute; top: 14px; inset-inline-start: 14px;
  font-size: 11px; font-weight: 600; letter-spacing: 0.12em; text-transform: uppercase;
  padding: 6px 12px; border-radius: 999px;
  background: rgba(6,16,26,0.72); color: var(--brand-200);
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
}
.pcard__title { font-size: 22px; font-weight: 600; margin: 20px 0 8px; }
.pcard__desc { font-size: 15px; line-height: 1.55; color: var(--muted); }
.pcard__more {
  display: inline-flex; align-items: center; gap: 8px; margin-top: 10px;
  padding: 10px 2px;   /* ≥44px tap target without changing the visual */
  font-size: 14px; font-weight: 500; color: var(--brand-300);
  transition: gap 0.25s var(--ease);
}
.pcard__more svg { width: 17px; height: 17px; }
.pcard__more:hover { gap: 12px; }

/* =========================================================
   CASE STUDIES — homepage cards
   ========================================================= */
.cases { background: var(--black); padding: 30px 0 150px; }
.cases__head { margin-bottom: 48px; }
.cases__sub { max-width: 540px; margin-top: 22px; font-size: 18px; line-height: 1.55; color: var(--muted); }
/* auto-fit so the row stays balanced whatever the number of case studies —
   two cards share the width instead of leaving an empty third column. */
.cases__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
  gap: 28px;
}
.ccard {
  display: flex; flex-direction: column;
  border-radius: var(--radius-lg); overflow: hidden;
  background: #0a0e14;
  border: 1px solid rgba(255,255,255,0.06);
  transition: transform 0.4s var(--ease), border-color 0.4s var(--ease);
}
.ccard__media { position: relative; display: block; height: 230px; overflow: hidden; }
.ccard__media img { width: 100%; height: 100%; object-fit: cover; display: block; transition: transform 0.6s var(--ease); }
/* lift, blue border and photo zoom need a real pointer - see .pcard__media */
@media (hover: hover) and (pointer: fine) {
  .ccard:hover { transform: translateY(-6px); border-color: rgba(91,184,240,0.35); }
  .ccard:hover .ccard__media img { transform: scale(1.05); }
  .ccard:hover .ccard__more svg { transform: translateX(4px); }
  [dir="rtl"] .ccard:hover .ccard__more svg { transform: scaleX(-1) translateX(4px); }
}
.ccard__body { padding: 24px 26px 26px; display: flex; flex-direction: column; gap: 10px; flex: 1; }
.ccard__title { font-size: 22px; font-weight: 600; letter-spacing: -0.01em; }
.ccard__sum { font-size: 15px; line-height: 1.55; color: var(--muted); }
.ccard__more {
  margin-top: auto; padding-top: 14px;
  display: inline-flex; align-items: center; gap: 8px;
  font-size: 14px; font-weight: 500; color: var(--brand-300);
}
.ccard__more svg { width: 17px; height: 17px; transition: transform 0.25s var(--ease); }

/* =========================================================
   CASE STUDY — article page (case-study.html)
   ========================================================= */
.cs-page { background: var(--black); }
.cs-hero { padding: 150px 0 0; }
.cs-hero > .container > * { max-width: 720px; margin-inline: auto; }
.cs-backrow { margin-bottom: 34px; }
.cs-back {
  display: inline-flex; align-items: center; gap: 8px;
  font-size: 14px; color: var(--muted);
  transition: color 0.2s var(--ease);
}
.cs-back:hover { color: #fff; }
.cs-back svg { width: 16px; height: 16px; }
.cs-cat {
  display: inline-block;
  font-size: 11px; font-weight: 600; letter-spacing: 0.12em; text-transform: uppercase;
  padding: 6px 12px; border-radius: 999px;
  background: rgba(24,153,232,0.12); border: 1px solid rgba(91,184,240,0.35);
  color: var(--brand-200); margin-bottom: 22px;
}
.cs-title { font-size: clamp(34px, 4vw, 54px); font-weight: 500; line-height: 1.02; letter-spacing: -0.02em; }
.cs-standfirst { margin-top: 20px; font-size: 19px; line-height: 1.55; color: var(--muted); max-width: 680px; }
.cs-meta {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 18px;
  margin-top: 40px; padding-top: 26px;
  border-top: 1px solid var(--line);
}
.cs-meta dt { font-size: 11px; letter-spacing: 0.14em; text-transform: uppercase; color: var(--muted-dim); margin-bottom: 6px; }
.cs-meta dd { font-size: 15.5px; color: rgba(255,255,255,0.88); line-height: 1.5; }
.cs-cover {
  margin: 46px auto 0;
  max-width: 860px;
  border-radius: var(--radius-lg); overflow: hidden;
  border: 1px solid rgba(255,255,255,0.07);
  aspect-ratio: 16 / 9;
  background: #0a0e14;
}
.cs-hero > .container > .cs-cover { max-width: 860px; }
.cs-cover img { width: 100%; height: 100%; object-fit: cover; display: block; }
.cs-body { max-width: 720px; margin: 64px auto 0; }
.cs-body h2 { font-size: clamp(24px, 2.4vw, 32px); font-weight: 600; letter-spacing: -0.01em; margin: 44px 0 16px; color: #7cc6fb; }
.cs-body p { font-size: 17px; line-height: 1.7; color: rgba(255,255,255,0.82); margin-bottom: 16px; }
.cs-body b, .cs-body strong { font-weight: 600; color: #fff; }
.cs-body a { color: var(--brand-300); }
.cs-body a:hover { text-decoration: underline; }
.cs-list { margin: 0 0 16px; padding-inline-start: 22px; list-style: disc; }
.cs-list li { font-size: 17px; line-height: 1.7; color: rgba(255,255,255,0.82); margin-bottom: 8px; }
.cs-list li::marker { color: rgba(124,198,251,0.7); }
.cs-figure { margin: 34px 0; }
.cs-figure img { width: 100%; border-radius: var(--radius-md); border: 1px solid rgba(255,255,255,0.07); display: block; }
.cs-figure figcaption { margin-top: 10px; font-size: 13px; color: var(--muted-dim); text-align: center; }
.cs-quote {
  margin: 38px 0; padding: 26px 28px;
  border-inline-start: 3px solid var(--brand-300);
  background: rgba(24,153,232,0.06);
  border-radius: 0 var(--radius-md) var(--radius-md) 0;
}
.cs-quote blockquote { font-size: 19px; line-height: 1.55; color: rgba(255,255,255,0.92); }
.cs-quote figcaption { margin-top: 12px; font-size: 13px; color: var(--muted); }
/* provenance line under a quote's attribution - where it was originally said */
.cs-quote__src {
  display: block; margin-top: 5px;
  font-size: 12px; letter-spacing: 0.04em;
  color: var(--muted-dim);
}
.cs-statgrid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; margin: 36px 0; }
.cs-stat {
  padding: 22px 20px; border-radius: var(--radius-md);
  background: linear-gradient(160deg, rgba(20,52,80,0.45), rgba(10,28,44,0.55));
  border: 1px solid rgba(91,184,240,0.18);
}
.cs-stat b {
  display: block; font-size: 30px; font-weight: 600; letter-spacing: -0.02em;
  background: linear-gradient(100deg, #7cc6fb 0%, #35a8f4 40%, #8fd4ff 60%, #7cc6fb 100%);
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent; color: transparent;
  filter: drop-shadow(0 0 10px rgba(90,184,240,0.35));
}
.cs-stat span { display: block; font-size: 13px; color: var(--muted); margin-top: 4px; }
.cs-video {
  margin: 34px 0; aspect-ratio: 16 / 9;
  border-radius: var(--radius-md); overflow: hidden;
  border: 1px solid rgba(255,255,255,0.07); background: #0a0e14;
}
.cs-video iframe, .cs-video video { width: 100%; height: 100%; display: block; border: 0; }
.cs-cta { text-align: center; padding: 90px 0 100px; }
.cs-cta .section-title { margin-bottom: 30px; }
.cs-cta .btn { margin-inline: auto; }
.cs-foot { border-top: 1px solid var(--line); padding: 26px 0 34px; }
.cs-foot .container { display: flex; justify-content: space-between; align-items: center; gap: 20px; flex-wrap: wrap; font-size: 14px; color: rgba(255,255,255,0.55); }
.cs-foot a { color: rgba(255,255,255,0.75); transition: color 0.2s var(--ease); }
.cs-foot a:hover { color: #fff; }

/* =========================================================
   CONTACT
   ========================================================= */
.contact { background: var(--black); padding: 100px 0 120px; }
.contact__inner { display: grid; grid-template-columns: 0.9fr 1.1fr; gap: 56px; align-items: start; }
.contact__sub { margin: 22px 0 32px; font-size: 18px; line-height: 1.55; color: var(--muted); max-width: 420px; }
.contact__list { list-style: none; display: flex; flex-direction: column; gap: 16px; margin-bottom: 30px; }
.contact__list li { display: flex; align-items: center; gap: 14px; }
.contact__ico {
  display: grid; place-items: center; flex: 0 0 auto;
  width: 44px; height: 44px; border-radius: 12px;
  background: #0f0f0f; border: 1px solid rgba(255, 255, 255, 0.205); color: var(--brand-300);
}
.contact__ico svg { width: 20px; height: 20px; }
.contact__list a { font-size: 17px; color: rgba(255,255,255,0.9); }
.contact__list a:hover { color: #fff; }
.contact__socials { display: flex; gap: 12px; }
.contact__socials a {
  width: 44px; height: 44px; border-radius: 50%;
  display: grid; place-items: center;
  background: rgba(255,255,255,0.06); border: 1px solid rgba(255,255,255,0.12); color: #fff;
  transition: background 0.25s var(--ease), color 0.25s var(--ease);
}
.contact__socials a:hover { background: rgba(255,255,255,0.16); }
.contact__socials svg { width: 19px; height: 19px; }

.contact__form {
  background: #0a0e14; border: 1px solid rgba(255,255,255,0.07);
  border-radius: var(--radius-lg); padding: 34px 34px 30px;
}
.contact__form-title { font-size: 22px; font-weight: 600; margin-bottom: 22px; }
.field { display: flex; flex-direction: column; gap: 8px; margin-bottom: 18px; }
.field label { font-size: 13px; letter-spacing: 0.04em; color: var(--muted); }
.field__opt {
  font-size: 11px; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--muted-dim); margin-inline-start: 6px;
}
.field input, .field textarea {
  font-family: inherit; font-size: 15px; color: #fff;
  background: rgba(255,255,255,0.04); border: 1px solid rgba(255,255,255,0.10);
  border-radius: 10px; padding: 13px 15px; resize: vertical;
  transition: border-color 0.2s var(--ease), background 0.2s var(--ease);
}
.field input::placeholder, .field textarea::placeholder { color: rgba(255,255,255,0.32); }
.field input:focus, .field textarea:focus { outline: none; border-color: rgba(91,184,240,0.6); background: rgba(255,255,255,0.06); }
.contact__submit { width: 100%; justify-content: center; margin-top: 6px; }
.contact__note { font-size: 12.5px; color: var(--muted-dim); margin-top: 14px; text-align: center; }
/* sent state: the button itself confirms, so the feedback lands where the
   finger/cursor already is. The label is wrapped in a span by script.js so it
   can crossfade while the pill's colour transitions underneath. */
.contact__submit-label { display: inline-flex; align-items: center; gap: 10px; transition: opacity .18s ease, transform .18s ease; }
.contact__submit.is-swapping .contact__submit-label { opacity: 0; transform: translateY(4px); }
.contact__submit.is-sent,
.contact__submit.is-sent:hover { background: #3ecf8e; color: #04140c; box-shadow: 0 10px 28px rgba(62,207,142,.28); transform: none; }
.contact__submit:disabled { cursor: default; }
.contact__check { width: 18px; height: 18px; }
.contact__check path { stroke-dasharray: 24; stroke-dashoffset: 24; }
.contact__submit.is-sent .contact__check path { animation: check-draw .45s .12s var(--ease) forwards; }
@keyframes check-draw { to { stroke-dashoffset: 0; } }

/* success/error sit directly under the submit button. They are always in the
   DOM (not [hidden]) so they can animate open: grid 0fr → 1fr gives a real
   height transition without measuring, and the box styling lives on the inner
   <p> so padding/border collapse with it. */
.contact__msg {
  display: grid; grid-template-rows: 0fr;
  opacity: 0; transform: translateY(-6px);
  visibility: hidden;
  transition: grid-template-rows .45s var(--ease), opacity .35s var(--ease),
    transform .45s var(--ease), visibility 0s linear .45s;
}
.contact__msg.is-shown {
  grid-template-rows: 1fr; opacity: 1; transform: none; visibility: visible;
  transition: grid-template-rows .45s var(--ease), opacity .35s var(--ease) .08s,
    transform .45s var(--ease), visibility 0s;
}
.contact__msg > p {
  min-height: 0; overflow: hidden;
  font-size: 14.5px; text-align: center; border-radius: 10px;
}
.contact__msg.is-shown > p { margin-top: 14px; padding: 14px 16px; border: 1px solid; }
.contact__msg > p { transition: margin-top .45s var(--ease), padding .45s var(--ease); }
.contact__success > p { background: rgba(62,207,142,0.12); border-color: rgba(62,207,142,0.4); color: #8ef0c0; }
.contact__error > p { background: rgba(232,86,70,0.12); border-color: rgba(232,86,70,0.42); color: #ffab9f; }
.contact__error a { color: inherit; text-decoration: underline; }
@media (prefers-reduced-motion: reduce) {
  .contact__msg, .contact__msg.is-shown, .contact__msg > p, .contact__submit-label { transition: none; }
  .contact__submit.is-sent .contact__check path { animation: none; stroke-dashoffset: 0; }
}

/* =========================================================
   BENEFITS
   ========================================================= */
.benefits {
  position: relative;
  padding: 120px 0 130px;
  /* no overflow:hidden here — it would disable position:sticky on the pinned title */
  background:
    radial-gradient(80% 70% at 20% 60%, rgba(35,134,218,0.35), transparent 55%),
    linear-gradient(150deg, #188ae8 0%, #1584de 48%, #1164b4 100%);
}
.benefits__disc {
  position: absolute; top: 24px; left: 40%;
  width: 220px; height: 260px;
  background: radial-gradient(circle at 50% 40%, rgba(200,230,255,0.6), transparent 68%);
  filter: blur(6px);
}
.benefits__inner {
  position: relative; z-index: 3;
  display: grid; grid-template-columns: 1fr 1fr; gap: 50px; align-items: start;
}
.benefits__left {
  position: sticky;         /* heading stays pinned while the cards scroll */
  top: 120px;
  align-self: start;
}
.benefits__left .section-title { margin-top: 24px; line-height: 1.06; }
.benefits__stats { display: flex; flex-direction: column; gap: 22px; }
.stat {
  border-radius: var(--radius-lg);
  padding: 34px 34px 30px;
  min-height: 240px;
  display: flex; flex-direction: column; justify-content: space-between;
}
.stat--light { background: #fff; color: #0b0b0c; }
.stat--dark {                /* navy glassmorphism — matches the site's blue system */
  background: linear-gradient(160deg, rgba(20,52,80,0.55), rgba(10,28,44,0.62));
  border: 1px solid rgba(91,184,240,0.18);
  backdrop-filter: blur(18px);
  -webkit-backdrop-filter: blur(18px);
  color: #fff;
}
.stat__num { font-size: clamp(48px, 6vw, 78px); font-weight: 500; letter-spacing: -0.03em; line-height: 1; }
.stat__num span { font-weight: 500; }
.stat__label { font-size: 18px; }
.stat--light .stat__label { color: #0b0b0c; }

/* =========================================================
   TESTIMONIALS
   ========================================================= */
.testimonials { background: var(--black); padding: 110px 0 130px; }
.testimonials__head { text-align: center; margin-bottom: 60px; }
.testimonials__head .section-title { margin-top: 22px; font-size: clamp(38px, 4.6vw, 62px); }
.testimonials__grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 28px; }
.tcard {
  background: #0a0d12;
  border: 1px solid rgba(255,255,255,0.05);
  border-radius: var(--radius-md);
  padding: 30px;
  min-height: 395px;
  /* head + logo stack from the top; the quote is pushed to the bottom edge by
     its own auto margin, which keeps quotes baseline-aligned across the row
     the way justify-content:space-between did before the logo was added */
  display: flex; flex-direction: column;
  transition: transform .4s var(--ease), border-color .4s var(--ease);
}
.tcard:hover { transform: translateY(-4px); border-color: rgba(255,255,255,0.12); }
.tcard__head { display: flex; align-items: center; gap: 16px; }
.tavatar { width: 64px; height: 64px; border-radius: 50%; flex: 0 0 auto; background-size: cover; }
.tcard__name { font-size: 21px; font-weight: 500; letter-spacing: -0.01em; }
.tcard__role { font-size: 12px; letter-spacing: 0.14em; text-transform: uppercase; color: var(--muted); margin-top: 5px; }
/* client logo — forced to flat white because these cards are near-black and the
   partner artwork is full-colour: ESTL sits at 2.03:1 on #0a0d12 and all but
   vanishes. brightness(0) invert(1) takes any logo to 19.5:1 regardless of its
   source colour, and keeps the card monochrome instead of adding a colour spot.
   Left edge lines up with the avatar (both sit on the card's padding edge). */
.tcard__logo {
  display: block;
  /* Sized per logo via --logo-h because the source PNGs carry different amounts
     of transparent padding, and object-fit:contain fits the whole canvas — not
     the ink. ESTL's mark fills only 52% of its canvas height, so a shared box
     painted it at half the size of Diego's (which fills 100%). Measured ink
     fractions: ESTL .52, Diego 1.0, Marist .89 — the per-logo values below
     divide through those so the *visible* marks land at a matched optical size,
     with the wide lockup kept slightly shorter than the squarer marks. */
  height: var(--logo-h, 46px); width: auto; max-width: 170px;
  object-fit: contain; object-position: left center;
  margin-top: 20px;
  filter: brightness(0) invert(1);
  opacity: 0.7;
  transition: opacity .3s var(--ease);
}
.tcard:hover .tcard__logo { opacity: 0.9; }
.tcard__role b { color: var(--brand-300); font-weight: 500; }
.tcard blockquote { font-size: 18px; line-height: 1.55; color: rgba(255,255,255,0.9); margin-top: auto; padding-top: 26px; }

/* =========================================================
   TEAM — Our Team (founders)
   ========================================================= */
/* sits in the black "proof" zone between testimonials and contact, so it
   borrows the .tcard recipe (near-black fill, hairline border) rather than the
   frosted glass used by cards on the blue field — glass has nothing to refract
   against here. */
/* the top used to be 20px, tuned for Testimonials sitting above with its own
   130px of black. With Testimonials hidden, Team opens straight off the blue
   Impact section and "Our Team" landed 48px under the colour edge; 110px puts
   the eyebrow ~138px down, same as Services and Portfolio. The bottom stays
   trimmed because Contact below opens on 100px. If Testimonials comes back,
   drop the top to ~20px again. */
.team { background: var(--black); padding: 110px 0 40px; }
.team__head { text-align: center; margin-bottom: 60px; }
.team__head .section-title { margin-top: 22px; }
/* as wide as the card row, so on desktop the subtitle reads as one line in all
   three languages (FR is the longest, ~865px); balance keeps any narrower wrap even */
.team__sub {
  max-width: 1020px; margin: 22px auto 0; font-size: 18px; line-height: 1.55; color: var(--muted);
  text-wrap: balance;
}
/* capped so three portrait cards keep their tall proportion instead of
   stretching wide at 1280 — cards land ~321px, close to a 3:4 frame */
.team__grid {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 28px;
  max-width: 1020px; margin-inline: auto;
}
.tmcard {
  position: relative;
  border-radius: var(--radius-lg);
  transition: transform .45s var(--ease);
}
.tmcard:focus { outline: none; }
/* :has(:focus-visible), never :focus-within -- a mouse click focuses the
   LinkedIn link (or the tabindex card itself), and :focus-within then held the
   hover state open after the pointer left, e.g. on coming back from the
   LinkedIn tab. :focus-visible only matches keyboard focus. */
.tmcard:hover, .tmcard:focus-visible, .tmcard:has(:focus-visible) { transform: translateY(-10px) scale(1.03); }

/* ---- resting state: portrait frame with the name over a scrim ---- */
.tmcard__frame {
  position: relative; overflow: hidden;
  aspect-ratio: 3 / 4;
  border-radius: inherit;
  border: 1px solid rgba(255,255,255,0.08);
  background: #0a0d12;
}
.tmcard__media { position: absolute; inset: 0; display: grid; place-items: center; }
.tmcard__media--1 { background: linear-gradient(165deg, #9fd4f7 0%, #2d7bb4 45%, #0d2c44 100%); }
.tmcard__media--2 { background: linear-gradient(165deg, #d6eefd 0%, #4b93bd 45%, #0b2438 100%); }
.tmcard__media--3 { background: linear-gradient(165deg, #5bb8f0 0%, #1d6ba5 45%, #082033 100%); }
/* placeholder until real portraits exist — sized to read as a deliberate
   monogram panel rather than a missing image */
.tmcard__mono {
  font-size: 84px; font-weight: 600; letter-spacing: 0.03em;
  color: rgba(255,255,255,0.34);
  text-shadow: 0 2px 24px rgba(4,16,26,0.4);
  transform: translateY(-8%);
}
/* portraits stay in natural colour -- they're transparent cutouts, so the
   blue .tmcard__media--N gradient behind them is the backdrop; nothing is laid
   over the photo itself */
.tmcard__photo {
  width: 100%; height: 100%; object-fit: cover; object-position: top center;
  display: block;
}
/* bottom scrim so the name stays legible over any portrait */
.tmcard__scrim {
  position: absolute; inset: auto 0 0 0; height: 62%;
  background: linear-gradient(180deg, rgba(4,10,18,0) 0%, rgba(4,10,18,0.72) 58%, rgba(4,10,18,0.94) 100%);
}
/* bottom padding clears the pinned LinkedIn pill: 26 edge + 30 pill + 14 gap */
.tmcard__rest {
  position: absolute; inset: auto 0 0 0; z-index: 2;
  padding: 0 24px 70px;
  transition: opacity .35s var(--ease), transform .45s var(--ease);
}
.tmcard:hover .tmcard__rest, .tmcard:focus-visible .tmcard__rest,
.tmcard:has(:focus-visible) .tmcard__rest {
  opacity: 0; transform: translateY(10px);
}

/* ---- hover state: blue panel, name at the top, bio at the bottom ---- */
/* bottom padding leaves the pill's spot free, so the bio ends just above it */
.tmcard__panel {
  position: absolute; inset: 0; z-index: 3;
  display: flex; flex-direction: column; justify-content: space-between;
  padding: 30px 26px 72px;
  border-radius: inherit; overflow: hidden;
  background: linear-gradient(170deg, #1a6fb5 0%, #0d4273 48%, #072a47 100%);
  border: 1px solid rgba(91,184,240,0.45);
  box-shadow: 0 26px 60px rgba(4,16,26,0.55), inset 0 1px 0 rgba(255,255,255,0.12);
  opacity: 0; pointer-events: none;
  transition: opacity .4s var(--ease);
}
/* pointer-events flips with opacity so the panel's own content takes the hover.
   :has(:focus-visible) keeps it open while the LinkedIn link holds keyboard
   focus -- tabbing to the link reads the same as pointing at the card. */
.tmcard:hover .tmcard__panel,
.tmcard:focus-visible .tmcard__panel,
.tmcard:has(:focus-visible) .tmcard__panel { opacity: 1; pointer-events: auto; }
/* same decorative grid the Approach cards use, so the panel reads as part of
   the existing card family rather than a new surface */
.tmcard__grid {
  position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background-image:
    linear-gradient(rgba(255,255,255,0.08) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255,255,255,0.08) 1px, transparent 1px);
  background-size: 38px 38px;
  -webkit-mask-image: radial-gradient(72% 62% at 50% 42%, #000, transparent 76%);
  mask-image: radial-gradient(72% 62% at 50% 42%, #000, transparent 76%);
}
/* name settles down from the top, bio rises from the bottom, so the swap reads
   as the card reorganising rather than two layers blinking */
.tmcard__phead, .tmcard__bio {
  position: relative; z-index: 1;
  transition: transform .45s var(--ease);
}
.tmcard__phead { transform: translateY(-8px); }
.tmcard__bio { transform: translateY(8px); }
.tmcard:hover .tmcard__phead, .tmcard:focus-visible .tmcard__phead,
.tmcard:has(:focus-visible) .tmcard__phead,
.tmcard:hover .tmcard__bio,   .tmcard:focus-visible .tmcard__bio,
.tmcard:has(:focus-visible) .tmcard__bio { transform: translateY(0); }

.tmcard__name { font-size: 22px; font-weight: 500; letter-spacing: -0.01em; line-height: 1.2; }
/* the "Co-Founder ·" lead never breaks mid-phrase (Arabic "شريك مؤسِّس" was
   splitting across lines); balance evens out whatever wraps after it */
.tmcard__role {
  font-size: 11px; letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--brand-300); margin-top: 8px;
  text-wrap: balance;
}
.tmcard__role-lead { white-space: nowrap; }
.tmcard__panel .tmcard__role { color: rgba(191,228,251,0.9); }
.tmcard__bio { font-size: 14.5px; line-height: 1.6; color: rgba(255,255,255,0.86); }

/* ---- LinkedIn pill, pinned under the title in both states ---- */
/* its own layer above the panel (z 4 > 3): it sits under the role on the
   portrait, and when the panel fades in over the face it stays exactly where it
   was -- the bio ends just above it -- so the pointer never chases it.
   outlined rather than solid: it has to read over a dark scrim and the saturated
   blue panel alike, and a filled button would out-shout the name. */
.tmcard__li {
  position: absolute; z-index: 4;
  inset-inline-start: 24px; bottom: 26px;
  height: 30px; box-sizing: border-box;
  display: inline-flex; align-items: center; gap: 7px;
  padding: 0 14px 0 11px;
  border-radius: 999px;
  border: 1px solid rgba(255,255,255,0.30);
  background: rgba(255,255,255,0.10);
  color: #fff;
  font-size: 12.5px; font-weight: 500; line-height: 1; letter-spacing: 0.01em;
  transition: background .25s var(--ease), border-color .25s var(--ease),
              color .25s var(--ease), transform .25s var(--ease);
}
.tmcard__li svg { width: 14px; height: 14px; flex: none; }
/* inverts to white on hover so it reads as the one actionable thing on the card */
.tmcard__li:hover { background: #fff; border-color: #fff; color: #0d4273; transform: translateY(-1px); }
.tmcard__li:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }

/* =========================================================
   CTA + FOOTER
   ========================================================= */
.cta { position: relative; overflow: hidden; padding: 100px 0 32px; min-height: 520px; display: flex; align-items: flex-start; }
.cta__bg {
  position: absolute; inset: 0; z-index: 0;
  background:
    radial-gradient(90% 80% at 50% 30%, rgba(39,142,226,0.5), transparent 55%),
    linear-gradient(160deg, #188ae8 0%, #1584de 45%, #1164b4 100%);
}
.cta__inner { position: relative; z-index: 5; width: 100%; display: flex; flex-direction: column; min-height: 440px; }
.cta__top { margin-top: 88px; }
.cta__title { font-size: clamp(38px, 5vw, 68px); font-weight: 500; line-height: 1.0; letter-spacing: -0.03em; }
/* wrap is the safety net for the tablet band: at ~834px the French pair of
   buttons is ~27px wider than the column. It never triggers on desktop. */
.cta__actions { display: flex; flex-wrap: wrap; gap: 14px; margin-top: 34px; }

.footer {
  margin-top: auto;
  display: grid; grid-template-columns: 1fr auto; gap: 40px;
  align-items: end;
  padding-top: 28px;
}
.footer__name { font-size: 22px; font-weight: 600; }
.footer__mail { font-size: 16px; color: rgba(255,255,255,0.8); margin-top: 10px; display: inline-block; }
.footer__mail:hover { color: #fff; }
.footer__cols { display: flex; gap: 80px; }
.footer__col { display: flex; flex-direction: column; gap: 12px; }
.footer__col-h { font-size: 17px; margin-bottom: 6px; }
.footer__col a { font-size: 15px; color: rgba(255,255,255,0.7); transition: color .2s; }
.footer__col a:hover { color: #fff; }
.footer__copy {
  grid-column: 1 / -1;
  margin-top: 14px;
  padding-top: 18px;
  border-top: 1px solid rgba(255,255,255,0.10);
  font-size: 14px;
  color: rgba(255,255,255,0.55);
}

/* =========================================================
   REVEAL ANIMATION
   ========================================================= */
.reveal { opacity: 0; transform: translateY(28px); transition: opacity 0.8s var(--ease), transform 0.8s var(--ease); }
.reveal.is-in { opacity: 1; transform: none; }
.reveal[data-delay="1"] { transition-delay: 0.12s; }
.reveal[data-delay="2"] { transition-delay: 0.24s; }
/* The hero is the page's Largest Contentful Paint, so it can't wait for script.js
   to add .is-in - on a slow phone that held the heading back ~2.5s. Pure CSS, so
   it starts on the first frame; shorter and closer than .reveal because it plays
   while the page is still settling, where a long tail reads as sluggish. */
.hero__enter { animation: heroEnter 0.55s var(--ease) both; }
.hero__enter--late { animation-delay: 0.08s; }
@keyframes heroEnter { from { opacity: 0; transform: translateY(16px); } }
@media (prefers-reduced-motion: reduce) {
  .reveal { opacity: 1; transform: none; transition: none; }
  .hero__enter { animation: none; }
  .partners__track, .about__panel::after, .hero__word { animation: none !important; }
  html.smooth-scroll { scroll-behavior: auto; }
}

/* =========================================================
   RESPONSIVE
   ========================================================= */
/* narrow laptops / big tablets in landscape: the desktop nav is still the
   right call here, but at full size the French labels ("Demander une
   consultation gratuite") leave no slack, so trim the type and padding. */
@media (min-width: 1025px) and (max-width: 1180px) {
  .nav__inner { gap: 12px; }
  .nav__pill { gap: 2px; padding: 6px; }
  .nav__pill a { font-size: 14px; padding: 8px 11px; }
  .nav__cta { font-size: 14px; padding-block: 10px; padding-inline: 16px 13px; }
  .nav__lang { font-size: 13px; padding: 9px 11px; }
}

@media (max-width: 1024px) {
  :root { --pad: 28px; }

  /* hero: drop the forced full-viewport height, single column, CTAs restored */
  .hero { min-height: auto; padding: 130px 0 76px; }
  .hero__content { grid-template-columns: 1fr; align-items: start; gap: 26px; }
  .hero__right { margin-inline-start: 0; max-width: none; }
  .hero-dash { display: none; } /* 6-panel dashboard too dense for narrow screens */
  .hero__actions {
    display: flex; flex-direction: column; align-items: stretch;
    gap: 12px; margin-top: 28px; max-width: 400px;
  }
  .hero__actions .btn { width: 100%; justify-content: center; }

  .about__intro { grid-template-columns: 1fr; }
  .about__lead { margin-inline-start: 0; }
  .about__values { grid-template-columns: 1fr; }
  .collage { grid-template-columns: 1fr 1fr; grid-auto-rows: 140px; }
  .collage__item--tall { grid-row: span 1; }
  .collage__item--wide { grid-column: span 2; }
  .testimonials__grid { grid-template-columns: 1fr; max-width: 520px; margin-inline: auto; }
  .cases__grid { grid-template-columns: 1fr; max-width: 520px; margin-inline: auto; }
  /* narrower than the other one-column grids — at 520px a 3:4 portrait card
     would stand ~690px tall and swamp the viewport */
  .team__grid { grid-template-columns: 1fr; max-width: 380px; margin-inline: auto; }
  .benefits__inner { grid-template-columns: 1fr; }
  .benefits__left { position: static; }
  .process__strip { grid-template-columns: repeat(2, 1fr); }
  .contact__inner { grid-template-columns: 1fr; gap: 44px; }
  .contact__sub { max-width: none; }
}

/* --- nav: the burger takes over for the whole tablet range ------------------
   The desktop nav (logo + 4 links + FR + CTA) needs ~1100px to sit on one
   line. Below that the pill squeezed its labels onto 2-3 lines and, in
   French, pushed the CTA clean off the right edge -- so the burger now takes
   over at the same 1024px breakpoint where the page already goes one-column.
   These are the rules that used to live in the 820px block. ---------------- */
@media (max-width: 1024px) {
  /* --- nav: one floating liquid-glass bar holding logo, FR and burger
     (same glass recipe as the desktop .nav__pill) --- */
  .nav__pill, .nav__cta { display: none; }
  .nav__burger { display: flex; }
  .nav, .nav.is-scrolled { padding: 10px 0; padding-top: calc(10px + env(safe-area-inset-top)); }
  .nav__inner {
    margin-inline: 12px;
    padding-block: 7px; padding-inline: 18px 7px;
    gap: 8px;
    border-radius: 30px;
    background: linear-gradient(180deg, rgba(255,255,255,0.26) 0%, rgba(255,255,255,0.10) 100%);
    backdrop-filter: blur(18px) saturate(1.7);
    -webkit-backdrop-filter: blur(18px) saturate(1.7);
    border: 1px solid rgba(255,255,255,0.30);
    box-shadow:
      inset 0 1px 0 rgba(255,255,255,0.6),
      inset 0 -8px 14px rgba(255,255,255,0.04),
      0 8px 22px rgba(4,16,26,0.20);
    transition: border-radius 0.3s var(--ease), background 0.3s var(--ease);
    will-change: transform;
  }
  /* once content scrolls under it, a light navy tint keeps the logo legible */
  .nav.is-scrolled .nav__inner {
    background:
      linear-gradient(180deg, rgba(255,255,255,0.22) 0%, rgba(255,255,255,0.08) 100%),
      rgba(9,30,48,0.38);
  }
  /* FR + burger sit inside the bar, so they drop their own glass */
  .nav__lang, .nav__burger {
    width: 44px; height: 44px; padding: 0;
    border-radius: 999px;
    background: rgba(255,255,255,0.14);
    border: 1px solid rgba(255,255,255,0.22);
    box-shadow: inset 0 1px 0 rgba(255,255,255,0.35);
    backdrop-filter: none; -webkit-backdrop-filter: none;
    will-change: auto;
  }
  /* open: the bar grows into a darker panel so the links stay readable */
  .nav.is-open .nav__inner {
    flex-wrap: wrap; row-gap: 6px;
    border-radius: 26px;
    padding-bottom: 12px;
    background: rgba(9,30,48,0.92);
  }
  .nav.is-open .nav__pill {
    display: flex; order: 3; flex-basis: calc(100% - 11px); margin-block: 4px 0; margin-inline: 0 11px;
    flex-direction: column; align-items: stretch; gap: 2px; padding: 6px 0 2px;
    border-radius: 0;
    background: none; border: none; box-shadow: none;
    border-top: 1px solid rgba(255,255,255,0.12);
    backdrop-filter: none; -webkit-backdrop-filter: none;
    animation: menuIn 0.35s var(--ease);
  }
  .nav.is-open .nav__pill a { padding: 14px 12px; font-size: 16px; }
  .nav.is-open .nav__cta { display: inline-flex; order: 4; flex-basis: calc(100% - 11px); margin-inline-end: 11px; justify-content: center; padding: 15px; }
  @keyframes menuIn { from { opacity: 0; transform: translateY(-8px); } }
  .nav.is-open .nav__burger span:first-child { transform: translateY(3.5px) rotate(45deg); }
  .nav.is-open .nav__burger span:last-child { transform: translateY(-3.5px) rotate(-45deg); }

}

@media (max-width: 820px) {
  .hero { padding-top: 116px; }
  /* headlines: the tight desktop leading reads cramped at phone sizes.
     every top-level title shares the hero's 1.12 so the whole page matches
     (.benefits__left override + .cs-title listed by name — they'd otherwise
     win on specificity / live on the case-study page). */
  .hero__title,
  .section-title,
  .benefits__left .section-title,
  .cs-title,
  .cta__title { line-height: 1.12; }
  /* lighter gradient + a soft glow so the word never sinks into the dark bg.
     background-image (not the shorthand) — the shorthand resets background-clip
     back to border-box and the gradient paints a solid block over the text. */
  .hero__word {
    background-image: linear-gradient(100deg, #bfe4fb 0%, #7cc6fb 38%, #eaf6fe 58%, #bfe4fb 100%);
    filter: drop-shadow(0 0 10px rgba(140,210,255,0.55)) drop-shadow(0 0 22px rgba(90,184,240,0.35));
  }
  /* let hand-placed line breaks wrap naturally on phones */
  .hero__subtitle br, .partners .section-title br { display: none; }

  /* --- hero CTAs: regular-width buttons, left aligned (not edge-to-edge) --- */
  .hero__actions {
    flex-direction: row; flex-wrap: wrap;
    align-items: center; justify-content: flex-start;
    max-width: none; gap: 10px;
  }
  .hero__actions .btn { width: auto; }

  /* --- services: single column + artwork moved into normal flow (fixes overlap) --- */
  .services__inner { grid-template-columns: 1fr; gap: 30px; }
  .services__sticky { position: static; }
  .scard { position: relative; top: 0; min-height: 0; padding: 28px 28px 30px; }
  .scard__grid { -webkit-mask-image: none; mask-image: none; background-image: none; flex: 0 0 auto; margin: 2px 0; }
  .scard__art {
    position: static; display: block;
    width: 74%; max-width: 300px; height: auto;
    margin: 14px auto 6px;
    transform: none; top: auto; inset-inline-end: auto;
  }
  .scard__desc { max-width: none; }
  .scard__art--cc { width: 88%; max-width: 340px; }  /* PNG has extra transparent padding */

  /* --- process: descriptions always visible (no hover on touch) --- */
  .pstep { min-height: 0; }
  .pstep__desc { max-height: none; opacity: 1; margin-top: 14px; transform: none; overflow: visible; }
  .pstep__ico { transform: none; }
  /* step number moves to the top-right, on the same line as the icon —
     stacked above the icon it had no breathing room */
  .pstep__n {
    position: absolute; z-index: 2;
    top: 32px; inset-inline-end: 30px;
    font-size: 44px; line-height: 46px;  /* 46px matches the icon box height */
  }

  /* --- Who We Are: CTAs live in the hero and the footer already --- */
  .about__actions { display: none; }
  /* with the buttons gone the title's 30px bottom margin + the grid's 40px row
     gap left ~70px of dead space above the paragraph — collapse to the 22px
     title→lead rhythm the other sections use */
  .about__copy .section-title { margin-bottom: 0; }
  .about__intro { gap: 22px; }

  /* --- footer CTA: regular-width buttons, left aligned --- */
  .cta__actions {
    flex-direction: row; flex-wrap: wrap;
    align-items: center; justify-content: flex-start; gap: 10px;
  }
  .cta__actions .btn { width: auto; justify-content: center; }
  .about__panel { padding: 40px 0 42px; }
  .about__panel::after { padding: 2px; }

  /* --- founders: split cards instead of full-height portraits ---
     a full-width 3:4 portrait per founder ran ~580px each (the section stood
     ~2050px, mostly empty monogram gradient). Phones get a half-and-half card in
     the contact-form recipe: a rounded portrait tile inset in the left half,
     name/role/LinkedIn centred in the other half. The bio is dropped
     here -- the role line already says what each founder does, and desktop
     keeps the full text on hover.
     .tmcard__frame / __panel / __ptop dissolve with display: contents so their
     children can be placed straight onto the card's grid -- no markup fork. */
  .team__head { text-align: start; margin-bottom: 36px; }
  .team__head .eyebrow--center { text-align: start; }
  .team__head .section-title--center { text-align: start; }
  .team__sub { margin-inline: 0; font-size: 17px; }
  .team__grid { max-width: none; gap: 14px; }
  /* the 1fr rows above and below centre the name + LinkedIn block vertically
     against the portrait, whatever height the role wraps to */
  .tmcard {
    display: grid;
    grid-template-columns: 1fr 1fr;
    grid-template-rows: 1fr auto auto 1fr;
    grid-template-areas: "media ." "media head" "media li" "media .";
    column-gap: 18px;
    padding: 12px;
    padding-inline-end: 16px;
    background: #0a0e14;
    border: 1px solid rgba(255,255,255,0.07);
  }
  .tmcard:hover, .tmcard:focus-visible, .tmcard:has(:focus-visible) { transform: none; }
  .tmcard__frame, .tmcard__panel { display: contents; }
  /* inset tile, not edge-to-edge: the gap to the card edge keeps it reading as
     a portrait frame. 2:3 for a properly vertical rectangle; photos are
     object-fit: cover from the top, so the desktop 3:4 crop just loses a sliver
     at the sides. Radius 10 sits inside the card's 18 with the 12px gap. */
  .tmcard__media {
    position: relative; grid-area: media;
    aspect-ratio: 2 / 3;
    border-radius: 10px; overflow: hidden;
  }
  .tmcard__mono { font-size: 44px; transform: none; color: rgba(255,255,255,0.42); }
  .tmcard__scrim, .tmcard__grid, .tmcard__phead, .tmcard__bio { display: none; }
  /* every desktop fade-out selector listed, or a sticky touch :hover / keyboard
     focus would fade the name out from under your thumb */
  .tmcard__rest,
  .tmcard:hover .tmcard__rest, .tmcard:focus-visible .tmcard__rest,
  .tmcard:has(:focus-visible) .tmcard__rest {
    position: static; grid-area: head;
    padding: 0; opacity: 1; transform: none;
  }
  .tmcard__name { font-size: 19px; }
  .tmcard__role { font-size: 10.5px; margin-top: 6px; line-height: 1.5; }
  /* the half-width column can't fit every title on one line (Arabic), so give
     all of them one shape: "Co-Founder" on its own line, the role underneath.
     Stacked, the separator dot would dangle at the line end, so it goes. */
  .tmcard__role-lead { display: block; }
  .tmcard__role-sep { display: none; }
  /* back into flow: on desktop it's pinned absolutely over the portrait */
  .tmcard__li {
    position: static; grid-area: li; justify-self: start;
    margin-top: 14px;
    border-color: rgba(255,255,255,0.22); background: rgba(255,255,255,0.06);
    color: rgba(255,255,255,0.9);
  }

  /* --- impact: compact 2x2 grid instead of a tall stack --- */
  .benefits__stats { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
  .stat { min-height: 150px; padding: 22px 20px 20px; }
  .stat__num { font-size: clamp(32px, 8vw, 52px); }
  .stat__label { font-size: 15px; }
  /* vertical gradient — same hero-blue family as desktop. Must resolve to the
     page black: Testimonials below is #000, and stopping on mid-blue left a hard
     horizontal seam between the two sections on tall, narrow viewports. */
  .benefits {
    background:
      radial-gradient(95% 45% at 30% 18%, rgba(35,134,218,0.30), transparent 60%),
      linear-gradient(180deg, #188ae8 0%, #1584de 42%, #146fbe 68%, #0a3766 86%, #000 100%);
  }

  /* --- contact form: 16px inputs prevent iOS zoom-jump --- */
  .field input, .field textarea { font-size: 16px; }
  .contact__form { padding: 28px 24px 26px; }

  /* --- case study page --- */
  .cs-hero { padding-top: 120px; }
  .cs-meta { grid-template-columns: 1fr 1fr; }
  .cs-statgrid { grid-template-columns: 1fr; }
  .cs-cover { aspect-ratio: 16 / 10; }

  /* --- CTA + footer: no decorative emptiness; clear the home-indicator --- */
  .cta { min-height: auto; padding: 88px 0 calc(32px + env(safe-area-inset-bottom)); }
  .cta__inner { min-height: auto; }
  .cta__top { margin-top: 44px; }
  .footer { grid-template-columns: 1fr; align-items: start; }
  .footer__cols { gap: 50px; }
  .footer__col { gap: 15px; }
  /* larger CTA + footer type and buttons on phones */
  .cta__title { font-size: clamp(44px, 11.5vw, 60px); }
  .cta__actions { gap: 12px; margin-top: 38px; }
  .cta__actions .btn { font-size: 17px; padding: 17px 24px; }
  .footer { padding-top: 40px; gap: 44px; }
  .footer__name { font-size: 26px; }
  .footer__mail { font-size: 18px; }
  .footer__col-h { font-size: 20px; margin-bottom: 8px; }
  .footer__col a { font-size: 18px; }
  .footer__copy { font-size: 15px; }
  .partners { padding: 74px 0 60px; }
  /* smaller tiles cover less ground per second, so the loop runs quicker */
  .partners__track { animation-duration: 24s; }
  /* Who We Are: shorter paragraph variants */
  .txt-long { display: none; }
  .txt-short { display: inline; }

  /* --- phones: cheaper glass so scrolling stays smooth on mid-range devices ---
     backdrop-filter re-blurs whatever is behind an element on every scroll frame.
     The cards and buttons sit on smooth gradients, where the blur is close to
     invisible, so they drop it entirely. The nav floats over busy content and keeps
     a lighter blur. The per-element GPU layers (will-change, see "rendering
     stability") only existed to stop blur seams, so they go too - on a phone
     they cost graphics memory. The grain texture blends over whole sections. */
  .about__panel, .scard, .pstep, .stat--dark, .plogo,
  .btn--glass, .btn--glass-dark, .hdash__panel,
  .pcard__cat {   /* category chips on the portfolio and case-study photos: 72% opaque */
    backdrop-filter: none; -webkit-backdrop-filter: none;
  }
  .nav__inner, .nav__pill, .nav__burger, .nav__lang, .nav__langmenu {
    backdrop-filter: blur(10px) saturate(1.5); -webkit-backdrop-filter: blur(10px) saturate(1.5);
  }
  /* the WhatsApp button is ~90% opaque green - the blur behind it never showed.
     .nav prefix: the button's own rule comes later in this file */
  .nav .nav__wa { backdrop-filter: none; -webkit-backdrop-filter: none; }
  .pstep, .scard, .stat--dark, .about__panel, .plogo,
  .nav__pill, .nav__lang, .nav__burger, .btn--glass, .btn--glass-dark,
  .hdash__panel {
    will-change: auto;
  }
  /* Grain, minus the expensive part. mix-blend-mode: overlay makes the phone
     recombine the texture with everything under it on every scroll frame; the
     texture itself is cheap. So phones get noise that carries its speckle in the
     alpha channel (feColorMatrix moves the turbulence into alpha over white) and
     composites normally: it lightens like overlay did, breaking the banding on
     the big blue gradients, with no per-frame work. */
  .grain {
    mix-blend-mode: normal;
    opacity: 0.1;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='matrix' values='0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 1 0 0 0 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  }
  .grain--soft { opacity: 0.07; }
  /* "Marketing" shine: background-position on clipped text plus a drop-shadow
     can't be composited, so it repaints every frame while it runs. Phones keep
     the shimmer (the user wants it) but start it after the hero entrance has
     finished, so the two don't compete during the first, busiest second.
     .hero.is-offscreen pauses it once the visitor scrolls past. */
  .hero__word { animation-delay: 0.75s; }
}

@media (max-width: 520px) {
  :root { --pad: 20px; }
  .hero__title { font-size: 44px; }
  .section-title { font-size: 32px; }
  .btn { font-size: 15px; padding: 14px 18px; }
  .plogo { width: 120px; height: 120px; padding: 22px; }
  .plogo--lg { padding: 11px 8px; }
  .footer__cols { gap: 34px; }
  .process__strip { grid-template-columns: 1fr; }
  .portfolio__head { flex-direction: column; align-items: flex-start; gap: 16px; }
  .pcard { width: 80vw; max-width: 330px; }
  /* the fixed 250px height made a near-square box that cropped ~25% off the
     sides of the 16:10 portfolio covers; match their ratio instead */
  .pcard__media { height: auto; aspect-ratio: 16 / 10; }
  .cs-meta { grid-template-columns: 1fr; }
}


/* =========================================================
   WhatsApp — "Start a Conversation"
   Same liquid-glass recipe as .nav__pill / .nav__lang, tinted
   WhatsApp green. --wa-a1/--wa-a2 drive the tint opacity so the
   button can go airier over colour and denser over black, where
   a translucent green would otherwise read muddy.
   Mobile only in the header; every other placement shows the label.
   ========================================================= */
:root { --wa: 37, 211, 102; --wa-deep: 29, 168, 81; }

.nav__wa, .btn--wa {
  --wa-a1: 0.92;
  --wa-a2: 0.80;
  color: #fff;
  background:
    linear-gradient(180deg, rgba(255,255,255,0.16) 0%, rgba(255,255,255,0.02) 100%),
    linear-gradient(180deg, rgba(var(--wa), var(--wa-a1)) 0%, rgba(var(--wa-deep), var(--wa-a2)) 100%);
  backdrop-filter: blur(18px) saturate(1.7);
  -webkit-backdrop-filter: blur(18px) saturate(1.7);
  border: 1px solid rgba(255,255,255,0.34);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.55),
    inset 0 -8px 14px rgba(255,255,255,0.05),
    0 8px 22px rgba(16,120,60,0.26);
}
.nav__wa:hover, .btn--wa:hover {
  --wa-a1: 1;
  --wa-a2: 0.90;
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.6),
    0 12px 28px rgba(16,120,60,0.34);
}

/* header: icon only, and mobile only — desktop keeps the consultation CTA alone */
.nav__wa {
  display: none;
  align-items: center; justify-content: center;
  flex: 0 0 auto;
  width: 42px; height: 42px;
  border-radius: 999px;
  transition: transform 0.35s var(--ease), background 0.3s var(--ease),
    box-shadow 0.35s var(--ease);
}
.nav__wa svg { width: 21px; height: 21px; }
.nav__wa:hover { transform: translateY(-2px); }

/* full-label button — 1px less padding so the border keeps it the
   same height as the solid .btn siblings beside it */
.btn--wa { padding: 14px 21px; }
.btn--wa svg { width: 20px; height: 20px; flex: 0 0 auto; }

/* the "Or reach us directly" rule under the contact form's submit button */
.contact__alt { display: flex; align-items: center; gap: 12px; margin: 18px 0 14px; }
.contact__alt span { flex: 1; height: 1px; background: rgba(255,255,255,0.16); }
.contact__alt em {
  font-style: normal; font-size: 12.5px; letter-spacing: 0.02em;
  color: var(--muted-dim); white-space: nowrap;
}
.contact__wa { width: 100%; justify-content: center; }

/* over black there is nothing for the blur to pick up, so the tint
   carries the colour on its own */
.contact__wa, .cs-cta .btn--wa {
  --wa-a1: 0.96;
  --wa-a2: 0.88;
  backdrop-filter: none; -webkit-backdrop-filter: none;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.4), 0 8px 22px rgba(16,120,60,0.22);
}
.contact__wa:hover, .cs-cta .btn--wa:hover { --wa-a1: 1; --wa-a2: 0.94; }

/* the case-study closing block holds two buttons now: a flex row so they
   sit side by side and stretch to a common height (the consultation button
   is taller on its own — the arrow pill sets its height) */
.cs-cta__actions {
  display: flex; justify-content: center; align-items: stretch;
  flex-wrap: wrap; gap: 14px;
}
.cs-cta__actions .btn { margin: 0; }

@media (max-width: 820px) {
  /* rides inside the floating glass bar, between FR and the burger.
     that bar already follows the page, so this is the persistent
     WhatsApp entry point on phones — no separate floating bubble. */
  .nav__wa { display: inline-flex; width: 44px; height: 44px; }
}
@media (max-width: 380px) {
  /* three round buttons + logo get tight on the smallest phones */
  .nav__lang, .nav__burger, .nav__wa { width: 40px; height: 40px; }
  .nav__wa svg { width: 19px; height: 19px; }
}


/* =========================================================
   Arabic
   Applies wherever the document (or a subtree) is marked lang="ar".
   The <head> of an Arabic page must also load the face:

     <link rel="preconnect" href="https://fonts.googleapis.com">
     <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
     <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=IBM+Plex+Sans+Arabic:wght@400;500;600&display=swap">

   It is deliberately NOT loaded on the English and French pages -- they have no
   Arabic glyphs to set, so it would be a download for nothing.
   ========================================================= */
/* body sets --font directly, so matching only the <html lang="ar"> element loses
   to it on the way down -- body has to be named too. */
[lang="ar"],
[lang="ar"] body {
  font-family: var(--font-ar);
  /* Arabic needs more leading than Latin: no capitals to anchor the line, and
     the dots and diacritics sit outside the main band. */
  line-height: 1.75;
}

/* 1.75 is right for a paragraph and wrong for everything else. These set no
   line-height of their own, so in English they take the browser default (~1.2)
   and on Arabic pages they were inheriting body copy leading instead -- 1.75 on a
   27px card title, and on the 84px team monogram a line box 147px tall. The cost
   is mostly vertical: cards grow, and titles like "تسويق وتنظيم الفعاليات" fall
   apart once they wrap at narrower widths. Still looser than Latin would take,
   just not paragraph-loose. */
[lang="ar"] .scard__title,
[lang="ar"] .vcard__title,
[lang="ar"] .pcard__title,
[lang="ar"] .ccard__title,
[lang="ar"] .contact__form-title,
[lang="ar"] .tcard__name,
/* the impact figures carry a lot of visual weight, and at 18px/400 the Arabic
   label under them read as a footnote rather than as what the number counts */
[lang="ar"] .stat__label      { line-height: 1.35; font-size: 21px; font-weight: 500; }
/* a pill and a display glyph, both sized by their own box */
[lang="ar"] .pcard__cat       { line-height: 1.2; }
[lang="ar"] .tmcard__mono     { line-height: 1; }
/* Latin/number runs the bidi algorithm must not reorder. A phone number is the
   worst offender: "+212 7 00 08 25 31" renders as "31 25 08 00 7 212+" inside an
   RTL paragraph, because each space-separated group is reordered right-to-left.
   Isolating the run pins it back to left-to-right. Apply to phone numbers, emails,
   URLs and any figure carrying a leading or trailing sign. */
[lang="ar"] .ltr,
[lang="ar"] [dir="ltr"] {
  direction: ltr;
  unicode-bidi: isolate;
}
/* The big figures are designed as "40+" and "480,000+". The sign is a neutral
   character, so at the end of an RTL run bidi moves it to the far side and the
   number reads "+40" -- which an Arabic reader parses as "positive 40" rather
   than "40 or more". Pin the whole figure so the sign stays where it was set. */
[lang="ar"] .stat__num,
[lang="ar"] .cs-stat b {
  direction: ltr;
  unicode-bidi: isolate;
  /* direction:ltr is only here to stop bidi reordering "40+" into "+40" -- but it
     also flips what text-align:start means, so the figure was landing on the LEFT
     edge of a right-aligned card while its label sat on the right. Pin it back to
     the reading edge; the digits keep their own left-to-right run inside. */
  text-align: right;
}
/* The contact details are the textbook case from the note above: without this,
   "+212 7 00 08 25 31" renders as "31 25 08 00 7 212+". Matched by href/type so
   no class has to be added to the English markup. Inputs keep their text on the
   right so the field still lines up with the rest of the form. */
[lang="ar"] a[href^="tel:"],
[lang="ar"] a[href^="mailto:"] {
  direction: ltr;
  unicode-bidi: isolate;
}
[lang="ar"] input[type="tel"],
[lang="ar"] input[type="email"] {
  direction: ltr;
  text-align: right;
}

/* Display leading. The big titles run 0.96-1.06 in English, which works because
   Latin caps have a flat top and a shallow descender. Arabic stacks dots above
   (ن ت ث) and below (ب ي ج) the letter band, so at that leading the marks from one
   line very nearly touch the next.

   A first pass added +0.12 and it was not enough: at 42px a two-liner like
   "حين تتحوّل الاستراتيجية / إلى أثر قابل للقياس." still closed up, because the ج
   and ق tails on the upper line reach down into the ل and أ below. Display Arabic
   wants roughly 1.3 where Latin display takes 1.0. Each title still keeps its own
   designed value -- the hero tightest, the sticky benefits heading loosest -- the
   whole set is just shifted up. */
[lang="ar"] .hero__title                { line-height: 1.22; }
[lang="ar"] .section-title              { line-height: 1.32; }
[lang="ar"] .benefits__left .section-title { line-height: 1.36; }
[lang="ar"] .cs-title                   { line-height: 1.32; }
[lang="ar"] .cta__title                 { line-height: 1.28; }
/* The phone tier up at 820px already loosens every title to a shared 1.12, but it
   does that with plain class selectors -- these attribute selectors outrank them,
   and a media query adds no specificity of its own. Left alone, the desktop values
   above would follow Arabic onto phones and land TIGHTER than the English does
   there. This has to live below them to win on source order. */
@media (max-width: 820px) {
  [lang="ar"] .hero__title,
  [lang="ar"] .section-title,
  [lang="ar"] .benefits__left .section-title,
  [lang="ar"] .cs-title,
  [lang="ar"] .cta__title { line-height: 1.38; }
  /* same story as the titles: the phone tier drops .stat__label to 15px with a
     plain class, which this attribute selector would otherwise outrank and leave
     Arabic at the full 21px on a narrow card */
  [lang="ar"] .stat__label { font-size: 17px; }
}

/* Arabic has no letter case, so uppercasing and tracking do nothing but damage
   -- they break the joins between letters. */
[lang="ar"] .eyebrow,
[lang="ar"] .cs-cat,
[lang="ar"] .pcard__cat,
[lang="ar"] .cs-meta dt,
[lang="ar"] .field label,
[lang="ar"] .field__opt,
[lang="ar"] .tcard__role,
[lang="ar"] .tmcard__role {
  text-transform: none;
  letter-spacing: 0;
}

/* ...which leaves them too small. These sizes were chosen for Latin uppercase:
   at 13px "WHO WE ARE" puts a solid 10px cap-height band on the page and 0.22em
   of tracking spreads it across 83px. Arabic has no capitals, carries much of its
   height in dots and descenders, and has just given up the tracking -- so at the
   same 13px "من نحن" measures 8px tall and 41px wide and reads as a caption
   rather than a section label.

   Matching the Latin cap-height exactly (~1.22x) was still too quiet in place, and
   so was 1.45x. Azzam asked for 26px, which is twice the English size: at that
   point the eyebrow stops being a caption over the heading and becomes a small
   heading of its own, so it carries 600 rather than 500 to hold that weight. It
   keeps the English 75% white though -- full white was tried at this size and read
   as too hard against the heading. Arabic labels stay shorter than their English
   counterparts whatever the size, which is the script being compact, not a defect:
   the fix for width would be tracking, and tracking is the one thing Arabic must
   not have. */
[lang="ar"] .eyebrow {
  font-size: 26px;
  font-weight: 600;
  /* colour deliberately NOT overridden: it inherits the English rgba(255,255,255,
     0.75), which holds the eyebrow back from the solid-white section title. Full
     white was tried and read as too hard next to the heading. */
  margin-bottom: 32px;
}
[lang="ar"] .eyebrow b     { font-weight: 600; }
[lang="ar"] .eyebrow--sm   { font-size: 23px; margin-bottom: 28px; }

/* The chips and role labels share the eyebrow's design language but not its job --
   a pill sitting on a card image can't take 26px without dominating the card, so
   they get a smaller lift and keep their weight. */
[lang="ar"] .cs-cat,
[lang="ar"] .pcard__cat    { font-size: 18px; }
[lang="ar"] .tcard__role,
[lang="ar"] .tmcard__role  { font-size: 17px; }
[lang="ar"] .cs-stat span  { font-size: 16px; }

/* These three can't take the full 1.45x: each one labels something, and a label
   that matches or outgrows its own value inverts the hierarchy. Held just under
   the thing they describe -- dd is 15.5px, the input is 15px, and .field__opt
   rides inline beside the label it qualifies. */
[lang="ar"] .cs-meta dt    { font-size: 14px; }
[lang="ar"] .field label   { font-size: 15.5px; }
[lang="ar"] .field__opt    { font-size: 13.5px; }

/* =========================================================
   RTL
   Everything above uses logical properties, which flip on their own. These are
   the cases that cannot: transforms have no logical form, and a chevron has to
   be mirrored rather than repositioned.
   Hooked to dir="rtl" rather than lang="ar" -- direction is the actual concern.
   ========================================================= */

/* chevrons point the other way */
[dir="rtl"] .arrow::before,
[dir="rtl"] .pf-arrow svg,
[dir="rtl"] .pcard__more svg,
[dir="rtl"] .ccard__more svg { transform: scaleX(-1); }

/* the nudge-on-hover has to travel the other way too. On .ccard__more the
   mirror is already applied, so a positive translateX now moves it leftward --
   order matters here. */
[dir="rtl"] .btn:hover .arrow { transform: translateX(-2px); }
/* (the .ccard nudge lives with the card, inside its hover media query) */

/* the growing bars must anchor to the right edge */
[dir="rtl"] .hdash__bar { transform-origin: right center; }

/* the logo marquee: the track is laid out right-to-left, so it has to travel
   the opposite way or the logos scroll away from their own start point */
[dir="rtl"] .partners__track { animation-name: marquee-rtl; }
@keyframes marquee-rtl { to { transform: translateX(50%); } }

/* Service-card artwork stays on the right in Arabic instead of mirroring with the
   rest of the layout. Two reasons: Azzam wants it there, and .scard__grid's glow is
   a radial MASK -- a background, which direction never flips -- so its focal point
   sits at 75% (the right) whatever the direction. Mirroring the art to the left
   pulled it out from under its own halo and left the glow lighting empty grid.
   Under dir=rtl, inset-inline-start resolves to the right edge, so these keep the
   same offsets the English design uses, just measured from the other side. */
[dir="rtl"] .scard__art {
  inset-inline-end: auto;
  inset-inline-start: 16%;
}
[dir="rtl"] .scard__art--wide { inset-inline-start: 6%; }

/* =========================================================
   WIDE SCREENS  (min-width tiers)
   The layout is desktop-first against a 1280px container, so past ~1400px
   the content column stops growing and the page reads as a narrow strip
   with dead margins on both sides. These tiers widen the shell and lift the
   type caps in step, so the proportions hold and only the scale changes.
   Everything keys off --container / --pad, so the nav, the hero dashboard
   rail and the horizontal card rails follow automatically.
   ========================================================= */
@media (min-width: 1500px) {
  :root { --container: 1400px; --pad: 52px; }

  .hero__title    { font-size: clamp(46px, 6.4vw, 96px); }
  .hero__subtitle { max-width: 500px; }
  .hero__right    { max-width: 580px; }

  .section-title  { font-size: clamp(34px, 4.1vw, 62px); }
  .cta__title     { font-size: clamp(38px, 5vw, 74px); }
  .stat__num      { font-size: clamp(48px, 6vw, 84px); }
}

@media (min-width: 1800px) {
  :root { --container: 1560px; --pad: 64px; }

  .hero__title    { font-size: 104px; }
  .hero__subtitle { max-width: 540px; font-size: 22px; }
  .hero__right    { max-width: 640px; }
  .hero-dash      { width: clamp(380px, 50vw, 800px); }

  .section-title  { font-size: 68px; }
  .cta__title     { font-size: 80px; }
  .stat__num      { font-size: 88px; }
}

/* 4K / ultrawide — one last step so the margins don't run away again */
@media (min-width: 2200px) {
  :root { --container: 1760px; --pad: 72px; }

  .hero__title    { font-size: 116px; }
  .hero-dash      { width: clamp(380px, 46vw, 900px); }
  .section-title  { font-size: 74px; }
  .cta__title     { font-size: 88px; }
}
