/* ==========================================================================
   Weam AlHebshi — a theatre programme

   Grammar: chaptered editorial. The page is a printed programme. Chapters are
   the unit, grounds hard-cut between them, and each chapter carries its own
   scroll device rather than the whole page sharing one fade-up.

   Signature move: the house lights. `--house` (0 blacked out, 1 full lights)
   is written by scroll.js and drives the auditorium at the top of the page and
   the dimming around the theatre chapter.

   RTL: logical properties throughout. No physical left/right in layout code,
   so Arabic and English mirror from one stylesheet.
   ========================================================================== */

/* ----------------------------------------------------------------- font --- */

/* Somar, self-hosted as a single variable file covering weights 100 to 900.
   One 73KB request replaces the two Google-hosted Arabic families it stands in
   for. It carries its own Latin, so mixed Arabic/Latin strings ("MBC وSBC",
   "2004 – 2011") stay in one voice on the Arabic page. */
/* Latin faces, self-hosted (Google Fonts' variable builds, Latin subset).
   No third-party stylesheet in the critical path, and the files cache for
   a year. unicode-range keeps them off any page with no Latin text. */
@font-face {
  font-family: 'Playfair Display';
  font-style: normal;
  font-weight: 400 900;
  font-display: swap;
  src: url('/fonts/playfair-display-var.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'IBM Plex Sans';
  font-style: normal;
  font-weight: 100 700;
  font-display: swap;
  src: url('/fonts/ibm-plex-sans-var.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Somar';
  src: url('/fonts/somar-var.woff2') format('woff2');
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

/* --------------------------------------------------------------- tokens --- */

:root {
  /* Brand palette, overridden per-site by partials/head.ejs */
  --canvas: #f7f3ed;
  --ink: #11161b;
  --brand: #563761;
  --highlight: #f8be43;
  --accent: #ef604b;

  /* House lights, written by scroll.js */
  --house: 0;

  /* Grounds */
  --paper: var(--canvas);
  --paper-warm: color-mix(in srgb, var(--canvas) 92%, var(--brand) 8%);
  --ink-ground: color-mix(in srgb, var(--brand) 78%, #0b0509 22%);
  --brand-ground: var(--brand);
  --stage: #0c0810;

  /* Type colours. The mixes are set by measured contrast on the cream ground,
     not by eye: at 62% and 40% the secondary and faint tiers came in at 4.3:1
     and 2.8:1 against small text. */
  --tx: var(--ink);
  --tx-soft: color-mix(in srgb, var(--ink) 72%, var(--canvas));
  --tx-faint: color-mix(in srgb, var(--ink) 58%, var(--canvas));

  /* Two-stop accent, one hue. The brand coral is 2.95:1 on cream, which is
     fine for a rule or a large display figure and fails for the 12-13px
     labels it was being used on. This is the light-ground stop; --accent
     itself stays the dark-ground stop. */
  --accent-deep: color-mix(in srgb, var(--accent) 66%, #000);
  --on-dark: #f4efe6;
  --on-dark-soft: color-mix(in srgb, #f4efe6 66%, var(--brand));

  --rule: color-mix(in srgb, var(--ink) 14%, var(--canvas));
  --rule-dark: color-mix(in srgb, #f4efe6 20%, transparent);

  /* 4px base scale */
  --s1: 4px;  --s2: 8px;   --s3: 12px;  --s4: 16px;
  --s5: 24px; --s6: 32px;  --s7: 48px;  --s8: 64px;
  --s9: 96px; --s10: 128px; --s11: 176px;

  --gutter: clamp(20px, 5vw, 72px);
  --measure: 62ch;
  --wrap: 1180px;
  --chapter-pad: clamp(72px, 11vh, 152px);

  --r2: 2px; --r4: 4px; --r8: 8px; --r16: 16px; --r24: 24px; --pill: 999px;

  --ease: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-io: cubic-bezier(0.65, 0, 0.35, 1);
}

/* Somar carries both display and body in Arabic. Hierarchy comes from weight
   and scale rather than from a serif/sans pairing, which is why the very large
   headings drop to 300 below. Playfair and IBM Plex Sans carry the Latin page. */
html[lang='ar'] {
  --display: 'Somar', 'Noto Sans Arabic', 'Segoe UI', Tahoma, system-ui, sans-serif;
  --text: 'Somar', 'Noto Sans Arabic', 'Segoe UI', Tahoma, system-ui, sans-serif;
  /* Somar's Arabic descenders are deep; below ~1.4 the glyphs overflow
     their own line box and collide with whatever follows. */
  --display-lh: 1.42;
  --text-lh: 1.85;
  --display-track: 0;
  /* Somar's variable default is 900. Anything that fails to state a weight
     renders Black, so the weight is always explicit. */
  --display-weight: 400;
  --display-weight-xl: 300;
}

html[lang='en'] {
  --display: 'Playfair Display', Georgia, serif;
  --text: 'IBM Plex Sans', system-ui, sans-serif;
  --display-lh: 1.04;
  --text-lh: 1.62;
  --display-track: -0.02em;
  --display-weight: 400;
  --display-weight-xl: 400;
}

/* ---------------------------------------------------------------- reset --- */

*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-block-start: 96px;
}

body {
  margin: 0;
  background: var(--stage);
  color: var(--tx);
  font-family: var(--text);
  font-size: 1rem;
  line-height: var(--text-lh);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}

body.is-locked { overflow: hidden; }

img, svg, video { max-width: 100%; height: auto; display: block; }

h1, h2, h3 {
  margin: 0;
  font-family: var(--display);
  font-weight: var(--display-weight, 400);
  line-height: var(--display-lh);
  letter-spacing: var(--display-track);
  text-wrap: balance;
}

p, ul, ol, dl, figure, blockquote { margin: 0; }
ul, ol { padding: 0; list-style: none; }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }

:focus-visible {
  outline: 3px solid var(--highlight);
  outline-offset: 3px;
  border-radius: var(--r4);
}

::selection { background: var(--highlight); color: var(--ink); }

.sr-only {
  position: absolute;
  inline-size: 1px; block-size: 1px;
  overflow: hidden; clip-path: inset(50%);
  white-space: nowrap;
}

.skip-link {
  position: fixed;
  inset-block-start: -100px;
  inset-inline-start: var(--s4);
  z-index: 300;
  padding: var(--s3) var(--s5);
  background: var(--ink);
  color: var(--canvas);
  border-radius: var(--pill);
  transition: inset-block-start 240ms var(--ease);
}
.skip-link:focus { inset-block-start: var(--s4); }

/* ================================================================ chrome === */

.topbar {
  position: fixed;
  inset-block-start: max(var(--s4), env(safe-area-inset-top));
  inset-inline: 0;
  z-index: 150;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  grid-template-areas: 'spacer dock actions';
  align-items: center;
  gap: clamp(12px, 1.5vw, 24px);
  padding-inline: var(--gutter);
  color: var(--ink);
  mix-blend-mode: normal;
  pointer-events: none;
}

.topbar > * { pointer-events: auto; }



.topbar__actions { grid-area: actions; display: flex; align-items: center; justify-content: flex-end; gap: var(--s2); }

.topbar__lang {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s2);
  min-block-size: 62px;
  padding-inline: 18px;
  border: 1px solid rgba(255,255,255,.58);
  border-radius: 22px;
  background:
    linear-gradient(135deg, rgba(255,255,255,.5), rgba(255,255,255,.16) 45%, rgba(255,255,255,.32)),
    color-mix(in srgb, var(--canvas) 71%, transparent);
  -webkit-backdrop-filter: blur(28px) saturate(1.75);
  backdrop-filter: blur(28px) saturate(1.75);
  font-family: var(--text);
  font-size: 0.8125rem;
  font-weight: 500;
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.75),
    inset 0 -1px 0 rgba(86,55,97,.1),
    0 18px 50px -18px rgba(12,8,16,.38);
  transition: background-color 220ms var(--ease), color 220ms var(--ease), transform 220ms var(--ease);
}

.topbar__lang:hover {
  background: var(--highlight);
  color: var(--ink);
  transform: translateY(-1px);
}

/* Past the title page the bar steps down a size so it takes less of the
   reading screen. */
.topbar__lang, .dock__desktop { transition: min-block-size 320ms var(--ease), box-shadow 320ms var(--ease); }
html.is-scrolled .topbar__lang,
html.is-scrolled .dock__desktop { min-block-size: 50px; box-shadow: inset 0 1px 0 rgba(255,255,255,.75), 0 10px 30px -16px rgba(12,8,16,.4); }
html.is-scrolled .dock__item { min-block-size: 36px; }

/* ------------------------------------------------------- floating dock --- */

/* A single navigation surface replaces the old top-right index and separate
   folio. The backing is deliberately translucent: saturation and a pair of
   inset highlights create depth without obscuring the page underneath. */
[hidden] { display: none !important; }

.dock {
  grid-area: dock;
  position: static;
  z-index: auto;
  display: flex;
  justify-content: center;
  min-inline-size: 0;
  padding: 0;
  pointer-events: none;
}

.dock__desktop {
  position: relative;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  gap: 2px;
  inline-size: max-content;
  max-inline-size: 100%;
  min-block-size: 62px;
  padding: 9px 10px 8px;
  border: 1px solid rgba(255, 255, 255, 0.58);
  border-radius: 23px;
  background:
    linear-gradient(135deg, rgba(255,255,255,.5), rgba(255,255,255,.16) 45%, rgba(255,255,255,.32)),
    color-mix(in srgb, var(--canvas) 71%, transparent);
  -webkit-backdrop-filter: blur(28px) saturate(1.75);
  backdrop-filter: blur(28px) saturate(1.75);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.75),
    inset 0 -1px 0 rgba(86,55,97,.1),
    0 18px 50px -18px rgba(12,8,16,.46),
    0 3px 12px -5px rgba(12,8,16,.24);
  color: var(--ink);
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: none;
  pointer-events: auto;
  isolation: isolate;
}

.dock__desktop::-webkit-scrollbar { display: none; }

.dock__desktop::before {
  content: '';
  position: absolute;
  inset: 1px 8% auto;
  block-size: 34%;
  border-radius: var(--pill);
  background: linear-gradient(180deg, rgba(255,255,255,.44), transparent);
  pointer-events: none;
  z-index: -1;
}

.dock__item {
  --dock-scale: 1;
  --dock-lift: 0px;
  position: relative;
  z-index: 1;
  flex: none;
  display: grid;
  place-items: center;
  min-block-size: 44px;
  padding-inline: clamp(9px, 1vw, 15px);
  border-radius: 15px;
  transform: translateY(var(--dock-lift)) scale(var(--dock-scale));
  transform-origin: 50% 100%;
  transition:
    color 180ms var(--ease),
    background-color 180ms var(--ease),
    box-shadow 180ms var(--ease),
    transform 90ms linear;
  will-change: transform;
}

.dock__label {
  position: relative;
  z-index: 1;
  font-family: var(--text);
  font-size: clamp(0.66rem, 0.78vw, 0.78rem);
  font-weight: 500;
  line-height: 1;
  white-space: nowrap;
}

html[lang='ar'] .dock__label { font-size: clamp(0.74rem, 0.9vw, 0.88rem); }

.dock__item:hover,
.dock__item:focus-visible {
  background: rgba(255,255,255,.46);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.72), 0 7px 18px -12px rgba(12,8,16,.65);
}

.dock__item[aria-current='true'] {
  color: color-mix(in srgb, var(--brand) 84%, #000);
  background: color-mix(in srgb, var(--highlight) 20%, rgba(255,255,255,.38));
}

.dock__dot {
  position: absolute;
  inset-block-end: 4px;
  inline-size: 4px;
  block-size: 4px;
  border-radius: 50%;
  background: var(--accent);
  opacity: 0;
  transform: scale(.4);
  transition: opacity 180ms var(--ease), transform 240ms var(--ease);
}

.dock__item[aria-current='true'] .dock__dot { opacity: 1; transform: scale(1); }

.dock__progress {
  position: absolute;
  inset-inline-start: 18px;
  inset-block-end: 0;
  inline-size: calc((100% - 36px) * var(--read, 0));
  block-size: 1px;
  border-radius: var(--pill);
  background: color-mix(in srgb, var(--accent) 74%, transparent);
  transition: inline-size 80ms linear;
  pointer-events: none;
}

.dock__mobile {
  position: relative;
  display: none;
  inline-size: min(100%, 430px);
  pointer-events: auto;
}

.dock__mobile-toggle,
.dock__mobile-panel {
  border: 1px solid rgba(255,255,255,.6);
  background:
    linear-gradient(135deg, rgba(255,255,255,.54), rgba(255,255,255,.2)),
    color-mix(in srgb, var(--canvas) 76%, transparent);
  -webkit-backdrop-filter: blur(28px) saturate(1.8);
  backdrop-filter: blur(28px) saturate(1.8);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.82),
    inset 0 -1px 0 rgba(86,55,97,.1),
    0 20px 48px -18px rgba(12,8,16,.58),
    0 4px 14px -7px rgba(12,8,16,.34);
}

.dock__mobile-toggle {
  position: relative;
  z-index: 2;
  inline-size: 100%;
  min-block-size: 54px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s4);
  padding-inline: 19px 17px;
  border-radius: 19px;
  color: var(--ink);
}

.dock__mobile-current {
  min-inline-size: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: .9rem;
  font-weight: 600;
}

html[lang='ar'] .dock__mobile-current { font-size: 1rem; }

.dock__mobile-bars {
  flex: none;
  display: inline-flex;
  flex-direction: column;
  gap: 5px;
  inline-size: 18px;
}

.dock__mobile-bars i {
  display: block;
  inline-size: 18px;
  block-size: 1.5px;
  border-radius: var(--pill);
  background: currentColor;
  transition: transform 260ms var(--ease);
}

.dock__mobile-toggle[aria-expanded='true'] .dock__mobile-bars i:first-child {
  transform: translateY(3.25px) rotate(45deg);
}

.dock__mobile-toggle[aria-expanded='true'] .dock__mobile-bars i:last-child {
  transform: translateY(-3.25px) rotate(-45deg);
}

