/* Erfan Naji — interactivity layer.
   Nothing here overrides the locked design system: it adds behaviour on top of
   the round-7b tokens, using the same --ease, --gutter, --display and colour
   variables. Every effect is gated on html.anim and neutralised under
   prefers-reduced-motion. Remove this file and its script and the page falls
   back to the design as approved. */

/* ================= 1 · display numerals ================= */
.figures { padding: clamp(3rem, 8vh, 5.5rem) var(--gutter) clamp(4rem, 10vh, 7rem); }
.figures .eyebrow { margin-bottom: clamp(2rem, 5vh, 3.4rem); }

.figrow {
  display: grid; gap: clamp(2.4rem, 5vw, 3rem);
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  border-top: 1px solid var(--line); padding-top: clamp(2rem, 5vh, 3rem);
}
.fig p {
  margin-top: 1rem; color: var(--grey); font-size: .9rem; line-height: 1.6;
  max-width: 15rem; text-wrap: balance;
}
.fignum {
  display: block; font-family: var(--display); font-weight: 500;
  font-size: clamp(4.6rem, 15vw, 18rem); line-height: .84;
  letter-spacing: -.035em; font-variant-numeric: proportional-nums;
  color: var(--porcelain);
}
/* the zero reads as a statement, not an absence */
.fig:last-child .fignum { color: var(--water); }
/* "40+" — the plus lives outside the counter text so the count-up never eats it */
.fignum--plus::after { content: "+"; font-size: .45em; vertical-align: .55em; margin-left: .05em; }

/* ================= 2 · expand in place ================= */
.pmore {
  display: inline-flex; align-items: center; justify-content: space-between; gap: 1rem;
  width: 100%; margin: 1.1rem 0 0; padding: .7rem 0;
  border-top: 1px solid var(--line); border-bottom: 1px solid var(--line);
  color: var(--grey); font-size: .8rem; letter-spacing: .14em; text-transform: uppercase;
  transition: color .25s var(--ease), border-color .25s var(--ease);
}
.pmore:hover { color: var(--porcelain); border-color: var(--line-strong); }
/* the sign is drawn, not typed: two hairline bars, dead centre by construction.
   Rotating the whole disc 135° turns the plus into the close cross with one
   continuous move — no glyph swap, no baseline wobble. */
.pmore-sign {
  position: relative; display: inline-block; flex: none;
  width: 1.5rem; height: 1.5rem; border: 1px solid currentColor; border-radius: 50%;
}
.pmore-sign::before, .pmore-sign::after {
  content: ""; position: absolute; left: 50%; top: 50%;
  background: currentColor; transform: translate(-50%, -50%);
}
.pmore-sign::before { width: .58rem; height: 1px; }
.pmore-sign::after { width: 1px; height: .58rem; }
html.anim .pmore-sign { transition: transform .5s var(--ease); }
.pmore[aria-expanded="true"] { color: var(--porcelain); }
.pmore[aria-expanded="true"] .pmore-sign { transform: rotate(135deg); }

.pdetail { overflow: hidden; height: 0; }
.pdetail dl { padding: 1.1rem 0 .2rem; }
.pdetail dt {
  font-size: .72rem; letter-spacing: .18em; text-transform: uppercase;
  color: var(--water); margin-bottom: .35rem;
}
.pdetail dd { color: var(--grey); font-size: .92rem; line-height: 1.65; margin-bottom: 1rem; }
.pdetail dd:last-child { margin-bottom: 0; }

/* the practice card must be able to grow without the carousel clipping it */
.ptrack .pcard { height: auto; align-self: start; }

/* ================= 3 · scroll-resolved photography ================= */
/* The restrained cousin of a dither: a fine line-screen sits over the image and
   clears as the photograph scrolls into place. --r runs 0 (texture) to 1 (photo). */
[data-resolve] { --r: 1; position: relative; overflow: hidden; }
[data-resolve] img { will-change: transform, filter; }

