/* ============================================================
   CONCORD MANAGEMENT CONSULTANCY
   Ivory & black editorial system — vanilla CSS, no build step.
   Order: tokens → reset → type → primitives → layout → sections
   ============================================================ */

/* ---------- 1. Tokens ---------- */
:root {
  /* Palette — ivory + black only. No third colour. */
  --ink:        #0A0A0A;
  --ink-2:      #16150F;
  --ivory:      #F5F2E9;
  --ivory-2:    #EDE9DC;
  --muted:      #33312A;   /* body text on ivory - darkened for readability */
  --muted-inv:  #D9D5C9;   /* body text on ink   - lightened for readability */
  --line:       rgba(10, 10, 10, .16);
  --line-soft:  rgba(10, 10, 10, .08);
  --line-inv:   rgba(245, 242, 233, .18);
  --line-inv-soft: rgba(245, 242, 233, .09);

  /* Type.
     Sabon is a licensed desktop/web font and is not served by Google Fonts.
     It is listed first so it is used wherever it is installed or self-hosted;
     EB Garamond (same Garamond lineage) carries the design everywhere else.
     See README → "Fonts" to self-host the real Sabon. */
  --font-display: "Sabon", "Sabon Next LT", "Sabon LT Std", "EB Garamond", Georgia, "Times New Roman", serif;
  --font-sans: "Jost", "Futura", "Century Gothic", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;

  /* Type scale */
  --fs-display-1: clamp(2.4rem, 11.5vw, 10.5rem);
  --fs-display-2: clamp(2.9rem, 7vw, 6rem);
  --fs-display-3: clamp(2.1rem, 3.9vw, 3.35rem);
  --fs-h3:        clamp(1.35rem, 2vw, 1.75rem);
  --fs-lede:      clamp(1.18rem, 1.5vw, 1.48rem);
  --fs-body:      clamp(1.06rem, 1.15vw, 1.18rem);
  /* Running prose is ONE size. This used to be 1rem against --fs-body's
     ~1.06rem, and a 1px difference does not read as hierarchy - it reads as a
     mistake, which is exactly how it looked with a .pillar__desc sitting next
     to a plain <p>. Every consumer of this token is a description, a bio, a
     list item or a link, so they all belong at body size. The deliberate step
     up is --fs-lede for section intros; that one is far enough away to be
     legible as a choice. */
  --fs-small:     var(--fs-body);
  --fs-micro:     .84rem;   /* uppercase labels and buttons                      */
  --fs-nav:       .8rem;    /* nav bar only, so micro cannot crowd it            */
  --fs-eyebrow:   clamp(.86rem, 1vw, 1rem);

  /* Spacing scale */
  --sp-1: .5rem;   --sp-2: .875rem; --sp-3: 1.25rem; --sp-4: 2rem;
  --sp-5: 3rem;    --sp-6: 4.5rem;  --sp-7: 7rem;    --sp-8: 10rem;
  --section-y: clamp(5rem, 11vw, 10.5rem);
  --gutter: clamp(1.25rem, 5vw, 5rem);
  --shell: 1440px;

  /* Consistent geometry — this brand is sharp, not rounded. */
  --radius: 0px;
  --radius-sm: 0px;
  --border: 1px;

  --shadow-1: 0 1px 2px rgba(10,10,10,.05);
  --shadow-2: 0 18px 48px -24px rgba(10,10,10,.35);

  /* Motion */
  --ease: cubic-bezier(.22, .61, .36, 1);
  --ease-out: cubic-bezier(.16, 1, .3, 1);
  --dur-1: .3s;
  --dur-2: .6s;
  --dur-3: .9s;
  --dur-page-in: .85s;    /* content fading in on first load */
  --dur-page: 1s;         /* cross-fade between pages        */
  --ease-soft: cubic-bezier(.33, 0, .18, 1);

  --header-h: 84px;
}

/* ---------- 2. Reset ---------- */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: var(--header-h);
}

body {
  background: var(--ivory);
  color: var(--ink);
  font-family: var(--font-sans);
  font-size: var(--fs-body);
  font-weight: 300;
  line-height: 1.7;
  letter-spacing: .005em;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
}

img, svg, video { display: block; max-width: 100%; }
img { height: auto; }
button, input, textarea, select { font: inherit; color: inherit; }
button { background: none; border: 0; cursor: pointer; }
ul, ol { list-style: none; padding: 0; }
a { color: inherit; text-decoration: none; }
hr { border: 0; border-top: var(--border) solid var(--line); }

:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 3px;
}
.section--dark :focus-visible,
.site-footer :focus-visible { outline-color: var(--ivory); }

::selection { background: var(--ink); color: var(--ivory); }
.section--dark ::selection, .site-footer ::selection { background: var(--ivory); color: var(--ink); }

.skip-link {
  position: fixed; top: -100px; left: var(--gutter); z-index: 200;
  background: var(--ink); color: var(--ivory);
  padding: .75rem 1.25rem;
  font-size: var(--fs-micro); letter-spacing: .18em; text-transform: uppercase;
  transition: top var(--dur-1) var(--ease);
}
.skip-link:focus { top: 1rem; }

.sprite { position: absolute; width: 0; height: 0; overflow: hidden; }

/* ---------- 3. Typography ---------- */
.display {
  font-family: var(--font-display);
  font-weight: 400;
  line-height: .95;
  letter-spacing: -.02em;
  text-wrap: balance;
}
.display em { font-style: italic; }
/* .95 is set on .display for the huge one-or-two-line hero type, where tight
   leading is the point. A heading that runs to three lines at 60px+ needs the
   lines to stop touching - "Doha-rooted. Gulf-focused. Future-ready." was
   the case that showed it. */
.display--2 { font-size: var(--fs-display-2); line-height: 1.08; }
.display--3 { font-size: var(--fs-display-3); line-height: 1.05; }

.lede {
  font-size: var(--fs-lede);
  line-height: 1.62;
  color: var(--muted);
}
.section--dark .lede { color: var(--muted-inv); }

p { color: var(--muted); }
.section--dark p { color: var(--muted-inv); }

.eyebrow {
  /* flex is kept so the existing alignment holds; the gap went with the
     marker, since there is no longer a second item to sit beside. */
  display: flex; align-items: center;
  font-size: var(--fs-eyebrow);
  font-weight: 600;
  letter-spacing: .22em;
  text-transform: uppercase;
  color: var(--ink);
}
.eyebrow--light { color: var(--ivory); }

.link-arrow {
  display: inline-flex; align-items: center; gap: .6rem;
  font-size: var(--fs-small); font-weight: 500;
  letter-spacing: .16em; text-transform: uppercase;
  padding-bottom: .35rem;
  border-bottom: var(--border) solid var(--line);
  transition: border-color var(--dur-1) var(--ease), gap var(--dur-1) var(--ease);
}
.link-arrow__ico { transition: transform var(--dur-2) var(--ease-out); }
.link-arrow:hover { border-color: currentColor; }
.link-arrow:hover .link-arrow__ico { transform: translateX(5px); }

/* ---------- 4. Layout primitives ---------- */
.shell {
  width: 100%;
  max-width: var(--shell);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.section { padding-block: var(--section-y); position: relative; }
.section--dark { background: var(--ink); color: var(--ivory); }

/* A hairline for the one place two same-toned sections must sit together.
   why-concord.html has six content sections bookended by a dark hero and a
   dark CTA band. With both ends fixed dark and six slots between them, strict
   alternation is arithmetically impossible - one repeat is forced. Given the
   choice, the repeat goes between two IVORY sections rather than producing
   three consecutive blacks running into the footer. This rule gives that one
   join a visible edge so it still reads as two sections. */
.section--divided { border-top: var(--border) solid var(--line); }
.section--dark + .section--divided { border-top-color: transparent; }
.section--dark .display { color: var(--ivory); }

/* 62ch is a reading measure - it belongs to the intro paragraph, not to the
   heading. Applying it to the whole block capped the heading at ~679px and
   forced "The founders behind every engagement." onto two lines. The intro
   keeps its own 52ch below, so the measure is preserved where it matters. */
.section__head { margin-bottom: clamp(3rem, 6vw, 5.5rem); }
/* Every section title aligns to the reading direction: left in English, right
   in Arabic. `start` rather than `left` is what makes that automatic. The
   --center class stays in the markup so nothing else has to change, but it no
   longer centres - mixing centred and left-aligned titles read as an error. */
.section__head--center { margin-inline: 0; text-align: start; }
.section__head--center .eyebrow { justify-content: flex-start; }
.section__head .display { margin-top: var(--sp-3); }
.section__intro { margin-top: var(--sp-3); max-width: 52ch; }
.section__head--center .section__intro { margin-inline: 0; }

/* ---------- 5. Buttons ---------- */
.btn {
  --btn-bg: transparent;
  --btn-fg: currentColor;
  --btn-bd: currentColor;
  position: relative;
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 52px;
  padding: .9rem 2.1rem;
  border: var(--border) solid var(--btn-bd);
  background: var(--btn-bg);
  color: var(--btn-fg);
  font-size: var(--fs-micro);
  font-weight: 500;
  letter-spacing: .2em;
  text-transform: uppercase;
  overflow: hidden;
  isolation: isolate;
  transition: color var(--dur-2) var(--ease), border-color var(--dur-2) var(--ease);
}
/* wipe fill on hover — one shared treatment across the site */
.btn::after {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background: var(--btn-fill, var(--ivory));
  transform: scaleY(0); transform-origin: bottom;
  transition: transform var(--dur-2) var(--ease-out);
}
.btn:hover::after, .btn:focus-visible::after { transform: scaleY(1); }

.btn--solid { --btn-bg: var(--ivory); --btn-fg: var(--ink); --btn-bd: var(--ivory); --btn-fill: transparent; }
.btn--solid:hover, .btn--solid:focus-visible { color: var(--ivory); background: transparent; }

.btn--ghost { --btn-fg: var(--ivory); --btn-bd: rgba(245,242,233,.5); --btn-fill: var(--ivory); }
.btn--ghost:hover, .btn--ghost:focus-visible { color: var(--ink); border-color: var(--ivory); }

.btn--dark { --btn-bg: var(--ink); --btn-fg: var(--ivory); --btn-bd: var(--ink); --btn-fill: transparent; }
.btn--dark:hover, .btn--dark:focus-visible { color: var(--ink); background: transparent; }

/* --- Glimmer: the two actions we actually want people to take -------------
   A slow light sweep across the face, same idea as the hamburger so the site
   has one "this is a control" signal rather than two.

   .btn already owns ::after for the hover wipe (z-index:-1 under an
   `isolation: isolate` context), so the sweep uses ::before. Both sit at
   z-index -1; ::after paints later, which is what we want - hovering wipes
   the fill straight over the glimmer instead of the two fighting.

   .btn also already sets overflow:hidden, so the sweep clips to the border
   box on its own. The gradient is light, so this belongs on the dark-faced
   buttons (--ghost over dark sections, --dark on the form); on an ivory
   --solid button it would be invisible, which is why it is opt-in per button
   rather than applied to .btn. */
.btn--glimmer::before {
  content: ""; position: absolute; top: 0; left: -60%;
  width: 45%; height: 100%;
  z-index: -1;
  pointer-events: none;
  background: linear-gradient(100deg,
    rgba(245, 242, 233, 0) 0%,
    rgba(245, 242, 233, .3) 50%,
    rgba(245, 242, 233, 0) 100%);
  animation: btn-glimmer 4.6s var(--ease) infinite;
}
/* Holds off-screen for most of the cycle, so it reads as an occasional
   catch of light rather than a barber's pole. */
@keyframes btn-glimmer {
  0%   { left: -60%; }
  45%  { left: 115%; }
  100% { left: 115%; }
}
/* Arabic reads right-to-left, so the sweep travels the other way: it should
   follow the eye across the label, not run against it. The gradient angle is
   mirrored too (100deg -> 80deg) so the leading edge stays the leading edge. */
[dir="rtl"] .btn--glimmer::before {
  animation-name: btn-glimmer-rtl;
  background: linear-gradient(80deg,
    rgba(245, 242, 233, 0) 0%,
    rgba(245, 242, 233, .3) 50%,
    rgba(245, 242, 233, 0) 100%);
}
@keyframes btn-glimmer-rtl {
  0%   { left: 115%; }
  45%  { left: -60%; }
  100% { left: -60%; }
}
/* While the hover fill is up, the sweep would be crossing a solid panel that
   is about to be the opposite colour - stop it and let the wipe read cleanly. */
.btn--glimmer:hover::before,
.btn--glimmer:focus-visible::before { animation-play-state: paused; opacity: 0; }

/* ---------- 6. Header & navigation ---------- */
.scroll-progress {
  position: fixed; inset: 0 0 auto 0; z-index: 120;
  height: 2px; pointer-events: none;
}
.scroll-progress span {
  display: block; height: 100%; width: 100%;
  background: var(--ivory);
  transform: scaleX(0); transform-origin: left;
  opacity: 0;
  transition: opacity var(--dur-2) var(--ease);
}
.scroll-progress.is-on span { opacity: 1; }

.site-header {
  position: fixed; inset: 0 0 auto 0; z-index: 110;
  color: var(--ivory);
  /* black liquid glass — translucent ink + blur, at every scroll position */
  background: rgba(10, 10, 10, .72);
  backdrop-filter: blur(24px) saturate(1.5);
  -webkit-backdrop-filter: blur(24px) saturate(1.5);
  border-bottom: var(--border) solid rgba(245, 242, 233, .10);
  transition: background var(--dur-2) var(--ease), border-color var(--dur-2) var(--ease);
}
/* no backdrop-filter (older Firefox): fall back to solid ink so it is never see-through */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .site-header { background: rgba(10, 10, 10, .94); }
}
.header__inner {
  /* deliberately NOT .shell — on a 2560px screen a centred 1440px bar leaves the
     logo stranded mid-air. Full bleed, gutter padding, logo pinned left. */
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--sp-4);
  width: 100%;
  padding-inline: var(--gutter);
  min-height: var(--header-h);
}
.header__right {
  display: flex; align-items: center;
  gap: clamp(1.25rem, 2.4vw, 2.75rem);
}