.dock__mobile-panel {
  position: absolute;
  inset-inline: 0;
  inset-block-start: calc(100% + var(--s2));
  max-block-size: min(64svh, 540px);
  padding: var(--s4);
  border-radius: 24px;
  overflow-y: auto;
  overscroll-behavior: contain;
  color: var(--ink);
  transform-origin: 50% 0;
  animation: dock-open 320ms var(--ease) both;
}

@keyframes dock-open {
  from { opacity: 0; transform: translateY(-10px) scale(.96); }
  to { opacity: 1; transform: none; }
}

.dock__mobile-title {
  padding: var(--s2) var(--s3) var(--s4);
  color: var(--tx-faint);
  font-size: .72rem;
  font-weight: 600;
  letter-spacing: .1em;
  text-transform: uppercase;
}

html[lang='ar'] .dock__mobile-title { font-size: .82rem; letter-spacing: 0; }

.dock__mobile-list {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 3px;
}

.dock__mobile-link {
  display: flex;
  align-items: center;
  gap: var(--s3);
  min-block-size: 50px;
  padding: var(--s2) var(--s3);
  border-radius: 14px;
  font-size: .82rem;
  line-height: 1.25;
  transition: background-color 180ms var(--ease), transform 180ms var(--ease);
}

html[lang='ar'] .dock__mobile-link { font-size: .92rem; }

.dock__mobile-link:hover,
.dock__mobile-link:focus-visible,
.dock__mobile-link[aria-current='true'] {
  background: rgba(255,255,255,.58);
}

.dock__mobile-link:active { transform: scale(.98); }

.dock__mobile-num {
  flex: none;
  color: var(--accent-deep);
  font-size: .66rem;
  font-weight: 600;
  letter-spacing: .06em;
}

/* ------------------------------------------------------- glass, adaptive --- */

/* Thinner glass: less canvas in the mix, more of the page through it, a
   stronger blur so what shows is colour rather than detail, and a hairline
   of light along the top edge. On the dark chapters (data-ground, from
   scroll.js) the same glass goes smoky so the labels stay readable. */
.topbar__lang, .dock__desktop, .dock__mobile-toggle, .dock__mobile-panel {
  border-color: rgba(255,255,255,.55);
  background:
    linear-gradient(160deg, rgba(255,255,255,.42), rgba(255,255,255,.08) 40%, rgba(255,255,255,.18)),
    color-mix(in srgb, var(--canvas) 30%, transparent);
  -webkit-backdrop-filter: blur(40px) saturate(1.9);
  backdrop-filter: blur(40px) saturate(1.9);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.85),
    inset 0 -1px 0 rgba(86,55,97,.06),
    0 16px 40px -20px rgba(12,8,16,.35);
  transition: background-color 400ms var(--ease), border-color 400ms var(--ease), color 400ms var(--ease), min-block-size 320ms var(--ease), box-shadow 320ms var(--ease);
}
.dock__desktop::before { background: linear-gradient(180deg, rgba(255,255,255,.34), transparent); }

html[data-ground='dark'] .topbar__lang,
html[data-ground='dark'] .dock__desktop,
html[data-ground='dark'] .dock__mobile-toggle,
html[data-ground='dark'] .dock__mobile-panel {
  color: var(--on-dark);
  border-color: rgba(255,255,255,.16);
  background:
    linear-gradient(160deg, rgba(255,255,255,.14), rgba(255,255,255,.02) 40%, rgba(255,255,255,.06)),
    rgba(22, 12, 28, .34);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.22),
    inset 0 -1px 0 rgba(0,0,0,.2),
    0 16px 40px -20px rgba(0,0,0,.6);
}
html[data-ground='dark'] .dock__desktop::before { background: linear-gradient(180deg, rgba(255,255,255,.12), transparent); }
html[data-ground='dark'] .dock__item:hover,
html[data-ground='dark'] .dock__item:focus-visible { background: rgba(255,255,255,.12); box-shadow: inset 0 1px 0 rgba(255,255,255,.18); }
html[data-ground='dark'] .dock__item[aria-current='true'] { color: var(--ink); background: color-mix(in srgb, var(--highlight) 78%, #fff); }
html[data-ground='dark'] .dock__mobile-link:hover,
html[data-ground='dark'] .dock__mobile-link[aria-current='true'] { background: rgba(255,255,255,.14); }
html[data-ground='dark'] .dock__mobile-title { color: var(--on-dark-soft); }
html[data-ground='dark'] .dock__mobile-lang { color: var(--ink); }
html[data-ground='dark'] .topbar__lang:hover { color: var(--ink); }

/* ============================================================ title page === */

/* The programme cover. The only place on the page with a spotlight. */
.title {
  position: relative;
  min-block-size: 100svh;
  display: grid;
  align-items: center;
  padding-block: clamp(120px, 18vh, 200px) clamp(72px, 12vh, 140px);
  padding-inline: var(--gutter);
  background: var(--stage);
  color: var(--on-dark);
  overflow: clip;
  isolation: isolate;
}

/* The light itself. --mx / --my are written by scroll.js. */
.title__house {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
}

.title__pool {
  position: absolute;
  inset: -20%;
  background:
    radial-gradient(
      42vmax 42vmax at var(--mx, 50%) var(--my, 42%),
      color-mix(in srgb, var(--highlight) 26%, transparent) 0%,
      color-mix(in srgb, var(--highlight) 9%, transparent) 34%,
      transparent 68%
    );
  transition: background 60ms linear;
}

.title__haze {
  position: absolute;
  inset: 0;
  background:
    radial-gradient(
      60vmax 60vmax at var(--mx, 50%) var(--my, 42%),
      color-mix(in srgb, var(--brand) 34%, transparent) 0%,
      transparent 62%
    );
  mix-blend-mode: screen;
  opacity: 0.7;
}

/* The portrait is carved out of the dark by the light: the image is masked to
   the spotlight, so she is only where the beam is. */
.title__portrait {
  position: absolute;
  inset-block: 0;
  inset-inline-end: 0;
  inline-size: min(58vw, 720px);
  z-index: 1;
  margin: 0;
  pointer-events: none;
  -webkit-mask-image:
    radial-gradient(
      38vmax 38vmax at var(--mx, 50%) var(--my, 42%),
      #000 0%, rgba(0, 0, 0, 0.72) 38%, transparent 72%
    );
  mask-image:
    radial-gradient(
      38vmax 38vmax at var(--mx, 50%) var(--my, 42%),
      #000 0%, rgba(0, 0, 0, 0.72) 38%, transparent 72%
    );
}

.title__portrait img {
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
  object-position: 50% 16%;
  filter: contrast(1.06) saturate(0.92);
}

/* The plate never depends on the light for legibility: type contrast is fixed
   regardless of where the spotlight happens to be. */
.title__plate {
  position: relative;
  z-index: 2;
  inline-size: min(100%, var(--wrap));
  margin-inline: auto;
}
/* Each line of the plate measures itself; the plate is the page wrap, so the
   words sit at the reading edge on any screen width. */
.title__place, .title__name, .title__lede { max-inline-size: 40ch; }

.title__place {
  font-size: 0.75rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--highlight);
  margin-block-end: var(--s6);
}

html[lang='ar'] .title__place {
  letter-spacing: 0;
  text-transform: none;
  font-size: 0.9rem;
}

.title__name {
  font-size: clamp(3rem, 11vw, 8rem);
  line-height: 1.06;
  color: #fff;
  margin-block-end: var(--s5);
  text-shadow: 0 2px 40px rgba(0, 0, 0, 0.6);
}

html[lang='ar'] .title__name { line-height: 1.34; font-weight: var(--display-weight-xl); }

.title__role {
  font-family: var(--display);
  font-size: clamp(1.15rem, 2.8vw, 1.9rem);
  color: var(--highlight);
  margin-block-end: var(--s5);
  /* Wide enough for the longest phrase plus the pill's padding with margin
     to spare; 460 fit it by a single pixel. */
  inline-size: min(520px, calc(100vw - (var(--gutter) * 2)));
  min-block-size: 2.2em;
}

.title__role-shell {
  display: inline-grid;
  align-items: center;
  inline-size: max-content;
  max-inline-size: 100%;
  min-block-size: 1.75em;
  padding: .2em .62em .28em;
  border: 1px solid color-mix(in srgb, var(--highlight) 42%, rgba(255,255,255,.2));
  border-radius: .48em;
  background:
    linear-gradient(180deg, rgba(255,255,255,.16), transparent 68%),
    color-mix(in srgb, var(--highlight) 16%, rgba(12,8,16,.62));
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.2),
    inset 0 -1px 0 color-mix(in srgb, var(--highlight) 24%, transparent),
    0 8px 20px -13px rgba(0,0,0,.8);
  overflow: hidden;
  vertical-align: top;
  transition: inline-size 350ms var(--ease), background-color 260ms var(--ease);
  will-change: inline-size;
}

.title__role-word {
  grid-area: 1 / 1;
  display: inline-block;
  justify-self: start;
  inline-size: max-content;
  white-space: nowrap;
  line-height: 1.28;
  opacity: 1;
  filter: blur(0);
  transform: translateY(0);
  transition: opacity 240ms var(--ease), filter 240ms var(--ease), transform 240ms var(--ease);
}

.title__role.is-leaving .title__role-word {
  opacity: 0;
  filter: blur(9px);
  transform: translateY(-.28em);
}

.title__role-piece {
  display: inline-block;
  opacity: 0;
  filter: blur(9px);
  transform: translateY(.22em);
  animation: role-piece-in 380ms var(--ease) forwards;
  animation-delay: calc(var(--piece, 0) * 18ms);
}

@keyframes role-piece-in {
  to { opacity: 1; filter: blur(0); transform: translateY(0); }
}

.title__role.is-wrapping .title__role-word {
  inline-size: auto;
  white-space: normal;
  text-wrap: balance;
}

.title__role[data-flip-static] .title__role-shell {
  inline-size: auto !important;
}

.title__role[data-flip-static] .title__role-word {
  inline-size: auto;
  white-space: normal;
}

.title__lede { text-wrap: pretty; }

.title__lede {
  font-size: clamp(1rem, 1.5vw, 1.125rem);
  line-height: 1.75;
  color: var(--on-dark-soft);
  max-inline-size: 46ch;
  margin-block-end: var(--s7);
}

.title__cta {
  display: inline-flex;
  align-items: center;
  gap: var(--s3);
  min-block-size: 52px;
  padding-inline: var(--s6);
  border-radius: var(--pill);
  background: var(--highlight);
  color: var(--ink);
  font-weight: 600;
  font-size: 0.95rem;
  transition: transform 220ms var(--ease), background-color 220ms var(--ease);
}

.title__cta:hover { transform: translateY(-2px); background: #ffd06b; }
.title__cta svg { inline-size: 18px; block-size: 18px; }
/* The arrow points the way the language reads. */
html[dir='rtl'] .title__cta svg { transform: scaleX(-1); }

/* ============================================================== chapters === */

.ch {
  position: relative;
  padding-block: var(--chapter-pad);
  overflow: clip;
}

.ch__inner {
  position: relative;
  z-index: 1;
  inline-size: min(100% - (var(--gutter) * 2), var(--wrap));
  margin-inline: auto;
}

/* Grounds hard-cut between chapters. Each restates `color` alongside its
   tokens: `color` inherits as a computed value, so redefining --tx on a
   subtree alone would leave the text inking from <body>. */
.ch--paper { background: var(--paper); --tx: var(--ink); color: var(--tx); }
.ch--ink   { background: var(--ink-ground); --tx: var(--on-dark); --tx-soft: var(--on-dark-soft); --rule: var(--rule-dark); color: var(--tx); }
.ch--brand { background: var(--brand-ground); --tx: var(--on-dark); --tx-soft: var(--on-dark-soft); --rule: var(--rule-dark); color: var(--tx); }
.ch--stage { background: var(--stage); --tx: var(--on-dark); --tx-soft: var(--on-dark-soft); --rule: var(--rule-dark); color: var(--tx); }

/* Light type on dark ground needs compensation on three axes. */
.ch--ink, .ch--brand, .ch--stage { line-height: calc(var(--text-lh) + 0.06); letter-spacing: 0.005em; }

/* Anchor links land the heading under the fixed bar rather than behind it. */
.ch { scroll-margin-block-start: 84px; }

/* A pointer light on the dark grounds: a soft pool that follows the cursor
   (--lx/--ly from scroll.js), the same idea as the title page's spotlight at a
   fraction of the strength. Touch never sees it. */
.ch--ink::after, .ch--brand::after, .ch--stage::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background: radial-gradient(560px circle at var(--lx, 50%) var(--ly, 50%),
              rgba(255, 255, 255, 0.055), transparent 62%);
  opacity: var(--lo, 0);
  transition: opacity 500ms var(--ease);
}
.ch--ink > *, .ch--brand > *, .ch--stage > * { position: relative; z-index: 1; }
.ch--ink p, .ch--brand p, .ch--stage p { font-weight: 300; }
html[lang='ar'] .ch--ink p,
html[lang='ar'] .ch--brand p,
html[lang='ar'] .ch--stage p { font-weight: 400; }

/* -------------------------------------------------------- chapter head --- */

/* More space above a heading than below it: the gap belongs to the boundary
   between chapters, not to the heading-and-body pair. */
.ch__head { margin-block-end: clamp(40px, 6vh, 72px); max-inline-size: 34ch; }
.ch__head--wide { max-inline-size: 46ch; }
.ch__head--centre { max-inline-size: 46ch; margin-inline: auto; text-align: center; }

.ch__folio {
  font-family: var(--text);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.22em;
  color: var(--accent-deep);
  margin-block-end: var(--s4);
  font-variant-numeric: tabular-nums;
}

.ch--ink .ch__folio, .ch--brand .ch__folio, .ch--stage .ch__folio { color: var(--highlight); }

.ch__eyebrow {
  font-size: 0.8125rem;
  color: var(--tx-soft);
  margin-block-end: var(--s3);
}

.ch__title {
  font-size: clamp(2rem, 5.4vw, 3.6rem);
}

html[lang='ar'] .ch__title { font-weight: var(--display-weight-xl); }
html[lang='ar'] .close__heading,
html[lang='ar'] .vision__label { font-weight: var(--display-weight-xl); }

.ch__title--rail { font-size: clamp(1.9rem, 4.4vw, 3rem); }

