/* ============================================================
   about.css — About page.
   Layout language: paper ground (#f1eee8) with two dark
   chapters (hero, team). No ghost words, no arch motifs.
   Vertical rhythm is expressed in svh so that the founders
   deck and the contact footer each hold a single viewport.
   ============================================================ */

:root {
  --paper: #f1eee8;
  --ink: #0a0a0a;
  --accent: #2e5c3c;          /* leaf green — for paper grounds  */
  --accent-inv: #a8c9a4;      /* the same hue lifted for dark    */
  --accent-soft: rgba(46, 92, 60, .12);
  --line: rgba(10, 10, 10, .12);
  --line-inv: rgba(255, 255, 255, .16);
  --e-power: cubic-bezier(.22, 1, .36, 1);
}

/* The shared scrolled-nav tint is pure white, which reads as a white bar
   laid over this page's warm paper. Tint it with the paper instead.
   :not(.nav-dark) is load-bearing: without it this rule ties with
   #nav.nav-scrolled.nav-dark on specificity and, loading later, would win —
   flattening the nav to paper over the hero and team chapters. */
.about-page #nav.nav-scrolled:not(.nav-dark) {
  background: rgba(241, 238, 232, .88);
  box-shadow: 0 1px 0 rgba(10, 10, 10, .07);
}

.about-page {
  background: var(--paper);
  /* One width for every portrait plate on the page. The founders' plates and
     the team's are the same object at the same scale — two people who happen
     to be named first, not a different kind of card — so the two places that
     draw one read the same token instead of agreeing by coincidence. */
  --plate-w: clamp(190px, 21vw, 290px);
  /* The shared --grey (#767676) is tuned for a pure-white ground, where it
     clears 4.5:1 by a hair. On paper it drops to 3.92:1, so every label,
     caption and bio on this page would sit under the floor. Overriding the
     token here fixes all of them at once, in about.css and shared.css alike.
     #67625a on paper = 5.22:1. */
  --grey: #67625a;
}

/* ============================================================
   1. HERO — the journey
   ============================================================ */
.about-hero {
  position: relative;
  min-height: 100vh;
  min-height: 100svh;
  display: grid;
  grid-template-rows: 1fr auto;
  overflow: hidden;
  background: #0b0b0b;
  color: #fff;
  padding: calc(var(--nav-h) + clamp(20px, 4svh, 46px)) clamp(20px, 5vw, 64px)
           clamp(18px, 3.4svh, 38px);
}
/* Without this the grid column takes its automatic minimum from the journey
   strip's max-content width, and on phones the whole hero grows to ~950px. */
.about-hero > * { min-width: 0; }

.ah-bg {
  position: absolute;
  inset: 0;
  z-index: 0;
}
.ah-bg picture,
.ah-img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  will-change: transform;
}
.ah-scrim {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background:
    linear-gradient(180deg, rgba(8, 8, 8, .74) 0%, rgba(8, 8, 8, .34) 34%,
                            rgba(8, 8, 8, .58) 66%, rgba(8, 8, 8, .92) 100%),
    linear-gradient(90deg, rgba(8, 8, 8, .58) 0%, rgba(8, 8, 8, 0) 62%);
}

.ah-copy {
  position: relative;
  z-index: 2;
  align-self: center;
  min-height: 0;
  /* Sized in px/vw, not ch: `ch` here would resolve against this element's
     own (small, sans) font and squeeze the display-size title beneath it. */
  max-width: min(620px, 48vw);
}
.ah-eyebrow {
  display: block;
  font-size: clamp(.56rem, .72vw, .68rem);
  letter-spacing: .3em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, .74);
  margin-bottom: clamp(10px, 1.6svh, 18px);
  /* Each character is its own inline-block for the stagger, which lets a line
     break fall mid-word. The string is short, so keep it on one line. */
  white-space: nowrap;
}
.ah-char {
  display: inline-block;
  white-space: pre;
}
.ah-title {
  font-family: var(--serif);
  font-weight: 400;
  font-size: clamp(2rem, min(5.2vw, 8svh), 4.6rem);
  line-height: 1.02;
  letter-spacing: -.015em;
  margin: 0;
  max-width: 14ch;
}
.ah-title .word { line-height: 1.06; }
.ah-sub {
  margin-top: clamp(10px, 1.6svh, 18px);
  max-width: 42ch;
  font-size: clamp(.8rem, 1.05vw, .95rem);
  font-weight: 300;
  line-height: 1.75;
  color: rgba(255, 255, 255, .78);
}

/* -- the stage: fact ledger + a deck of built work ---------
   Replaces the dated timeline. The studio has one published
   founding year and four dated projects, which is too little
   to carry a timeline UI — so the same facts are restated as
   a standing ledger, and the work becomes a stacked deck that
   deals itself card by card. Nothing here claims a date the
   site does not already publish. */
.ah-stage {
  position: relative;
  z-index: 2;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: end;
  gap: clamp(18px, 3vw, 56px);
}

.ah-facts {
  display: flex;
  flex-wrap: wrap;
  gap: clamp(14px, 2.6vw, 46px);
  margin: 0;
  padding-top: clamp(12px, 2svh, 20px);
  border-top: 1px solid rgba(255, 255, 255, .18);
}
.ah-fact { min-width: 0; }
.ah-fk {
  display: block;
  font-size: .58rem;
  letter-spacing: .24em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, .58);
  margin-bottom: 7px;
}
.ah-fv {
  display: block;
  margin: 0;
  font-family: var(--serif);
  font-size: clamp(1rem, 1.9vw, 1.5rem);
  line-height: 1.1;
  color: #fff;
  white-space: nowrap;
}

/* -- the deck --------------------------------------------
   Four plates stacked in depth. The topmost is dealt to the
   back of the pile on a timer (and on scroll), so the hero
   keeps moving without asking the reader to do anything.

   The plate is sized from ONE variable and its height is
   derived from it, so the 4:5 crop is identical at every
   width. Sizing height independently (a svh clamp, as this
   had) meant the ratio drifted with the window: wide and
   letterboxed on a phone, postage-stamp on a laptop. The
   inner `min()` lets a short window shrink the whole plate
   rather than squash it. */