/* transparent-over-hero → solid on scroll */
.site-header { color: var(--ivory); }
.site-header.is-stuck {
  /* over ivory sections it has to read as black, not grey */
  background: rgba(10, 10, 10, .90);
  border-bottom-color: rgba(245, 242, 233, .16);
}

.logo { display: flex; align-items: center; gap: .8rem; }
.logo__mark {
  width: auto; height: 52px;
  fill: currentColor;
  flex: none;
}
.logo__type { display: grid; gap: .18em; }
.logo__name {
  /* max-content on both lockup lines: they are grid items, and a stretched
     item reports the COLUMN width, not its own text width. Measuring that
     would feed the sub-line's width back in as its own target. */
  width: max-content;
  font-family: var(--font-display);
  font-size: 1.62rem; font-weight: 400;
  letter-spacing: .16em; text-transform: uppercase;
  line-height: 1;
}
.logo__sub {
  /* width:max-content so the box hugs the text - main.js measures this and
     then tunes tracking (Latin) or size (Arabic) so the sub-line ends up
     exactly as wide as the wordmark above it. */
  width: max-content;
  font-size: .64rem; font-weight: 400;
  letter-spacing: .3em; text-transform: uppercase;
  line-height: 1; opacity: .82;
}
/* Until the script runs, keep it from looking obviously mismatched. */
.logo__type { align-items: start; }

.nav__list { display: flex; align-items: center; gap: clamp(1.2rem, 2.4vw, 2.6rem); }
.nav__link {
  position: relative;
  display: block;
  padding: .5rem 0;
  font-size: var(--fs-nav);
  font-weight: 400;
  letter-spacing: .2em;
  text-transform: uppercase;
  opacity: .88;
  transition: opacity var(--dur-1) var(--ease);
}
.nav__link::after {
  content: ""; position: absolute; left: 0; bottom: 0;
  width: 100%; height: 1px; background: currentColor;
  transform: scaleX(0); transform-origin: right;
  transition: transform var(--dur-2) var(--ease-out);
}
.nav__link:hover, .nav__link.is-active { opacity: 1; }
.nav__link:hover::after, .nav__link.is-active::after { transform: scaleX(1); transform-origin: left; }

.burger { display: inline-flex; align-items: center; gap: .6rem; padding: .5rem 0; min-height: 44px; }
.burger__box { display: block; width: 26px; height: 12px; position: relative; }
.burger__box i {
  position: absolute; left: 0; width: 100%; height: 1px; background: currentColor;
  transition: transform var(--dur-2) var(--ease-out), opacity var(--dur-1) var(--ease);
}
.burger__box i:first-child { top: 0; }
.burger__box i:last-child { bottom: 0; }
.burger[aria-expanded="true"] .burger__box i:first-child { transform: translateY(5.5px) rotate(45deg); }
.burger[aria-expanded="true"] .burger__box i:last-child { transform: translateY(-5.5px) rotate(-45deg); }


/* ---------- 7. Hero ---------- */
.hero {
  position: relative;
  min-height: 100vh;   /* fallback */
  min-height: 100svh;  /* avoids the mobile URL-bar jump */
  display: flex; align-items: flex-end;
  padding-block: calc(var(--header-h) + 3rem) clamp(5rem, 12vh, 8rem);
  background: var(--ink);           /* fallback if the photo is missing */
  color: var(--ivory);
  overflow: hidden;
}
.hero__media { position: absolute; inset: 0; z-index: 0; }

/* Fallback backdrop: a stone-arch silhouette drawn in CSS, visible when
   assets/hero-arches.jpg is absent or still loading. */
.hero__media::before {
  content: ""; position: absolute; inset: 0;
  background-color: #14120E;
  background-image: url("data:image/svg+xml,%3Csvg%20xmlns=%22http://www.w3.org/2000/svg%22%20viewBox=%220%200%201600%201000%22%20preserveAspectRatio=%22xMidYMid%20slice%22%3E%3Cdefs%3E%3ClinearGradient%20id=%22s%22%20x1=%220%22%20y1=%220%22%20x2=%220%22%20y2=%221%22%3E%3Cstop%20offset=%220%22%20stop-color=%22%234A4335%22/%3E%3Cstop%20offset=%22.6%22%20stop-color=%22%232B2620%22/%3E%3Cstop%20offset=%221%22%20stop-color=%22%231A1713%22/%3E%3C/linearGradient%3E%3ClinearGradient%20id=%22t%22%20x1=%220%22%20y1=%220%22%20x2=%220%22%20y2=%221%22%3E%3Cstop%20offset=%220%22%20stop-color=%22%238A8069%22%20stop-opacity=%22.8%22/%3E%3Cstop%20offset=%221%22%20stop-color=%22%233A342A%22%20stop-opacity=%22.95%22/%3E%3C/linearGradient%3E%3CradialGradient%20id=%22glow%22%20cx=%22.5%22%20cy=%22.62%22%20r=%22.55%22%3E%3Cstop%20offset=%220%22%20stop-color=%22%236B5F45%22%20stop-opacity=%22.55%22/%3E%3Cstop%20offset=%221%22%20stop-color=%22%236B5F45%22%20stop-opacity=%220%22/%3E%3C/radialGradient%3E%3C/defs%3E%3Crect%20width=%221600%22%20height=%221000%22%20fill=%22url(%23s)%22/%3E%3Crect%20width=%221600%22%20height=%221000%22%20fill=%22url(%23glow)%22/%3E%3Cg%20fill=%22url(%23t)%22%3E%3Crect%20x=%22120%22%20y=%22470%22%20width=%22120%22%20height=%22530%22/%3E%3Crect%20x=%22250%22%20y=%22330%22%20width=%22150%22%20height=%22670%22/%3E%3Crect%20x=%22390%22%20y=%22540%22%20width=%22100%22%20height=%22460%22/%3E%3Crect%20x=%22660%22%20y=%22300%22%20width=%22130%22%20height=%22700%22/%3E%3Crect%20x=%22790%22%20y=%22190%22%20width=%22160%22%20height=%22810%22/%3E%3Crect%20x=%22950%22%20y=%22410%22%20width=%22120%22%20height=%22590%22/%3E%3Crect%20x=%221180%22%20y=%22360%22%20width=%22140%22%20height=%22640%22/%3E%3Crect%20x=%221330%22%20y=%22240%22%20width=%22150%22%20height=%22760%22/%3E%3Crect%20x=%221480%22%20y=%22500%22%20width=%22110%22%20height=%22500%22/%3E%3C/g%3E%3Cpath%20d=%22M0%200H1600V1000H0ZM80%201000L80%20520Q80%20255%20280%20165Q480%20255%20480%20520L480%201000ZM600%201000L600%20520Q600%20255%20800%20165Q1000%20255%201000%20520L1000%201000ZM1120%201000L1120%20520Q1120%20255%201320%20165Q1520%20255%201520%20520L1520%201000Z%22%20fill=%22%230C0B09%22%20fill-rule=%22evenodd%22/%3E%3C/svg%3E");
  background-size: cover;
  background-position: center;
}
.hero__img {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover; object-position: center 55%;
  opacity: 0;
  transform: scale(1.06);
  transition: opacity 1.1s var(--ease), transform 1.4s var(--ease-out);
  will-change: transform;
}
.hero__img.is-loaded { opacity: 1; transform: scale(1); }

/* Gradient scrim — guarantees headline contrast over any photograph. */
.hero__scrim {
  position: absolute; inset: 0;
  background:
    linear-gradient(180deg,
      rgba(10,10,10,.72) 0%,
      rgba(10,10,10,.34) 26%,
      rgba(10,10,10,.42) 52%,
      rgba(10,10,10,.86) 88%,
      rgba(10,10,10,.94) 100%),
    linear-gradient(94deg, rgba(10,10,10,.62) 0%, rgba(10,10,10,.12) 62%, rgba(10,10,10,.34) 100%);
}
.hero__grain {
  position: absolute; inset: 0; opacity: .3; 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='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)' opacity='.42'/%3E%3C/svg%3E");
}

.hero__inner { position: relative; z-index: 1; width: 100%; }

.hero__title {
  font-family: var(--font-display);
  font-size: var(--fs-display-1);
  font-weight: 400;
  line-height: .86;
  letter-spacing: -.012em;
  text-transform: uppercase;
  margin-block: clamp(1.2rem, 3vw, 2.2rem) clamp(1.6rem, 3vw, 2.4rem);
}
/* overflow:hidden is what lets each word rise out of its own line box. The
   display face reports more descent than the .86 line-height allows, so the
   box needs padding or it clips the glyph ink. */
.hero__title .line { display: block; overflow: hidden; padding-bottom: .26em; }
.hero__title .line > span { display: block; }

/* Outlined display word. Solid fill is the fallback; the stroke is applied
   only where -webkit-text-stroke is actually supported. */
.outline { color: var(--ivory); }
@supports (-webkit-text-stroke: 1px currentColor) {
  .outline {
    color: transparent;
    -webkit-text-stroke: clamp(1.3px, .17vw, 2.6px) var(--ivory);
    paint-order: stroke fill;
  }
}

.hero__lede {
  max-width: 46ch;
  font-size: var(--fs-lede);
  color: rgba(245, 242, 233, .93);
}
.hero__actions { display: flex; flex-wrap: wrap; gap: var(--sp-2); margin-top: clamp(2rem, 4vw, 3rem); }


/* ---------- 8. About ---------- */
.about__grid {
  display: grid;
  grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
  grid-template-areas: "head body" "head stat";
  column-gap: clamp(2rem, 7vw, 7rem);
  row-gap: clamp(2.5rem, 5vw, 4rem);
  align-items: start;
}
/* Sticks while its body column scrolls, matching .split__aside. Without this
   the home page's opening heading was the only one on the site that scrolled
   away with its text - every other section keeps its heading in view. */
.about__head { grid-area: head; position: sticky; top: calc(var(--header-h) + 2rem); align-self: start; }
.about__body { grid-area: body; display: grid; gap: var(--sp-3); justify-items: start; }
.about__body .link-arrow { margin-top: var(--sp-2); }
.about__head .display { margin-top: var(--sp-3); }

.stat {
  grid-area: stat;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: center;
  gap: clamp(1.5rem, 4vw, 3.25rem);
  margin-top: var(--sp-3);
  background: var(--ink);
  color: var(--ivory);
  padding: clamp(1.75rem, 3vw, 2.75rem);
  border-radius: var(--radius);
  box-shadow: var(--shadow-2);
}
.stat__aside { display: grid; }
.stat__figure {
  font-family: var(--font-display);
  font-size: clamp(3.75rem, 7vw, 6rem);
  line-height: .9; letter-spacing: -.04em;
  color: var(--ivory);
  display: flex; align-items: flex-start;
}
.stat__unit { font-size: .42em; margin-top: .28em; margin-left: .06em; opacity: .6; }
.stat__label {
  font-size: var(--fs-micro); font-weight: 500;
  letter-spacing: .26em; text-transform: uppercase;
  color: var(--ivory);
}
.stat__rule { margin-block: var(--sp-2); border-top-color: var(--line-inv); }
.stat__note { font-size: var(--fs-small); color: var(--muted-inv); max-width: 42ch; }