.ch__lede {
  margin-block-start: var(--s5);
  font-size: clamp(1.0625rem, 1.7vw, 1.25rem);
  color: var(--tx-soft);
  max-inline-size: var(--measure);
  text-wrap: pretty;
}

.ch__head--centre .ch__lede { margin-inline: auto; }

/* ============================================================== devices === */

/* --- enter: the base flow reveal ---------------------------------------- */

[data-enter] {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity 640ms var(--ease), transform 640ms var(--ease);
  transition-delay: calc(var(--i, 0) * 55ms);
}

[data-enter].is-in { opacity: 1; transform: none; }

/* Safety net for a page whose script never ran: a JS error, a blocked
   request, or a browser without IntersectionObserver. scroll.js adds
   .js-ready as its first statement, so this never applies when scripting is
   healthy. Without it a broken script leaves a blank page. */
html:not(.js-ready) [data-enter] {
  animation: enter-fallback 1ms linear 2.5s forwards;
}

@keyframes enter-fallback { to { opacity: 1; transform: none; } }

/* Scroll-driven clips are worse than the fade on failure: with no --sc-p a
   wipe resolves to inset(... 100%) and the content is not merely unanimated,
   it is invisible. Unclip everything that depends on progress until the
   script has confirmed it is running. */
html:not(.js-ready) [data-wipe],
html:not(.js-ready) .theatre__title {
  clip-path: none;
}

html:not(.js-ready) .theatre__beam { opacity: 0.45; }
html:not(.js-ready) .method__stages { min-block-size: 0; display: grid; gap: var(--s5); }
html:not(.js-ready) .method__stage {
  position: static; opacity: 1; transform: none; pointer-events: auto;
}

/* --- kinetic: type that assembles --------------------------------------- */

.ln {
  display: block;
  overflow: hidden;
  /* The clip box is the line box, which is shorter than the glyph extent;
     without this the wipe slices ascenders and descenders. */
  padding-block: 0.14em;
  margin-block: -0.14em;
}

html[lang='ar'] .ln { padding-block: 0.24em; margin-block: -0.24em; }

.ln > span {
  display: block;
  transform: translateY(105%);
  transition: transform 760ms var(--ease);
  transition-delay: calc(var(--ln, 0) * 85ms);
}

[data-kinetic].is-in .ln > span { transform: none; }
html:not(.js-ready) .ln > span { transform: none; }

/* --- reveal: a wipe is a change of state -------------------------------- */

/* Driven from the chapter's own --sc-p rather than an entrance class, so the
   wipe tracks the hand instead of firing once. */
[data-wipe] {
  --w: clamp(0, calc((var(--sc-p, 0) - 0.12) / 0.3), 1);
}

[data-wipe='start'] { clip-path: inset(0 0 0 calc((1 - var(--w)) * 100%)); }
[data-wipe='end']   { clip-path: inset(0 calc((1 - var(--w)) * 100%) 0 0); }

/* In RTL the two panels should wipe in from the mirrored edges. */
html[dir='rtl'] [data-wipe='start'] { clip-path: inset(0 calc((1 - var(--w)) * 100%) 0 0); }
html[dir='rtl'] [data-wipe='end']   { clip-path: inset(0 0 0 calc((1 - var(--w)) * 100%)); }

/* ================================================================= about === */

.about { position: relative; }

.about__inner {
  display: grid;
  grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
  gap: clamp(32px, 7vw, 104px);
  align-items: start;
}

.about__inner .ch__head { margin-block-end: var(--s6); }

/* ---- portrait with orbits --------------------------------------------- */

.about__portrait {
  --ring: clamp(220px, 24vw, 340px);
  position: relative;
  inline-size: var(--ring);
  aspect-ratio: 1;
  margin: 0;
  margin-inline-start: clamp(8px, 2vw, 28px);
  border-radius: 50%;
  isolation: isolate;
}

.about__portrait img {
  inline-size: 100%;
  block-size: 100%;
  border-radius: 50%;
  object-fit: cover;
  object-position: 50% 14%;
  border: 4px solid var(--paper);
  box-shadow: 0 30px 60px -30px rgba(17, 22, 27, 0.45);
  filter: contrast(1.04) saturate(0.94);
}

/* Two arcs: a border with three transparent sides is a quarter arc. They
   turn against the chapter's scroll progress, so a reader who stops sees
   them stop. */
.about__orbit {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  border: 1.5px solid transparent;
  pointer-events: none;
  z-index: 1;
}
.about__orbit--a {
  inset: -9%;
  border-block-start-color: var(--highlight);
  border-inline-end-color: var(--highlight);
  rotate: calc(-30deg + var(--sc-p, 0) * 200deg);
}
.about__orbit--b {
  inset: -18%;
  border-block-end-color: var(--accent);
  rotate: calc(120deg + var(--sc-p, 0) * -140deg);
  opacity: 0.85;
}
.about__orbit--b::after {
  /* A small planet on the outer arc. */
  content: '';
  position: absolute;
  inset-block-end: -5px;
  inset-inline-start: 50%;
  inline-size: 9px; block-size: 9px;
  border-radius: 50%;
  background: var(--accent);
}

.about__portrait[data-enter] { transform: translateY(18px) scale(0.94); }
.about__portrait[data-enter].is-in { transform: none; }

/* ---- prose ------------------------------------------------------------ */

.about__body { display: grid; gap: var(--s5); }

.about__para {
  color: var(--tx-soft);
  font-size: 1.0625rem;
  max-inline-size: var(--measure);
  text-wrap: pretty;
}

.about__para--lead {
  font-family: var(--display);
  font-size: clamp(1.3rem, 2.4vw, 1.85rem);
  line-height: 1.55;
  color: var(--tx);
}
html[lang='ar'] .about__para--lead { line-height: 1.7; font-weight: 400; }

/* The closing thought, set apart with a rule so it reads as her own voice. */
.about__para--note {
  font-family: var(--display);
  font-size: clamp(1.1rem, 1.7vw, 1.3rem);
  line-height: 1.5;
  color: var(--brand);
  padding-inline-start: var(--s5);
  border-inline-start: 3px solid var(--highlight);
}
html[lang='ar'] .about__para--note { line-height: 1.7; }

/* ---- facts ------------------------------------------------------------ */

.about__facts {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--s4);
  margin-block-start: var(--s3);
  padding-block-start: var(--s5);
  border-block-start: 1px solid var(--rule);
  list-style: none; padding-inline: 0;
}

.about__fact { display: grid; gap: 4px; }
.about__fact-val {
  font-family: var(--display);
  font-size: clamp(1.7rem, 3vw, 2.4rem);
  line-height: 1;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}
.about__fact-label { font-size: 0.82rem; color: var(--tx-soft); }

@media (max-width: 1040px) {
  .about__inner { grid-template-columns: 1fr; gap: var(--s6); }
  .about__portrait { --ring: clamp(200px, 56vw, 300px); margin-inline: auto; }
  .about__inner .ch__head { margin-block-end: var(--s5); }
}
@media (max-width: 520px) {
  .about__facts { grid-template-columns: 1fr 1fr; }
}

/* ================================================================ vision === */

.vision { position: relative; padding-block: clamp(88px, 14vh, 180px); overflow: hidden; }

/* A soft brand glow that crosses the chapter as it is read. */
.vision__glow {
  position: absolute;
  inset-block-start: 50%;
  inset-inline-start: calc(-20% + var(--sc-p, 0) * 80%);
  inline-size: min(70vw, 900px);
  aspect-ratio: 1;
  translate: 0 -50%;
  border-radius: 50%;
  background: radial-gradient(closest-side, color-mix(in srgb, var(--brand) 55%, transparent), transparent 72%);
  pointer-events: none;
}

.vision__grid {
  position: relative;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 340px), 1fr));
  gap: clamp(24px, 4vw, 56px);
  perspective: 1400px;
}

.vision__panel { min-inline-size: 0; display: grid; }
.vision__wipe { display: grid; }
.glare { display: grid; }
/* Each card tips in from its own side of the screen. */
.vision__panel--start[data-enter] { transform: translateX(-30px) rotateY(10deg); transform-origin: 0 50%; }
.vision__panel--end[data-enter]   { transform: translateX(30px) rotateY(-10deg); transform-origin: 100% 50%; }
html[dir='rtl'] .vision__panel--start[data-enter] { transform: translateX(30px) rotateY(-10deg); transform-origin: 100% 50%; }
html[dir='rtl'] .vision__panel--end[data-enter]   { transform: translateX(-30px) rotateY(10deg); transform-origin: 0 50%; }
.vision__panel[data-enter].is-in,
html[dir='rtl'] .vision__panel[data-enter].is-in { transform: none; }

/* ---------------------------------------------------------- glare card --- */

/* Ported from a React/Tailwind component to plain CSS. The behaviour is the
   same: a holographic foil and a specular sheen that track the pointer, over a
   card that tilts toward it.
   `--glare-max` is the single dial for how loud the foil gets. */
.glare {
  --m-x: 50%;
  --m-y: 50%;
  --r-x: 0deg;
  --r-y: 0deg;
  --bg-x: 50%;
  --bg-y: 50%;
  --duration: 300ms;
  --easing: ease;
  --foil-size: 100%;
  --opacity: 0;
  /* The single dial for how loud the effect gets. The source component uses
     0.6, which is built for a card carrying almost no copy; these carry a
     paragraph each, so it sits far lower. Both the foil and the sheen read
     this, so one number moves the whole effect. */
  --glare-max: 0.1;
  --radius: 28px;

  position: relative;
  block-size: 100%;
  perspective: 600px;
  /* Contains the blend modes so the foil never composites against the page. */
  isolation: isolate;
  contain: layout style;
}

.glare__tilt {
  position: relative;
  display: grid;
  block-size: 100%;
  padding: clamp(28px, 4vw, 52px);
  border: 1px solid var(--rule-dark);
  border-radius: var(--radius);
  background: color-mix(in srgb, var(--on-dark) 5%, transparent);
  overflow: hidden;
  transform-origin: center;
  transform: rotateY(var(--r-x)) rotateX(var(--r-y));
  transition: transform var(--duration) var(--easing);
  will-change: transform;
}

/* Each layer rounds itself rather than relying on the ancestor's clip. A
   blended layer inside a 3D-transformed ancestor gets composited separately,
   and a composited layer is clipped to the ancestor's *square* bounds, so the
   foil painted into the corners. */
.glare__sheen,
.glare__foil {
  position: absolute;
  inset: 0;
  z-index: 1;
  opacity: var(--opacity);
  pointer-events: none;
  border-radius: var(--radius);
  clip-path: inset(0 round var(--radius));
  transition: opacity var(--duration) var(--easing);
}

/* Specular highlight, close to the source component. */
.glare__sheen {
  mix-blend-mode: soft-light;
  background: radial-gradient(
    farthest-corner circle at var(--m-x) var(--m-y),
    rgba(255, 255, 255, 0.7) 10%,
    rgba(255, 255, 255, 0.55) 20%,
    rgba(255, 255, 255, 0) 88%
  );
}

.glare__foil {
  --step: 5%;
  --foil-svg: url("data:image/svg+xml,%3Csvg width='26' height='26' viewBox='0 0 26 26' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M2.99994 3.419C2.99994 3.419 21.6142 7.43646 22.7921 12.153C23.97 16.8695 3.41838 23.0306 3.41838 23.0306' stroke='white' stroke-width='5' stroke-miterlimit='3.86874' stroke-linecap='round' style='mix-blend-mode:darken'/%3E%3C/svg%3E");
  --pattern: var(--foil-svg) center / 100% no-repeat;
  --rainbow: repeating-linear-gradient(
      0deg,
      rgb(255, 119, 115) calc(var(--step) * 1),
      rgba(255, 237, 95, 1) calc(var(--step) * 2),
      rgba(168, 255, 95, 1) calc(var(--step) * 3),
      rgba(131, 255, 247, 1) calc(var(--step) * 4),
      rgba(120, 148, 255, 1) calc(var(--step) * 5),
      rgb(216, 117, 255) calc(var(--step) * 6),
      rgb(255, 119, 115) calc(var(--step) * 7)
    ) 0% var(--bg-y) / 200% 700% no-repeat;
  --diagonal: repeating-linear-gradient(
      128deg,
      #0e152e 0%,
      hsl(180, 10%, 60%) 3.8%,
      hsl(180, 10%, 60%) 4.5%,
      hsl(180, 10%, 60%) 5.2%,
      #0e152e 10%,
      #0e152e 12%
    ) var(--bg-x) var(--bg-y) / 300% no-repeat;
  --shade: radial-gradient(
      farthest-corner circle at var(--m-x) var(--m-y),
      rgba(255, 255, 255, 0.1) 12%,
      rgba(255, 255, 255, 0.15) 20%,
      rgba(255, 255, 255, 0.25) 120%
    ) var(--bg-x) var(--bg-y) / 300% no-repeat;

  background: var(--pattern), var(--rainbow), var(--diagonal), var(--shade);
  background-blend-mode: hue, hue, hue, overlay;
  mix-blend-mode: color-dodge;
  /* No `will-change: background` here. Promoting this to its own compositing
     layer is what let it escape the rounded corner clip, and it buys nothing:
     the background positions move through custom properties, which repaint
     regardless. */
}

.glare__foil::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  clip-path: inset(0 round var(--radius));
  background: inherit;
  background-size: var(--foil-size), 200% 400%, 800%, 200%;
  background-position:
    center,
    0% var(--bg-y),
    calc(var(--bg-x) * -1) calc(var(--bg-y) * -1),
    var(--bg-x) var(--bg-y);
  background-blend-mode: soft-light, hue, hard-light;
  mix-blend-mode: exclusion;
}

/* Copy sits above the blended layers, never inside them. The original blends
   its content with soft-light, which would drop this text well below the
   contrast floor the rest of the page is held to. */
.glare__content {
  position: relative;
  z-index: 2;
}

/* Readability under the foil is handled with a halo on the glyphs rather than
   a panel behind them. A scrim reads as a dark box sitting inside the card;
   a shadow hugs the letterforms and is invisible as a shape.
   Both shadows scale with --opacity, so they are fully transparent at rest and
   only appear while the foil is lit. */