.ah-deck {
  position: relative;
  justify-self: end;
  /* 17.5vw was the "too small to even see" case: 187px on a 1280 laptop and
     156px on a 1366×600. The floor is raised to 200px — the width at which
     a 4:5 photograph reads as a photograph rather than a swatch — and the
     svh term only pulls it below that on a window too short to hold it. */
  --deck-w: clamp(200px, min(19vw, 30svh), 250px);
  width: var(--deck-w);
}
.ah-cards {
  list-style: none;
  position: relative;
  margin: 0;
  padding: 0;
  height: calc(var(--deck-w) * 1.25);
}
.ah-card {
  position: absolute;
  inset: 0;
  overflow: hidden;
  border-radius: 4px;
  background: rgba(255, 255, 255, .06);
  box-shadow: 0 12px 34px rgba(0, 0, 0, .38);
  transform-origin: center bottom;
  will-change: transform, opacity;
}
.ah-card img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
/* Static fallback: without JS the four plates would sit exactly on top of
   one another, so fan them by hand. GSAP overwrites these once it runs. */
.ah-card:nth-child(1) { transform: translate(0, 0) rotate(0deg); z-index: 4; }
.ah-card:nth-child(2) { transform: translate(6px, 7px) rotate(1.6deg); z-index: 3; }
.ah-card:nth-child(3) { transform: translate(12px, 14px) rotate(3.2deg); z-index: 2; }
.ah-card:nth-child(4) { transform: translate(18px, 21px) rotate(4.8deg); z-index: 1; }

/* The caption rides ON the plate it names. It used to sit under the deck as
   a single shared line, which meant the title of the work was one plate
   removed from the photograph of it — and on the light half of an image it
   had nothing to sit against. Scrim first, type second. */
.ah-card-scrim {
  position: absolute;
  inset: auto 0 0 0;
  height: 62%;
  pointer-events: none;
  background: linear-gradient(180deg, rgba(6, 6, 6, 0) 0%, rgba(6, 6, 6, .34) 42%,
                                      rgba(6, 6, 6, .82) 100%);
}
.ah-card-tag {
  position: absolute;
  left: clamp(9px, 5%, 15px);
  right: clamp(9px, 5%, 15px);
  bottom: clamp(9px, 4.5%, 14px);
  display: grid;
  gap: 3px;
  opacity: 0;
  transition: opacity .45s var(--e-power);
}
/* Only the plate on top is legible; the ones behind it are 6px of edge, and
   a caption there would be a stripe of noise. */
.ah-card.is-front .ah-card-tag { opacity: 1; }
.ahc-t {
  font-family: var(--serif);
  font-size: clamp(.85rem, 1.25vw, 1.15rem);
  line-height: 1.12;
  color: #fff;
  text-shadow: 0 1px 5px rgba(0, 0, 0, .55);
}
.ahc-p {
  font-size: clamp(.52rem, .66vw, .6rem);
  letter-spacing: .16em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, .8);
  text-shadow: 0 1px 4px rgba(0, 0, 0, .55);
}

.ah-deck-count {
  display: flex;
  align-items: baseline;
  justify-content: flex-end;
  gap: 3px;
  margin: 9px 0 0;
  font-size: .58rem;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, .58);
}
.ah-deck-count b {
  font-family: var(--serif);
  font-weight: 400;
  font-size: .92rem;
  letter-spacing: 0;
  color: #fff;
}
.ah-deck-count i {
  font-style: normal;
  letter-spacing: 0;
  margin-right: .5em;
}

.ah-cue {
  position: absolute;
  right: clamp(20px, 5vw, 64px);
  top: 50%;
  z-index: 3;
  display: flex;
  align-items: center;
  gap: 12px;
  transform: rotate(90deg);
  transform-origin: right center;
}
.ah-cue-txt {
  font-size: .58rem;
  letter-spacing: .28em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, .72);
}
.ah-cue-line {
  display: block;
  width: 48px;
  height: 1px;
  background: rgba(255, 255, 255, .5);
  transform-origin: left;
  animation: ahCue 2.4s var(--e-power) infinite;
}
@keyframes ahCue {
  0%   { transform: scaleX(0); transform-origin: left; }
  45%  { transform: scaleX(1); transform-origin: left; }
  55%  { transform: scaleX(1); transform-origin: right; }
  100% { transform: scaleX(0); transform-origin: right; }
}

/* ============================================================
   2. PHILOSOPHY — the position
   ============================================================ */
.phil-section {
  position: relative;
  background: var(--paper);
  padding: clamp(56px, 8.5svh, 108px) clamp(20px, 5vw, 64px);
}
.phil-wrap {
  max-width: 1240px;
  margin: 0 auto;
}
.phil-top {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 20px;
  padding-bottom: 14px;
  border-bottom: 1px solid var(--line);
  margin-bottom: clamp(26px, 4svh, 46px);
}
.phil-top .s-label { margin-bottom: 0; }
.phil-meta {
  font-size: .62rem;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--grey);
}
.phil-meta i {
  font-style: normal;
  color: var(--accent);
  margin-right: 8px;
}