/* ---------- 9. Services ---------- */
/* Hairline grid: one shared rule between cells, no boxed cards. */
.grid-services {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--border);
  background: var(--line-inv-soft);
  border-block: var(--border) solid var(--line-inv-soft);
}
.svc { background: var(--ink); }
.svc__btn {
  position: relative;
  display: grid;
  gap: var(--sp-3);
  width: 100%;
  min-height: 268px;
  padding: clamp(1.75rem, 2.6vw, 2.75rem);
  text-align: left;
  color: var(--ivory);
  grid-template-rows: 1fr auto;
  isolation: isolate;
  transition: color var(--dur-2) var(--ease);
}
.svc__btn::before {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background: var(--ivory);
  transform: scaleY(0); transform-origin: bottom;
  transition: transform var(--dur-2) var(--ease-out);
}
.svc__btn:hover, .svc__btn:focus-visible { color: var(--ink); }
.svc__btn:hover::before, .svc__btn:focus-visible::before { transform: scaleY(1); }


.svc__body { display: grid; gap: .6rem; align-content: start; }
.svc__title {
  font-family: var(--font-display);
  font-size: var(--fs-h3);
  letter-spacing: .01em;
  line-height: 1.2;
}
.svc__desc { font-size: var(--fs-small); color: var(--muted-inv); transition: color var(--dur-2) var(--ease); max-width: 34ch; }
.svc__btn:hover .svc__desc, .svc__btn:focus-visible .svc__desc { color: var(--muted); }

.svc__more {
  display: inline-flex; align-items: center; gap: .55rem;
  font-size: var(--fs-micro); font-weight: 500;
  letter-spacing: .2em; text-transform: uppercase;
  opacity: .65;
  transition: opacity var(--dur-2) var(--ease), gap var(--dur-2) var(--ease);
}
.svc__btn:hover .svc__more, .svc__btn:focus-visible .svc__more { opacity: 1; gap: .95rem; }


/* ---------- 10. Why Concord ---------- */
.grid-why {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: clamp(2rem, 4vw, 3.5rem);
}
.pillar {
  display: grid; gap: var(--sp-2); align-content: start;
  padding-top: var(--sp-4);
  border-top: var(--border) solid var(--line);
}

.pillar__title {
  font-family: var(--font-display);
  font-size: var(--fs-h3); font-weight: 400;
  letter-spacing: .01em;
  margin-top: var(--sp-1);
}
.pillar__desc { font-size: var(--fs-small); color: var(--muted); max-width: 30ch; }

/* ---------- 11. Testimonials ---------- */
.quotes__stage { position: relative; max-width: 62rem; margin-inline: 0; text-align: start; }
/* The UA sheet already hides [hidden], but a `display` declaration in a class
   rule out-ranks it and the block reappears. State it explicitly for both the
   stage (why-concord.html) and a whole hidden section (index.html). */
.quotes__stage[hidden],
.section[hidden] { display: none; }
.quotes__mark {
  height: 44px; width: auto; fill: var(--ivory); opacity: .28;
  /* no auto margin: `auto` is physical and would pin the mark to the left
     edge in RTL while the text sits right */
  margin: 0 0 clamp(1.75rem, 3vw, 2.5rem);
}
.quotes__viewport { position: relative; display: grid; }
.quote {
  grid-area: 1 / 1;
  display: grid; gap: var(--sp-4);
  opacity: 0; visibility: hidden;
  transform: translateY(14px);
  transition: opacity var(--dur-2) var(--ease), transform var(--dur-2) var(--ease-out), visibility var(--dur-2);
  pointer-events: none;
}
.quote.is-active { opacity: 1; visibility: visible; transform: none; pointer-events: auto; }
.quote blockquote {
  font-family: var(--font-display);
  font-size: clamp(1.4rem, 2.9vw, 2.35rem);
  font-weight: 400; font-style: italic;
  line-height: 1.32; letter-spacing: -.015em;
  color: var(--ivory);
  text-wrap: balance;
}
.quote blockquote::before { content: "\201C"; }
.quote blockquote::after  { content: "\201D"; }
.quote figcaption { display: grid; gap: .3rem; }
.quote__name {
  font-size: var(--fs-micro); font-weight: 500;
  letter-spacing: .26em; text-transform: uppercase; color: var(--ivory);
}
.quote__role { font-size: var(--fs-small); color: var(--muted-inv); }

.quotes__nav {
  display: flex; align-items: center; justify-content: flex-start; gap: var(--sp-3);
  margin-top: clamp(2.25rem, 4vw, 3.25rem);
}
.qbtn {
  display: grid; place-items: center;
  width: 46px; height: 46px;
  border: var(--border) solid var(--line-inv);
  color: var(--ivory);
  transition: background var(--dur-1) var(--ease), color var(--dur-1) var(--ease), border-color var(--dur-1) var(--ease);
}
.qbtn:hover { background: var(--ivory); color: var(--ink); border-color: var(--ivory); }
.quotes__dots { display: flex; align-items: center; gap: .55rem; }
.qdot {
  width: 30px; height: 44px;
  position: relative;
}
.qdot::after {
  content: ""; position: absolute; left: 0; top: 50%; translate: 0 -50%;
  width: 100%; height: 1px; background: var(--ivory); opacity: .3;
  transition: opacity var(--dur-1) var(--ease), height var(--dur-1) var(--ease);
}
.qdot.is-active::after { opacity: 1; height: 2px; }

/* ---------- 12. Contact ---------- */
.contact__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(2.5rem, 7vw, 6.5rem);
  align-items: start;
}
.contact__intro .display { margin-top: var(--sp-3); }
.contact__intro .lede { margin-top: var(--sp-3); max-width: 44ch; }

.details { margin-top: clamp(2.25rem, 4vw, 3.25rem); display: grid; }
.details__row {
  display: grid;
  grid-template-columns: minmax(88px, 130px) 1fr;
  gap: var(--sp-3);
  padding-block: var(--sp-3);
  border-top: var(--border) solid var(--line);
}
/* The first row's top border drew a line immediately under the "Headquarters"
   label, which read as an underline on the label rather than as the first
   separator in the list. The rules between rows and the closing rule stay. */
.details__row:first-child { border-top: none; }
.details__row:last-child { border-bottom: var(--border) solid var(--line); }
.details dt {
  font-size: var(--fs-micro); font-weight: 500;
  letter-spacing: .22em; text-transform: uppercase;
  color: var(--ink);
}
.details dd { font-size: var(--fs-small); color: var(--muted); }
/* `> a`, NOT `a`. The "Follow" row puts the social icons inside a <dd> too, and
   `.details dd a` (0,1,2) outranks `.social a` (0,1,1) - so the underline, the
   hover colour and, on phones, the inline-block-plus-padding touch target were
   all landing on the icon rings and pulling their glyphs out of centre.
   The child combinator draws the line exactly where it belongs: the values in
   this list that ARE links, and nothing nested deeper. */
.details dd > a {
  border-bottom: var(--border) solid var(--line);
  transition: border-color var(--dur-1) var(--ease), color var(--dur-1) var(--ease);
}
.details dd > a:hover { color: var(--ink); border-color: var(--ink); }

/* Form */
.form { display: grid; gap: var(--sp-3); }
.field { display: grid; gap: .5rem; }
.field label {
  font-size: var(--fs-micro); font-weight: 500;
  letter-spacing: .22em; text-transform: uppercase;
}
.field input, .field textarea {
  width: 100%;
  min-height: 52px;
  padding: .85rem 0;
  background: transparent;
  border: 0;
  border-bottom: var(--border) solid var(--line);
  border-radius: var(--radius-sm);
  font-size: var(--fs-body);
  transition: border-color var(--dur-1) var(--ease);
}
.field textarea { resize: vertical; min-height: 120px; line-height: 1.6; }
.field input::placeholder, .field textarea::placeholder { color: rgba(51, 49, 42, .62); }
.field input:hover, .field textarea:hover { border-bottom-color: rgba(10,10,10,.34); }
.field input:focus, .field textarea:focus {
  outline: none;
  border-bottom-color: var(--ink);
  border-bottom-width: 2px;
}
.field input:focus-visible, .field textarea:focus-visible { outline: 2px solid var(--ink); outline-offset: 4px; }

.field__err {
  font-size: var(--fs-small); color: var(--ink); opacity: 0;
  height: 0; overflow: hidden;
  transition: opacity var(--dur-1) var(--ease);
}
.field.is-invalid input, .field.is-invalid textarea { border-bottom-color: var(--ink); border-bottom-width: 2px; }
.field.is-invalid .field__err { opacity: .9; height: auto; padding-top: .15rem; }
.field.is-invalid label { text-decoration: underline; text-underline-offset: 4px; }

/* Honeypot. Hidden with the clip technique rather than left: -9999px, which in
   RTL pushes the document out to ~11,000px wide and makes the whole page
   scrollable sideways into empty space. */
.hp {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0; border: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
}
/* the field itself still lays out at its default ~286px and, in RTL, that box
   hangs off the left edge of the page - clipped and invisible, but it should
   not be there at all */
.hp input, .hp label { width: 1px; max-width: 1px; min-width: 0; }

.form__submit { margin-top: var(--sp-2); justify-self: start; min-width: 220px; }
.form__submit[disabled] { opacity: .55; cursor: progress; }
.form__spinner {
  display: none;
  width: 14px; height: 14px; margin-left: .7rem;
  border: 1px solid currentColor; border-top-color: transparent;
  border-radius: 50%;
  animation: spin .7s linear infinite;
}
.form.is-sending .form__spinner { display: block; }
@keyframes spin { to { transform: rotate(360deg); } }

.form__status {
  font-size: var(--fs-small);
  padding-left: var(--sp-3);
  border-left: 2px solid var(--line);
  min-height: 0;
  opacity: 0; height: 0; overflow: hidden;
  transition: opacity var(--dur-2) var(--ease);
}
.form__status.is-shown { opacity: 1; height: auto; padding-block: .35rem; }
.form__status.is-ok { border-left-color: var(--ink); color: var(--ink); }
.form__status.is-error { border-left-color: var(--ink); color: var(--ink); }

/* --- The same form on a dark section ---
   Every rule above assumes an ivory ground: ink underlines, a dark-on-light
   placeholder, an ink focus ring, and a .btn--dark submit whose whole face is
   var(--ink). Drop that onto a black section and the fields lose their
   underlines and the submit button disappears into the background entirely.

   Section tone is decided per page by the alternating pattern, so a form can
   legitimately land on either ground - these mirror the light treatment
   rather than restyling it. All of them out-rank the base rules on
   specificity, so source order here does not matter. */
.section--dark .field input,
.section--dark .field textarea,
.section--dark .field select {
  color: var(--ivory);
  background: transparent;
  border-bottom-color: rgba(245, 242, 233, .34);
}
.section--dark .field input::placeholder,
.section--dark .field textarea::placeholder { color: rgba(245, 242, 233, .5); }
.section--dark .field input:hover,
.section--dark .field textarea:hover,
.section--dark .field select:hover { border-bottom-color: rgba(245, 242, 233, .6); }
.section--dark .field input:focus,
.section--dark .field textarea:focus,
.section--dark .field select:focus { border-bottom-color: var(--ivory); }
/* The closed select is ivory text on `transparent`, which resolves to the ink
   section behind it. The dropdown list is painted separately and has no
   section behind it, so it took the ivory text onto a white popup and the
   options were unreadable. Give the list its own ground. (macOS draws this
   list natively and ignores both declarations, which is fine - it uses the
   system colours there.) */
.section--dark .field select option { background: var(--ink); color: var(--ivory); }
.section--dark .field input:focus-visible,
.section--dark .field textarea:focus-visible { outline-color: var(--ivory); }
.section--dark .field.is-invalid input,
.section--dark .field.is-invalid textarea { border-bottom-color: var(--ivory); }
.section--dark .field__err { color: var(--ivory); }
/* The address / email block sits beside the form. Its colours are ink-on-ivory
   too - var(--muted) is #33312A - so on a dark section it rendered as black
   text on black. */