.glare__content .vision__label,
.glare__content .vision__body {
  text-shadow:
    0 1px 14px rgba(12, 8, 16, calc(var(--opacity) * 3)),
    0 0 5px rgba(12, 8, 16, calc(var(--opacity) * 2.4)),
    0 0 2px rgba(12, 8, 16, calc(var(--opacity) * 2));
}

/* Hover only where there is a real pointer: touch would latch the foil on
   after the first tap and never release it. */
@media (hover: hover) and (pointer: fine) {
  .glare:hover {
    --opacity: var(--glare-max);
    --easing: linear;
    --duration: 200ms;
  }
}

.vision__label {
  font-size: clamp(1.6rem, 3.4vw, 2.4rem);
  color: var(--highlight);
  margin-block-end: var(--s5);
}

.vision__body {
  font-size: clamp(1rem, 1.5vw, 1.15rem);
  color: var(--on-dark-soft);
  max-inline-size: 46ch;
  text-wrap: pretty;
}

/* ============================================================== services === */

/* Lateral rail. The chapter's height is the travel; the pin holds the row
   still while the page scrolls past it. */
/* Trimmed so the peak keeps the longest span on the page. */
.svc { padding-block: 0; block-size: 205vh; }

.svc__pin {
  position: sticky;
  inset-block-start: 0;
  block-size: 100svh;
  display: flex;
  align-items: center;
  overflow: hidden;
}
.svc__pin .ch__wm { inset-block-start: 8vh; }

.svc__rail {
  position: relative;
  display: flex;
  align-items: stretch;
  gap: clamp(16px, 2vw, 28px);
  padding-inline: var(--gutter);
  will-change: transform;
  /* Room for the cards to sit forward and back. */
  perspective: 1400px;
}

.rail-item { flex: none; inline-size: clamp(280px, 30vw, 400px); }

.svc__lead {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: center;
  inline-size: clamp(260px, 26vw, 360px);
}

.svc__count {
  position: absolute;
  inset-block-end: 6%;
  inset-inline-start: -0.05em;
  font-family: var(--display);
  font-size: clamp(6rem, 12vw, 11rem);
  line-height: 1;
  color: color-mix(in srgb, var(--brand) 7%, transparent);
  pointer-events: none;
  z-index: -1;
}

.svc__card {
  position: relative;
  display: flex;
  flex-direction: column;
  padding: clamp(24px, 2.6vw, 36px);
  border-radius: var(--r24);
  background: #fffdf9;
  border: 1px solid var(--rule);
  box-shadow: 0 1px 2px rgba(17, 22, 27, 0.04);
  overflow: hidden;
  /* --d is 0 for the card nearest the centre of the screen, 1 at the edges:
     the row curves away from the reader. Pointer tilt rides on top. */
  transform:
    translateY(calc(var(--d, 0) * 14px))
    scale(calc(1 - var(--d, 0) * 0.05))
    rotateX(var(--tx, 0deg)) rotateY(var(--ty, 0deg));
  opacity: calc(1 - var(--d, 0) * 0.28);
  transition: transform 400ms var(--ease), box-shadow 300ms var(--ease), opacity 400ms var(--ease);
}

.svc__card:hover {
  box-shadow: 0 24px 60px -30px rgba(17, 22, 27, 0.35);
  border-color: color-mix(in srgb, var(--highlight) 60%, var(--rule));
}

/* Accent bar along the top edge; grows on hover. */
.svc__bar {
  position: absolute;
  inset-block-start: 0;
  inset-inline-start: 0;
  inline-size: 44%;
  block-size: 4px;
  background: linear-gradient(90deg, var(--accent), var(--highlight));
  border-end-end-radius: 4px;
  transition: inline-size 500ms var(--ease);
}
html[dir='rtl'] .svc__bar { background: linear-gradient(270deg, var(--accent), var(--highlight)); }
.svc__card:hover .svc__bar { inline-size: 100%; }

.svc__num {
  position: absolute;
  inset-block-start: 14px;
  inset-inline-end: 20px;
  font-family: var(--display);
  font-size: 3.2rem;
  line-height: 1;
  color: color-mix(in srgb, var(--brand) 8%, transparent);
  font-variant-numeric: tabular-nums;
  pointer-events: none;
}

.svc__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  inline-size: 56px; block-size: 56px;
  border-radius: 50%;
  background: color-mix(in srgb, var(--brand) 12%, var(--canvas));
  color: var(--brand);
  margin-block-end: var(--s5);
  flex: none;
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--brand) 18%, transparent),
              0 0 0 7px color-mix(in srgb, var(--brand) 5%, transparent);
  transition: transform 500ms var(--ease), background-color 300ms var(--ease), color 300ms var(--ease);
}
.svc__icon svg { inline-size: 24px; block-size: 24px; }
.svc__card:hover .svc__icon { transform: rotate(-8deg) scale(1.06); background: var(--highlight); color: var(--ink); }

.svc__title { font-size: clamp(1.15rem, 2vw, 1.45rem); margin-block-end: var(--s3); }
.svc__body { font-size: 0.95rem; color: var(--tx-soft); margin-block-end: var(--s5); }

.svc__aud { margin-block-start: auto; padding-block-start: var(--s4); border-block-start: 1px solid var(--rule); }
.svc__aud-label { font-size: 0.75rem; color: var(--tx-faint); margin-block-end: var(--s3); }
.svc__aud-list { display: flex; flex-wrap: wrap; gap: var(--s2); }
.svc__aud-list li {
  padding: 4px var(--s3);
  border-radius: var(--pill);
  background: color-mix(in srgb, var(--brand) 8%, var(--canvas));
  font-size: 0.75rem;
  color: var(--tx-soft);
}

.svc__end { display: flex; align-items: center; inline-size: clamp(240px, 24vw, 320px); }
.svc__end-line {
  font-family: var(--display);
  font-size: clamp(1.2rem, 2.4vw, 1.7rem);
  color: var(--accent-deep);
  text-wrap: balance;
}

@media (max-width: 1040px) {
  /* Cards size to their own content; stretching to the tallest sibling left
     a void between the body and the tags on a phone. */
  .svc__rail { align-items: flex-start; }
  .svc__card { min-block-size: 0; }
}

/* =========================================================== methodology === */

.method { padding-block: 0; block-size: 220vh; }

.method__pin {
  position: sticky;
  inset-block-start: 0;
  block-size: 100svh;
  display: grid;
  align-items: center;
  padding-block: clamp(88px, 12vh, 132px) clamp(48px, 8vh, 88px);
}

.method__frame {
  position: relative;
  inline-size: min(100% - (var(--gutter) * 2), var(--wrap));
  margin-inline: auto;
  display: grid;
  grid-template-columns: minmax(0, 0.8fr) minmax(0, 1.2fr);
  gap: clamp(28px, 5vw, 80px);
  align-items: center;
}

.method__head { align-self: center; }
.method__head .ch__title { font-size: clamp(1.8rem, 4.4vw, 3rem); }

/* ---- stages: the readable content ------------------------------------- */

.method__stages {
  position: relative;
  margin-block-start: clamp(24px, 4vh, 40px);
  min-block-size: 9.5rem;
}

/* All five stack in the same place and crossfade; the inactive ones stay in
   the document so a screen reader still gets the whole method in order. */
.method__stage {
  position: absolute;
  inset-block-start: 0;
  inset-inline: 0;
  opacity: 0;
  transform: translateY(10px);
  transition: opacity 480ms var(--ease), transform 480ms var(--ease);
  pointer-events: none;
}

.method[data-step='0'] .method__stage:nth-child(1),
.method[data-step='1'] .method__stage:nth-child(2),
.method[data-step='2'] .method__stage:nth-child(3),
.method[data-step='3'] .method__stage:nth-child(4),
.method[data-step='4'] .method__stage:nth-child(5) {
  opacity: 1;
  transform: none;
  pointer-events: auto;
}

.method__stage-title {
  font-size: clamp(1.25rem, 2.4vw, 1.7rem);
  color: var(--on-dark);
  margin-block-end: var(--s3);
}

.method__stage-body {
  font-size: 1rem;
  color: var(--on-dark-soft);
  max-inline-size: 42ch;
  text-wrap: pretty;
}

/* ---- the dial ---------------------------------------------------------- */

.method__dialbox { display: grid; place-items: center; }

.method__dial {
  --dial: clamp(260px, 30vw, 380px);
  --node: clamp(40px, 4.4vw, 52px);
  /* Half the dial, less half a node, so the discs sit centred on the ring. */
  --radius: calc((var(--dial) / 2) - (var(--node) / 2) - 6px);
  --turn: calc(360deg / var(--steps));

  position: relative;
  inline-size: var(--dial);
  aspect-ratio: 1;
  /* The tilt is what gives it depth. Pointer tilt from [data-tilt] rides on
     top through --tx / --ty. */
  transform:
    perspective(1100px)
    rotateX(calc(9deg + var(--tx, 0deg)))
    rotateY(var(--ty, 0deg));
  transform-style: preserve-3d;
  transition: transform 500ms var(--ease);
}