html.anim [data-resolve] { --r: 0; }
html.anim [data-resolve] img {
  filter:
    grayscale(calc((1 - var(--r)) * 88%))
    contrast(calc(1 + (1 - var(--r)) * .18))
    brightness(calc(1 - (1 - var(--r)) * .16));
  transform: scale(calc(1 + (1 - var(--r)) * .045));
}
html.anim [data-resolve]::before {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  opacity: calc((1 - var(--r)) * .55);
  background: repeating-linear-gradient(
    90deg,
    rgba(11, 14, 15, .85) 0 1px,
    rgba(11, 14, 15, 0) 1px 4px
  );
}
/* the caption is content, not texture — keep it above the screen */
[data-resolve] figcaption { position: relative; z-index: 1; }

/* ================= 4 · headline drift ================= */
/* Horizontal movement against a vertical scroll. Small on purpose: this brand
   earns attention by being measured, so the move should register as craft
   rather than as an effect. */
html.anim [data-drift] {
  --d: 0;
  transform: translate3d(calc(var(--d) * 1px), 0, 0);
  will-change: transform;
}

/* ================= reduced motion ================= */
@media (prefers-reduced-motion: reduce) {
  html.anim [data-resolve] { --r: 1 !important; }
  html.anim [data-resolve] img { filter: none !important; transform: none !important; }
  html.anim [data-resolve]::before { display: none !important; }
  html.anim [data-drift] { transform: none !important; }
  html.anim .pmore-sign { transition: none !important; }
}

@media (max-width: 700px) {
  .fignum { font-size: clamp(3.6rem, 20vw, 6rem); }
  .figrow { grid-template-columns: repeat(2, 1fr); gap: 2rem 1.5rem; }
}

/* ================= 5 · the living composer =================
   The composer is where the whole site is aimed, so it earns the most
   interaction. Two problems it solves: a blank box is the hardest thing to
   ask a stranger to fill, and people hesitate when they can't tell what
   pressing Send will actually do. */
.starters {
  display: flex; flex-wrap: wrap; gap: .5rem; margin-bottom: .85rem;
}
.starter {
  border: 1px solid var(--line); border-radius: 999px;
  padding: .5rem 1rem; color: var(--grey);
  font-size: .78rem; letter-spacing: .1em; text-transform: uppercase;
  transition: color .25s var(--ease), border-color .25s var(--ease),
              background-color .25s var(--ease);
}
.starter:hover { color: var(--porcelain); border-color: var(--line-strong); }
.starter.is-used { background: var(--porcelain); color: var(--ink); border-color: var(--porcelain); }

.wa-preview {
  overflow: hidden; height: 0; max-width: 34rem;
}
.wa-inner { padding-top: .9rem; }
.wa-head {
  display: flex; align-items: center; gap: .5rem; margin-bottom: .5rem;
  font-size: .7rem; letter-spacing: .16em; text-transform: uppercase; color: var(--mist);
}
.wa-dot {
  width: .45rem; height: .45rem; border-radius: 50%; background: var(--water);
  flex: none;
}
.wa-bubble {
  position: relative; border: 1px solid var(--line); border-radius: 10px 10px 10px 2px;
  background: rgba(127, 178, 196, .07); padding: .8rem .95rem .55rem;
}
.wa-text {
  color: var(--porcelain); font-size: .95rem; line-height: 1.55;
  white-space: pre-wrap; overflow-wrap: anywhere; margin: 0;
}
.wa-meta {
  display: flex; justify-content: space-between; gap: 1rem; margin-top: .45rem;
  font-size: .68rem; letter-spacing: .1em; text-transform: uppercase; color: var(--mist);
}
/* the count brightens as the ceiling approaches — the only warning the visitor
   gets before the field stops accepting keystrokes */
.wa-count { transition: color .3s var(--ease); }
.wa-count.is-near { color: var(--porcelain); }

/* ================= 6 · counted gallery ================= */
.gcount {
  display: flex; align-items: baseline; gap: .2rem;
  font-family: var(--display); font-weight: 500; line-height: .85;
  letter-spacing: -.02em; color: var(--porcelain);
}
.gcount .g-now { font-size: clamp(2.6rem, 6vw, 4.6rem); }
.gcount .g-sep,
.gcount .g-all { font-size: clamp(1rem, 2vw, 1.5rem); color: var(--mist); }
html.anim .gcount .g-now { transition: opacity .18s var(--ease); }
.gcount .g-now.is-swap { opacity: .25; }
.gallery-head .gallery-nav { align-items: center; }
.g-caption {
  display: block; margin-top: .4rem; font-size: .78rem; letter-spacing: .16em;
  text-transform: uppercase; color: var(--grey); min-height: 1.2em;
}