.section--dark .details dt { color: var(--ivory); }
.section--dark .details dd { color: var(--muted-inv); }
.section--dark .details dd > a { color: var(--ivory); border-bottom-color: rgba(245, 242, 233, .4); }
.section--dark .details dd > a:hover { color: var(--ivory); border-bottom-color: var(--ivory); }
.section--dark .details__row { border-color: var(--line-inv-soft); }
.section--dark .details__row:last-child { border-bottom-color: var(--line-inv-soft); }
.section--dark .form__privacy { color: var(--muted-inv); }
.section--dark .form__status.is-ok,
.section--dark .form__status.is-error { border-left-color: var(--ivory); color: var(--ivory); }
/* the solid-ink submit becomes a ghost button, which is the same control read
   against the opposite ground */
.section--dark .btn--dark {
  --btn-bg: transparent;
  --btn-fg: var(--ivory);
  --btn-bd: rgba(245, 242, 233, .5);
  --btn-fill: var(--ivory);
}
.section--dark .btn--dark:hover,
.section--dark .btn--dark:focus-visible { color: var(--ink); border-color: var(--ivory); }

/* ---------- 12b. Social links ----------
   Brand glyphs are filled shapes, unlike the site's own line icons (.pillar__ico
   and .lang__globe both set fill:none + a stroke). These get fill:currentColor
   and no stroke so they inherit the surrounding text colour and work on either
   ground - the footer is always dark, but the "Follow" row sits in the contact
   details, which is ivory on contact.html and dark on the home page. */
.social {
  display: flex; flex-wrap: wrap;
  gap: .55rem;
  list-style: none;
  padding: 0; margin: 0;
}
.social a {
  display: grid; place-items: center;
  width: 42px; height: 42px;
  color: inherit;
  border: var(--border) solid currentColor;
  border-radius: 50%;
  opacity: .72;
  transition: opacity var(--dur-2) var(--ease), transform var(--dur-2) var(--ease);
}
/* SIZE THE GLYPH SO (ring - glyph) IS EVEN.
   42 and 17 leave 25px of slack, so centring put the glyph at 12.5px - half a
   CSS pixel off a whole-pixel boundary, permanently. At 100% zoom the browser
   rounds that one way and it is invisible; below about 50% zoom, 12.5 CSS px
   is 6.25 device px and it snaps the other way, so the glyph lifts inside its
   ring and the whole row reads as having shifted up.
   An even difference has an exact midpoint and cannot round: 42-18 = 24 -> 12.
   The same arithmetic governs the two --inline sizes below. */
.social svg {
  width: 18px; height: 18px;
  fill: currentColor; stroke: none;
  /* the glyph, not the ring, is what should look centred */
  display: block;
}
.social a:hover, .social a:focus-visible { opacity: 1; transform: translateY(-2px); }
.social a:active { transform: translateY(-2px) scale(.94); }

/* Both social rows are positioned EXPLICITLY rather than by leaning on the
   <ul> filling whatever box it lands in.
   `justify-content` only centres the icons if the list itself is as wide as
   its parent. In the footer the list is a grid item, which Chrome stretches -
   so it looked right there - but an engine that shrink-wraps the item instead
   leaves the "centred" row sitting wherever the shrunk box happens to start,
   which is the row sliding to the left edge on a phone. Declaring the box's
   own width and alignment removes the dependency, and reads the same in
   Chrome as it always did. */

/* Footer row: centred under the brand and columns, above the legal rule.
   The width is stated as 100% rather than max-content. Shrink-wrapping the
   list to its contents sounds tidier, but max-content resolves to a rounded
   value - 194.391px against 194.4px of icons and gaps - so the box was 0.009px
   narrower than the row it holds. With flex-wrap on, that is a coin flip at
   any zoom level where the rounding lands the other way, and the fourth icon
   drops to a second line. A full-width box has nothing to round, and it
   centres just as explicitly. */
.site-footer .social {
  justify-content: center;
  justify-self: stretch;     /* alignment as a grid item   */
  width: 100%;
  margin-inline: 0;
  margin-top: clamp(2rem, 4vw, 3rem);
}

/* Inside the contact details list the row is already labelled "Follow", so the
   circles shrink and sit flush with the other values. `start`, not left: in
   Arabic the whole list mirrors and the icons belong on the right. */
.social--inline {
  justify-content: flex-start;
  justify-self: start;
  margin-inline: 0;
  padding-inline: 0;
  width: auto;
  gap: .45rem;
  margin-top: .15rem;
}
.social--inline a { width: 36px; height: 36px; }
.social--inline svg { width: 16px; height: 16px; }   /* 36 - 16 = 20 -> 10 exactly */

/* ---------- 13. Footer ---------- */
.site-footer {
  background: var(--ink);
  color: var(--ivory);
  padding-block: clamp(3.5rem, 7vw, 6rem) clamp(2rem, 4vw, 3rem);
}
.footer__inner { display: grid; gap: clamp(2.5rem, 5vw, 4rem); }

/* Four EQUAL columns gave every list the same width regardless of what was in
   it. Contact holds contact@consultconcord.co, one unbreakable token needing
   194-216px depending on the type size, but the column was only ever 118-191px
   - so the address had to split at the <wbr> on every screen size. Services
   was squeezed too ("Enterprise Certifications" wants 167-186px).

   The tracks are now weighted to their contents: Contact widest, Services next,
   the two short link lists narrower. Measured need vs. track at 1440px:
     About  76 -> 155    Services 186 -> 209
     Why   117 -> 155    Contact  216 -> 246

   Contact's floor is `max-content`, not 0. A weighted fr share alone left it
   at exactly 194px against an address needing exactly 194px around 1150px
   wide - arithmetically "fitting" while a scrollbar, OS display scaling or a
   different default font size was enough to tip it into two lines.
   max-content means "as wide as the content needs without wrapping", so the
   track is now derived from the address itself instead of from a ratio that
   happens to land close enough. */
.footer__cols {
  display: grid;
  grid-template-columns:
    minmax(max-content, .85fr)   /* About        */
    minmax(max-content, 1.15fr)  /* Services     */
    minmax(max-content, .85fr)   /* Why Concord  */
    minmax(max-content, 1.35fr); /* Contact      */
  gap: clamp(1.5rem, 3vw, 2.5rem);
}
/* Below ~1150px four tracks cannot all hold their contents no matter how the
   share is split - the footer's own brand column is taking 1fr of the row.
   Two columns give each list roughly double the width, which the address
   clears comfortably, so fall back earlier than the old 900px breakpoint. */