/* The face: a domed disc with a bevelled rim, lit from the top. */
.method__dial::before {
  content: '';
  position: absolute;
  inset: 5%;
  border-radius: 50%;
  background:
    radial-gradient(circle at 38% 30%, rgba(255,255,255,.10), transparent 46%),
    radial-gradient(circle at 50% 50%, color-mix(in srgb, var(--on-dark) 4%, var(--ink-ground)), color-mix(in srgb, #000 22%, var(--ink-ground)) 100%);
  box-shadow:
    inset 0 2px 0 rgba(255,255,255,.10),
    inset 0 -14px 30px rgba(0,0,0,.35),
    inset 0 0 0 1px rgba(255,255,255,.06),
    0 40px 70px -40px rgba(0,0,0,.9),
    0 0 0 1px rgba(0,0,0,.25);
  transform: translateZ(-18px);
}

/* A slow light sweeping the face, and a dashed outer ring turning with the
   scroll: the dial reads as a mechanism, not a diagram. */
.method__dial::after {
  content: '';
  position: absolute;
  inset: -7%;
  border-radius: 50%;
  border: 1px dashed color-mix(in srgb, var(--highlight) 40%, transparent);
  background: conic-gradient(from calc(var(--step-f, 0) * 72deg - 40deg),
              transparent 0 62%, color-mix(in srgb, var(--highlight) 10%, transparent) 78%, transparent 92%);
  rotate: calc(var(--step-f, 0) * -36deg);
  transition: rotate 520ms var(--ease);
  transform: translateZ(-30px);
  pointer-events: none;
}

.method__orbit { position: absolute; inset: 0; inline-size: 100%; block-size: 100%; filter: drop-shadow(0 0 6px color-mix(in srgb, var(--highlight) 45%, transparent)); }

.method__orbit-track {
  stroke: var(--rule-dark);
  stroke-width: 1.5;
  fill: none;
}

/* Circumference of r=112 is ~703.7. The dash offset walks it as the chapter
   advances, so the arc closes exactly as the last stage lights. */
.method__orbit-fill {
  stroke: url(#method-arc);
  stroke-width: 3;
  fill: none;
  stroke-linecap: round;
  stroke-dasharray: 703.7;
  stroke-dashoffset: calc(703.7 - (703.7 * var(--step-p, 0)));
  transition: stroke-dashoffset 520ms var(--ease);
}

/* Reads as the head of the dial: the stage under it is the live one. */
.method__marker {
  position: absolute;
  /* Nodes always sit 6px inside the box (the --radius formula), so a fixed
     offset clears the active disc and its halo at every dial size. */
  inset-block-start: -18px;
  /* `translate` is physical, so pairing it with inset-inline-start throws the
     marker off-centre in RTL. Auto margins centre it in both directions. */
  inset-inline: 0;
  margin-inline: auto;
  inline-size: 10px;
  block-size: 10px;
  border-radius: 2px;
  background: var(--highlight);
  rotate: 45deg;
  box-shadow: 0 0 0 6px color-mix(in srgb, var(--highlight) 16%, transparent);
}

.method__ring {
  position: absolute;
  inset: 0;
  margin: 0;
  padding: 0;
  list-style: none;
  /* Turns so the active stage arrives under the marker. --step-f is
     continuous, so this glides rather than snapping between stages. */
  rotate: calc(var(--step-f, 0) * var(--turn) * -1);
  transition: rotate 520ms var(--ease);
}

.method__node {
  position: absolute;
  inset-block-start: 50%;
  inset-inline-start: 50%;
  inline-size: var(--node);
  block-size: var(--node);
  margin-block-start: calc(var(--node) / -2);
  margin-inline-start: calc(var(--node) / -2);
  /* Place on the ring, then hand the counter-rotation to the face. */
  transform: rotate(calc(var(--n) * var(--turn))) translateY(calc(var(--radius) * -1));
}

.method__node-face {
  display: grid;
  place-items: center;
  inline-size: 100%;
  block-size: 100%;
  border-radius: 50%;
  /* A raised disc: lit rim, dark underside, a shadow onto the face. */
  background:
    radial-gradient(circle at 35% 28%, rgba(255,255,255,.14), transparent 55%),
    color-mix(in srgb, var(--on-dark) 9%, var(--ink-ground));
  border: 1px solid color-mix(in srgb, var(--on-dark) 16%, transparent);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.14),
    inset 0 -3px 6px rgba(0,0,0,.35),
    0 10px 18px -8px rgba(0,0,0,.8);
  color: var(--on-dark-soft);
  font-family: var(--display);
  font-size: 0.95rem;
  font-variant-numeric: tabular-nums;
  transform: translateZ(14px);
  /* Undoes the node's placement angle and the ring's turn, so numerals stay
     upright at every position. */
  rotate: calc((var(--n) * var(--turn) * -1) + (var(--step-f, 0) * var(--turn)));
  transition: rotate 520ms var(--ease), background-color 420ms var(--ease),
              color 420ms var(--ease), box-shadow 420ms var(--ease);
}

.method[data-step='0'] .method__node:nth-child(1) .method__node-face,
.method[data-step='1'] .method__node:nth-child(2) .method__node-face,
.method[data-step='2'] .method__node:nth-child(3) .method__node-face,
.method[data-step='3'] .method__node:nth-child(4) .method__node-face,
.method[data-step='4'] .method__node:nth-child(5) .method__node-face {
  background-color: var(--highlight);
  background-image:
    radial-gradient(circle at 35% 28%, rgba(255,255,255,.55), transparent 50%),
    linear-gradient(180deg, var(--highlight), color-mix(in srgb, var(--highlight) 70%, var(--accent)));
  border-color: color-mix(in srgb, var(--highlight) 70%, #fff);
  color: var(--ink);
  font-weight: 600;
  transform: translateZ(26px) scale(1.12);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.6),
    inset 0 -3px 6px rgba(0,0,0,.18),
    0 14px 24px -10px rgba(0,0,0,.8),
    0 0 0 8px color-mix(in srgb, var(--highlight) 14%, transparent),
    0 0 40px color-mix(in srgb, var(--highlight) 45%, transparent);
  animation: node-pulse 2.6s ease-in-out infinite;
}
@keyframes node-pulse {
  0%, 100% { box-shadow: inset 0 1px 0 rgba(255,255,255,.6), inset 0 -3px 6px rgba(0,0,0,.18), 0 14px 24px -10px rgba(0,0,0,.8), 0 0 0 8px color-mix(in srgb, var(--highlight) 14%, transparent), 0 0 40px color-mix(in srgb, var(--highlight) 45%, transparent); }
  50%      { box-shadow: inset 0 1px 0 rgba(255,255,255,.6), inset 0 -3px 6px rgba(0,0,0,.18), 0 14px 24px -10px rgba(0,0,0,.8), 0 0 0 14px color-mix(in srgb, var(--highlight) 8%, transparent), 0 0 56px color-mix(in srgb, var(--highlight) 60%, transparent); }
}

/* The stage number, large, at the centre of the dial. */
.method__core {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  margin: 0;
  pointer-events: none;
}

.method__core-num {
  grid-area: 1 / 1;
  font-family: var(--display);
  font-size: clamp(3.5rem, 8vw, 6rem);
  line-height: 1;
  color: color-mix(in srgb, var(--on-dark) 14%, transparent);
  font-variant-numeric: tabular-nums;
  opacity: 0;
  transform: scale(0.9);
  transition: opacity 420ms var(--ease), transform 420ms var(--ease);
}

.method[data-step='0'] .method__core-num:nth-child(1),
.method[data-step='1'] .method__core-num:nth-child(2),
.method[data-step='2'] .method__core-num:nth-child(3),
.method[data-step='3'] .method__core-num:nth-child(4),
.method[data-step='4'] .method__core-num:nth-child(5) {
  opacity: 1;
  transform: none;
  color: color-mix(in srgb, var(--highlight) 34%, transparent);
}

.method__rail {
  position: absolute;
  inset-inline-start: 0;
  inset-block-end: -28px;
  inline-size: 100%;
  block-size: 2px;
  background: var(--rule-dark);
  border-radius: 2px;
}

.method__rail-fill {
  display: block;
  block-size: 100%;
  inline-size: calc(var(--step-p, 0) * 100%);
  background: linear-gradient(to inline-end, var(--accent), var(--highlight));
  border-radius: 2px;
  transition: inline-size 420ms var(--ease);
}

/* ============================================================== timeline === */

.tl { position: relative; }

.tl__depth {
  position: absolute;
  inset-block-start: 10%;
  inset-inline-end: -12%;
  inline-size: clamp(320px, 46vw, 720px);
  aspect-ratio: 1;
  border-radius: 50%;
  background: radial-gradient(circle at 40% 40%,
              color-mix(in srgb, var(--brand) 14%, transparent), transparent 66%);
  z-index: 0;
  pointer-events: none;
}

/* The beam's SVG box is 20px wide and its long run sits at x=19, which lands
   19px in from the content edge in both directions. --tl-line records that so
   the milestone dots can align to it without repeating the number. */
.tl {
  --tl-pad: clamp(40px, 6vw, 84px);
  --tl-line: 19px;
  --tl-dot: 11px;
}

.tl__wrap { position: relative; padding-inline-start: var(--tl-pad); }

.tl__beam {
  position: absolute;
  inset-block-start: 0;
  inset-inline-start: 0;
  inline-size: 20px;
  pointer-events: none;
}

.tl__beam-svg { display: block; overflow: visible; }

/* The cap sits on the head of the beam and lights when the reader arrives. */
.tl__beam-cap {
  position: absolute;
  inset-block-start: -7px;
  /* Centred on the beam's line, which sits --tl-line in from the wrap's
     inline-start edge in both reading directions. */
  inset-inline-start: calc(var(--tl-line) - 7.5px);
  inline-size: 15px;
  block-size: 15px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  border: 1px solid var(--rule);
  background: var(--paper);
  box-shadow: 0 2px 8px rgba(17, 22, 27, 0.16);
  transition: box-shadow 300ms var(--ease);
}

.tl__beam-cap > span {
  inline-size: 7px;
  block-size: 7px;
  border-radius: 50%;
  background: var(--paper);
  border: 1px solid var(--rule);
  transition: background-color 300ms var(--ease), border-color 300ms var(--ease);
}

.tl__beam-cap.is-lit { box-shadow: none; }
.tl__beam-cap.is-lit > span {
  background: var(--accent);
  border-color: var(--accent-deep);
}

.tl__list { display: grid; gap: clamp(32px, 5vh, 60px); }

.tl__item { position: relative; }

.tl__dot {
  position: absolute;
  inset-block-start: 11px;
  inset-inline-start: calc((var(--tl-pad) - var(--tl-line) + (var(--tl-dot) / 2)) * -1);
  inline-size: var(--tl-dot);
  block-size: var(--tl-dot);
  border-radius: 50%;
  background: var(--paper);
  border: 2px solid var(--brand);
  transition: background-color 400ms var(--ease), transform 400ms var(--ease);
}

.tl__item.is-in .tl__dot { background: var(--highlight); transform: scale(1.12); }
.tl__item.is-current .tl__dot {
  border-color: var(--accent);
  box-shadow: 0 0 0 5px color-mix(in srgb, var(--accent) 16%, transparent);
}

/* The year, oversized and faint, behind the entry. */
.tl__ghost {
  position: absolute;
  inset-block-start: -0.42em;
  inset-inline-start: -0.04em;
  font-family: var(--display);
  font-size: clamp(3.2rem, 7vw, 6rem);
  line-height: 1;
  font-weight: 600;
  color: color-mix(in srgb, var(--brand) 7%, transparent);
  pointer-events: none;
  z-index: 0;
}
html[lang='ar'] .tl__ghost { font-weight: var(--display-weight-xl); }

.tl__year, .tl__what, .tl__figure { position: relative; z-index: 1; }

.tl__year {
  font-size: 0.8125rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  color: var(--accent-deep);
  font-variant-numeric: tabular-nums;
  margin-block-end: var(--s2);
}

.tl__what {
  font-family: var(--display);
  font-size: clamp(1.1rem, 2.2vw, 1.5rem);
  max-inline-size: 48ch;
  text-wrap: pretty;
}

/* Wide screens: the beam runs down the centre and entries alternate sides,
   each tipping in from the beam. */
@media (min-width: 1041px) {
  .tl__wrap { padding-inline-start: 0; }
  .tl__beam { inset-inline-start: calc(50% - 10px); }

  .tl__item { inline-size: calc(50% - var(--tl-pad)); }
  .tl__item--b { margin-inline-start: auto; }

  /* Entries on the start side read towards the beam. */
  .tl__item--a { text-align: end; }
  .tl__item--a .tl__what, .tl__item--a .tl__figure { margin-inline-start: auto; }
  .tl__item--a .tl__ghost { inset-inline-start: auto; inset-inline-end: -0.04em; }

  /* The line sits 9px past the centre (box at 50% - 10px, run at x = 19). */
  .tl__item--a .tl__dot {
    inset-inline-start: auto;
    inset-inline-end: calc((var(--tl-pad) + 9px + (var(--tl-dot) / 2)) * -1);
  }
  .tl__item--b .tl__dot {
    inset-inline-start: calc((var(--tl-pad) - 9px + (var(--tl-dot) / 2)) * -1);
  }

  .tl__item[data-enter] { transform: perspective(1000px) rotateY(-14deg) translateX(28px); transform-origin: 100% 50%; }
  .tl__item--b[data-enter] { transform: perspective(1000px) rotateY(14deg) translateX(-28px); transform-origin: 0 50%; }
  html[dir='rtl'] .tl__item--a[data-enter] { transform: perspective(1000px) rotateY(14deg) translateX(-28px); transform-origin: 0 50%; }
  html[dir='rtl'] .tl__item--b[data-enter] { transform: perspective(1000px) rotateY(-14deg) translateX(28px); transform-origin: 100% 50%; }
  /* Stated for RTL as well: the mirrored entrance rules above are more
     specific than the plain arrival rule and would otherwise hold. */
  .tl__item[data-enter].is-in,
  html[dir='rtl'] .tl__item[data-enter].is-in { transform: none; }
}

/* Optional per-milestone image, uploaded from the admin panel. Sized so a
   photograph supports the entry rather than taking the chapter over. */
.tl__figure {
  margin-block-start: var(--s5);
  max-inline-size: min(100%, 520px);
  border-radius: var(--r16);
  overflow: hidden;
  background: var(--paper-warm);
  border: 1px solid var(--rule);
}

.tl__figure img {
  inline-size: 100%;
  /* Both dimensions overridden together: setting only one leaves the other
     resolving to the attribute's raw pixel value and blows out the layout. */
  block-size: auto;
  aspect-ratio: 16 / 10;
  object-fit: cover;
  transition: transform 700ms var(--ease);
}

.tl__item:hover .tl__figure img { transform: scale(1.03); }

@media (prefers-reduced-motion: reduce) {
  .tl__item:hover .tl__figure img { transform: none; }
}

/* ================================================================ impact === */

.impact { position: relative; }

/* Grain: an SVG noise tile at low opacity, so the purple field has tooth. */
.impact::before {
  content: '';
  position: absolute;
  inset: 0;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  opacity: 0.06;
  mix-blend-mode: soft-light;
  pointer-events: none;
}

.impact__grid {
  position: relative;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 200px), 1fr));
  gap: clamp(24px, 3.5vw, 48px);
  margin: 0;
}

.impact__cell { position: relative; text-align: center; }

/* The figure: extruded type. Six stacked shadows in the amber's own darker
   tones make the depth; one soft shadow beneath makes it sit on the ground. */
.impact__fig {
  display: flex;
  justify-content: center;
  align-items: flex-start;
  gap: 2px;
  /* A number and its "+" is an LTR expression in both languages. */
  direction: ltr;
  font-family: var(--display);
  font-size: clamp(2.6rem, 5.6vw, 4.6rem);
  line-height: 1;
  color: var(--highlight);
  font-variant-numeric: tabular-nums;
  margin-block-end: var(--s4);
}