.phil-statement {
  font-family: var(--serif);
  font-weight: 400;
  font-size: clamp(1.7rem, 5.1vw, 4.1rem);
  line-height: 1.1;
  letter-spacing: -.015em;
  max-width: 18ch;
  margin: 0 0 clamp(28px, 4.2svh, 54px);
}
.phil-statement .word { line-height: 1.14; }
.phil-chip {
  display: inline-block;
  vertical-align: middle;
  width: clamp(74px, 9vw, 152px);
  height: clamp(44px, 5.4vw, 88px);
  overflow: hidden;
  border-radius: 3px;
  margin: 0 .18em;
  transform: translateY(-.06em);
}
.phil-chip img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.phil-band {
  position: relative;
  /* Was full-bleed, pulled past the page edges with negative margins. It
     read stretched, and it was the only element on the page not sitting on
     the content column. It now spans exactly the same 1240px as the
     statement above and the two-column foot below, so the chapter has one
     left edge and one right edge all the way down. */
  margin: 0 0 clamp(26px, 3.8svh, 48px);
}
.phil-band-media {
  overflow: hidden;
  border-radius: 4px;
  /* Its own 16:9 rather than a fixed height: at 1240 wide the old
     clamp(…,460px) cropped a 2.7:1 letterbox out of a 16:9 photograph,
     which is what made it look stretched. The max-height keeps it off
     short screens; the crop it takes there is mild. */
  aspect-ratio: 16 / 9;
  max-height: 60svh;
  will-change: clip-path;
}
.phil-band-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  will-change: transform;
}
.phil-band-cap {
  display: flex;
  align-items: baseline;
  gap: 12px;
  margin-top: 9px;
  font-size: .64rem;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--grey);
}
.pb-cap-i {
  font-style: normal;
  color: var(--accent);
  flex-shrink: 0;
}

.phil-foot {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(24px, 4vw, 72px);
  padding-top: clamp(18px, 3svh, 34px);
  border-top: 1px solid var(--line);
}
/* shared.css sets .s-body to 1.9 — generous for a 560px measure, loose at
   the width this column actually gets. Item: reduce space between text. */
.phil-body { max-width: none; line-height: 1.7; }
.phil-body-2 {
  font-size: clamp(1rem, 1.7vw, 1.35rem);
  line-height: 1.5;
  font-weight: 300;
  color: var(--ink);
  max-width: 30ch;
  justify-self: end;
}

/* ============================================================
   3. FOUNDERS — an editorial two-up

   Rebuilt from the ground up. The accordion this replaces asked the reader
   to press a tab to meet the second founder, gave the open one an enormous
   plate, and spent a whole viewport doing it. There are two people; two
   people is a list, not an interface. Both are readable at once, the
   portrait is a narrow standing plate rather than a half-screen panel, and
   the chapter is as tall as its content.
   ============================================================ */
.founders-section {
  position: relative;
  background: var(--paper);
  /* svh rather than a px ceiling on the vertical padding: on a 1280×720
     laptop the fixed clamp put 76px above and 72px below two rows that
     already came to 590px, and the chapter ran 17px past the window. Tied
     to the window's own height it gives that back where there is no room
     and keeps the full measure where there is. */
  padding: clamp(44px, 7.5svh, 108px) clamp(20px, 5vw, 64px) clamp(44px, 7svh, 100px);
  border-top: 1px solid var(--line);
}
.fd-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 20px;
  flex-wrap: wrap;
  max-width: 1240px;
  margin: 0 auto clamp(26px, 4svh, 48px);
  padding-bottom: 14px;
  border-bottom: 1px solid var(--line);
}
.fd-head .s-label { margin-bottom: 0; }
.fd-heading {
  font-family: var(--serif);
  font-weight: 400;
  font-size: clamp(1.35rem, 3.1vw, 2.5rem);
  line-height: 1.12;
  margin: 0;
  text-align: right;
  flex: 1 1 auto;
}

.fd-list {
  list-style: none;
  max-width: 1240px;
  margin: 0 auto;
  padding: 0;
  display: grid;
  gap: clamp(30px, 5svh, 64px);
}
.founder {
  position: relative;
  display: grid;
  /* Three columns: the ledger index, the portrait plate, the copy. The plate
     is --plate-w — the same width the team reel gives its people, so the two
     founders read as the first two entries of one cast rather than as
     thumbnails introducing it. */
  grid-template-columns: auto var(--plate-w) minmax(0, 1fr);
  column-gap: clamp(16px, 2.6vw, 44px);
  align-items: start;
  padding-top: clamp(18px, 2.6svh, 28px);
  border-top: 1px solid var(--line);
  /* Written per frame by about.js: 1 when the row is at the middle of the
     screen, 0 at the edges — the same proximity field the team reel runs on.
     Every depth cue below is a function of it. */
  --fp: 0;
  perspective: 1100px;
}
/* The second founder steps in from the left, so the pair reads as a spread
   rather than a table. */
.founder:nth-child(2) { margin-left: clamp(0px, 5vw, 88px); }

.fd-index {
  font-family: var(--serif);
  font-size: clamp(.85rem, 1.2vw, 1.05rem);
  line-height: 1;
  color: var(--accent);
  padding-top: .35em;
}

.fd-portrait {
  position: relative;
  display: block;
  aspect-ratio: 3 / 4;
  overflow: hidden;
  border-radius: 5px;
  /* Depth off --fp, in the same idiom as .tm-plate: elevation, scale and lift
     are all functions of one number. Nothing transitions on them — the value
     is already smoothed frame to frame, and a transition on top of a
     per-frame write only adds lag.
     --tx/--ty are the pointer's position across the plate, -1..1, so the
     plate turns to face the hand. They rest at 0, which is a flat plate. */
  scale: calc(.972 + var(--fp) * .028);
  translate: 0 calc(var(--fp) * -12px);
  transform: rotateX(calc(var(--ty, 0) * -3.4deg)) rotateY(calc(var(--tx, 0) * 4.4deg));
  box-shadow: 0 calc(12px + var(--fp) * 20px) calc(30px + var(--fp) * 40px)
              rgba(20, 16, 10, calc(.13 + var(--fp) * .13));
  will-change: transform, scale, translate;
}
/* A veil that lifts as the row reaches the middle of the screen — distance,
   without a filter and its repaint cost. Same device as the team plates. */