@media (max-width: 1150px) {
  .footer__cols { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
/* One line each. "WHY CONCORD" is two words at .22em tracking, so it was the
   only title that wrapped - which pushed that column's first link a line lower
   than the other three and broke the row of lists across the footer. The grid
   tracks above carry a max-content floor, so nowrap cannot cause an overflow:
   each column is guaranteed at least the width its own title needs. */
.fcol__title {
  font-size: var(--fs-micro); font-weight: 500; letter-spacing: .22em;
  text-transform: uppercase; color: var(--ivory); margin-bottom: var(--sp-2);
  white-space: nowrap;
}
.fcol ul { display: grid; gap: .5rem; }
.fcol a { font-size: var(--fs-small); color: var(--muted-inv); transition: color var(--dur-1) var(--ease); }
.fcol a:hover { color: var(--ivory); }


/* brand, centred and low on the page */
.footer__brand {
  justify-self: center; text-align: center;
  display: grid; justify-items: center; gap: 1.1rem;
  margin-top: clamp(1rem, 3vw, 2.5rem);
}
.footer__brand .logo__mark { height: clamp(46px, 6vw, 64px); width: auto; fill: currentColor; }
.footer__brand .logo__type { display: grid; gap: .3em; justify-items: center; }
.footer__brand .logo__name {
  font-family: var(--font-display);
  font-size: clamp(1.7rem, 4vw, 2.75rem); font-weight: 400;
  letter-spacing: .2em; text-transform: uppercase; line-height: 1;
}
.footer__brand .logo__sub {
  font-size: clamp(.58rem, .95vw, .7rem); letter-spacing: .34em;
  text-transform: uppercase; line-height: 1; opacity: .72;
}

.footer__rule { width: 100%; border-top-color: var(--line-inv); }
.footer__legal {
  display: flex; flex-wrap: wrap; justify-content: space-between; gap: var(--sp-2);
  width: 100%; font-size: var(--fs-small); color: var(--muted-inv);
}

/* ---------- 14. Dropdown navigation ---------- */
.nav__item { position: relative; }
.nav__link { display: inline-flex; align-items: center; gap: .45rem; }

.nav__caret {
  width: 5px; height: 5px;
  border-right: 1px solid currentColor;
  border-bottom: 1px solid currentColor;
  rotate: 45deg;
  translate: 0 -2px;
  opacity: .7;
  transition: rotate var(--dur-2) var(--ease), translate var(--dur-2) var(--ease);
}
.has-menu:hover .nav__caret,
.has-menu:focus-within .nav__caret { rotate: 225deg; translate: 0 1px; }

.menu {
  position: absolute;
  top: calc(100% + 10px);
  left: 50%;
  translate: -50% 0;
  min-width: 246px;
  padding: .5rem;
  background: rgba(10, 10, 10, .88);
  backdrop-filter: blur(22px) saturate(1.35);
  -webkit-backdrop-filter: blur(22px) saturate(1.35);
  border: var(--border) solid rgba(245, 242, 233, .16);
  box-shadow: 0 26px 60px -28px rgba(0, 0, 0, .9);
  opacity: 0; visibility: hidden;
  transform: translateY(-7px);
  transition: opacity var(--dur-2) var(--ease),
              transform var(--dur-2) var(--ease-out),
              visibility var(--dur-2);
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .menu { background: rgba(10, 10, 10, .97); }
}
/* a small bridge so the pointer can cross the gap without the panel closing */
.menu::before { content: ""; position: absolute; inset: -12px 0 auto 0; height: 14px; }

.has-menu:hover .menu,
.has-menu:focus-within .menu,
.nav__item.is-open .menu {
  opacity: 1; visibility: visible; transform: none;
}

.menu__list { display: grid; }
.menu__list a {
  display: block;
  padding: .7rem .9rem;
  font-size: var(--fs-micro);
  font-weight: 400;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: rgba(245, 242, 233, .78);
  white-space: nowrap;
  transition: background var(--dur-1) var(--ease), color var(--dur-1) var(--ease),
              padding-left var(--dur-1) var(--ease);
}
.menu__list a:hover, .menu__list a:focus-visible {
  background: rgba(245, 242, 233, .1);
  color: var(--ivory);
  padding-left: 1.25rem;
}

/* ---------- 14b. Site menu panel ----------
   One panel, two behaviours:
   • wide screens — a full-screen overview of every page and section
   • phones       — a sidebar that slides in from the left and covers the screen */
.menu-panel {
  position: fixed; inset: 0; z-index: 105;
  background: var(--ink);
  color: var(--ivory);
  overflow-y: auto; overscroll-behavior: contain;
  padding: calc(var(--header-h) + clamp(2rem, 5vw, 4rem)) var(--gutter) clamp(2.5rem, 5vw, 4rem);
  opacity: 0; visibility: hidden;
  transition: opacity var(--dur-2) var(--ease), visibility var(--dur-2);
}
.menu-panel[hidden] { display: none; }
.menu-panel.is-open { opacity: 1; visibility: visible; }
body.nav-open { overflow: hidden; }

.menu-panel__inner {
  width: 100%; max-width: var(--shell); margin-inline: auto;
  display: grid; gap: clamp(2rem, 4vw, 3.25rem);
  align-content: start;
}
.menu-panel__eyebrow {
  font-size: var(--fs-micro); font-weight: 500;
  letter-spacing: .28em; text-transform: uppercase;
  color: var(--muted-inv);
}

.menu-panel__grid {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: clamp(1.5rem, 3vw, 3rem);
  border-top: var(--border) solid var(--line-inv-soft);
  padding-top: clamp(1.5rem, 3vw, 2.5rem);
}
.mgroup {
  display: grid; gap: var(--sp-2); align-content: start;
  opacity: 0; transform: translateY(16px);
  transition: opacity .5s var(--ease), transform .5s var(--ease-out);
}
.menu-panel.is-open .mgroup { opacity: 1; transform: none; }
.menu-panel.is-open .mgroup:nth-child(1) { transition-delay:  90ms; }
.menu-panel.is-open .mgroup:nth-child(2) { transition-delay: 150ms; }
.menu-panel.is-open .mgroup:nth-child(3) { transition-delay: 210ms; }
.menu-panel.is-open .mgroup:nth-child(4) { transition-delay: 270ms; }
.menu-panel.is-open .mgroup:nth-child(5) { transition-delay: 330ms; }

.mgroup__title {
  /* reserve two lines so a wrapping title ("Why Concord") does not push its
     sub-list out of line with the neighbouring columns */
  min-height: 2.3em;
  font-family: var(--font-display);
  font-size: clamp(1.35rem, 2.1vw, 1.95rem);
  font-weight: 400; line-height: 1.15;
  letter-spacing: .03em; text-transform: uppercase;
  padding-bottom: .2rem;
}
.mgroup__title.is-active { text-decoration: underline; text-underline-offset: 8px; text-decoration-thickness: 1px; }
.mgroup__list { display: grid; gap: .1rem; }
.mgroup__list a {
  display: block; padding: .4rem 0; min-height: 34px;
  font-size: var(--fs-micro); letter-spacing: .16em; text-transform: uppercase;
  color: var(--muted-inv);
  transition: color var(--dur-1) var(--ease), padding-left var(--dur-1) var(--ease);
}
.mgroup__list a:hover, .mgroup__list a:focus-visible { color: var(--ivory); padding-left: .5rem; }

.menu-panel__foot {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: var(--sp-3);
  border-top: var(--border) solid var(--line-inv-soft);
  padding-top: clamp(1.5rem, 3vw, 2.25rem);
}
.menu-panel__mail {
  font-size: var(--fs-small); color: var(--muted-inv);
  border-bottom: var(--border) solid var(--line-inv);
  transition: color var(--dur-1) var(--ease), border-color var(--dur-1) var(--ease);
}
.menu-panel__mail:hover { color: var(--ivory); border-color: var(--ivory); }

/* ---------- 14c. Inner-page hero ---------- */
.page-hero {
  position: relative;
  background: var(--ink);
  color: var(--ivory);
  padding-block: calc(var(--header-h) + clamp(3.5rem, 9vw, 7rem)) clamp(3.5rem, 8vw, 6.5rem);
  overflow: hidden;
}
.page-hero::before {
  content: ""; position: absolute; inset: 0;
  background: radial-gradient(120% 130% at 12% 0%, rgba(107, 95, 69, .3) 0%, rgba(10, 10, 10, 0) 62%);
}
.page-hero > * { position: relative; }
.page-hero--short { padding-bottom: clamp(2.5rem, 6vw, 4.5rem); }
.display--1b {
  font-family: var(--font-display);
  font-size: clamp(2.6rem, 7.5vw, 6rem);
  font-weight: 400; line-height: .96; letter-spacing: -.02em;
  color: var(--ivory);
  margin-top: var(--sp-3);
}
.display--1b em { font-style: italic; }
.page-hero__lede {
  margin-top: var(--sp-3);
  max-width: 48ch;
  font-size: var(--fs-lede);
  color: rgba(245, 242, 233, .8);
}

/* ---------- 14d. Split layout (aside + body) ---------- */
.split {
  display: grid;
  grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
  column-gap: clamp(2rem, 7vw, 7rem);
  row-gap: var(--sp-4);
  align-items: start;
}
.split__aside { position: sticky; top: calc(var(--header-h) + 2rem); }
.split__aside .display { margin-top: var(--sp-3); }
.split__body { display: grid; gap: var(--sp-3); justify-items: start; }

/* ---------- Display headings: size to the column, not the window ----------
   --fs-display-2 is clamp(2.9rem, 7vw, 6rem), so on a 1920 screen it reaches
   96px. But these headings do not live in a 1920 box - they sit in the 5fr
   aside of a .split, which is about 487px wide. 96px type in a 487px column
   is roughly five characters a line, which is why the headings broke into
   three and four lines no matter how wide the window got. The window was
   never the constraint; the column was.

   Two changes, together:

   1. The aside gets wider above 1200px (5fr -> 6fr). Enough to give the
      heading real room without the body column feeling starved.

   2. The type is measured against its own container instead of the viewport.
      cqw is a percentage of the container's inline size, so the heading now
      scales with the box it is actually in - a wide .section__head gets
      larger type than a narrow .split__aside, automatically, at every width.

   Left alone: .display--1b in the page heroes. Those sit in the full 1280px
   shell where 96px already fits on one line, so they keep viewport sizing. */
@media (min-width: 1200px) {
  .split,
  .about__grid { grid-template-columns: minmax(0, 6fr) minmax(0, 7fr); }
}
/* the matching .svc-row__inner rules live further down, next to that grid's
   own definition - it is declared after this point, so a copy here would be
   overridden by it */

.section__head,
.split__aside,
.about__head,
.svc-row__lead { container-type: inline-size; }

@supports (container-type: inline-size) {
  /* the rem floor and ceiling still bound it; cqw only decides where
     between them this particular column lands */
  .split__aside  > .display--2,
  .about__head   > .display--2,
  .svc-row__lead > .display--2 {
    font-size: clamp(2.4rem, 11.5cqw, 5.5rem);
  }
  /* .section__head now spans the full shell rather than 62ch, so the ratio
     drops to match: 5cqw of ~1280px lands around 64px, which keeps even the
     longest heading here ("The founders behind every engagement.") on one
     line while staying in proportion with the column headings above. */
  .section__head > .display--2 {
    font-size: clamp(2.4rem, 5cqw, 4.5rem);
  }
}

/* No forced breaks in display headings, at any width.
   A hard <br> fixes the break at a point chosen for one language: the English
   phrase splits where the author wanted, and the Arabic translation - a
   different length entirely - inherits that same split whether it suits the
   words or not. The emphasis is already carried by the italic in English and
   by kashida in Arabic, so the line does not need breaking to look composed.
   Removing it lets text-wrap:balance choose the break from the actual text,
   which is what makes the two languages behave the same way.

   The <br> stays in the markup rather than being deleted: the Arabic
   generator keys on text runs, and merging the two halves would produce one
   unknown key and silently drop the translation. A space was added before
   each <br> so the two halves stay separate words once it is suppressed. */
.display br { display: none; }

.note { font-size: var(--fs-small); }
.note a { border-bottom: var(--border) solid var(--line); }
.note a:hover { border-color: currentColor; }

.factgrid {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0; width: 100%; margin-top: var(--sp-3);
  border-top: var(--border) solid var(--line);
}
.factgrid > div { padding-block: var(--sp-3); border-bottom: var(--border) solid var(--line); }
.factgrid dt {
  font-size: var(--fs-micro); font-weight: 500;
  letter-spacing: .22em; text-transform: uppercase; color: var(--muted);
}
.factgrid dd { font-family: var(--font-display); font-size: 1.25rem; margin-top: .3rem; }

/* ---------- 14e. Team ---------- */
/* Four fixed columns left two founders hugging the left edge with a hole
   where the other two used to be. auto-fit drops the empty tracks and
   justify-content centres what remains, so two cards sit centred on the page
   and a third or fourth would still lay out correctly without another edit.
   The 24rem cap stops two cards stretching into billboards on a wide screen;
   the min() floor keeps a single card from overflowing a narrow one. */
.grid-team {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 16rem), 24rem));
  justify-content: center;
  gap: clamp(1.5rem, 3vw, 2.5rem);
}
.member {
  /* an implicit `auto` track sizes to max-content and can exceed the column,
     pushing the card past the gutter on narrow screens */
  display: grid; grid-template-columns: minmax(0, 1fr);
  gap: .5rem; align-content: start;
}
.member > * { min-width: 0; }
/* MOUNTED LIKE A PRINT.
   The photographs are shot on a pale studio backdrop and the section behind
   them is #0A0A0A, so butting the image straight up against the section put a
   hard light-on-dark edge around each one - the picture read as stamped onto
   the page rather than placed on it.

   Three things fix that, and they are the same three a framed print uses: a
   mat of empty board between the picture and its frame, a hairline where the
   picture actually starts, and a frame around the outside. Corners stay square
   - `--radius: 0` is the brand, and these would be the only rounded objects on
   the site - so the mat is what does the softening. The photographs themselves
   are left exactly as they were shot. */
.member__portrait {
  --mat: clamp(7px, 1.3vw, 12px);
  position: relative; overflow: hidden;
  /* One named cell that both the mark and the photograph sit in, so they stack
     without either being taken out of flow. */
  display: grid;
  grid-template-areas: "mount";
  place-items: center;
  aspect-ratio: 4 / 5;
  padding: var(--mat);
  /* Board catching a raking light from the top left: bright at the near
     corner, falling away across the mount, then lifting very slightly again
     at the far corner - that last rise is bounce, and it is what stops the
     ramp reading as a flat gradient. Only the mat shows it; the picture
     covers the middle. */
  background: linear-gradient(145deg,
    rgba(245, 242, 233, .155) 0%,
    rgba(245, 242, 233, .085) 34%,
    rgba(245, 242, 233, .045) 66%,
    rgba(245, 242, 233, .07)  100%);
  /* The frame edge, lit by the same source: the two sides facing it are
     brighter than the two turned away. Per-side colours rather than a
     border-image, so the hover below can still transition them.
     The light does NOT mirror in Arabic. A light source is physical, unlike
     the arrows and paddings that flip on [dir="rtl"] because they encode
     reading direction. */
  border: var(--border) solid;
  border-top-color: rgba(245, 242, 233, .30);
  border-left-color: rgba(245, 242, 233, .26);
  border-right-color: rgba(245, 242, 233, .12);
  border-bottom-color: rgba(245, 242, 233, .10);
  margin-bottom: var(--sp-2);
  transition: border-color var(--dur-2) var(--ease);
}
.member:hover .member__portrait {
  border-top-color: rgba(245, 242, 233, .48);
  border-left-color: rgba(245, 242, 233, .42);
  border-right-color: rgba(245, 242, 233, .22);
  border-bottom-color: rgba(245, 242, 233, .18);
}
.member__portrait > * { grid-area: mount; }
.member__portrait svg { height: 34%; width: auto; fill: rgba(245, 242, 233, .2); }

/* The photograph sits over the mark rather than replacing it, so the frame is
   never empty: no file yet, or a file that fails to load, and the mark is
   simply what shows. Fading in on decode stops the half-drawn flash you get
   from a plain <img> on a slow connection. object-position sits above centre
   because a portrait's subject does - dead-centre crops foreheads.

   The picture is a grid item filling its cell, NOT an absolutely positioned
   box inset by the mat. That was the first attempt and it is a trap: for an
   absolutely positioned REPLACED element, `width: auto` means the intrinsic
   width, not the width implied by the left and right insets, so the box was
   over-constrained and the right inset was dropped. The photograph then ran
   from the left mat straight over the right one and was clipped by
   overflow:hidden - a mount with board on two sides and none on the other. */
.member__photo {
  width: 100%; height: 100%;
  object-fit: cover; object-position: center 22%;
  opacity: 0;
  transition: opacity var(--dur-2) var(--ease);
}
.member__photo.is-loaded { opacity: 1; }

/* The hairline where the picture starts. A pseudo-element rather than a border
   on the <img> itself, so it paints OVER the photograph and stays crisp:
   ::after is the last child and the <img> is a real one before it.

   Nothing else goes here. There was a gradient scrim over the picture as well,
   darkening the top and foot so the pale studio backdrop would fade into the
   ink section - but it altered the lighting of a photograph somebody paid to
   have lit, which is not the stylesheet's business. The mat below already
   keeps the picture from touching the section, which was the actual problem.
   Do not reintroduce it. */
.member__portrait::after {
  content: "";
  position: absolute;
  inset: calc(var(--mat) - var(--border));
  /* Lit as an INNER bevel, which is the outer frame's lighting inverted: the
     cut nearest the light faces away from it and sits in shadow, while the far
     side of the opening turns back towards it and catches the highlight. That
     inversion is the whole reason a mount reads as cut rather than printed. */
  border: var(--border) solid;
  border-top-color: rgba(245, 242, 233, .13);
  border-left-color: rgba(245, 242, 233, .15);
  border-right-color: rgba(245, 242, 233, .30);
  border-bottom-color: rgba(245, 242, 233, .33);
  pointer-events: none;
}
.member__name { font-family: var(--font-display); font-size: var(--fs-h3); font-weight: 400; }
.member__role {
  font-size: var(--fs-micro); letter-spacing: .2em; text-transform: uppercase;
  color: var(--ivory); opacity: .75;
}
.member__bio { font-size: var(--fs-small); color: var(--muted-inv); }