/* ================= 7 · footer finale ================= */
html.anim .mega-mark .l1[data-drift],
html.anim .mega-mark .l2[data-drift] { display: block; }

@media (max-width: 700px) {
  .starters { gap: .4rem; }
  .starter { padding: .45rem .8rem; font-size: .72rem; }
}

/* ================= incidental fixes =================
   The decorative marquee is wider than the viewport. body already carries
   overflow-x: clip, but the document element does not, which leaves a ~39px
   horizontal scroll on narrow screens. */
html { overflow-x: clip; }

/* =====================================================================
   ROUND 2 — the site stops arriving and starts moving.
   ===================================================================== */

/* ---------- 8 · cross-page view transitions ----------
   Six separate HTML files behaving like one continuous surface. Two
   declarations do the work; browsers without support simply hard-cut as
   before, which is exactly today's behaviour. */
@media (prefers-reduced-motion: no-preference) {
  @view-transition { navigation: auto; }

  /* Sequenced, not simultaneous. Both used to start at t=0 — .26s out against
     .44s in — so for a quarter of a second two full copies of the page were on
     screen sliding opposite ways. That is what read as the previous page
     leaking into the next one, composer text and all. The incoming page now
     waits for the outgoing one to clear. */
  ::view-transition-old(root) { animation: vt-out .22s var(--ease) both; }
  ::view-transition-new(root) { animation: vt-in .34s var(--ease) .2s both; }
  @keyframes vt-out { to { opacity: 0; transform: translateY(-8px); } }
  @keyframes vt-in { from { opacity: 0; transform: translateY(12px); } }

  /* The wordmark is deliberately NOT a shared element. It was, and because it
     collapses to E–N on scroll, the outgoing page handed over a collapsed mark
     while the incoming page rendered a full one at scrollY 0 — the group then
     morphed between the two states and you saw ERFAN NAJI and E–N at once.
     Letting it cross-fade inside the root snapshot removes the ghost. */
}

/* ---------- 9 · the marquee answers the scroll ----------
   "How things going left and right." It drifts on its own, but scrolling
   drives it: faster with you, and it reverses when you scroll back up. The
   skew is what sells it as momentum rather than a loop. */
html.anim .marquee-track.is-live {
  animation: none !important;
  will-change: transform;
}
.marquee { cursor: default; }

/* ---------- 10 · hero leaves as a scene ---------- */
html.anim [data-parallax] {
  --py: 0;
  transform: translate3d(0, calc(var(--py) * 1px), 0);
  will-change: transform;
}

/* ---------- 11 · the texture reaches the type ----------
   The line-screen governs photography; letting it govern the footer wordmark
   too is what makes the site read as one material rather than good layout
   wrapped around good photos. */
/* the wordmark takes data-resolve from the script, so it inherits the same
   ::before line-screen the photographs use. Only the clipping needs undoing —
   a display-scale wordmark must not be cropped by the texture wrapper. */
.mega-mark .l1[data-resolve], .mega-mark .l2[data-resolve] { overflow: visible; }

/* ---------- 12 · magnetic controls ----------
   Only where there is a real cursor to be magnetic towards. */
@media (hover: hover) and (pointer: fine) {
  html.anim [data-magnet] {
    --mx: 0; --my: 0;
    transform: translate3d(calc(var(--mx) * 1px), calc(var(--my) * 1px), 0);
    transition: transform .35s var(--ease);
  }
  html.anim [data-magnet].is-pulled { transition: transform .08s linear; }
  /* the nav CTA already had a hover lift; keep it, layered on the magnet */
  html.anim .nav-cta[data-magnet]:hover { box-shadow: 0 6px 24px rgba(243,241,234,.12); }
}

/* ---------- 13 · the practices get a display numeral ---------- */
/* the head row is baseline-aligned, so a 90px numeral would lift itself out of
   the row and crowd the fixed nav. Sit it on the bottom edge instead. */