.fd-portrait::after {
  content: '';
  position: absolute;
  inset: 0;
  background: var(--paper);
  opacity: calc(.22 - var(--fp) * .22);
  pointer-events: none;
}
.fd-portrait.junais { background: linear-gradient(148deg, #2f3a30, #55684f 58%, #93a389); }
.fd-portrait.ashar  { background: linear-gradient(148deg, #2c3138, #4d5560 58%, #8b939e); }
.fd-grid {
  position: absolute;
  inset: 0;
  background-image: linear-gradient(rgba(255, 255, 255, .16) 1px, transparent 1px),
                    linear-gradient(90deg, rgba(255, 255, 255, .16) 1px, transparent 1px);
  background-size: 30px 30px;
  -webkit-mask-image: radial-gradient(130% 100% at 26% 14%, #000 22%, transparent 78%);
  mask-image: radial-gradient(130% 100% at 26% 14%, #000 22%, transparent 78%);
  opacity: .55;
}
.fd-glyph {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--serif);
  font-size: clamp(3.6rem, 8.4vw, 7.2rem);
  line-height: .8;
  color: rgba(255, 255, 255, .9);
  mix-blend-mode: overlay;
  user-select: none;
  /* Counter-parallax: the initial drifts against the plate's own travel,
     which is what actually reads as depth rather than as sliding. about.js
     supplies --fdrift. */
  translate: calc(var(--fdrift, 0) * 1px) 0;
}
/* A slow diagonal pass of light across the plate, so a flat gradient does
   not sit completely dead beside live type. Runs only on hover, so it costs
   nothing while the reader is elsewhere. */
.fd-sheen {
  position: absolute;
  inset: -30% -60%;
  background: linear-gradient(76deg, transparent 38%, rgba(255, 255, 255, .16) 50%, transparent 62%);
  transform: translateX(-70%);
  transition: transform 1.15s var(--e-power);
  pointer-events: none;
}
.founder:hover .fd-sheen { transform: translateX(70%); }

.fd-copy { min-width: 0; padding-top: clamp(0px, .6svh, 6px); }
.founder-name {
  font-family: var(--serif);
  font-weight: 400;
  font-size: clamp(1.5rem, 3.2vw, 2.6rem);
  line-height: 1.04;
  margin: 0;
  overflow: hidden;
}
.fd-name-in {
  display: block;
  will-change: translate;
  transition: translate .9s var(--e-power);
}
html.ab-ready .fd-name-in { translate: 0 105%; }
html.ab-ready .founder.is-in .fd-name-in { translate: 0 0; }

.founder-title {
  display: block;
  margin: 5px 0 clamp(9px, 1.4svh, 15px);
  font-size: .62rem;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--accent);
}
.founder-bio {
  font-size: clamp(.82rem, 1.02vw, .93rem);
  line-height: 1.62;
  font-weight: 300;
  color: var(--grey);
  max-width: 52ch;
  margin: 0;
}
html.ab-ready .founder .founder-title,
html.ab-ready .founder .founder-bio,
html.ab-ready .founder .fd-index {
  opacity: 0;
  translate: 0 22px;
  transition: opacity .8s var(--e-power), translate .8s var(--e-power);
}
html.ab-ready .founder.is-in .founder-title,
html.ab-ready .founder.is-in .founder-bio,
html.ab-ready .founder.is-in .fd-index {
  opacity: 1;
  translate: 0 0;
}
html.ab-ready .founder.is-in .founder-title { transition-delay: .1s; }
html.ab-ready .founder.is-in .founder-bio   { transition-delay: .16s; }

/* The plate is uncovered rather than slid in: a curtain drawn up the frame,
   with the picture inside starting fractionally over-scaled so it settles
   into place as the last of the frame clears. Clip and scale only — the
   plate keeps its layout box throughout, which is what lets it arrive
   without the row reflowing under the copy beside it.
   The transition names its properties rather than using `all`, so the
   per-frame depth writes above are not caught up in it. */
html.ab-ready .founder .fd-portrait {
  clip-path: inset(0 0 100% 0);
  opacity: 0;
  transition: clip-path 1.15s var(--e-power), opacity .5s var(--e-power);
}
html.ab-ready .founder.is-in .fd-portrait {
  clip-path: inset(0 0 0 0);
  opacity: 1;
}
html.ab-ready .founder .fd-glyph,
html.ab-ready .founder .fd-grid {
  opacity: 0;
  scale: 1.14;
  transition: opacity .9s var(--e-power) .28s, scale 1.4s var(--e-power) .18s;
}
html.ab-ready .founder.is-in .fd-glyph { opacity: 1; scale: 1; }
html.ab-ready .founder.is-in .fd-grid  { opacity: .55; scale: 1; }

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* ============================================================
   4. TEAM — a horizontal reel, pinned and scrubbed
   Paper ground, not black: no-black-backgrounds is a standing rule.
   ============================================================ */
.team-section {
  position: relative;
  /* Colour AND image: a bare `background:` shorthand with a gradient leaves
     background-color transparent, so anything reading the computed colour
     (the no-black-backgrounds check included) sees rgba(0,0,0,0). */
  background-color: var(--paper);
  background-image: linear-gradient(180deg, var(--paper), #e8e3da);
  color: var(--ink);
  border-top: 1px solid var(--line);
  overflow: hidden;
  /* The pin adds the scroll distance; the section itself is one screen. */
  min-height: 100svh;
  display: grid;
  grid-template-rows: auto minmax(0, 1fr) auto;
  gap: clamp(16px, 3svh, 40px);
  padding: calc(var(--nav-h) + clamp(20px, 4svh, 52px)) 0 clamp(20px, 3.6svh, 46px);
}
.tm-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: clamp(16px, 3vw, 48px);
  flex-wrap: wrap;
  padding: 0 clamp(20px, 5vw, 64px);
}
.tm-head-l { min-width: 0; }
.tm-heading {
  font-family: var(--serif);
  font-weight: 400;
  font-size: clamp(1.5rem, min(3.6vw, 5svh), 3rem);
  line-height: 1.08;
  margin: 0;
  max-width: 18ch;
}
.team-count {
  font-size: clamp(.66rem, .84vw, .74rem);
  letter-spacing: .04em;
  color: var(--grey);
  font-weight: 300;
  text-align: right;
  max-width: 26ch;
}
.team-count b {
  font-family: var(--serif);
  font-weight: 400;
  font-size: 1.5rem;
  color: var(--accent);
  margin-right: 6px;
}

/* -- the stage: a track that slides sideways as the page scrolls --
   The stage clips; the track is wider than the viewport and is moved by
   ScrollTrigger while the section is pinned. Without JS the track simply
   scrolls horizontally by hand — every card stays reachable. */
.tm-stage {
  position: relative;
  min-height: 0;
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}
.tm-stage::-webkit-scrollbar { display: none; }
html.ab-ready .tm-stage.is-reel { overflow: hidden; }

.tm-track {
  list-style: none;
  margin: 0;
  padding: 0 clamp(20px, 5vw, 64px);
  height: 100%;
  display: flex;
  align-items: stretch;
  gap: clamp(14px, 1.8vw, 30px);
  width: max-content;
  will-change: transform;
}

.team-card {
  position: relative;
  flex: 0 0 auto;
  width: var(--plate-w);
  display: grid;
  grid-template-rows: minmax(0, 1fr) auto;
  gap: clamp(8px, 1.2svh, 14px);
  min-height: 0;
  /* --near is written per-frame by about.js: 1 at the middle of the screen,
     0 at the edges. Every depth cue below is a function of it, so the reel
     reads as a continuous field rather than a row of boxes flipping an
     .is-active class on and off. */
  --near: 0;
  perspective: 900px;
}
/* Cards fan slightly off the baseline so the reel reads as a hand of
   photographs rather than a row of boxes. GSAP overwrites this on the
   pinned path; it is the no-JS look and the phone look. */
.team-card:nth-child(even) { padding-top: clamp(10px, 2.4svh, 34px); }

.tm-plate {
  position: relative;
  display: block;
  min-height: 0;
  border-radius: 4px;
  overflow: hidden;
  background: #2b2b2e;
  /* Elevation, scale and lean all interpolate off --near. No transition on
     transform: the value itself is already smoothed frame to frame, and a
     transition on top of a per-frame write only adds lag. */
  scale: calc(.955 + var(--near) * .075);
  translate: 0 calc(var(--near) * -10px);
  box-shadow: 0 calc(10px + var(--near) * 16px) calc(28px + var(--near) * 34px)
              rgba(20, 16, 10, calc(.13 + var(--near) * .14));
  will-change: transform, scale, translate;
}
.tm-mono {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-style: normal;
  font-family: var(--serif);
  font-size: clamp(2.4rem, 4.6vw, 4.2rem);
  line-height: 1;
  letter-spacing: .04em;
  color: rgba(255, 255, 255, .94);
  /* The gradients run light at the lower right, where a plain white
     monogram loses its edge. A hairline shadow keeps it crisp on all
     eight without tinting the plate. */
  text-shadow: 0 2px 6px rgba(0, 0, 0, .4);
  /* Counter-parallax: the monogram drifts against the plate's own travel,
     which is what actually reads as depth. about.js supplies --drift. */
  translate: calc(var(--drift, 0) * 1px) 0;
  opacity: calc(.62 + var(--near) * .38);
}
.tm-grain {
  position: absolute;
  inset: 0;
  background-image: linear-gradient(rgba(255, 255, 255, .1) 1px, transparent 1px);
  background-size: 100% 5px;
  opacity: .5;
  mix-blend-mode: overlay;
}
/* A veil that lifts as the card approaches the middle — distance, without
   a filter and its repaint cost. */
.tm-plate::after {
  content: '';
  position: absolute;
  inset: 0;
  background: var(--paper);
  opacity: calc(.26 - var(--near) * .26);
  pointer-events: none;
}

.tm-meta {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  grid-template-areas: 'num name' 'num role';
  align-items: baseline;
  column-gap: 10px;
  row-gap: 3px;
  padding-top: clamp(8px, 1.2svh, 12px);
  border-top: 1px solid var(--line);
}
.tm-num {
  grid-area: num;
  align-self: start;
  font-size: .58rem;
  letter-spacing: .18em;
  color: var(--accent);
  transition: opacity .6s var(--e-power), translate .6s var(--e-power);
}
.team-name {
  grid-area: name;
  font-family: var(--serif);
  font-weight: 400;
  font-size: clamp(1rem, 1.5vw, 1.42rem);
  line-height: 1.1;
  margin: 0;
  overflow: hidden;
  color: var(--ink);
}
/* The reveal rides `translate` so GSAP keeps `transform` for the reel's
   own motion. The start state is gated behind html.ab-ready, so a page
   whose script never runs still shows every name. */
.tm-name-in {
  display: block;
  will-change: translate;
  transition: translate .8s var(--e-power);
}
html.ab-ready .team-card .tm-name-in { translate: 0 105%; }
html.ab-ready .team-card.is-in .tm-name-in { translate: 0 0; }

.team-role {
  grid-area: role;
  font-size: clamp(.56rem, .74vw, .66rem);
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--grey);
  transition: color .5s var(--e-power), opacity .6s var(--e-power),
              translate .6s var(--e-power);
}
.team-card.is-active .team-role { color: var(--accent); }
/* The number and the role ride the same .is-in gate as the name. Ungated
   they paint while the name is still translated out of its mask, so a card
   entering the stage reads as a role with nobody attached to it. Same gate,
   so each card arrives whole. */
html.ab-ready .team-card .tm-num,
html.ab-ready .team-card .team-role {
  opacity: 0;
  translate: 0 60%;
}
html.ab-ready .team-card.is-in .tm-num,
html.ab-ready .team-card.is-in .team-role {
  opacity: 1;
  translate: 0 0;
}
/* Same gate again for the plate, or an unrevealed card announces itself as
   a lone colour chip floating beside nothing. Qualified at source rather
   than fought with :not() — the two selectors would otherwise tie on
   specificity and source order alone would decide it.
   Opacity only: scale and box-shadow are now written per frame from --near,
   and a transition on top of a per-frame write is pure lag. */
html.ab-ready .tm-plate { opacity: 0; }
html.ab-ready .team-card.is-in .tm-plate {
  opacity: 1;
  transition: opacity .7s var(--e-power);
}

/* -- foot: progress + hint -------------------------------- */
.tm-foot {
  display: flex;
  align-items: center;
  gap: clamp(14px, 2.4vw, 32px);
  padding: 0 clamp(20px, 5vw, 64px);
}
.tm-progress {
  position: relative;
  display: block;
  flex: 1 1 auto;
  height: 1px;
  background: rgba(10, 10, 10, .12);
  overflow: hidden;
}
.tm-progress-fill {
  position: absolute;
  inset: 0;
  background: var(--accent);
  transform: scaleX(0);
  transform-origin: left;
}
.tm-hint {
  flex: 0 0 auto;
  font-size: .58rem;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--grey);
}

/* ============================================================
   5. VALUES — three chapters on paper
   ============================================================ */
.values-section {
  position: relative;
  background: var(--paper);
  color: var(--ink);
  padding: clamp(56px, 8.5svh, 108px) clamp(20px, 5vw, 64px) clamp(52px, 7.5svh, 96px);
}
.val-shell {
  max-width: 1240px;
  margin: 0 auto;
  display: grid;
  grid-template-columns: minmax(210px, 300px) minmax(0, 1fr);
  gap: clamp(30px, 5vw, 96px);
  align-items: start;
}
.val-spine {
  position: sticky;
  top: calc(var(--nav-h) + clamp(24px, 6svh, 64px));
}
.val-spine .s-label { margin-bottom: 14px; }
.val-heading {
  font-family: var(--serif);
  font-weight: 400;
  font-size: clamp(1.7rem, 3.4vw, 3rem);
  line-height: 1.1;
  margin: 0 0 clamp(14px, 2.2svh, 24px);
}
.val-counter {
  display: flex;
  align-items: baseline;
  gap: 4px;
  font-family: var(--serif);
  line-height: 1;
  margin-bottom: 10px;
  /* Lining figures of equal width: the counter swaps 01 → 02 → 03 in place,
     and proportional digits make the rail beneath it shift as it does. */
  font-variant-numeric: tabular-nums;
  font-feature-settings: 'tnum' 1;
}
.val-counter b {
  font-weight: 400;
  font-size: clamp(2.4rem, 4.6vw, 4rem);
  color: var(--accent);
}
.val-counter i {
  font-style: normal;
  font-size: 1rem;
  color: var(--grey);
}
.val-rail {
  display: block;
  position: relative;
  height: 2px;
  width: 100%;
  max-width: 220px;
  background: var(--line);
  overflow: hidden;
}
.val-rail-fill {
  position: absolute;
  inset: 0;
  background: var(--accent);
  transform: scaleX(0);
  transform-origin: left;
}
.val-spine-note {
  margin-top: 13px;
  font-size: .78rem;
  line-height: 1.6;
  font-weight: 300;
  color: var(--grey);
  max-width: 24ch;
}

.val-stack {
  display: grid;
  gap: clamp(40px, 7svh, 92px);
}
.value-card {
  position: relative;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  /* Separate axes on purpose. The wide gap belongs between the numeral and
     the content column; as a `gap` shorthand it also landed between image,
     title and copy, which is what made the card read loose no matter what
     the margins below said. Rows are spaced by those margins alone. */
  column-gap: clamp(16px, 2.6vw, 40px);
  row-gap: 0;
  align-items: start;
}
.value-card:nth-child(2) { margin-left: clamp(0px, 6vw, 92px); }
.value-card:nth-child(3) { margin-left: clamp(0px, 2.5vw, 40px); }
.value-num {
  font-family: var(--serif);
  font-size: clamp(1.1rem, 1.7vw, 1.5rem);
  line-height: 1;
  color: var(--accent);
  padding-top: 4px;
}
.val-media {
  grid-column: 2;
  overflow: hidden;
  border-radius: 4px;
  /* Proximity: image, title and copy are one thought, so the gaps inside a
     card stay far smaller than the gap between cards (below). The old
     30px/12px/1.8 stack read as three loose fragments. */
  margin-bottom: clamp(8px, 1.2svh, 13px);
  will-change: clip-path;
}
.val-media img {
  width: 100%;
  height: 100%;
  max-height: 52svh;
  object-fit: cover;
  display: block;
  will-change: transform;
}
.value-title {
  grid-column: 2;
  font-family: var(--serif);
  font-weight: 400;
  font-size: clamp(1.4rem, 3vw, 2.5rem);
  line-height: 1.12;
  margin: 0 0 4px;
}
.value-desc {
  grid-column: 2;
  font-size: clamp(.82rem, 1.05vw, .95rem);
  line-height: 1.6;
  font-weight: 300;
  color: var(--grey);
  max-width: 46ch;
  margin: 0;
}

/* ============================================================
   6. AWARDS & PRESS — the ledger
   ============================================================ */
.awards-section {
  position: relative;
  background: var(--paper);
  padding: clamp(52px, 8svh, 100px) clamp(20px, 5vw, 64px) clamp(52px, 8svh, 100px);
  border-top: 1px solid var(--line);
}
.aw-inner {
  max-width: 1240px;
  margin: 0 auto;
}
.aw-head {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: end;
  gap: 16px;
  margin-bottom: clamp(20px, 3.2svh, 38px);
}
.aw-head .s-label { grid-column: 1; margin-bottom: 8px; }
.aw-heading {
  grid-column: 1;
  font-family: var(--serif);
  font-weight: 400;
  font-size: clamp(1.8rem, 4.4vw, 3.6rem);
  line-height: 1.08;
  margin: 0;
}
.aw-meta {
  grid-column: 2;
  grid-row: 2;
  font-size: .68rem;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--grey);
  white-space: nowrap;
}
.aw-meta b {
  font-family: var(--serif);
  font-weight: 400;
  font-size: 1.2rem;
  color: var(--accent);
  letter-spacing: 0;
  margin-right: 6px;
}

.awards-list {
  list-style: none;
  margin: 0;
  padding: 0;
  border-top: 1px solid var(--line);
}
/* Three columns on one baseline. Two things were breaking the years:
   the middle cell was a nested flex box, so name and org each found their
   own baseline and the year aligned to neither; and Instrument Serif sets
   proportional figures, so 2024 and 2022 were not the same width and the
   column read ragged. Fixed column + tabular figures + a shared baseline. */
.award-row {
  position: relative;
  display: grid;
  grid-template-columns: clamp(66px, 7.5vw, 104px) minmax(0, 1fr) auto;
  align-items: baseline;
  column-gap: clamp(14px, 2.4vw, 40px);
  padding: clamp(14px, 2.2svh, 24px) clamp(8px, 1.2vw, 18px);
  border-bottom: 1px solid var(--line);
  color: var(--ink);
  overflow: hidden;
  isolation: isolate;
}
.aw-wipe {
  position: absolute;
  inset: 0;
  z-index: -1;
  background: var(--accent-soft);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform .7s var(--e-power);
}
.award-row:hover .aw-wipe { transform: scaleX(1); }

.award-year {
  font-family: var(--serif);
  font-size: clamp(1.35rem, 2.4vw, 2.1rem);
  line-height: 1;
  letter-spacing: .01em;
  font-variant-numeric: tabular-nums lining-nums;
  font-feature-settings: 'tnum' 1, 'lnum' 1;
  color: var(--ink);
  opacity: .3;
  transition: opacity .5s var(--e-power), color .5s var(--e-power);
}
.award-row:hover .award-year { opacity: 1; color: var(--accent); }

.award-name {
  min-width: 0;
  font-size: clamp(.92rem, 1.5vw, 1.35rem);
  font-weight: 300;
  line-height: 1.28;
  transition: translate .6s var(--e-power);
}
.award-row:hover .award-name { translate: 6px 0; }
.award-org {
  font-size: .66rem;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--grey);
  text-align: right;
  white-space: nowrap;
  transition: color .5s var(--e-power);
}
.award-row:hover .award-org { color: var(--ink); }