.odo {
  display: inline-flex;
  align-items: flex-start;
  font-variant-numeric: lining-nums tabular-nums;
  color: var(--highlight);
  text-shadow:
    0 1px 0 color-mix(in srgb, var(--highlight) 80%, #000),
    0 2px 0 color-mix(in srgb, var(--highlight) 68%, #000),
    0 3px 0 color-mix(in srgb, var(--highlight) 58%, #000),
    0 4px 0 color-mix(in srgb, var(--highlight) 50%, #000),
    0 5px 0 color-mix(in srgb, var(--highlight) 42%, #000),
    0 6px 0 color-mix(in srgb, var(--highlight) 34%, #000),
    0 8px 14px rgba(0, 0, 0, .45);
}

/* One column per digit: a strip of 0–9 twice, scrolled to the value in the
   second run so every column turns at least once.
   Lining figures (the face defaults to old-style, whose 9s descend and 0s
   sit at x-height) so every digit fits a 1.1em row; the mask hides the
   little shadow that still bleeds in from the row above. */
.odo__col {
  display: inline-block;
  block-size: 1.1em;
  margin-block: -0.05em;
  overflow: hidden;
  /* overflow alone is not honoured on the composited strip while the cell's
     own reveal transform is running; clip-path is. */
  clip-path: inset(0);
  vertical-align: top;
  -webkit-mask-image: linear-gradient(transparent, #000 16%, #000 84%, transparent);
  mask-image: linear-gradient(transparent, #000 16%, #000 84%, transparent);
}
.odo__strip {
  display: block;
  transform: translateY(0);
  transition: transform 2200ms cubic-bezier(.16, .9, .22, 1);
  transition-delay: calc(var(--k, 0) * 110ms);
}
.odo__strip > span { display: block; block-size: 1.1em; line-height: 1.1em; }
.impact__cell.is-rolling .odo__strip,
html:not(.js-ready) .odo__strip { transform: translateY(calc((10 + var(--d, 0)) * -1.1em)); }

.odo__sep { display: inline-block; block-size: 1.1em; line-height: 1.1em; margin-block: -0.05em; }
.impact__suffix { font-size: 0.55em; color: var(--accent); margin-block-start: 0.2em; text-shadow: 0 2px 0 color-mix(in srgb, var(--accent) 60%, #000), 0 8px 14px rgba(0,0,0,.45); }

.impact__label {
  margin: 0;
  font-size: 0.9375rem;
  color: var(--on-dark-soft);
  max-inline-size: 22ch;
  margin-inline: auto;
}

.impact__notes {
  position: relative;
  display: grid;
  gap: var(--s3);
  margin-block-start: clamp(40px, 6vh, 72px);
  justify-items: center;
  text-align: center;
}

.impact__notes li { color: var(--on-dark-soft); max-inline-size: 60ch; }

/* ============================================================ experience === */

.xp { position: relative; }

.xp__ledgers {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr));
  gap: clamp(20px, 2.4vw, 32px);
  perspective: 1600px;
}

/* A ledger: raised paper, a huge ghost numeral, the head ruled off. */
.xp__card {
  position: relative;
  padding: clamp(26px, 2.8vw, 40px);
  border-radius: 22px;
  background:
    linear-gradient(180deg, rgba(255,255,255,.7), rgba(255,255,255,.35)),
    var(--paper);
  border: 1px solid var(--rule);
  box-shadow:
    inset 0 1px 0 #fff,
    0 30px 60px -40px rgba(17, 22, 27, .45),
    0 2px 6px -3px rgba(17, 22, 27, .12);
  overflow: hidden;
  transform: rotateX(var(--tx, 0deg)) rotateY(var(--ty, 0deg));
  transition: transform 500ms var(--ease), box-shadow 400ms var(--ease), opacity 640ms var(--ease);
}
.xp__card[data-enter] { transform: translateY(28px) rotateX(-6deg); transform-origin: 50% 100%; }
.xp__card[data-enter].is-in { transform: rotateX(var(--tx, 0deg)) rotateY(var(--ty, 0deg)); }
.xp__card:hover { box-shadow: inset 0 1px 0 #fff, 0 40px 70px -40px rgba(86, 55, 97, .5), 0 4px 10px -4px rgba(17, 22, 27, .14); }

/* Cover photo across the top of the card; the ghost numeral rides over it. */
.xp__cover {
  margin: calc(-1 * clamp(26px, 2.8vw, 40px)) calc(-1 * clamp(26px, 2.8vw, 40px)) var(--s5);
  aspect-ratio: 16 / 9;
  overflow: hidden;
  background: var(--paper-warm);
  position: relative;
}
.xp__cover::after {
  content: '';
  position: absolute; inset: 0;
  background: linear-gradient(to top, rgba(255,255,255,.55), transparent 55%);
}
.xp__cover img {
  inline-size: 100%; block-size: 100%; object-fit: cover; display: block;
  transition: transform 900ms var(--ease);
}
.xp__card:hover .xp__cover img { transform: scale(1.03); }
.xp__card--cover .xp__ghost { color: color-mix(in srgb, #fff 55%, transparent); mix-blend-mode: overlay; }

.xp__ghost {
  position: absolute;
  inset-block-start: -0.18em;
  inset-inline-end: -0.06em;
  font-family: var(--display);
  font-size: clamp(6rem, 9vw, 9rem);
  line-height: 1;
  font-weight: 600;
  color: color-mix(in srgb, var(--brand) 6%, transparent);
  pointer-events: none;
}
html[lang='ar'] .xp__ghost { font-weight: var(--display-weight-xl); }

.xp__cardhead {
  position: relative;
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s3);
  padding-block-end: var(--s4);
  margin-block-end: var(--s4);
  border-block-end: 1px solid var(--rule);
}
.xp__cardhead::after {
  content: '';
  position: absolute;
  inset-block-end: -1px;
  inset-inline-start: 0;
  inline-size: 38%;
  block-size: 2px;
  background: linear-gradient(90deg, var(--highlight), var(--accent));
  transform: scaleX(0);
  transform-origin: 0 50%;
  transition: transform 900ms var(--ease) 200ms;
}
html[dir='rtl'] .xp__cardhead::after { transform-origin: 100% 50%; background: linear-gradient(270deg, var(--highlight), var(--accent)); }
.xp__card.is-in .xp__cardhead::after { transform: scaleX(1); }

.xp__gtitle { font-size: clamp(1.3rem, 1.6vw, 1.55rem); color: var(--brand); text-wrap: balance; }
.xp__count { flex: none; font-size: 0.85rem; letter-spacing: .06em; color: var(--tx-soft); }
html[lang='ar'] .xp__count { letter-spacing: 0; font-size: .85rem; }

/* Rows: the year rides a rail at the start edge; a tick on the rail marks
   each entry. */
.xp__list {
  position: relative;
  display: grid;
  gap: 0;
  margin: 0; padding: 0; list-style: none;
  --rail: 6.6rem;
}
.xp__list::before {
  content: '';
  position: absolute;
  inset-block: 8px;
  inset-inline-start: calc(var(--rail) + 6px);
  inline-size: 1px;
  background: var(--rule);
}

.xp__row {
  position: relative;
  display: grid;
  grid-template-columns: var(--rail) 14px minmax(0, 1fr);
  gap: var(--s4);
  align-items: baseline;
  padding-block: var(--s4);
  border-radius: 12px;
  transition: background-color 260ms var(--ease), opacity 640ms var(--ease), transform 640ms var(--ease);
}
.xp__row:hover { background: color-mix(in srgb, var(--brand) 5%, transparent); }

.xp__year {
  font-size: 0.86rem;
  font-weight: 600;
  color: var(--accent-deep);
  font-variant-numeric: tabular-nums;
  text-align: end;
  white-space: nowrap;
}
.xp__tick {
  align-self: center;
  inline-size: 9px; block-size: 9px;
  border-radius: 50%;
  background: var(--paper);
  border: 2px solid var(--brand);
  transition: background-color 300ms var(--ease), transform 300ms var(--ease);
}
.xp__row:hover .xp__tick { background: var(--highlight); transform: scale(1.2); }
.xp__text { font-size: 1.0625rem; line-height: 1.6; color: var(--tx); text-wrap: pretty; }

@media (max-width: 520px) {
  .xp__list { --rail: 5rem; }
  .xp__card { transform: none; }
}

/* =============================================================== theatre === */
/* THE PEAK. The only chapter that takes the ground back to darkness. */

.theatre { padding-block: 0; }

/* Authored silence: the lights fall with nothing on screen. This is the held
   breath before the peak, not dead scroll. */
.theatre__dark {
  block-size: 78vh;
  background: linear-gradient(to bottom, var(--paper), var(--stage));
}

/* The peak takes the most scroll room on the page by a visible margin. The
   long tail is the lights staying down for a beat after the last production,
   before they come back up for the closing chapters. */
.theatre__stage {
  position: relative;
  padding-block: clamp(96px, 22vh, 260px) clamp(150px, 48vh, 560px);
  overflow: clip;
}

.theatre__beam {
  position: absolute;
  inset-block-start: -10%;
  inset-inline-start: 50%;
  translate: -50% 0;
  inline-size: min(120vw, 1100px);
  block-size: 120%;
  background:
    radial-gradient(closest-side ellipse at 50% 0%,
      color-mix(in srgb, var(--highlight) 20%, transparent) 0%,
      color-mix(in srgb, var(--brand) 16%, transparent) 42%,
      transparent 74%);
  /* Opens as the chapter is entered, driven by the chapter's own progress. */
  opacity: clamp(0, calc((var(--sc-p, 0) - 0.05) / 0.28), 1);
  pointer-events: none;
}

.theatre__inner { max-inline-size: 1180px; }
.theatre__lede { max-inline-size: 56ch; }

/* The one iris on the page. */
.theatre__title {
  --w: clamp(0, calc((var(--sc-p, 0) - 0.14) / 0.26), 1);
  clip-path: circle(calc(20% + var(--w) * 90%) at 50% 50%);
  margin-block-end: var(--s7);
  /* clip-path is relative to the border box, so give the display type room. */
  padding-block: 0.12em;
}

.theatre__heading {
  font-size: clamp(2.6rem, 9vw, 6rem);
  color: #fff;
  line-height: 1.1;
  text-shadow: 0 2px 50px rgba(0, 0, 0, 0.55);
}

html[lang='ar'] .theatre__heading { line-height: 1.34; font-weight: var(--display-weight-xl); }

.theatre__since {
  margin-block-start: var(--s3);
  font-size: 0.8125rem;
  letter-spacing: 0.2em;
  color: var(--highlight);
  font-variant-numeric: tabular-nums;
}

.theatre__lede {
  font-size: clamp(1.05rem, 2vw, 1.35rem);
  line-height: 1.85;
  color: var(--on-dark-soft);
  max-inline-size: 56ch;
  margin-block-end: clamp(48px, 8vh, 88px);
  text-wrap: pretty;
}

/* Showreel. Lives inside the lit stage rather than in the dark lead-in: that
   gap is the deliberate silence before the chapter and should stay empty. */
.theatre__film {
  position: relative;
  margin: 0 0 clamp(48px, 8vh, 88px);
  max-inline-size: min(100%, 760px);
  border-radius: var(--r24);
  overflow: hidden;
  background: #000;
  border: 1px solid var(--rule-dark);
  box-shadow: 0 30px 70px -40px rgba(0, 0, 0, 0.8);
}

.theatre__film-video {
  display: block;
  inline-size: 100%;
  /* Both dimensions set together: overriding one leaves the other resolving
     to the element's intrinsic value and distorts the frame. */
  block-size: auto;
  aspect-ratio: 16 / 9;
  object-fit: cover;
}

.theatre__film-toggle {
  position: absolute;
  inset-block-end: var(--s4);
  inset-inline-end: var(--s4);
  inline-size: 44px;
  block-size: 44px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: color-mix(in srgb, var(--stage) 72%, transparent);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  color: var(--on-dark);
  box-shadow: inset 0 0 0 1px var(--rule-dark);
  transition: background-color 200ms var(--ease), transform 200ms var(--ease);
}

.theatre__film-toggle:hover {
  background: var(--highlight);
  color: var(--ink);
  transform: scale(1.06);
}

.theatre__film-toggle svg { inline-size: 18px; block-size: 18px; }

.theatre__film-caption {
  padding: var(--s4) var(--s5);
  font-size: 0.875rem;
  color: var(--on-dark-soft);
  background: color-mix(in srgb, var(--on-dark) 4%, transparent);
}

.theatre__bill-label {
  font-size: 0.75rem;
  letter-spacing: 0.2em;
  color: var(--accent);
  margin-block-end: var(--s5);
}

html[lang='ar'] .theatre__bill-label { letter-spacing: 0; font-size: 0.9rem; }

/* ---- playbills -------------------------------------------------------- */

.theatre__bills {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 250px), 1fr));
  gap: clamp(18px, 2.4vw, 32px);
  list-style: none; margin: 0; padding: 0;
  perspective: 1200px;
}

.bill { display: grid; gap: var(--s3); }
.bill[data-enter] { transform: translateY(30px) rotateX(-8deg); transform-origin: 50% 100%; }
.bill[data-enter].is-in { transform: none; }

.bill__poster {
  position: relative;
  margin: 0;
  aspect-ratio: 3 / 4;
  border-radius: 14px;
  overflow: hidden;
  background: #0b0810;
  border: 1px solid var(--rule-dark);
  box-shadow: 0 24px 50px -30px rgba(0, 0, 0, 0.9);
  transition: transform 500ms var(--ease), box-shadow 500ms var(--ease);
}
.bill:hover .bill__poster { transform: translateY(-6px); box-shadow: 0 34px 60px -30px rgba(0, 0, 0, 0.95); }

.bill__poster img { inline-size: 100%; block-size: 100%; object-fit: cover; display: block; }

/* Direction-aware hover. --dx/--dy hold the entry direction as a unit
   vector (set by scroll.js); the image slides 20px away from that edge and
   the caption arrives from it, over a 40% scrim, as in the source component.
   Oversized 15% so the slide never shows an edge. */
.bill__poster img, .bill__stage {
  transform: scale(1.15);
  transition: transform 200ms ease-out;
}
.bill__over {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  gap: 2px;
  padding: var(--s4);
  background: rgba(0, 0, 0, .4);
  color: #fff;
  opacity: 0;
  transition: opacity 500ms ease-out;
  pointer-events: none;
}
.bill__over-name { font-family: var(--display); font-size: clamp(1rem, 1.5vw, 1.2rem); text-shadow: 0 2px 12px rgba(0,0,0,.6); }
.bill__over-line { font-size: .78rem; color: var(--on-dark-soft); }
.bill__over-name, .bill__over-line {
  transform: translate(calc(var(--dx, 0) * 20px), calc(var(--dy, 0) * 20px));
  transition: transform 500ms ease-out, opacity 500ms ease-out;
}
/* Touch screens have no hover: the caption lives inside the poster all the
   time, over a bottom gradient so an uploaded image still reads, and the
   duplicate caption under the card is kept for screen readers only. */
@media (hover: none) {
  .bill__over {
    opacity: 1;
    background: linear-gradient(to top, rgba(0, 0, 0, .82), rgba(0, 0, 0, .3) 50%, transparent 78%);
  }
  .bill__over-name, .bill__over-line { transform: none; }
  .bill__mark { display: none; }
  .bill__meta {
    position: absolute; inline-size: 1px; block-size: 1px; overflow: hidden;
    clip-path: inset(50%); white-space: nowrap;
  }
}

/* Phones: two posters per row, so a 3:4 card stays a card and not a wall. */
@media (max-width: 700px) {
  /* One column: items enter the screen one at a time, so an index-based
     stagger only makes the later ones feel late. Reveal on arrival. */
  [data-enter] { transition-delay: 0ms !important; }

  .theatre__bills { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
  .bill__poster { border-radius: 12px; }
  .bill__over { padding: var(--s3); }
  .bill__over-name { font-size: 1rem; line-height: 1.3; }
  .bill__over-line { font-size: .74rem; }
}

@media (hover: hover) and (pointer: fine) {
  .bill[data-dir]:hover .bill__poster img,
  .bill[data-dir]:hover .bill__stage { transform: scale(1.15) translate(calc(var(--dx, 0) * -20px), calc(var(--dy, 0) * -20px)); }
  .bill[data-dir]:hover .bill__over { opacity: 1; }
  .bill[data-dir]:hover .bill__mark { opacity: 0; }
  .bill__mark { transition: opacity 300ms ease-out; }
  .bill[data-dir]:hover .bill__over-name,
  .bill[data-dir]:hover .bill__over-line { transform: none; }
  .bill:hover .bill__curtain--a { transform: translateX(-104%); }
}

/* Without a poster: a lit stage with the title standing in it. */
.bill__stage {
  position: absolute; inset: 0;
  display: grid; place-items: end center;
  padding: var(--s4);
  background:
    linear-gradient(180deg, #17101d, #0b0810 70%),
    var(--stage);
}
.bill__spot {
  position: absolute;
  inset-block-start: -30%;
  inset-inline-start: 50%;
  translate: -50% 0;
  inline-size: 140%;
  aspect-ratio: 1;
  background: radial-gradient(closest-side, color-mix(in srgb, var(--highlight) 34%, transparent), transparent 70%);
}
html[dir='rtl'] .bill__spot { translate: 50% 0; }
.bill__mark {
  position: relative;
  font-family: var(--display);
  font-size: clamp(1.2rem, 1.8vw, 1.6rem);
  color: var(--on-dark);
  text-align: center;
  text-wrap: balance;
  text-shadow: 0 2px 20px rgba(0,0,0,.8);
}

/* Curtains: velvet with folds, a gold hem, parting to the sides on arrival. */
.bill__curtain {
  position: absolute;
  inset-block: -2%;
  inline-size: 52%;
  background:
    repeating-linear-gradient(90deg,
      color-mix(in srgb, var(--brand) 70%, #000) 0 8px,
      color-mix(in srgb, var(--brand) 88%, #000) 8px 16px,
      color-mix(in srgb, var(--brand) 60%, #000) 16px 24px),
    var(--brand);
  box-shadow: inset 0 -14px 0 color-mix(in srgb, var(--highlight) 75%, #000), 0 0 30px rgba(0,0,0,.6);
  transition: transform 1100ms cubic-bezier(.7, 0, .2, 1);
  transition-delay: calc(var(--i, 0) * 90ms + 240ms);
}
.bill__curtain--a { inset-inline-start: 0; }
.bill__curtain--b { inset-inline-end: 0; }
.bill.is-in .bill__curtain--a { transform: translateX(-104%); }
.bill.is-in .bill__curtain--b { transform: translateX(104%); }
html[dir='rtl'] .bill.is-in .bill__curtain--a { transform: translateX(104%); }
html[dir='rtl'] .bill.is-in .bill__curtain--b { transform: translateX(-104%); }

.bill__meta { display: grid; gap: 2px; }
.bill__name { font-family: var(--display); font-size: clamp(1.15rem, 1.7vw, 1.4rem); color: #fff; }
.bill__line { display: flex; gap: var(--s3); font-size: 0.8rem; color: var(--on-dark-soft); }
.bill__year { color: var(--highlight); font-variant-numeric: tabular-nums; }

/* =========================================================== credentials === */

.creds { position: relative; overflow: hidden; }

.creds__layout {
  position: relative;
  display: grid;
  grid-template-columns: minmax(260px, 5fr) 8fr;
  gap: clamp(32px, 5vw, 96px);
  align-items: start;
}

/* The heading keeps the wall company while the tiles scroll past. */
.creds__aside { position: sticky; inset-block-start: clamp(88px, 12vh, 128px); }
.creds__aside .ch__head { max-inline-size: 26ch; margin-block-end: var(--s5); }
.creds__aside .ch__title { font-size: clamp(1.9rem, 4vw, 3rem); text-wrap: balance; }

.creds__tally {
  display: flex; align-items: baseline; gap: var(--s3);
  padding-block-start: var(--s4);
  border-block-start: 1px solid var(--rule);
}
.creds__tally-num {
  font-family: var(--display);
  font-size: clamp(2.4rem, 4.5vw, 3.4rem);
  line-height: 1;
  color: var(--brand);
  font-variant-numeric: tabular-nums;
}
.creds__tally-label { font-size: 0.9rem; color: var(--tx-soft); max-inline-size: 14ch; }

.creds__grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(14px, 1.6vw, 22px);
  margin: 0; padding: 0; list-style: none;
  /* The tiles tip in from below; this is the room they tip through. */
  perspective: 1400px;
}

.creds__tile {
  position: relative;
  display: grid;
  gap: var(--s2);
  align-content: start;
  padding: clamp(20px, 2.2vw, 28px);
  padding-inline-start: calc(clamp(20px, 2.2vw, 28px) + 44px + var(--s3));
  min-block-size: 8.5rem;
  background: color-mix(in srgb, #fff 55%, var(--canvas));
  border: 1px solid var(--rule);
  border-radius: 18px;
  box-shadow: 0 1px 0 rgba(255,255,255,.6) inset, 0 10px 30px -24px rgba(17,22,27,.35);
  transform-origin: 50% 0;
  transition:
    opacity 640ms var(--ease), transform 640ms var(--ease),
    border-color 260ms var(--ease), box-shadow 260ms var(--ease);
  transition-delay: calc(var(--i, 0) * 55ms), calc(var(--i, 0) * 55ms), 0ms, 0ms;
}
.creds__tile[data-enter] { transform: translateY(34px) rotateX(-12deg); }
.creds__tile[data-enter].is-in { transform: none; }
.creds__tile--wide { grid-column: 1 / -1; }

@media (hover: hover) {
  .creds__tile:hover {
    border-color: color-mix(in srgb, var(--highlight) 70%, var(--rule));
    box-shadow: 0 1px 0 rgba(255,255,255,.6) inset, 0 18px 40px -22px rgba(86,55,97,.35);
    transform: translateY(-3px);
    transition-delay: 0ms;
  }
  .creds__tile:hover .creds__seal::before { transform: rotate(180deg); }
}

/* A seal: dashed outer ring, solid inner disc, the tick inside. */
.creds__seal {
  position: absolute;
  inset-block-start: clamp(20px, 2.2vw, 28px);
  inset-inline-start: clamp(20px, 2.2vw, 28px);
  inline-size: 44px; block-size: 44px;
  display: grid; place-items: center;
  color: var(--ink);
}
.creds__seal::before {
  content: '';
  position: absolute; inset: 0;
  border-radius: 50%;
  border: 1.5px dashed color-mix(in srgb, var(--highlight) 80%, var(--ink));
  transition: transform 900ms var(--ease);
}
.creds__seal::after {
  content: '';
  position: absolute; inset: 7px;
  border-radius: 50%;
  background: var(--highlight);
}
.creds__seal svg { position: relative; inline-size: 16px; block-size: 16px; }

.creds__num {
  position: absolute;
  inset-block-start: 10px;
  inset-inline-end: 16px;
  font-family: var(--display);
  font-size: 2.6rem;
  line-height: 1;
  color: color-mix(in srgb, var(--brand) 9%, transparent);
  font-variant-numeric: tabular-nums;
  pointer-events: none;
}

.creds__title {
  font-family: var(--display);
  font-size: clamp(1.05rem, 1.35vw, 1.2rem);
  font-weight: 500;
  line-height: 1.35;
  color: var(--ink);
  margin: 0;
  text-wrap: pretty;
}
html[lang='ar'] .creds__title { font-weight: 500; line-height: 1.5; }

.creds__issuer {
  margin: 0;
  font-size: 0.78rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--tx-faint);
}
html[lang='ar'] .creds__issuer { letter-spacing: 0; font-size: 0.85rem; }

@media (max-width: 1040px) {
  .creds__layout { grid-template-columns: 1fr; gap: var(--s6); }
  .creds__aside { position: static; }
  .creds__aside .ch__head { max-inline-size: 30ch; }
}
@media (max-width: 700px) {
  .creds__grid { grid-template-columns: 1fr; }
  .creds__tile { min-block-size: 0; }
}

/* ---- ghost watermark: the chapter's one word, oversized, behind ------- */

.ch__wm {
  position: absolute;
  inset-block-start: clamp(24px, 6vh, 64px);
  inset-inline-end: -0.08em;
  font-family: var(--display);
  font-size: clamp(6rem, 18vw, 17rem);
  line-height: 0.9;
  font-weight: 600;
  letter-spacing: -0.02em;
  color: transparent;
  -webkit-text-stroke: 1px color-mix(in srgb, var(--ink) 9%, transparent);
  white-space: nowrap;
  pointer-events: none;
  user-select: none;
  z-index: 0;
  /* Follows the chapter progress a little so it drifts as you read. */
  transform: translateY(calc(var(--sc-p, 0) * -6vh));
}
html[lang='ar'] .ch__wm { font-weight: var(--display-weight-xl); letter-spacing: 0; }
.ch--ink .ch__wm, .ch--brand .ch__wm, .ch--stage .ch__wm {
  -webkit-text-stroke-color: color-mix(in srgb, #fff 10%, transparent);
}
.ch__wm ~ .ch__inner { position: relative; z-index: 1; }

/* =================================================================== why === */

.why { position: relative; overflow: hidden; }

.why__head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--s4); }
.why__head .ch__head { margin-block-end: clamp(24px, 4vh, 40px); }

.why__pause {
  flex: none;
  inline-size: 44px; block-size: 44px;
  display: grid; place-items: center;
  border-radius: 50%;
  color: var(--on-dark);
  background: color-mix(in srgb, var(--on-dark) 8%, transparent);
  box-shadow: inset 0 0 0 1px var(--rule-dark);
  transition: background-color 200ms var(--ease), transform 200ms var(--ease);
}
.why__pause:hover { background: var(--highlight); color: var(--ink); transform: scale(1.06); }
.why__pause svg { inline-size: 18px; block-size: 18px; }

.why__bands { display: grid; gap: clamp(14px, 1.8vw, 22px); padding-block: var(--s3); }

/* Each band is two copies of its list, moved by one copy's width and
   looped: the second copy takes over exactly where the first left. */
.why__bands { direction: ltr; }
.why__band {
  display: flex;
  gap: clamp(12px, 1.4vw, 18px);
  inline-size: max-content;
  --speed: 60s;
  animation: band-a var(--speed) linear infinite;
}
.why__band--b { animation-name: band-b; --speed: 72s; }
.why__bands:hover .why__band, .why__bands.is-paused .why__band { animation-play-state: paused; }
@keyframes band-a { to { transform: translateX(calc(-50% - clamp(12px, 1.4vw, 18px) / 2)); } }
@keyframes band-b { from { transform: translateX(calc(-50% - clamp(12px, 1.4vw, 18px) / 2)); } to { transform: none; } }

.why__track {
  display: flex;
  gap: clamp(12px, 1.4vw, 18px);
  margin: 0; padding: 0; list-style: none;
  flex: none;
}

html[dir='rtl'] .why__pill { direction: rtl; }
.why__pill {
  display: flex;
  align-items: center;
  gap: var(--s4);
  inline-size: clamp(300px, 26vw, 400px);
  padding: clamp(16px, 1.8vw, 22px) clamp(18px, 2vw, 26px);
  border-radius: 999px;
  background:
    linear-gradient(135deg, rgba(255,255,255,.08), rgba(255,255,255,.02)),
    color-mix(in srgb, var(--on-dark) 3%, transparent);
  border: 1px solid var(--rule-dark);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.08), 0 20px 40px -30px rgba(0,0,0,.8);
  transition: border-color 260ms var(--ease), background-color 260ms var(--ease);
}
.why__pill:hover { border-color: color-mix(in srgb, var(--highlight) 60%, transparent); }

.why__n {
  flex: none;
  font-family: var(--display);
  font-size: 1.9rem;
  line-height: 1;
  color: var(--highlight);
  font-variant-numeric: tabular-nums;
  text-shadow: 0 0 18px color-mix(in srgb, var(--highlight) 40%, transparent);
}
.why__text { color: var(--on-dark-soft); font-size: 0.95rem; text-wrap: pretty; }

@media (max-width: 700px) {
  .why__pill { inline-size: min(78vw, 320px); }
}

/* The bands keep moving on every device, and any of them can be grabbed:
   scroll.js freezes the band under the pointer, moves it with the drag, and
   resumes the motion from where it was left. pan-y leaves vertical page
   scrolling to the browser and hands horizontal drags to the script. */
.why__band { touch-action: pan-y; cursor: grab; user-select: none; -webkit-user-select: none; }
.why__band.is-held { cursor: grabbing; }
.why__pill { -webkit-user-drag: none; }
@media (max-width: 860px) {
  .why__bands { padding-inline: 0; }
  .why__pause { inline-size: 40px; block-size: 40px; }
}
}

/* ================================================================= close === */

.close { padding-block: clamp(88px, 14vh, 176px); }

.close__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 340px), 1fr));
  gap: clamp(40px, 6vw, 88px);
  align-items: start;
}

.close__heading {
  font-size: clamp(2.2rem, 6vw, 4rem);
  color: var(--on-dark);
  margin-block-end: var(--s6);
}

.close__invite {
  font-size: clamp(1.05rem, 1.8vw, 1.25rem);
  color: var(--on-dark-soft);
  max-inline-size: 46ch;
  margin-block-end: var(--s7);
  text-wrap: pretty;
}

.close__inline {
  color: var(--highlight);
  border-block-end: 1px solid color-mix(in srgb, var(--highlight) 50%, transparent);
  transition: border-color 200ms var(--ease);
}
.close__inline:hover { border-block-end-color: var(--highlight); }

/* Social accounts: the brand glyph in the link colour, beside the handle. */
/* An icon has no baseline to sit on, so this row centres instead. */
.close__meta .close__row--logo { align-items: center; }
.close__key--logo { display: inline-flex; align-items: center; min-inline-size: 9ch; color: var(--highlight); line-height: 1; }
.close__logo { inline-size: 22px; block-size: 22px; fill: currentColor; }
.colophon__glyph { inline-size: 16px; block-size: 16px; fill: currentColor; flex: none; }
.colophon__social { display: inline-flex; align-items: center; gap: 8px; }

.close__meta { display: grid; gap: var(--s3); margin-block-end: var(--s6); }

.close__meta li {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s3);
  align-items: baseline;
  font-size: 0.9375rem;
  color: var(--on-dark);
}

.close__key {
  min-inline-size: 9ch;
  font-size: 0.75rem;
  letter-spacing: 0.1em;
  color: var(--on-dark-soft);
}

html[lang='ar'] .close__key { letter-spacing: 0; font-size: 0.85rem; }

.close__reach {
  display: grid;
  gap: var(--s4);
  align-content: start;
  padding: clamp(24px, 3vw, 40px);
  border-radius: var(--r24);
  background:
    linear-gradient(160deg, rgba(255,255,255,.10), rgba(255,255,255,.02)),
    color-mix(in srgb, var(--on-dark) 3%, transparent);
  border: 1px solid var(--rule-dark);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.1), 0 30px 70px -40px rgba(0, 0, 0, 0.7);
}
.close__reach-title { font-size: .78rem; letter-spacing: .14em; text-transform: uppercase; color: var(--on-dark); margin-block-end: var(--s2); }
html[lang='ar'] .close__reach-title { letter-spacing: 0; font-size: .9rem; text-transform: none; }

/* A reach button: icon disc, label and the number, an arrow that travels. */
.reach {
  display: grid;
  grid-template-columns: 52px minmax(0, 1fr) 24px;
  align-items: center;
  gap: var(--s4);
  min-block-size: 76px;
  padding: var(--s3) var(--s4);
  border-radius: 18px;
  background: rgba(255,255,255,.05);
  border: 1px solid var(--rule-dark);
  color: var(--on-dark);
  transition: transform 260ms var(--ease), background-color 260ms var(--ease), border-color 260ms var(--ease), box-shadow 260ms var(--ease);
}
.reach:hover, .reach:focus-visible { transform: translateY(-3px); background: rgba(255,255,255,.09); border-color: color-mix(in srgb, var(--highlight) 60%, transparent); box-shadow: 0 24px 40px -28px rgba(0,0,0,.9); }
.reach:active { transform: translateY(0) scale(.99); }

.reach__icon {
  display: grid; place-items: center;
  inline-size: 52px; block-size: 52px;
  border-radius: 50%;
  color: var(--ink);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.5), 0 10px 20px -10px rgba(0,0,0,.8);
}
.reach__icon svg { inline-size: 24px; block-size: 24px; }
.reach--wa .reach__icon svg { inline-size: 26px; block-size: 26px; }
.reach--wa .reach__icon { background: linear-gradient(180deg, #4fe08a, #25b563); }
.reach--tel .reach__icon { background: linear-gradient(180deg, var(--highlight), color-mix(in srgb, var(--highlight) 70%, var(--accent))); }
.reach--mail .reach__icon { background: linear-gradient(180deg, #fff, #e6dfe9); }

.reach__text { display: grid; gap: 2px; min-inline-size: 0; }
.reach__label { font-weight: 600; font-size: 1rem; }
.reach__value { font-size: .85rem; color: var(--on-dark); font-variant-numeric: tabular-nums; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.reach__arrow { color: var(--highlight); transition: transform 260ms var(--ease); }
.reach__arrow svg { inline-size: 22px; block-size: 22px; }
html[dir='rtl'] .reach__arrow svg { transform: scaleX(-1); }
.reach:hover .reach__arrow { transform: translateX(4px); }
html[dir='rtl'] .reach:hover .reach__arrow { transform: translateX(-4px); }

/* ============================================================== quotes ==== */

.quotes__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 320px), 1fr));
  gap: clamp(20px, 2.6vw, 32px);
}

.quote {
  padding: clamp(28px, 3.4vw, 40px);
  border-radius: var(--r24);
  background: #fffdf9;
  border: 1px solid var(--rule);
  transform: perspective(900px) rotateX(var(--tx, 0deg)) rotateY(var(--ty, 0deg));
  transition: transform 400ms var(--ease);
}

.quote__body p {
  font-family: var(--display);
  font-size: clamp(1.1rem, 2vw, 1.35rem);
  color: var(--tx);
  text-wrap: pretty;
}

.quote__by {
  display: flex; align-items: center; gap: var(--s3);
  margin-block-start: var(--s5);
  padding-block-start: var(--s4);
  border-block-start: 1px solid var(--rule);
}

.quote__photo { inline-size: 44px; block-size: 44px; border-radius: 50%; object-fit: cover; flex: none; }
.quote__name { display: block; font-weight: 600; font-size: 0.9375rem; }
.quote__role { display: block; font-size: 0.8125rem; color: var(--tx-faint); }

/* ============================================================== gallery ==== */

.gal__grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 280px), 1fr));
  gap: clamp(12px, 1.6vw, 20px);
}

.gal__fig {
  position: relative;
  margin: 0;
  border-radius: var(--r16);
  overflow: hidden;
  background: var(--paper-warm);
  aspect-ratio: 4 / 5;
}

.gal__fig img { inline-size: 100%; block-size: 100%; object-fit: cover; transition: transform 700ms var(--ease); }
.gal__fig:hover img { transform: scale(1.04); }

.gal__cap {
  position: absolute;
  inset-block-end: 0; inset-inline: 0;
  padding: var(--s6) var(--s4) var(--s4);
  background: linear-gradient(to top, rgba(12, 8, 16, 0.86), transparent);
  color: #fff;
  font-size: 0.85rem;
}

/* ============================================================= colophon ==== */

.colophon {
  background: var(--stage);
  color: var(--on-dark);
  padding-block: clamp(48px, 8vh, 96px) var(--s6);
  border-block-start: 1px solid var(--rule-dark);
}

.colophon__inner {
  inline-size: min(100% - (var(--gutter) * 2), var(--wrap));
  margin-inline: auto;
  display: grid;
  gap: var(--s5);
}

.colophon__name { font-family: var(--display); font-size: 1.5rem; }
.colophon__cols { display: grid; gap: var(--s2); font-size: 0.9375rem; }
.colophon__muted { color: var(--on-dark-soft); }
.colophon__social { display: flex; flex-wrap: wrap; gap: var(--s5); font-size: 0.9375rem; }
.colophon__handle { color: var(--on-dark-soft); font-size: 0.8125rem; }

.colophon__link {
  border-block-end: 1px solid transparent;
  transition: border-color 200ms var(--ease), color 200ms var(--ease);
}
.colophon__link:hover { color: var(--highlight); border-block-end-color: var(--highlight); }

.colophon__legal {
  margin-block-start: var(--s5);
  padding-block-start: var(--s5);
  border-block-start: 1px solid var(--rule-dark);
  font-size: 0.8125rem;
  color: var(--on-dark-soft);
}

/* =========================================================== minimal pages == */

.minimal-page { min-block-size: 100svh; display: grid; place-items: center; padding: var(--gutter); background: var(--paper); }
.minimal-page__inner { text-align: center; max-inline-size: 52ch; }
.minimal-page__code { font-family: var(--display); font-size: clamp(4rem, 16vw, 9rem); line-height: 1; color: color-mix(in srgb, var(--ink) 9%, transparent); margin-block-end: var(--s4); }
.minimal-page__title { font-size: clamp(1.75rem, 5vw, 2.5rem); margin-block-end: var(--s4); }
.minimal-page__body { color: var(--tx-soft); margin-block-end: var(--s6); }
.minimal-page__detail { margin-block-start: var(--s7); padding: var(--s4); text-align: start; font-size: 0.75rem; background: var(--paper-warm); border-radius: var(--r8); overflow-x: auto; }

.btn {
  display: inline-flex; align-items: center; justify-content: center;
  min-block-size: 48px; padding-inline: var(--s6);
  border-radius: var(--pill); background: var(--ink); color: var(--canvas);
  font-weight: 500;
}

/* ================================================================ curtain === */

/* Only exists while scripting is running and only on the first visit of a
   session; scroll.js lifts it and then removes it. */
.curtain {
  position: fixed;
  inset: 0;
  z-index: 400;
  display: grid;
  place-items: center;
  background: var(--stage);
  pointer-events: none;
}
html:not(.js-ready) .curtain, .curtain[hidden] { display: none; }
.curtain__mark {
  inline-size: 18px; block-size: 18px;
  border-radius: 50%;
  background: var(--highlight);
  box-shadow: 0 0 0 1.5px var(--on-dark), 0 0 40px 6px color-mix(in srgb, var(--highlight) 40%, transparent);
  animation: curtain-mark 900ms var(--ease) both;
}
.curtain.is-lifting { animation: curtain-lift 700ms cubic-bezier(.7, 0, .3, 1) 150ms forwards; }
@keyframes curtain-mark { from { opacity: 0; transform: scale(.6); } to { opacity: 1; transform: none; } }
@keyframes curtain-lift { to { transform: translateY(-100%); } }

.dock__mobile-lang {
  display: none;
  margin-block-start: var(--s3);
  padding: var(--s3) var(--s4);
  border-radius: 14px;
  min-block-size: 46px;
  align-items: center;
  justify-content: center;
  font-weight: 600;
  background: color-mix(in srgb, var(--highlight) 26%, rgba(255,255,255,.4));
}

/* ============================================================ responsive === */

@media (min-width: 1181px) and (max-width: 1380px) {
  .topbar { gap: var(--s2); padding-inline: var(--s5); }
  .topbar__lang { min-block-size: 58px; padding-inline: var(--s3); }
  .dock__desktop { min-block-size: 58px; padding-inline: 7px; }
  .dock__item { padding-inline: 4px; }
  .dock__label { font-size: .68rem; }
  html[lang='ar'] .dock__label { font-size: .76rem; }
}

@media (max-width: 1180px) {
  /* One row: brand and the chapter toggle. The language switch lives in the
     sheet, so the bar takes 44px of the screen instead of ~110. */
  .topbar {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas: 'dock';
    gap: var(--s2);
    padding-inline: clamp(12px, 4vw, 32px);
  }
  .topbar__actions { display: none; }
  .dock__mobile-lang { display: flex; }
  .dock__mobile { inline-size: 100%; justify-self: stretch; }
  .dock__mobile-toggle { min-block-size: 44px; border-radius: 16px; }

  .topbar__lang { min-block-size: 44px; border-radius: 16px; }
  .topbar__actions { justify-self: end; }
  .topbar__lang { padding-inline: var(--s4); }
  .dock__desktop { display: none; }
  .dock__mobile { display: block; }
}

@media (max-width: 1040px) {
  .about__inner { grid-template-columns: 1fr; }
  .method__frame { grid-template-columns: 1fr; gap: var(--s5); justify-items: center; }
  .method__head { text-align: center; }
  .method__head .ch__lede { display: none; }
  .method__stages { min-block-size: 11rem; }
  .method__stage-body { margin-inline: auto; }
  /* The dial leads on a narrow screen; the stage text sits under it. */
  .method__dialbox { order: -1; }
  .method__dial { --dial: clamp(220px, 62vw, 300px); }
}

@media (max-width: 860px) {
  /* A 40px backdrop blur is the single most expensive thing a phone GPU is
     asked to do here; half of it reads the same through the glass. */
  .topbar__lang, .dock__desktop, .dock__mobile-toggle, .dock__mobile-panel {
    -webkit-backdrop-filter: blur(18px) saturate(1.6);
    backdrop-filter: blur(18px) saturate(1.6);
  }

  /* Phone cover: the portrait sits above the words, full width, fading into
     the dark; the plate begins below the face rather than over it. */
  .title {
    min-block-size: auto;
    display: block;
    padding-block: 0 clamp(48px, 8vh, 80px);
    padding-inline: 0;
  }

  .title__portrait {
    position: relative;
    inset: auto;
    inline-size: 100%;
    block-size: min(64svh, 560px);
    margin-block-end: calc(-1 * min(16svh, 130px));
    z-index: 1;
    -webkit-mask-image: linear-gradient(to bottom, #000 0%, #000 52%, rgba(0,0,0,.55) 74%, transparent 100%);
    mask-image: linear-gradient(to bottom, #000 0%, #000 52%, rgba(0,0,0,.55) 74%, transparent 100%);
  }
  .title__portrait img { object-position: 50% 12%; }

  .title__plate {
    position: relative;
    z-index: 2;
    padding-inline: var(--gutter);
    max-inline-size: none;
  }

  /* Step the display type down a rung: the desktop floor wraps a hero name to
     too many lines at phone widths. */
  .title__name { font-size: clamp(2.4rem, 13vw, 3.4rem); }
  .title__role { font-size: clamp(1.05rem, 4.6vw, 1.4rem); }

  .svc { block-size: 280vh; }
  .method { block-size: 260vh; }
  .theatre__dark { block-size: 30vh; }

  .xp__row { flex-direction: column; align-items: flex-start; }
}

@media (max-width: 520px) {
  .dock__mobile-panel { padding: var(--s3); }
  .dock__mobile-link { padding-inline: 10px; }
  .title__cta { inline-size: 100%; }
  .rail-item { inline-size: min(78vw, 320px); }
  .svc__lead { inline-size: min(78vw, 300px); }
  .theatre__play { flex-direction: column; align-items: flex-start; gap: var(--s2); }
}

/* ================================================================= motion === */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }

  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }

  [data-enter] { opacity: 1; transform: none; }
  .ln > span { transform: none; }

  /* The card keeps its shape and its copy; the tilt and the holographic
     layers are pure decoration and go entirely. */
  .glare__tilt { transform: none !important; }
  .glare__sheen,
  .glare__foil { display: none; }

  /* Wipes and irises become plain visible content rather than clipped ones. */
  [data-wipe], .theatre__title { clip-path: none !important; }
  .theatre__beam { opacity: 0.5; }

  /* No spin and no tilt. The dial keeps its shape as a static diagram and the
     stages become an ordinary list, which is the readable form anyway. */
  .method__dial { transform: none !important; }
  .method__ring { rotate: 0deg !important; }
  .method__node-face { rotate: calc(var(--n) * var(--turn) * -1) !important; }

  .method__stages { min-block-size: 0; display: grid; gap: var(--s5); }
  .method__stage { position: static; opacity: 1; transform: none; pointer-events: auto; }

  /* The rail's transform is navigation, not decoration: zeroing it would park
     the chapter on its first card and make the rest unreachable. It becomes a
     real scroll region instead. */
  .svc { block-size: auto; padding-block: var(--chapter-pad); }
  .svc__pin { position: static; block-size: auto; }
  .svc__rail {
    overflow-x: auto;
    scroll-snap-type: x proximity;
    padding-block: var(--s3);
    transform: none !important;
  }
  .rail-item { scroll-snap-align: center; }

  .method { block-size: auto; padding-block: var(--chapter-pad); }
  .method__pin { position: static; block-size: auto; }

  .title__pool, .title__haze { transition: none; }

  /* Nothing may stay hidden behind a motion that never runs. */
  .bill__curtain, .curtain { display: none !important; }
  .why__band { animation: none !important; inline-size: auto; flex-wrap: wrap; }
  .why__track[aria-hidden='true'] { display: none; }
  .why__pause { display: none; }
  .method__node-face { animation: none !important; }
  .odo__strip { transition: none !important; }
  .ch--ink::after, .ch--brand::after, .ch--stage::after { display: none; }
  .about__orbit { rotate: 0deg !important; }
}

@media print {
  .topbar, .dock, .title__house, .theatre__beam { display: none !important; }
  [data-enter] { opacity: 1 !important; transform: none !important; }
  [data-wipe], .theatre__title { clip-path: none !important; }
  .ch { padding-block: 24px; break-inside: avoid; }
  body { background: #fff; color: #000; }
}