.pnum-wrap { margin-left: auto; align-self: flex-end; }
.pnum {
  display: flex; align-items: baseline; gap: .35rem;
  font-family: var(--display); font-weight: 500; line-height: .8;
  letter-spacing: -.03em; color: var(--porcelain);
}
.pnum .p-now { font-size: clamp(2.8rem, 7vw, 5.6rem); }
.pnum .p-sep, .pnum .p-all { font-size: clamp(1rem, 2vw, 1.6rem); color: var(--mist); }
html.anim .pnum .p-now { transition: opacity .16s var(--ease), transform .3s var(--ease); }
.pnum .p-now.is-swap { opacity: .2; transform: translateY(-6px); }
.ptag {
  display: block; text-align: right; margin-top: .3rem;
  font-size: .72rem; letter-spacing: .18em; text-transform: uppercase; color: var(--water);
  min-height: 1.1em;
}

/* ---------- 14 · links wipe rather than recolour ---------- */
html.anim .p-link, html.anim .head-link, html.anim .site-nav ul a, html.anim .to-top { position: relative; }
html.anim .p-link::before, html.anim .head-link::before, html.anim .site-nav ul a::before,
html.anim .to-top::before {
  content: ""; position: absolute; left: 0; right: 0; bottom: -3px; height: 1px;
  background: currentColor; transform: scaleX(0); transform-origin: right;
  transition: transform .4s var(--ease);
}
html.anim .p-link:hover::before, html.anim .head-link:hover::before,
html.anim .site-nav ul a:hover::before, html.anim .to-top:hover::before { transform: scaleX(1); transform-origin: left; }

/* ---------- 15 · gallery cards travel at their own rates ---------- */
html.anim .gallery .card { will-change: transform; }

@media (prefers-reduced-motion: reduce) {
  html.anim [data-parallax] { transform: none !important; }
  html.anim [data-magnet] { transform: none !important; }
  html.anim .marquee-track.is-live { transform: none !important; }
}

@media (max-width: 760px) {
  .pnum { margin-left: 0; }
  .ptag { text-align: left; }
}

/* =====================================================================
   16 · the advisory as a sequence, not a grid
   The four practices describe a progression — brief, evaluation, move,
   the space you end up living in. A 2x2 grid states that badly: four
   equal boxes read as four unrelated services. So the left column holds
   still with the number and the rail while the right column travels,
   the same way a good print spread keeps a running head.
   No scroll hijacking: the page scrolls at its normal speed throughout.
   ===================================================================== */
.flow {
  display: grid;
  grid-template-columns: minmax(0, .36fr) minmax(0, .64fr);
  gap: clamp(2rem, 5vw, 5rem);
  margin: 2rem var(--gutter) clamp(4rem, 10vh, 7rem);
}

.flow-stage {
  position: sticky; top: clamp(6rem, 15vh, 9.5rem);
  align-self: start; padding-top: .5rem;
}
.flow-num {
  display: flex; align-items: baseline; gap: .25rem;
  font-family: var(--display); font-weight: 500; line-height: .8;
  letter-spacing: -.035em; color: var(--porcelain);
}
/* The numeral is the left rail now that the practice photographs are gone: it
   changes as you descend, so it is the thing telling you where you are. */
.flow-num .flow-now { font-size: clamp(5rem, 14vw, 15rem); }
.flow-num i, .flow-num span { font-size: clamp(1rem, 1.8vw, 1.5rem); color: var(--mist); font-style: normal; }
html.anim .flow-num .flow-now { transition: opacity .16s var(--ease), transform .3s var(--ease); }
.flow-num .flow-now.is-swap { opacity: .2; transform: translateY(-8px); }

.flow-title {
  margin-top: .9rem; font-family: var(--display); font-weight: 500;
  font-size: clamp(1.1rem, 1.9vw, 1.6rem); line-height: 1.2; color: var(--porcelain);
  max-width: 12ch; min-height: 2.4em;
}
html.anim .flow-title { transition: opacity .2s var(--ease); }
.flow-title.is-swap { opacity: 0; }