/* -- the pointer preview ----------------------------------
   One fixed frame that rides the pointer; each row owns one of the plates
   stacked inside it and cross-fades to the top on hover. about.js writes
   the transform, so the lerp and the velocity tilt happen in one place and
   the browser only ever sees a composited change. */
.aw-peek {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 120;
  width: clamp(180px, 17vw, 260px);
  aspect-ratio: 4 / 3;
  margin: 0;
  border-radius: 5px;
  overflow: hidden;
  pointer-events: none;
  opacity: 0;
  visibility: hidden;
  box-shadow: 0 22px 60px rgba(20, 16, 10, .3);
  transition: opacity .38s var(--e-power), visibility 0s linear .38s;
  will-change: transform;
}
.aw-peek.is-live {
  opacity: 1;
  visibility: visible;
  transition: opacity .38s var(--e-power), visibility 0s linear 0s;
}
.aw-peek img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  opacity: 0;
  transition: opacity .4s var(--e-power);
}
.aw-peek img.is-shown { opacity: 1; }
/* No pointer, no preview — and nothing to load or paint on a phone. */
@media (hover: none), (pointer: coarse) {
  .aw-peek { display: none; }
}

/* ============================================================
   7. THE CLOSE — see close.css.
   This page used to end on its own `footer.ab-close`, a sheet built out of
   .cl-inner/.cl-top/.cl-rule/.cl-base/.cl-mark/.cl-legal plus overrides for
   shared.css's element-level `footer` bar. It is `footer.close` now, the
   same element on all four pages, so every one of those rules had markup to
   style on exactly one page and none of them have any left.

   They could not simply be left in place either: .cl-base, .cl-up,
   .cl-up-arrow and .cl-nav are names the new close uses too, and about.css
   loads after close.css — so the dead block would have quietly re-styled
   the live footer on this page alone.

   The one thing worth keeping was the reason for --paper: on this page the
   close lands on the same paper ground as the rest of the sheet. close.css
   takes `background: transparent` for exactly that, so it inherits it.
   ============================================================ */