/* ---------- 14f. Careers ---------- */
.openings { width: 100%; border-top: var(--border) solid var(--line); }
.opening {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: var(--sp-2);
  padding-block: var(--sp-3);
  border-bottom: var(--border) solid var(--line);
  transition: padding-left var(--dur-2) var(--ease);
}
.opening:hover { padding-left: .75rem; }
.opening__title { font-family: var(--font-display); font-size: var(--fs-h3); font-weight: 400; }
.opening__meta { font-size: var(--fs-small); color: var(--muted); margin-top: .2rem; }
.opening__cta {
  display: inline-flex; align-items: center; gap: .55rem; min-height: 44px;
  font-size: var(--fs-micro); font-weight: 500; letter-spacing: .2em; text-transform: uppercase;
}
.opening__cta span { transition: transform var(--dur-2) var(--ease-out); }
.opening:hover .opening__cta span { transform: translateX(5px); }

/* ---------- 14g. Services page ---------- */
.jump {
  position: sticky; top: var(--header-h); z-index: 90;
  background: var(--ivory);
  border-bottom: var(--border) solid var(--line-soft);
}
.jump__inner {
  display: flex; gap: clamp(1rem, 2.4vw, 2.4rem);
  overflow-x: auto; scrollbar-width: none;
  padding-block: var(--sp-2);
}
.jump__inner::-webkit-scrollbar { display: none; }
.jump__link {
  flex: none; min-height: 44px; display: inline-flex; align-items: center;
  font-size: var(--fs-micro); letter-spacing: .18em; text-transform: uppercase;
  color: var(--muted); white-space: nowrap;
  border-bottom: 2px solid transparent;
  transition: color var(--dur-1) var(--ease), border-color var(--dur-1) var(--ease);
}
.jump__link:hover, .jump__link.is-active { color: var(--ink); border-bottom-color: var(--ink); }

.svc-row { border-bottom: var(--border) solid var(--line); scroll-margin-top: calc(var(--header-h) + 60px); }
.svc-row__inner {
  display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
  column-gap: clamp(2rem, 7vw, 7rem); row-gap: var(--sp-4); align-items: start;
}
.svc-row--flip .svc-row__lead { order: 2; }
.svc-row--flip .svc-row__body { order: 1; }

/* Service rows: give the heading column the same width on every row.
   `order` swaps which side each half appears on, but it also changes which
   GRID COLUMN each lands in - so on flipped rows the heading sat in the 7fr
   track and on normal rows in the 5fr. Every heading was 96px before, so the
   difference was invisible; once the type is sized to its container it showed
   up as 57px on one row and 80px on the next. Mirroring the track sizes puts
   the lead back at a consistent width whichever side it is on.

   Above 900px only: below that the layout is a single column, and these
   selectors would otherwise out-rank that rule and rebuild the grid. */
@media (min-width: 901px) {
  .svc-row--flip .svc-row__inner { grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); }
}
@media (min-width: 1200px) {
  .svc-row__inner { grid-template-columns: minmax(0, 6fr) minmax(0, 7fr); }
  .svc-row--flip .svc-row__inner { grid-template-columns: minmax(0, 7fr) minmax(0, 6fr); }
}

.svc-row__lead .lede { margin-top: var(--sp-3); }
.svc-row__body { display: grid; gap: var(--sp-3); justify-items: start; }
.svc-row__label {
  font-size: var(--fs-micro); font-weight: 500; letter-spacing: .22em;
  text-transform: uppercase; color: var(--ink);
}
.ticklist { display: grid; gap: .6rem; width: 100%; }
.ticklist li {
  display: grid; grid-template-columns: 14px 1fr; gap: .85rem; align-items: start;
  font-size: var(--fs-small); color: var(--muted);
}
.ticklist li::before {
  content: ""; width: 8px; height: 8px; margin-top: .58em; background: var(--ink); rotate: 45deg;
}
.section--dark .ticklist li::before { background: var(--ivory); }

.custom { text-align: start; display: grid; justify-items: start; gap: var(--sp-3); }
.custom__plus {
  font-family: var(--font-display); font-size: clamp(3rem, 6vw, 5rem); line-height: 1;
  color: transparent; -webkit-text-stroke: 1px rgba(245, 242, 233, .5);
}
@supports not (-webkit-text-stroke: 1px currentColor) { .custom__plus { color: rgba(245,242,233,.4); } }
.custom .lede { max-width: 52ch; }

/* ---------- 14h. Why Concord page ---------- */
.steps { display: grid; gap: var(--sp-4); width: 100%; }
.step { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: var(--sp-3); align-items: start; }
/* Solid, not outlined. These were drawn as hollow numerals with
   -webkit-text-stroke and a transparent fill, which read as unfinished rather
   than as a deliberate device - and the effect is vendor-prefixed, so the
   @supports fallback rendered a different thing again. A filled numeral in
   the muted text colour is the same weight of emphasis without either
   problem, and it matches .phase__num further down the page. */
.step__num {
  font-family: var(--font-display); font-size: 1.6rem; line-height: 1;
  color: var(--muted);
}
.step__title { font-family: var(--font-display); font-size: var(--fs-h3); font-weight: 400; margin-bottom: .4rem; }
.step p { font-size: var(--fs-small); }

.grid-results {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--border); background: var(--line-inv-soft);
  border-block: var(--border) solid var(--line-inv-soft);
  margin-bottom: clamp(3rem, 7vw, 5.5rem);
}
.result { background: var(--ink); padding: clamp(1.5rem, 2.6vw, 2.5rem); display: grid; gap: .45rem; }
.result__figure {
  font-family: var(--font-display); font-size: clamp(3rem, 5.5vw, 4.5rem); line-height: .9;
  letter-spacing: -.03em; color: var(--ivory); display: flex; align-items: flex-start;
}
.result__unit { font-size: .4em; margin-top: .35em; margin-left: .08em; opacity: .6; }
.result__title {
  font-size: var(--fs-micro); font-weight: 500; letter-spacing: .22em;
  text-transform: uppercase; color: var(--ivory); margin-top: .3rem;
}
.result__desc { font-size: var(--fs-small); color: var(--muted-inv); }

.quotes__stage--compact { max-width: 54rem; }
.quotes__stage--compact .quote blockquote { font-size: clamp(1.25rem, 2.3vw, 1.85rem); }

.phases { display: grid; gap: 0; width: 100%; border-top: var(--border) solid var(--line); }
.phase { padding-block: var(--sp-3); border-bottom: var(--border) solid var(--line); }
.phase__title {
  display: flex; align-items: baseline; gap: .9rem;
  font-family: var(--font-display); font-size: var(--fs-h3); font-weight: 400; margin-bottom: .4rem;
}
/* Same treatment as .step__num in Our Approach: display face, muted fill.
   Sizing stays relative to the phase title it sits inside. */
.phase__num { font-family: var(--font-display); font-size: .72em; color: var(--muted); }
.phase p { font-size: var(--fs-small); max-width: 62ch; }

/* ---------- 14i. CTA band ---------- */
.cta { background: var(--ink); color: var(--ivory); padding-block: clamp(4rem, 9vw, 7rem); }
.cta__inner { display: grid; justify-items: start; text-align: start; gap: var(--sp-3); }
.cta .display { color: var(--ivory); }
.cta p { color: var(--muted-inv); }
.cta .btn { margin-top: var(--sp-2); }

/* ---------- 14j. Contact page ---------- */
.mapcard {
  display: grid; width: 100%; margin-top: clamp(2rem, 4vw, 3rem);
  border: var(--border) solid var(--line);
  transition: border-color var(--dur-2) var(--ease), transform var(--dur-2) var(--ease-out);
}
.mapcard:hover { border-color: var(--ink); transform: translateY(-3px); }
.mapcard__art { display: block; overflow: hidden; }
.mapcard__art svg { width: 100%; height: auto; display: block; }
.mapcard__body {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: var(--sp-2); padding: var(--sp-3);
  border-top: var(--border) solid var(--line);
}
.mapcard__title { font-family: var(--font-display); font-size: 1.2rem; }
.mapcard__meta {
  display: inline-flex; align-items: center; gap: .45rem;
  font-size: var(--fs-micro); font-weight: 500; letter-spacing: .2em;
  text-transform: uppercase; color: var(--muted);
}
.mapcard:hover .mapcard__meta { color: var(--ink); }

/* The Google embed that replaces .mapcard once the visitor asks for it. */
.mapframe {
  display: block; width: 100%;
  height: clamp(260px, 42vh, 380px);
  border: var(--border) solid var(--line);
  margin-top: clamp(2rem, 4vw, 3rem);
}
.contact__form-wrap .eyebrow { margin-bottom: var(--sp-3); }
.field__opt { font-weight: 300; letter-spacing: .06em; text-transform: none; opacity: .6; }
.field select {
  width: 100%; min-height: 52px; padding: .85rem 0;
  background: transparent; border: 0;
  border-bottom: var(--border) solid var(--line);
  border-radius: var(--radius-sm); font-size: var(--fs-body);
  transition: border-color var(--dur-1) var(--ease);
}
.field select:hover { border-bottom-color: rgba(10, 10, 10, .34); }
.field select:focus { outline: none; border-bottom-color: var(--ink); border-bottom-width: 2px; }
.form__privacy { font-size: var(--fs-small); color: var(--muted); opacity: 1; }


/* ---------- 16. Responsive ---------- */
@media (max-width: 1180px) {
  .menu-panel__grid { grid-template-columns: repeat(3, minmax(0, 1fr)); row-gap: var(--sp-4); }
}