.flow-rail { margin-top: clamp(1.6rem, 4vh, 2.6rem); }
.flow-rail ol { list-style: none; display: grid; gap: .1rem; }
.flow-rail a {
  display: grid; grid-template-columns: 2.2rem auto 1fr; align-items: center; gap: .7rem;
  padding: .65rem 0; text-decoration: none; color: var(--grey);
  font-size: .8rem; letter-spacing: .12em; text-transform: uppercase;
  transition: color .3s var(--ease);
}
.flow-rail a:hover { color: var(--porcelain); }
.flow-rail i {
  display: block; height: 1px; background: var(--line-strong);
  transform: scaleX(.45); transform-origin: left;
  transition: transform .45s var(--ease), background-color .45s var(--ease);
}
.flow-rail .rail-n { color: var(--mist); font-variant-numeric: tabular-nums; }
.flow-rail li.is-done i { transform: scaleX(.8); background: var(--line-strong); }
.flow-rail li.is-active i { transform: scaleX(1); background: var(--water); }
.flow-rail li.is-active a { color: var(--porcelain); }
.flow-rail li.is-active .rail-n { color: var(--water); }

/* the right column: each practice is a scene rather than a cell */
.block-flow { display: block; background: none; border: 0; margin: 0; }
.block-flow .block {
  padding: clamp(2.5rem, 6vh, 4.5rem) 0;
  border-top: 1px solid var(--line);
  scroll-margin-top: clamp(6rem, 16vh, 10rem);
}
.block-flow .block:first-child { border-top: 0; padding-top: 0; }
.block-flow .block:last-child { border-bottom: 1px solid var(--line); }
/* the tag is redundant with the rail once the sequence is legible */
.block-flow .block .tag { color: var(--mist); }

html.anim .block-flow .block {
  opacity: .34;
  transition: opacity .55s var(--ease), transform .55s var(--ease);
  transform: translateY(6px);
}
html.anim .block-flow .block.is-current { opacity: 1; transform: none; }

@media (max-width: 900px) {
  /* The full stage is a desktop affordance — but its job (telling you where
     you are in the sequence) matters MORE on a phone, where the four blocks
     otherwise read as a wall of text. So the stage shrinks to a pocket strip
     that rides under the nav; the same sync drives it. */
  .flow { grid-template-columns: 1fr; gap: 0; }
  .flow-stage { display: none; }
  html.anim .block-flow .block { opacity: 1; transform: none; }
}

/* ---------- 16b · pocket stage + fold-out (phone) ---------- */
.flow-pocket { display: none; }
@media (max-width: 900px) {
  .flow-pocket { --nav-h: 64px; position: sticky; top: var(--nav-h); z-index: 30;
    display: flex; align-items: baseline; gap: .4rem;
    margin: 0 calc(-1 * var(--gutter)) 1.2rem; padding: .65rem var(--gutter) .6rem;
    background: rgba(11, 14, 15, .9);
    -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px);
    border-bottom: 1px solid var(--line); }
  .flow-pocket .fp-now { font-family: var(--display); font-weight: 500; font-size: 1.5rem;
    line-height: 1; color: var(--porcelain); }
  .flow-pocket .fp-sep, .flow-pocket .fp-all { font-size: .8rem; color: var(--mist); font-style: normal; }
  .flow-pocket .fp-title { margin-left: auto; font-size: .72rem; letter-spacing: .16em;
    text-transform: uppercase; color: var(--water);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 58%; }
  html.anim .flow-pocket .fp-now, html.anim .flow-pocket .fp-title { transition: opacity .18s var(--ease); }
  .flow-pocket .fp-now.is-swap, .flow-pocket .fp-title.is-swap { opacity: .2; }
  .block-flow .bmore { margin-top: .3rem; }
}
/* the fold is a phone behaviour; desktop keeps every word visible and the
   button out of the way */
@media (min-width: 901px) {
  .block-flow .bmore { display: none; }
  .block-flow .bdetail { height: auto !important; overflow: visible; }
  .block-flow .bdetail dl { padding: 0; }
}

@media (prefers-reduced-motion: reduce) {
  html.anim .block-flow .block { opacity: 1 !important; transform: none !important; }
  html.anim .flow-num .flow-now, html.anim .flow-title { transition: none !important; }
}