/* ============================================================
   8. RESPONSIVE
   ============================================================ */
@media (max-width: 1024px) {
  /* Tablet: 17.5vw of an 834px screen is 146px, which was the "too small to
     even see" case. The deck is given a share of the width instead, and the
     column it sits in is allowed to shrink to pay for it. */
  .ah-stage { grid-template-columns: minmax(0, 1fr) auto; }
  .ah-deck { --deck-w: clamp(190px, min(30vw, 34svh), 300px); }

  .phil-statement { max-width: 22ch; }
  .phil-foot { grid-template-columns: 1fr; gap: 22px; }
  .phil-body-2 { justify-self: start; max-width: 40ch; font-size: 1.05rem; }

  .val-shell { grid-template-columns: 1fr; gap: clamp(26px, 4svh, 44px); }
  .val-spine {
    position: sticky;
    top: var(--nav-h);
    z-index: 5;
    display: grid;
    grid-template-columns: auto 1fr;
    align-items: center;
    gap: 14px 18px;
    background: var(--paper);
    padding: 14px 0;
    border-bottom: 1px solid var(--line);
  }
  .val-spine .s-label { grid-column: 1; margin-bottom: 0; }
  .val-heading { grid-column: 1 / -1; grid-row: 2; margin: 0; font-size: clamp(1.5rem, 5vw, 2.2rem); }
  .val-counter { grid-column: 2; grid-row: 1; justify-self: end; margin-bottom: 0; }
  .val-counter b { font-size: 1.8rem; }
  .val-rail { grid-column: 1 / -1; grid-row: 3; max-width: none; }
  .val-spine-note { display: none; }
  .value-card:nth-child(2),
  .value-card:nth-child(3) { margin-left: 0; }

  /* Both plates step down together — the token, not the card. */
  .about-page { --plate-w: clamp(180px, 30vw, 240px); }
}