@media (max-width: 1080px) {
  .grid-services { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .grid-why { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .grid-team { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 900px) {
  :root { --header-h: 72px; }

  /* the dropdown bar goes; the burger (already always visible) takes over */
  .nav { display: none; }

  /* panel enters from the left edge and covers the screen */
  .menu-panel {
    opacity: 1;
    transform: translateX(-100%);
    transition: transform var(--dur-2) var(--ease-out), visibility var(--dur-2);
  }
  .menu-panel.is-open { transform: translateX(0); }
  .menu-panel__grid { grid-template-columns: minmax(0, 1fr); gap: var(--sp-4); }
  .mgroup__title { min-height: 0; }
  .menu-panel__foot { flex-direction: column; align-items: stretch; text-align: center; }
  .menu-panel__foot .btn { width: 100%; }
  .mgroup__list { grid-template-columns: repeat(2, minmax(0, 1fr)); }

  .split, .svc-row__inner { grid-template-columns: minmax(0, 1fr); }
  /* Sticky headings only make sense while a second column scrolls alongside
     them. Once the grid is one column the heading and its body are stacked, so
     a pinned heading just sits on top of the text scrolling under it. Both
     asides must be released here - .about__head was sticky without this reset
     and overlapped the body copy on phones. */
  .split__aside,
  .about__head { position: static; }

  /* --- Touch targets ---
     These links are all fine to click with a cursor but were 25-29px tall,
     which is a small thing to hit with a thumb. Padding raises the hit area
     without moving the text: the list gaps shrink by the same amount the links
     grow, so the visual rhythm of each column is unchanged. */
  .fcol ul { gap: .05rem; }
  .fcol a { padding-block: .42rem; }
  .fcol__title { margin-bottom: calc(var(--sp-2) - .42rem); }
  .fcol__title a { display: inline-block; padding-block: .42rem; }
  /* `> a` again: the social rings are already 44px and must keep display:grid,
     or the glyph stops being centred and rides up inside the circle. */
  .details dd > a { display: inline-block; padding-block: .38rem; }
  .social--inline a { width: 44px; height: 44px; }
  .social--inline svg { width: 18px; height: 18px; }   /* 44 - 18 = 26 -> 13 exactly */
  .link-arrow { padding-block: .3rem; }
  .svc-row--flip .svc-row__lead,
  .svc-row--flip .svc-row__body { order: 0; }
  .grid-results { grid-template-columns: minmax(0, 1fr); }
  .footer__cols { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .jump { top: var(--header-h); }

  .about__grid {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas: "head" "body" "stat";
  }
  .stat { grid-template-columns: minmax(0, 1fr); gap: var(--sp-2); align-items: start; }
  .contact__grid { grid-template-columns: minmax(0, 1fr); }
  .section__head { max-width: none; }
}

@media (max-width: 640px) {
  /* grid columns for this range live in section 24 (2x2, not 1x4) */
  .svc__btn { min-height: 0; gap: var(--sp-2); padding: var(--sp-3); }
  .mgroup__list { grid-template-columns: minmax(0, 1fr); }
  .member__portrait { aspect-ratio: 4 / 5; }
  .opening { flex-direction: column; align-items: flex-start; }
  .step { grid-template-columns: minmax(0, 1fr); gap: .5rem; }
  .mapcard__body { flex-direction: column; align-items: flex-start; }
  .cta .btn, .custom .btn { width: 100%; }
  .hero { min-height: 92svh; align-items: flex-end; }
  .hero__actions .btn { flex: 1 1 100%; }
  .footer__legal { flex-direction: column; align-items: center; text-align: center; }
  .logo__sub { font-size: .52rem; letter-spacing: .24em; }
  .details__row { grid-template-columns: minmax(0, 1fr); gap: .35rem; }
  /* The row has collapsed, so the circles now sit directly under their own
     "Follow" label rather than beside it. A little more air keeps them from
     reading as part of the label. */
  .social--inline { margin-top: .35rem; }
}

@media (max-width: 380px) {
  .logo__name { font-size: 1.25rem; }
  .logo__mark { height: 38px; }
  .logo__sub { display: none; }
  /* At 320px the lockup wanted more width than its flex track allowed and the
     wordmark spilled past its own box (overflow is visible, so it showed
     rather than clipped). The arithmetic: 320 - 40 padding - 114 controls
     - 32 flex gap left 134px for content needing 155px. The gap is empty
     space between the logo and the controls, so that is what gives; the
     logo's own tracking tightens a little alongside it. */
  .header__inner { gap: .5rem; }
  .logo { gap: .55rem; }
  .logo__name { letter-spacing: .1em; }
}

/* Coarse pointers: don't strand hover-only affordances. */
@media (hover: none) {
  .svc__more { opacity: 1; }
  .link-arrow { border-color: currentColor; }
  .opening__cta { border-bottom: var(--border) solid var(--line); }
}

/* ---------- 17. Reduced motion ---------- */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
  [data-reveal] { opacity: 1 !important; transform: none !important; }
  .mgroup { opacity: 1 !important; transform: none !important; }
  .menu-panel { transition: none; }
  .hero__title .line > [data-reveal],
  .hero__title .line > [data-reveal].is-in { transform: none !important; }
  .hero__img { opacity: 1; transform: none; }
}

/* ---------- 18. Print ---------- */
@media print {
  .site-header, .menu-panel, .scroll-progress, .quotes__nav, .form__submit, .jump { display: none !important; }
  body { background: #fff; color: #000; }
  .section--dark, .site-footer, .stat, .page-hero, .cta { background: #fff !important; color: #000 !important; }
  .section--dark p, .stat__note, .page-hero__lede { color: #333 !important; }
  .display, .section--dark .display, .page-hero .display { color: #000 !important; }
  [data-reveal] { opacity: 1 !important; transform: none !important; }
  a[href^="http"]::after { content: " (" attr(href) ")"; font-size: .8em; }
}

/* ============================================================
   19. Motion system
   Scroll reveal, page transitions and click/hover feedback.
   NOTE: main.js has always set .is-in on [data-reveal] elements,
   but nothing styled them — the reveals below are what that
   existing script was written to drive.
   ============================================================ */

/* --- Scroll reveal ---
   The hidden state is scoped to html.js (set by an inline script in each
   page head) so a blocked or failed script can never leave content
   invisible — without JS these elements simply render as normal. */
.js [data-reveal] {
  opacity: 0;
  transform: translateY(30px);
  transition:
    opacity 1.25s var(--ease-soft) var(--reveal-delay, 0ms),
    transform 1.25s var(--ease-out) var(--reveal-delay, 0ms);
}
.js [data-reveal].is-in { opacity: 1; transform: none; }

/* Hero headline: each word rises out of its own clipping line. */
.js .hero__title .line > [data-reveal] { transform: translateY(105%); }
.js .hero__title .line > [data-reveal].is-in { transform: none; }

/* Eyebrow labels draw their rule out beside the text as they enter. */
/* No marker before section labels. They are uppercase with .22em tracking,
   which already reads as a label; a dash or a dot in front only competed with
   it. The label itself carries data-reveal, so it still animates in - the
   reveal simply belongs to the text now rather than to a decoration. */



/* --- Click + hover feedback --- */
.btn {
  transition: color var(--dur-2) var(--ease),
              border-color var(--dur-2) var(--ease),
              transform var(--dur-1) var(--ease);
}
.btn:active { transform: scale(.985); }

.svc__btn {
  transition: color var(--dur-2) var(--ease), transform var(--dur-1) var(--ease);
}
.svc__btn:active { transform: scale(.995); }

.qbtn:active { transform: scale(.94); }

.logo { transition: opacity var(--dur-2) var(--ease); }
.logo:hover { opacity: .82; }

/* An email address is one unbreakable token. In a narrow footer column it sets
   the track's min-content width and drags the whole grid wider than the
   viewport - which showed up as a horizontal scroll on phones. */
/* `anywhere` was the wrong tool. It permits a break between ANY two
   characters AND it feeds into min-content sizing, so the footer column was
   free to shrink to a few characters wide and the address came apart as
   "contact@consultc / oncord.co" - even at 1280px, where the column had room.

   `break-word` allows the same last-resort break but is ignored for
   min-content, so the column keeps asking for its natural width and only
   breaks when it genuinely cannot fit. The <wbr> in the markup then decides
   WHERE that break lands: after the @, so the address reads as two whole
   parts rather than a spill of characters. */
.fcol a, .details dd, .menu-panel__mail { overflow-wrap: break-word; }
.fcol a { display: inline-block; max-width: 100%; transition: color var(--dur-1) var(--ease), transform var(--dur-1) var(--ease); }
.fcol a:hover { transform: translateX(3px); }

.link-arrow:active, .opening:active { transform: scale(.995); }

/* ============================================================
   20. Header — larger logo, self-evident menu button
   ============================================================ */

/* The burger is bordered and shimmers on a slow loop so it reads as a
   control rather than three decorative lines. */
.burger {
  position: relative;
  display: inline-flex; align-items: center; justify-content: center;
  gap: 0;
  width: 54px; height: 44px; min-height: 44px;
  padding: 0;
  border: var(--border) solid rgba(245, 242, 233, .3);
  overflow: hidden;
  transition: border-color var(--dur-2) var(--ease), background var(--dur-2) var(--ease);
}
.burger::before {
  content: ""; position: absolute; top: 0; left: -60%;
  width: 55%; height: 100%;
  background: linear-gradient(100deg,
    rgba(245, 242, 233, 0) 0%,
    rgba(245, 242, 233, .5) 50%,
    rgba(245, 242, 233, 0) 100%);
  animation: burger-shimmer 3.8s var(--ease) infinite;
}
@keyframes burger-shimmer {
  0%   { left: -60%; }
  55%  { left: 115%; }
  100% { left: 115%; }
}
.burger:hover, .burger:focus-visible {
  border-color: var(--ivory);
  background: rgba(245, 242, 233, .09);
}
.burger[aria-expanded="true"] { border-color: var(--ivory); }
.burger[aria-expanded="true"]::before { animation: none; opacity: 0; }
.burger__box { width: 22px; }

/* ============================================================
   21. Why Concord — subject icons in place of the repeated logo
   ============================================================ */
.pillar { transition: border-top-color var(--dur-2) var(--ease); }
.pillar:hover { border-top-color: var(--ink); }
.pillar__ico {
  width: clamp(38px, 3.4vw, 46px); height: auto;
  fill: none;
  stroke: var(--ink);
  stroke-width: 1.25;
  stroke-linecap: round; stroke-linejoin: round;
  transition: transform var(--dur-2) var(--ease-out);
}
.pillar:hover .pillar__ico { transform: translateY(-3px) scale(1.04); }

/* ============================================================
   22. Footer — brand beside the link columns
   ============================================================ */
.footer__top {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 2.6fr);
  gap: clamp(2rem, 5vw, 4.5rem);
  align-items: start;
}
.footer__brand {
  /* the block sits at the left of the footer, but the mark centres over the
     wordmark below it rather than aligning to its left edge */
  justify-self: start; text-align: center;
  display: grid; justify-items: center; gap: 1rem;
  margin-top: 0;
  transition: opacity var(--dur-2) var(--ease);
}
.footer__brand:hover { opacity: .82; }
.footer__brand .logo__type { justify-items: center; }
.footer__brand .logo__mark { height: clamp(44px, 5vw, 58px); }
.footer__brand .logo__name { font-size: clamp(1.6rem, 2.6vw, 2.2rem); letter-spacing: .18em; }
.footer__brand .logo__sub { letter-spacing: .3em; opacity: .8; }

@media (max-width: 900px) {
  .footer__top { grid-template-columns: minmax(0, 1fr); gap: var(--sp-4); }
  .logo__mark { height: 44px; }
}

/* ============================================================
   23. Reduced motion — additions for the sections above
   ============================================================ */
@media (prefers-reduced-motion: reduce) {
  .burger::before { animation: none; opacity: 0; }

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

/* ============================================================
   24. Tablet and phone layout
   Four-up groups collapse to 2x2 rather than a single long list, so a
   phone still reads as a designed grid instead of a stack.
   Desktop (>1080px) is untouched by everything in this section.
   ============================================================ */

/* Tablet: 641-1080px keeps the two-column grids set in section 16. */
@media (max-width: 900px) {
  .header__right { gap: .6rem; }
  .grid-why { gap: clamp(1.75rem, 4vw, 3rem); }
}

@media (max-width: 640px) {
  :root { --section-y: clamp(3.5rem, 12vw, 5.5rem); }

  /* 2x2, not 1x4 */
  .grid-why   { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: clamp(1.5rem, 5vw, 2.25rem) clamp(1rem, 4vw, 1.75rem); }
  .grid-team  { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: clamp(1.5rem, 5vw, 2.25rem) clamp(1rem, 4vw, 1.75rem); }
  .footer__cols { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--sp-4) clamp(1rem, 4vw, 1.75rem); }
  .factgrid   { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .grid-services { grid-template-columns: repeat(2, minmax(0, 1fr)); }

  /* let the copy use the full column once the columns are narrow */
  .pillar__desc, .svc__desc, .member__bio { max-width: none; }
  .pillar { padding-top: var(--sp-3); }
  .pillar__ico { width: 34px; }

  /* header has three controls on one line now */
  .logo__mark { height: 40px; }
  .logo__name { font-size: 1.3rem; }
  .logo__sub  { font-size: .46rem; letter-spacing: .2em; }
  .header__right { gap: .45rem; }
  .burger { width: 46px; }
  .lang { padding: 0 .55rem; }

}

/* Very narrow: the six service cards need the full width to stay readable. */
@media (max-width: 520px) {
  .grid-services { grid-template-columns: minmax(0, 1fr); }
  .grid-results  { grid-template-columns: minmax(0, 1fr); }
}

@media (max-width: 380px) {
  .grid-why, .grid-team, .footer__cols { gap: var(--sp-3) .9rem; }
  .pillar__title, .member__name { font-size: 1.15rem; }
}

/* Short viewports (a 1280x800 laptop leaves ~660px of page) push the hero
   call-to-action just under the fold. Tightening the hero's vertical rhythm
   claws back ~115px there without touching the type size, so the design is
   unchanged on normal-height screens. Applies to both languages. */
@media (max-height: 760px) and (min-width: 641px) {
  .hero { padding-block: calc(var(--header-h) + 1rem) 1.5rem; }
  .hero__title { margin-block: .5rem .6rem; }
  .hero__actions { margin-top: 1rem; }
  .hero__lede { max-width: 42ch; }
}
/* ============================================================
   25. Language switch
   Two languages, so there is no menu: the control is a link straight to the
   other language's copy of the page you are on. Works with no JavaScript.
   ============================================================ */
.lang {
  display: inline-flex; align-items: center; justify-content: center; gap: .45rem;
  height: 44px; padding: 0 .8rem;
  border: var(--border) solid rgba(245, 242, 233, .3);
  color: var(--ivory);
  font-size: var(--fs-nav);
  font-weight: 500;
  letter-spacing: .14em;
  text-transform: uppercase;
  text-decoration: none;
  white-space: nowrap;
  transition: border-color var(--dur-2) var(--ease),
              background var(--dur-2) var(--ease),
              transform var(--dur-1) var(--ease);
}
.lang:hover, .lang:focus-visible {
  border-color: var(--ivory);
  background: rgba(245, 242, 233, .09);
}
.lang:active { transform: scale(.96); }
.lang__globe {
  width: 17px; height: 17px; flex: none;
  fill: none; stroke: currentColor; stroke-width: 1.4;
  stroke-linecap: round; stroke-linejoin: round;
}
.lang__code { line-height: 1; }
.lang__code[lang="ar"] { font-size: 1.15rem; letter-spacing: normal; text-transform: none; }
/* ============================================================
   26. Arabic / right-to-left
   ============================================================ */
/* Badr is a licensed typeface and is not on Google Fonts, so it is self-hosted.
   Drop the two files into assets/fonts/ and it takes effect with no other
   change; until then these rules 404 and the stack below falls through to
   Amiri, so the lockup still renders correctly.

   There is deliberately no local() source. Naming an installed copy would make
   the logo render from your own machine's fonts while every visitor without
   Badr silently got the fallback - the one difference you could never see. */
@font-face {
  font-family: "Badr";
  src: url("../assets/fonts/badr-regular.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Badr";
  src: url("../assets/fonts/badr-bold.woff2") format("woff2");
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

:root {
  --font-ar-display: "Amiri", "Noto Naskh Arabic", "Times New Roman", serif;
  --font-ar-sans: "IBM Plex Sans Arabic", "Noto Kufi Arabic", "Segoe UI", sans-serif;
  /* the lockup only - body copy stays on the Naskh/sans pairing above */
  --font-ar-logo: "Badr", "Amiri", "Noto Naskh Arabic", "Times New Roman", serif;
}

/* Arabic sits visually smaller than Latin at the same font-size, and its
   letterforms need more leading. Re-declaring the tokens here scales the whole
   Arabic side in one place - every rule that uses them follows automatically. */
[dir="rtl"] {
  --fs-lede:    clamp(1.32rem, 1.7vw, 1.65rem);
  --fs-body:    clamp(1.18rem, 1.28vw, 1.32rem);
  /* same collapse on the Arabic side, so both languages carry one prose size */
  --fs-small:   var(--fs-body);
  --fs-micro:   .95rem;
  --fs-nav:     .88rem;
  --fs-eyebrow: clamp(.98rem, 1.15vw, 1.12rem);
  --fs-h3:      clamp(1.5rem, 2.2vw, 1.95rem);
}

[dir="rtl"] body { font-family: var(--font-ar-sans); line-height: 1.95; }
[dir="rtl"] p, [dir="rtl"] .lede, [dir="rtl"] li { line-height: 1.95; }
[dir="rtl"] .ticklist li::before { margin-top: .72em; }

/* Arabic is cursive: letter-spacing pulls the joins apart and the word stops
   reading as a word. `!important` is deliberate - several component rules
   (.footer__brand .logo__sub among them) outrank a plain wildcard, and there
   is no case where tracking is wanted on Arabic text. */
[dir="rtl"] * { letter-spacing: normal !important; }

[dir="rtl"] .display,
[dir="rtl"] .display--1b,
[dir="rtl"] .hero__title,
[dir="rtl"] .quote blockquote,
[dir="rtl"] .svc__title,
[dir="rtl"] .pillar__title,
[dir="rtl"] .mgroup__title,
[dir="rtl"] .stat__figure,
[dir="rtl"] .result__figure,
[dir="rtl"] .member__name,
[dir="rtl"] .opening__title,
[dir="rtl"] .step__title,
[dir="rtl"] .phase__title,
[dir="rtl"] .mapcard__title,
[dir="rtl"] .factgrid dd { font-family: var(--font-ar-display); }

/* ---- Arabic lockup -------------------------------------------------------
   Both lines are Badr so the lockup reads as one drawn mark rather than two
   fonts stacked. The wordmark is bold and set noticeably larger than the Latin
   1.62rem, because Arabic sits optically smaller at the same font-size; the
   descriptor stays regular and subordinate.

   Neither width is set here. main.js measures the wordmark and scales the
   descriptor's font-size until the two edges line up - the same job tracking
   does on the Latin lockup, which Arabic cannot use without breaking its
   cursive joins. So these sizes set the RELATIVE weight of the two lines; the
   script settles the descriptor's final size at every breakpoint. */
[dir="rtl"] .logo__name {
  font-family: var(--font-ar-logo);
  font-size: 2.1rem;
  font-weight: 700;
}
[dir="rtl"] .logo__sub {
  font-family: var(--font-ar-logo);
  font-weight: 400;
  /* A starting point near the final size, so the first painted frame is close
     to the fitted one and the descriptor does not visibly jump on load.
     .85rem is roughly .40 of the 2.1rem wordmark - the same proportion the
     Latin lockup uses at .64rem/1.62rem - which is where the fit settles. */
  font-size: .85rem;
  opacity: .9;
}
[dir="rtl"] .footer__brand .logo__name { font-size: clamp(1.78rem, 3.4vw, 2.75rem); }

/* The header shrinks the wordmark at two breakpoints. Those rules are plain
   .logo__name, so the [dir="rtl"] rule above outranks them at every width and
   the Arabic mark would stay at its desktop size on a phone. These restate the
   step-downs in the same proportion the Latin lockup uses. */
@media (max-width: 640px) {
  [dir="rtl"] .logo__name { font-size: 1.68rem; }
}
@media (max-width: 380px) {
  [dir="rtl"] .logo__name { font-size: 1.6rem; }
}

/* Arabic has no case; uppercase transforms are noise on the label styles. */
[dir="rtl"] .eyebrow,
[dir="rtl"] .btn,
[dir="rtl"] .nav__link,
[dir="rtl"] .fcol__title,
[dir="rtl"] .stat__label,
[dir="rtl"] .quote__name,
[dir="rtl"] .svc__more,
[dir="rtl"] .link-arrow,
[dir="rtl"] .details dt,
[dir="rtl"] .field label,
[dir="rtl"] .jump__link,
[dir="rtl"] .menu__list a,
[dir="rtl"] .mgroup__list a,
[dir="rtl"] .result__title,
[dir="rtl"] .svc-row__label,
[dir="rtl"] .opening__cta,
[dir="rtl"] .member__role { text-transform: none; }

/* Arabic needs far more vertical room than the .86 line-height the Latin
   display face is set in: Naskh descenders and the diacritics sit well below
   the baseline and the hero lines clip them (.line is overflow:hidden). */
/* Naskh needs ~1.3 line-height where the Latin face runs at .86, so the same
   font-size would make the Arabic hero ~110px taller than the viewport and
   push the call-to-action buttons below the fold. Sized so that
   2 lines x (1.3 + .22 padding) still clears 100svh. */
/* Sized up to sit closer to the Latin headline, with leading generous enough
   that the descender dots of one line clear the ascenders of the next. */
/* Emphasis: the Latin headings italicise their closing words. Arabic has no
   italic, and slanting it would be synthetic oblique, so the emphasis is
   carried by kashida elongation in the copy itself (see
   tools/i18n-dictionary.js) with the text staying in Amiri. font-style is
   pinned to normal so no browser synthesises a slant. */
[dir="rtl"] .display em,
[dir="rtl"] .display--1b em {
  font-style: normal;
  font-weight: 400;
}

[dir="rtl"] .hero__title { font-size: clamp(2.8rem, 10vw, 9rem); line-height: 1.4; }

/* The Latin hero words rise out of a clipped line box. Arabic letters carry
   dots BELOW the baseline (the b and y of "nabni"), and that clip cut them in
   half - which read as stray white specks under the word. Arabic does not
   need the clip, so it is removed and the reveal becomes a short lift. */
[dir="rtl"] .hero__title .line { overflow: visible; padding-bottom: .06em; }
/* The dots that hang below ba and ya still reached into the next line. Line
   boxes sit flush by design, so the clearance has to be an explicit gap.
   Expressed in em so it tracks the headline size, clamped so it never falls
   below ~6px on a phone or overshoot on a large screen. */
/* Measured, not guessed: with no gap the ink of the two words overlapped by
   8px, because Amiri's dots and descenders sit outside the line box. .22em
   clears that and leaves ~10px of daylight, and being in em it holds at every
   headline size. */
[dir="rtl"] .hero__title .line:not(:last-child) { margin-bottom: clamp(10px, .22em, 44px); }
.js [dir="rtl"] .hero__title .line > [data-reveal] { transform: translateY(28px); }
.js [dir="rtl"] .hero__title .line > [data-reveal].is-in { transform: none; }
[dir="rtl"] .display { line-height: 1.45; }
/* matching the extra leading given to .display--2 on the Latin side; Arabic
   starts higher because naskh ascenders and marks need the room */
[dir="rtl"] .display--2 { line-height: 1.55; }
[dir="rtl"] .display--1b { line-height: 1.45; }
[dir="rtl"] .quote blockquote { line-height: 1.7; }
[dir="rtl"] .stat__figure, [dir="rtl"] .result__figure { line-height: 1.1; }

/* directional flips */
[dir="rtl"] .nav__link::after { transform-origin: left; }
[dir="rtl"] .nav__link:hover::after,
[dir="rtl"] .nav__link.is-active::after { transform-origin: right; }

[dir="rtl"] .link-arrow__ico,
[dir="rtl"] .svc__more span,
[dir="rtl"] .opening__cta span,
[dir="rtl"] .mapcard__meta span,
[dir="rtl"] .qbtn span { display: inline-block; transform: scaleX(-1); }
[dir="rtl"] .link-arrow:hover .link-arrow__ico { transform: scaleX(-1) translateX(5px); }
[dir="rtl"] .opening:hover .opening__cta span { transform: scaleX(-1) translateX(5px); }

[dir="rtl"] .fcol a:hover { transform: translateX(-3px); }
[dir="rtl"] .menu__list a:hover,
[dir="rtl"] .menu__list a:focus-visible { padding-left: .9rem; padding-right: 1.25rem; }
[dir="rtl"] .mgroup__list a:hover,
[dir="rtl"] .mgroup__list a:focus-visible { padding-left: 0; padding-right: .5rem; }
[dir="rtl"] .opening:hover { padding-left: 0; padding-right: .75rem; }

[dir="rtl"] .form__status {
  padding-left: 0; padding-right: var(--sp-3);
  border-left: 0; border-right: 2px solid var(--line);
}
[dir="rtl"] .svc__btn { text-align: right; }
[dir="rtl"] .stat__unit, [dir="rtl"] .result__unit { margin-left: 0; margin-right: .06em; }
[dir="rtl"] .ticklist li { grid-template-columns: 14px 1fr; }
[dir="rtl"] .skip-link { left: auto; right: var(--gutter); }

@media (max-width: 900px) {
  [dir="rtl"] .menu-panel { transform: translateX(100%); }
  [dir="rtl"] .menu-panel.is-open { transform: translateX(0); }
}

/* ============================================================
   27. Page transitions

   Fading the outgoing content out and the incoming content in cannot avoid a
   blank frame: the browser destroys the old document before it paints the new
   one, and what shows in the gap is the body background - the white/ivory
   flash. Cross-document view transitions fix this properly: the browser keeps
   a snapshot of the old page's last frame and cross-fades it into the new
   page's first frame, so there is no gap to see through.

   Both pages must opt in, which they do - every page loads this stylesheet.
   ============================================================ */
@view-transition { navigation: auto; }

::view-transition-old(root),
::view-transition-new(root) {
  animation-duration: var(--dur-page);
  animation-timing-function: var(--ease-soft);
}

/* First load (no previous page to cross-fade from) still eases in. */
@keyframes page-in { from { opacity: 0; } to { opacity: 1; } }

.js .site-header,
.js main,
.js .site-footer {
  /* `backwards`, not `both`: a forwards fill would pin opacity and block any
     later transition on these elements. */
  animation: page-in var(--dur-page-in) var(--ease-soft) backwards;
}
.js .site-header { animation-duration: calc(var(--dur-page-in) * .7); }
.js .site-footer { animation-delay: .12s; }

/* Where view transitions run, the arrival fade would play on top of the
   cross-fade and read as a double dip. Let the browser own it. */
@supports (view-transition-name: none) {
  .js .site-header,
  .js main,
  .js .site-footer { animation: none; }
}

/* ============================================================
   28. Reduced motion - additions for sections 24-27
   ============================================================ */
@media (prefers-reduced-motion: reduce) {
  .js .site-header, .js main, .js .site-footer { animation: none; }
  ::view-transition-old(root), ::view-transition-new(root) { animation: none; }
  .lang { transition: none; }
}