@media (max-width: 900px) {
  .aw-head { grid-template-columns: 1fr; }
  .aw-meta { grid-column: 1; grid-row: 3; margin-top: 10px; }
  /* The org drops under the name; the year keeps its own column so the
     ledger still reads down the left edge. */
  .award-row {
    grid-template-columns: clamp(52px, 13vw, 84px) minmax(0, 1fr);
    row-gap: 4px;
  }
  .award-org { grid-column: 2; text-align: left; white-space: normal; }
}

@media (max-width: 760px) {
  /* ---- hero: the ledger stacks, the deck sits beneath it ----
     The deck stops stretching to the column here. Left to fill the width
     it became a letterbox and the 4:5 photographs were cropped to a band;
     capping it and centring it keeps the plate the same shape it has on a
     desktop, only larger relative to the screen. */
  .about-hero { padding-bottom: clamp(14px, 2.6svh, 26px); }
  .ah-copy { max-width: none; }
  .ah-cue { display: none; }
  .ah-stage { grid-template-columns: 1fr; gap: clamp(14px, 2.4svh, 24px); }
  .ah-facts { gap: 14px 26px; }
  .ah-deck {
    justify-self: center;
    --deck-w: clamp(178px, min(54vw, 30svh), 260px);
    width: var(--deck-w);
  }
  .ah-deck-count { justify-content: center; }

  /* ---- founders: portrait over copy ----
     The plate keeps its 3/4 shape and the copy runs full-bleed beneath it;
     the index moves onto the same row as the plate. --plate-w is retuned
     rather than overridden per-element, so the founders' plate and the team
     card it is matched to shrink together and stay the same object. */
  .founder {
    grid-template-columns: auto minmax(0, 1fr);
    row-gap: clamp(12px, 2svh, 18px);
  }
  .about-page { --plate-w: min(62vw, 260px); }
  .fd-portrait { width: var(--plate-w); }
  .fd-copy { grid-column: 1 / -1; }
  .founder:nth-child(2) { margin-left: 0; }

  .phil-statement { font-size: clamp(1.55rem, 7.4vw, 2.6rem); max-width: 100%; }
  .phil-chip { width: clamp(58px, 17vw, 92px); height: clamp(34px, 10vw, 54px); }
  .phil-band-media { aspect-ratio: 4 / 3; max-height: 44svh; }

  /* ---- team: a swipeable strip, not a pinned reel ---- */
  .team-section {
    min-height: 0;
    padding: clamp(56px, 9svh, 90px) 0 clamp(26px, 4svh, 40px);
    grid-template-rows: auto auto auto;
  }
  .tm-stage { overflow-x: auto; scroll-snap-type: x mandatory; }
  html.ab-ready .tm-stage.is-reel { overflow-x: auto; }
  .tm-track { padding: 0 20px; gap: 14px; }
  .team-card {
    width: var(--plate-w);
    scroll-snap-align: center;
  }
  .team-card:nth-child(even) { padding-top: 0; }
  .tm-plate { aspect-ratio: 4 / 5; }
  .tm-hint { display: none; }
}

@media (max-width: 520px) {
  /* One org name — "South Asian Architecture Awards" — takes a second line
     at 360px while the other four fit on one, and a ledger with one row
     16px taller than its neighbours reads as mis-set. The tracking costs
     the most width here, so it gives way first; the names themselves are
     award records and are not abbreviated. */
  .award-org { font-size: .6rem; letter-spacing: .06em; }
}

/* Short windows (landscape phones, small laptops): height is the scarce
   axis. The founders' plate is capped against the window's own height —
   min() rather than a replacement clamp, so it gives ground only where
   there is none and keeps the shared width everywhere else. The team reel
   is not touched: it owns its own vertical budget through the pin. */
@media (max-height: 620px) and (min-width: 761px) {
  .founder { grid-template-columns: auto min(var(--plate-w), 34svh) minmax(0, 1fr); }
  .fd-glyph { font-size: clamp(2.4rem, 12svh, 4.2rem); }
}
@media (max-height: 660px) and (max-width: 760px) {
  /* 360×640 is the smallest screen the site targets, and there the hero's
     own content floor (copy + ledger + a 4:5 deck) came to 642px against a
     640px window — a two-pixel overrun that shows as a scrollbar before the
     reader has done anything. The deck gives up the difference; it is the
     one element here sized from a variable rather than from its text. The
     floor stays at 170px, below which the plate stops reading as a
     photograph — the two pixels come out of the svh term instead. */
  .ah-deck { --deck-w: clamp(170px, min(46vw, 27svh), 200px); }
  .ah-facts { padding-top: clamp(8px, 1.4svh, 14px); }
}
@media (max-height: 560px) and (max-width: 760px) {
  .fd-portrait { width: min(var(--plate-w), 27svh); }
  .fd-glyph { font-size: clamp(2rem, 11svh, 3.4rem); }
  .about-hero { padding-top: calc(var(--nav-h) + 10px); }
  .ah-title { font-size: clamp(1.5rem, 5.6svh, 2.4rem); }
  .ah-sub { display: none; }
  .ah-deck { --deck-w: clamp(120px, 26svh, 190px); }
}

/* ============================================================
   9. REDUCED MOTION
   ============================================================ */
@media (prefers-reduced-motion: reduce) {
  .ah-cue-line { animation: none; transform: scaleX(1); }
  .tm-name-in,
  .tm-plate,
  .fd-name-in,
  .fd-sheen,
  .aw-wipe,
  .award-name,
  .award-year { transition: none; }
  /* The founders' plate is uncovered rather than faded, so switching the
     transition off is not enough — the start state has to go with it, or the
     curtain stays down and the portrait never appears. */
  html.ab-ready .founder .fd-portrait,
  html.ab-ready .founder .fd-glyph,
  html.ab-ready .founder .fd-grid {
    transition: none;
    clip-path: none;
    opacity: 1;
    scale: 1;
  }
  html.ab-ready .founder .fd-grid { opacity: .55; }
  .fd-portrait { transform: none; }
  /* The pointer preview is a chase animation by definition; there is no
     reduced-motion version of it, so it simply does not run. */
  .aw-peek { display: none; }
}
