/* Page compositions.
   Sections are fluid — flex-wrap with flex-basis thresholds plus clamp() type
   and padding — so they degrade continuously rather than snapping at
   breakpoints. Only the nav uses a hard media query. */

.container { max-width: var(--measure); margin: 0 auto; padding-left: var(--gutter); padding-right: var(--gutter); }
.section   { padding-top: var(--section-y); padding-bottom: var(--section-y); }

/* ---- Section divider ----
   Two ivory sections running together have no boundary, so the reader cannot
   tell where one ends. This draws a hairline on the container's top edge —
   inside the 1180px measure, so it aligns with the content rather than
   bleeding — with a short brass segment marking the start.

   Only needed between same-ground sections: a deep-green band is its own
   divider, and the first section after a page title does not need one either. */
.section--ruled > .container { position: relative; padding-top: clamp(26px, 3.2vh, 44px); }
.section--ruled > .container::before {
  content: "";
  position: absolute;
  left: var(--gutter);
  right: var(--gutter);
  top: 0;
  height: 1px;
  background: var(--ink-14);
}
.section--ruled > .container::after {
  content: "";
  position: absolute;
  left: var(--gutter);
  top: 0;
  width: 56px;
  height: 1px;
  background: var(--brass);
}
.on-green.section--ruled > .container::before { background: var(--paper-16); }
.on-green.section--ruled > .container::after  { background: var(--brass-light); }

[dir="rtl"] .section--ruled > .container::after { left: auto; right: var(--gutter); }

/* Left-aligned to the container while bleeding right to the viewport edge. */
.bleed-left { padding-left: max(var(--gutter), calc((100vw - var(--measure)) / 2 + var(--gutter))); }

/* ----------------------------------------------------------- home hero ---- */

/* The hero is exactly one screen minus everything above it, and never taller.
   --nav-real is measured at runtime by site.js (it includes the WP admin bar);
   the fallback keeps the layout sane before JS runs. `100svh` rather than
   100vh so mobile browser chrome cannot push the composition out of reach.
   `height` rather than `min-height`: with min-height alone the portrait column
   grew past the viewport and, because the columns stretch to match, dragged
   the type column to nearly 1900px — which buried the copy below the fold. */
/* The hero sits below the navigation and fills the rest of the screen.
   --nav-real is measured at runtime by site.js and includes both the nav and
   the WP admin bar, so the composition never runs past the fold. */
.hero {
  display: flex;
  flex-wrap: wrap;
  align-items: stretch;
  height: calc(100svh - var(--nav-real, 121px));
  overflow: hidden;
}

@supports not (height: 100svh) {
  .hero { height: calc(100vh - var(--nav-real, 121px)); }
}


/* Roughly 62/38 as grow ratios on a zero basis. Note the ratios are applied to
   the columns' content boxes, so the type column's 128px of horizontal padding
   makes the rendered split land a few points wider than the numbers suggest —
   these are tuned for the result, not the arithmetic.
   Percentage bases plus that padding exceeded 100%, which made the flex line
   wrap: the type column dropped onto its own row and stretched to ~1850px,
   burying the copy far below the fold. */
.hero__type {
  flex: 58 1 0;
  min-width: 300px;
  /* Both columns are exactly the hero's height. Without this the column takes
     its content height, overflows the parent, and `justify-content: center`
     then centres the copy inside that oversized box — pushing the eyebrow and
     headline below the fold with a large empty gap above them. */
  height: 100%;
  min-height: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
  /* vertical padding scales with viewport height, not width — that is what was
     forcing the overflow on short screens */
  padding: clamp(24px, 4vh, 64px) var(--gutter);
}

/* The copy block sits hard-left against the measure so its left edge lands on
   the same vertical as the wordmark in the nav above it. It used to be
   `margin-inline: auto`, which centred it in a column that keeps growing with
   the viewport — so the headline slid further right the wider the screen got
   (438px off the wordmark at 3440px). The per-element ch caps below still
   govern the actual line lengths inside this box. */
.hero__inner {
  width: 100%;
  max-width: clamp(560px, 42vw, 860px);
  margin-inline: 0;
}
/* ch caps keep the line lengths sane inside that measure. The headline is
   display-sized so it needs far fewer characters than the lede.

   These are the real constraint on the copy block's width — the box can be as
   wide as it likes, the text stops here. That is correct for readability, and
   it is why the space between the copy and the portrait is closed by scaling
   the type on very wide screens (below) rather than by stretching the lines. */
.hero__title { max-width: min(100%, 17ch); }
.hero__lede  { max-width: min(100%, 52ch); }

/* ---- The spine: the eyebrow set vertically down the left edge ----
   It gives the column something to hang from and frees the horizontal space
   the eyebrow used to occupy. Rotated type is slower to read, so this is only
   ever a short label — never a sentence. */
.hero__type { position: relative; }

.hero__spine {
  position: absolute;
  left: var(--gutter);
  top: clamp(24px, 5vh, 64px);
  bottom: clamp(24px, 5vh, 64px);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 18px;
}
.hero__spine-label {
  writing-mode: vertical-rl;
  transform: rotate(180deg);   /* reads bottom-to-top, the editorial convention */
  font-size: var(--meta);
  font-weight: 400;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: var(--brass-deep);
  white-space: nowrap;
}
.hero__spine-rule {
  flex: 1 1 auto;
  width: 1px;
  min-height: 40px;
  background: linear-gradient(to bottom, var(--brass), rgba(138, 115, 80, 0));
}

/* The spine and the copy both hang off the measure's left edge, but they must
   not push each other around:

   - the COPY aligns exactly with the wordmark in the nav, because the eye reads
     that vertical as the page's left margin;
   - the SPINE sits in the outer margin, to the left of it.

   Previously the spine's 46px was added to the copy's padding, which shoved the
   headline off the wordmark's vertical at every width. Now the copy keeps the
   measure alignment and the spine is positioned back into the margin instead —
   there is ample room for it there once the viewport is wider than the measure.

   --hero-edge is that shared left vertical; --spine-gap is how far the spine
   sits outside it. Below the margin's width the spine falls back inside, which
   is what the max() guards. */
:root {
  --hero-edge: max(var(--gutter), calc((100vw - var(--measure)) / 2 + var(--gutter)));
  --spine-gap: 46px;
}

.hero__type.bleed-left {
  padding-left: var(--hero-edge);
}
.hero__spine { left: max(calc(var(--gutter) / 2), calc(var(--hero-edge) - var(--spine-gap))); }

[dir="rtl"] .hero__spine {
  left: auto;
  right: max(calc(var(--gutter) / 2), calc(var(--hero-edge) - var(--spine-gap)));
}
[dir="rtl"] .hero__spine-label { transform: none; }   /* Kufi reads top-to-bottom here */
[dir="rtl"] .hero__type.bleed-left {
  padding-left: var(--gutter);
  padding-right: var(--hero-edge);
}

/* Every gap in the stack is vh-relative so the whole column compresses
   together as the viewport shortens, instead of overflowing.
   The ch caps hold the line lengths readable now that the column is 70% wide —
   without them the headline would run to one long line and the lede would
   stretch well past a comfortable measure. */
.hero__title  { margin-top: clamp(10px, 1.8vh, 22px); }
.hero__lede   { margin-top: clamp(12px, 2vh, 24px); }
.hero__cta    { display: flex; flex-wrap: wrap; gap: clamp(16px, 3vw, 44px); align-items: center; margin-top: clamp(16px, 2.8vh, 32px); }
.hero__note   { display: flex; align-items: center; gap: 16px; margin-top: clamp(14px, 2.6vh, 40px); }
.hero__rule   { width: 34px; height: 1px; background: var(--brass); flex-shrink: 0; }

/* The headline is the biggest single consumer of height. It now sits in a 70%
   column, so it can take more width — but the vh ceiling still governs, since
   height is what pushes the composition past the fold. */
/* The headline is the biggest consumer of height, so it is governed by BOTH a
   vw and a vh term — whichever is smaller wins, which stops a short, wide
   window from pushing the composition past the fold.

   The vh term is what binds on a large monitor: at 1440px tall, 8.6vh caps the
   headline at ~124px, well above the 84px ceiling, so the ceiling is what
   actually limited it. Raising that ceiling is what lets the copy grow into the
   space beside the portrait on a wide screen, instead of leaving a void there —
   the type scales with the composition rather than the lines being stretched
   past a readable length. */
.hero__title.h-hero { font-size: clamp(36px, min(5vw, 8.6vh), 108px); }
.hero__lede { font-size: clamp(15px, min(1.25vw, 2.5vh), 23px); }

/* No vh floor here — the hero already sets the height, and a min-height on the
   column made it push past that and drag the type column with it.

   The grow ratio is a share of whatever is left over, so on a very wide screen
   42% of 3440px handed the portrait ~1400px and it began to dominate the page.
   The max-width caps it; the type column absorbs the remainder, which is the
   right way round — the copy is the content, the portrait is the accompaniment. */
.hero__media {
  flex: 42 1 0;
  position: relative;
  height: 100%;
  min-height: 0;
  /* Two caps, and the smaller wins: a share of the viewport for mid-size
     screens, and an absolute ceiling so an ultrawide does not crop the
     portrait into a close-up of her face and lose the room behind her. */
  max-width: min(46vw, 920px);
}

/* ---------------------------------------------------------------------------
   HERO PORTRAIT SHAPE — "leaf": top-left and bottom-right rounded, the other
   two corners square.

   TO REVERT to the original full-bleed rectangle, change one value below:
       --hero-leaf-on: 0;
   Radius and inset are both multiplied by it, so 0 restores square corners and
   removes the inset in one edit. Nothing else needs touching, and the rules
   can be left in place for a later change of mind.

   Note this is a deliberate exception to the brand rule "no border radius
   anywhere except avatar circles and carousel dots" (handoff rule 1),
   approved for the hero portrait only.
   --------------------------------------------------------------------------- */
:root {
  /* THE SWITCH. 1 = leaf shape, 0 = original full-bleed rectangle. */
  --hero-leaf-on: 1;

  --hero-leaf-radius: 120px;
  /* The full leaf needs both curved corners on screen. Running the photo flush
     to the viewport puts the bottom-right corner off-screen, so this inset
     pulls it away from the right and bottom edges just enough to show it. */
  --hero-leaf-gap: clamp(16px, 2.2vw, 40px);

  /* Both derived from the switch, so one edit turns the whole thing off. */
  --hero-leaf: calc(var(--hero-leaf-radius) * var(--hero-leaf-on));
  --hero-leaf-inset: calc(var(--hero-leaf-gap) * var(--hero-leaf-on));
}

.hero__media {
  padding: 0 var(--hero-leaf-inset) var(--hero-leaf-inset) 0;
}
/* .photo is height:100% of the padded box, so the inset comes off the image
   rather than overflowing it. */
.hero__media .photo { height: 100%; }

/* The leaf: top-left and bottom-right curved, the other two square. */
.hero__media .photo {
  border-radius: var(--hero-leaf) 0 var(--hero-leaf) 0;
  overflow: hidden;
}

[dir="rtl"] .hero__media {
  padding: 0 0 var(--hero-leaf-inset) var(--hero-leaf-inset);
}

/* The scrim sits inside .photo, so it inherits the clip and needs no radius of
   its own. The caption sits at the bottom-LEFT, which the leaf leaves square,
   so it needs no offset — but it must clear the inset the photo now carries. */
.hero__media .photo-caption { bottom: calc(clamp(20px, 3vw, 40px) + var(--hero-leaf-inset)); }

/* Mirror the corners in RTL so the curve still meets the text column. */
[dir="rtl"] .hero__media .photo {
  border-radius: 0 var(--hero-leaf) 0 var(--hero-leaf);
}

/* Stacked, a 120px radius on a full-width band is far too heavy — the curve
   would eat the top and bottom of the image. Scale it back with the column. */
@media (max-width: 860px) {
  :root { --hero-leaf-radius: 56px; }
}
@media (max-width: 480px) {
  :root { --hero-leaf-radius: 36px; }
}

/* Stacked. Once the columns wrap, "everything above the fold" would mean
   squeezing type and a photograph into one screen — which makes both bad. The
   type block leads and stays whole; the portrait follows at a fixed share of
   the viewport, so the fold falls inside the image rather than mid-sentence. */
@media (max-width: 860px) {
  /* percentage bases never wrap, so stack explicitly rather than relying on it.
     Height is released: stacked, the hero is type-screen + portrait, not one
     screen total. */
  .hero {
    height: auto;
    min-height: 0;
    overflow: visible;
    flex-direction: column;
    flex-wrap: nowrap;
  }
  .hero__type {
    flex: 0 0 auto;
    width: 100%;
    height: auto;   /* released: stacked, the column is content-sized */
    min-height: calc(100svh - var(--nav-real, 121px));
    justify-content: center;
    padding-top: clamp(20px, 3vh, 40px);
    padding-bottom: clamp(20px, 3vh, 40px);
  }

  /* Stacked, a vertical label eats width the copy needs and the column is no
     longer wide enough to centre a measure inside. Lay the eyebrow back down
     above the headline and release the measure. */
  .hero__type.bleed-left { padding-left: var(--gutter); padding-right: var(--gutter); }
  .hero__spine {
    position: static;
    flex-direction: row;
    align-items: center;
    gap: 14px;
    margin-bottom: 16px;
  }
  .hero__spine-label { writing-mode: horizontal-tb; transform: none; }
  .hero__spine-rule {
    flex: 0 0 34px;
    width: 34px;
    height: 1px;
    min-height: 0;
    background: var(--brass);
  }
  .hero__inner { max-width: none; margin-inline: 0; }
  .hero__media { flex: 0 0 auto; width: 100%; min-height: 0; height: 58svh; }
}

/* Smallest screens (iPhone SE and similar). At 320px the CTA row wraps to two
   lines and the meta note wraps to two — together that was 8px more than the
   screen. Full-width stacked buttons read better here anyway, and the note
   goes, being the least load-bearing line in the stack. */
@media (max-width: 380px) {
  .hero__cta { flex-direction: column; align-items: stretch; gap: 12px; }
  .hero__cta .btn { text-align: center; padding: 17px 24px; }
  .hero__cta .link-arrow { text-align: center; }
  .hero__note { display: none; }
  .hero__type { padding-top: 16px; padding-bottom: 16px; }
}

/* Short and wide (landscape phones, small laptops): the type column alone can
   exceed the screen, so drop the display size harder and tighten the rhythm. */
@media (max-height: 620px) and (min-width: 861px) {
  .hero__title.h-hero { font-size: clamp(30px, 6.4vh, 48px); }
  .hero__lede { font-size: 15px; line-height: 1.5; }
  .hero__type { padding-top: clamp(16px, 3vh, 28px); padding-bottom: clamp(16px, 3vh, 28px); }
  .hero__note { display: none; }   /* the least load-bearing line in the stack */
}

/* Every photograph carries the scrim. `.photo` is the positioning context and
   must fill its slot — without an explicit height the img collapses. */
.photo { position: relative; width: 100%; height: 100%; min-height: inherit; overflow: hidden; }
.photo img { width: 100%; height: 100%; object-fit: cover; }
.scrim { position: absolute; inset: 0; background: var(--scrim); pointer-events: none; }

/* In a fixed-ratio slot (clusters, bands) the wrapper takes the ratio. */
.cluster__item .photo { aspect-ratio: 3 / 4; height: auto; }
.band .photo { position: absolute; inset: 0; }

.photo-caption {
  position: absolute;
  left: clamp(20px, 3vw, 40px);
  bottom: clamp(20px, 3vw, 40px);
  display: flex;
  align-items: center;
  gap: 14px;
}
.photo-caption__rule { width: 34px; height: 1px; background: var(--brass-light); }
.photo-caption__text { font-size: 13px; color: var(--paper-80); }

/* --------------------------------------------------------------- rails ---- */
/* A 200px label column beside the content — the page's recurring structure. */

.rail { display: flex; flex-wrap: wrap; gap: var(--col-gap); }
.rail__label { flex: 0 1 200px; }
.rail__body  { flex: 1 1 520px; min-width: 280px; max-width: 760px; }

/* ------------------------------------------------------- the premise ------ */

/* Shorter than a standard section: the content is four short elements, and the
   default 120px+ padding left it 800px tall with more air than substance. */
.section--premise {
  padding-top: clamp(48px, 6vh, 84px);
  padding-bottom: clamp(48px, 6vh, 84px);
}

/* A rule across the top of the section — the signal that one part of the page
   has ended and another begun. Drawn on a pseudo-element of the container so
   it aligns to the 1180px measure rather than bleeding to the viewport, and a
   short brass segment sits at its left end to mark where the section starts. */
.section--premise .container { position: relative; }
.section--premise .container::before {
  content: "";
  position: absolute;
  left: var(--gutter);
  right: var(--gutter);
  top: 0;
  height: 1px;
  background: var(--ink-14);
}
.section--premise .container::after {
  content: "";
  position: absolute;
  left: var(--gutter);
  top: 0;
  width: 56px;
  height: 1px;
  background: var(--brass);
}
/* the rule sits on the container's own top edge, so push the content clear */
.section--premise .container { padding-top: clamp(28px, 3.5vh, 48px); }

/* the statement wants more room than the default body cap allows */
.section--premise .rail__body { max-width: 860px; }


/* The claim, in the display face with a brass italic phrase inside it. Larger
   than before — this is the section's whole reason to exist and it should
   outweigh everything around it. */
/* Bigger than the old 40px, but the measure widens with it — at 30ch the
   larger size ran to seven cramped lines and cost more height than the padding
   reduction saved. 44ch keeps it to four lines at a comfortable read. */
.premise {
  font-family: var(--display);
  font-weight: 300;
  font-size: clamp(28px, 3.4vw, 46px);
  line-height: 1.24;
  color: var(--green);
  margin: 0;
  max-width: 44ch;
  text-wrap: pretty;
}
.premise em { font-style: italic; color: var(--brass); }

/* Stacked, a display-size statement runs to eight or nine lines and the
   section ends up taller than it was on desktop. Drop the size and let the
   numerals sit two-up rather than stacking to three full rows.
   Placed after the base rule so it actually wins — an identical media query
   above it was silently overridden. */
@media (max-width: 860px) {
  .section--premise {
    padding-top: clamp(36px, 5vh, 56px);
    padding-bottom: clamp(36px, 5vh, 56px);
  }
  .premise { font-size: clamp(22px, 5.4vw, 28px); line-height: 1.3; max-width: none; }
  .stats { gap: 20px 24px; margin-top: 26px; padding-top: 20px; }
  .stat { flex: 1 1 130px; }
  .stat__n { font-size: 26px; }
  .stat__d { max-width: 22ch; }
}

/* The label needs no rule of its own here — the section divider above it does
   that job, and two stacked hairlines read as a mistake. */
.rail__label--ruled { border-top: 0; padding-top: 0; }

/* ------------------------------------------------------------ stat row ---- */

.stats { display: flex; flex-wrap: wrap; gap: clamp(24px, 3vw, 40px); margin-top: clamp(28px, 3.4vw, 40px); }
.stat { flex: 0 1 190px; }
.stat__n { font-size: clamp(28px, 2.6vw, 34px); }

/* Deliberately small and quiet. These are supporting detail under the claim —
   at 13px/1.7 they competed with it; at 12px they read as a caption, which is
   what they are. */
.stat__d {
  margin: 8px 0 0;
  max-width: 24ch;
  font-size: 12px;
  line-height: 1.65;
  color: rgba(27, 42, 38, 0.62);
}

/* A second hairline ties the numerals to the statement above them — without it
   they float with no relationship to anything. */
.stats--ruled {
  padding-top: 22px;
  border-top: 1px solid var(--ink-12);
}

/* -------------------------------------------------------- service rows ---- */

/* Shorter than a standard section: the ground change to deep green already
   signals the break, so the padding does not also have to. */
.section--work {
  padding-top: clamp(52px, 6.5vh, 92px);
  padding-bottom: clamp(52px, 6.5vh, 92px);
}

.rows {
  margin-top: clamp(28px, 3.4vw, 44px);
  border-top: 1px solid var(--paper-16);
}
.row {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 10px clamp(20px, 2.4vw, 34px);
  padding: clamp(22px, 2.4vw, 28px) 0;
  border-bottom: 1px solid var(--paper-16);
  transition: color var(--t-hover) ease;
}

/* The numeral is a marker, not a headline — small, brass, in a fixed column so
   the titles align regardless of its width. */
.row__n { flex: 0 0 38px; font-size: 22px; line-height: 1; }

.row__main { flex: 1 1 260px; display: block; }

/* Cormorant, not Jost. These are offering names under a Cormorant heading —
   in the UI face they read as interface labels, and at 38px they rivalled the
   58px h2 so nothing led. */
.row__title {
  display: block;
  font-family: var(--display);
  font-weight: 300;
  font-size: clamp(24px, 2.6vw, 32px);
  line-height: 1.1;
  color: var(--ivory);
}

/* A line of substance per row. Without it the meta had to carry the whole
   explanation from 10px, which it cannot. */
.row__desc {
  display: block;
  margin-top: 8px;
  max-width: 46ch;
  font-size: 13.5px;
  line-height: 1.7;
  color: var(--paper-70);
}

.row__meta { flex: 0 0 auto; margin-left: auto; text-align: right; }

.row:hover { color: var(--brass-light); }
.row:hover .row__title { color: var(--brass-light); }

/* Stacked, the meta wraps onto its own line — let it sit under the description
   as a quiet tail rather than pushing to the right edge of a narrow column. */
@media (max-width: 860px) {
  .section--work {
    padding-top: clamp(40px, 5vh, 64px);
    padding-bottom: clamp(40px, 5vh, 64px);
  }
  .row { padding: 20px 0; gap: 8px 18px; }
  .row__n { flex: 0 0 30px; font-size: 18px; }
  .row__desc { font-size: 13px; margin-top: 6px; }
  .row__meta { margin-left: 0; text-align: left; flex-basis: 100%; }
}

/* ------------------------------------------------------------ staircase --- */
/* Process stages descend diagonally. Indents collapse to 0 as space runs out. */

/* Shorter: the section ran to 1227px, nearly double 01 and 02, because each
   stage stacked its numeral above the heading. */
.section--process {
  padding-top: clamp(48px, 6vh, 84px);
  padding-bottom: clamp(48px, 6vh, 84px);
}

/* The eyebrow with a rule running off to the right — the section divider this
   section uses instead of a full-width line. */
.sec-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 24px;
}
.sec-head__rule {
  flex: 1 1 120px;
  height: 1px;
  background: var(--ink-14);
}
.on-green .sec-head__rule { background: var(--paper-16); }

.stair {
  display: flex;
  flex-direction: column;
  gap: clamp(28px, 3.4vw, 48px);
  margin-top: clamp(32px, 4vw, 52px);
}

/* Numeral beside the heading, not above it. Stacked, every stage was ~250px
   tall and only one was ever on screen at a time. */
.stair__step {
  display: flex;
  flex-wrap: wrap;
  gap: clamp(16px, 3vw, 44px);
  max-width: 820px;
}
.stair__step:nth-child(2) { margin-left: clamp(0px, 9vw, 150px); }
.stair__step:nth-child(3) { margin-left: clamp(0px, 18vw, 300px); }

.stair__n {
  flex: 0 0 70px;
  font-size: clamp(30px, 3.4vw, 44px);
  line-height: 1;
  margin: 0;
}
.stair__main { flex: 1 1 320px; }

.stair__h {
  font-family: var(--display);
  font-weight: 300;
  font-size: clamp(24px, 2.6vw, 32px);
  line-height: 1.1;
  color: var(--green);
  margin: 0;
}
.stair__b {
  margin: 12px 0 0;
  max-width: 56ch;
  font-size: 13.5px;
  line-height: 1.75;
  color: var(--ink-78);
}

/* Stacked, the staircase indent only steals width from an already narrow
   column — the descent cannot read at 320px anyway. Flatten it and let the
   numeral sit inline with the heading rather than wrapping above it. */
@media (max-width: 860px) {
  .section--process {
    padding-top: clamp(36px, 5vh, 56px);
    padding-bottom: clamp(36px, 5vh, 56px);
  }
  .stair { gap: 26px; }
  .stair__step:nth-child(2),
  .stair__step:nth-child(3) { margin-left: 0; }
  .stair__step { gap: 14px; align-items: baseline; flex-wrap: nowrap; }
  .stair__n { flex: 0 0 44px; font-size: 26px; }
  .stair__main { flex: 1 1 auto; min-width: 0; }
  .stair__b { font-size: 13px; margin-top: 8px; }
}

/* Same idea, horizontal: three columns at staggered top offsets. */
.stagger { display: flex; flex-wrap: wrap; gap: var(--col-gap); }
.stagger__col { flex: 1 1 260px; }
.stagger__col:nth-child(2) { margin-top: clamp(0px, 4vw, 52px); }
.stagger__col:nth-child(3) { margin-top: clamp(0px, 8vw, 104px); }

/* ---------------------------------------------------------- 04 — proof ---- */

.section--proof {
  padding-top: clamp(48px, 6vh, 84px);
  padding-bottom: clamp(48px, 6vh, 84px);
}

/* The heading sits above the whole section rather than inside the 200px rail,
   where at 58px it broke across three lines. */
.proof__h {
  font-family: var(--display);
  font-weight: 300;
  font-size: clamp(28px, 3.2vw, 42px);
  line-height: 1.08;
  color: var(--green);
  margin: clamp(18px, 2.4vw, 30px) 0 0;
  max-width: 20ch;
}
.proof__h em { font-style: italic; color: var(--brass); }

.proof__body { margin-top: clamp(26px, 3.2vw, 40px); align-items: flex-start; }

.proof__note { display: flex; align-items: baseline; gap: 12px; }
.proof__note-rule { flex: 0 0 28px; height: 1px; background: var(--brass); }
.proof__note span { font-size: 12px; line-height: 1.6; color: rgba(27, 42, 38, 0.62); }

/* ------------------------------------------------------------- 07 — CTA --- */

/* The CTA and the footer are both deep green and sit directly against each
   other, so without a boundary they read as one long dark mass and the call to
   action loses its edges. Rather than a plain hairline, the CTA sits on a
   slightly lighter ground with brass rules top and bottom — it reads as a
   panel set into the dark, which gives the last ask on the page its own frame. */
.section--cta {
  padding-top: clamp(48px, 6vh, 84px);
  padding-bottom: clamp(48px, 6vh, 84px);
  text-align: center;
  position: relative;
}

/* the lighter panel, inset to the container measure so it aligns with content */
.section--cta::before {
  content: "";
  position: absolute;
  inset: 0;
  background: rgba(242, 239, 233, 0.035);
  pointer-events: none;
}

/* brass hairline above and below, fading out at both ends so the rules feel
   drawn rather than stamped */
.section--cta::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  height: 1px;
  background: linear-gradient(
    to right,
    transparent,
    rgba(138, 115, 80, 0.55) 22%,
    rgba(138, 115, 80, 0.55) 78%,
    transparent
  );
  pointer-events: none;
}
.section--cta > .container { position: relative; z-index: 1; }

/* the closing rule, mirrored, drawn on the footer's top edge */
.footer { position: relative; }
.footer::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  height: 1px;
  background: linear-gradient(
    to right,
    transparent,
    rgba(138, 115, 80, 0.55) 22%,
    rgba(138, 115, 80, 0.55) 78%,
    transparent
  );
}
.cta__h {
  font-family: var(--display);
  font-weight: 300;
  font-size: clamp(28px, 3.2vw, 42px);
  line-height: 1.08;
  color: var(--ivory);
  margin: 0 auto;
  max-width: 20ch;
}
.cta__lede {
  font-size: 15px;
  line-height: 1.65;
  color: var(--paper-70);
  max-width: 46ch;
  margin: 18px auto 0;
}
.cta__action { margin: clamp(24px, 3vw, 32px) 0 0; }

/* ------------------------------------------------------- full-bleed band -- */

.band { position: relative; min-height: clamp(320px, 46vw, 560px); display: flex; align-items: center; }
.band__text {
  position: relative;
  font-family: var(--display);
  font-weight: 300;
  font-size: clamp(30px, 4vw, 54px);
  line-height: 1.2;
  color: var(--ivory);
  max-width: 22ch;
}

/* ------------------------------------------------------------ overhang ---- */
/* Panels that break their section boundary — the compositional signature. */

.overhang-top    { margin-top: clamp(-96px, -8vw, -40px); }

/* Halved from -110px. The portrait breaks into the section below, but nothing
   reserves that space, so at the old depth it landed on top of the first
   paragraph of prose. This keeps the gesture without the collision. */
.overhang-bottom { margin-bottom: clamp(-60px, -3vw, -24px); }

/* ------------------------------------------------------------ services ---- */

.offer { display: flex; flex-wrap: wrap; gap: var(--col-gap); }
/* The middle offering reverses — label rail right, content left — so the three
   sections do not read as one repeated block. */
.offer--reversed { flex-direction: row-reverse; }
[dir="rtl"] .offer--reversed { flex-direction: row; }
/* The label rail scales with the measure rather than sitting at a fixed 200px.
   Frozen, it left the numeral marooned in white space on a wide screen while
   the body column took every extra pixel. */
.offer__label { flex: 0 0 clamp(200px, 16vw, 300px); }
.offer__body  { flex: 1 1 520px; min-width: 280px; }
.offer__split { display: flex; flex-wrap: wrap; gap: var(--col-gap); margin-top: clamp(28px, 4vw, 44px); }
.offer__split > div { flex: 1 1 240px; }

/* The fee row accepts a price later without redesign — drop a string into
   .fee__value and nothing else moves. */
.fee {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 12px 24px;
  margin-top: clamp(28px, 4vw, 44px);
  padding: 22px 0;
  border-top: 1px solid var(--ink-14);
  border-bottom: 1px solid var(--ink-14);
}
.on-green .fee { border-color: var(--paper-16); }
.fee__label { flex: 0 0 90px; }
.fee__value { flex: 1 1 260px; }
.fee__link  { margin-left: auto; }

/* ------------------------------------------------------------- contact ---- */

.contact { display: flex; flex-wrap: wrap; gap: var(--col-gap); align-items: flex-start; }
.contact__form { flex: 1 1 520px; max-width: 620px; }
.contact__grid { display: flex; flex-wrap: wrap; gap: 28px 40px; }
.contact__grid > * { flex: 1 1 240px; }
.contact__grid > .field--wide { flex: 1 1 100%; }
.contact__submit { display: flex; flex-wrap: wrap; align-items: center; gap: 24px; margin-top: 32px; }
.contact__note { font-size: 13px; line-height: 1.7; color: var(--ink-60); max-width: 34ch; }

.practice { flex: 0 1 420px; padding: clamp(28px, 4vw, 44px); }
.practice__rows { display: flex; flex-direction: column; gap: 20px; margin-top: 28px; }
.practice__row  { display: flex; flex-direction: column; gap: 4px; }

/* -------------------------------------------------------------- footer ---- */

.footer { padding-top: clamp(48px, 6vw, 72px); padding-bottom: 36px; }
.footer__top { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 40px var(--col-gap); }
.footer .wordmark__first, .footer .wordmark__last { font-size: 42px; }
.footer__cols { display: flex; flex-wrap: wrap; gap: 56px; }
.footer__col  { display: flex; flex-direction: column; gap: 12px; }
.footer__col a { font-size: 13px; color: var(--paper-80); }
.footer__col a:hover { color: var(--brass-light); }
.footer__rule { height: 1px; background: var(--paper-14); margin: clamp(36px, 5vw, 56px) 0 24px; }
.footer__base { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 12px 24px; }
.footer__base span { font-size: 11px; color: var(--paper-50); }

/* --------------------------------------------------------------- pages ---- */

/* Kept in step with --section-y. At the old 96px ceiling this left a 120px
   void between the navigation and the eyebrow on every inner page. */
.page-head { padding-top: clamp(28px, 3.5vh, 52px); padding-bottom: clamp(28px, 3.5vh, 48px); }
.page-head .lede { margin-top: 24px; }

/* ---- Split page head ----
   Title and lede on one baseline-aligned row. Stacked in a body column beside
   the 200px label rail, the title broke at 14ch with a third of the row unused
   and the lede stranded below it. */
.head-split {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: clamp(24px, 5vw, 72px);
  margin-top: clamp(22px, 3vw, 34px);
}
/* 13ch was tuned when the measure was frozen at 1180px. Once the measure grows,
   that cap is narrower than the space available and the title wraps early —
   "Two ways to begin." broke across two lines on a 2560px screen with half the
   row sitting empty. 15ch still guards the line length on a laptop and lets the
   title stay on one line where there is genuinely room for it. */
.head-split__title { flex: 1 1 420px; max-width: 15ch; margin: 0; }
.head-split__lede  { flex: 1 1 300px; max-width: 44ch; margin: 0; padding-bottom: 8px; }

/* Stacked, "flex-end" would bottom-align a wrapped lede oddly — reset it and
   let the two sit as a normal stack. */
@media (max-width: 860px) {
  .head-split { display: block; }
  .head-split__title { max-width: 16ch; }
  .head-split__lede { margin-top: 18px; padding-bottom: 0; max-width: 50ch; }
}

.prose > * + * { margin-top: 24px; }
.prose p { max-width: 62ch; color: var(--ink-78); line-height: 1.85; }

.pullquote {
  font-family: var(--display);
  font-weight: 300;
  font-style: italic;
  font-size: var(--quote);
  line-height: 1.4;
  color: var(--green);
  max-width: 30ch;
  border-left: 2px solid var(--brass);
  padding-left: clamp(20px, 3vw, 34px);
  margin: clamp(32px, 4vw, 48px) 0 clamp(32px, 4vw, 48px) auto;
}

/* Credential table on the About page. */
.creds { border-top: 1px solid var(--paper-16); }
.cred {
  display: flex;
  flex-wrap: wrap;
  gap: 8px var(--col-gap);
  padding: 20px 0;
  border-bottom: 1px solid var(--paper-16);
}
.cred__year { flex: 0 0 120px; }
.cred__text { flex: 1 1 320px; }

/* ---- Fact line ----
   Three key/value pairs under the About lede, on a hairline. Fills the space
   that sat empty beneath it and gives the lede's claim about years something
   concrete to land on. Deliberately small — this is a head, not a CV. */
.factline {
  display: flex;
  flex-wrap: wrap;
  gap: 18px clamp(28px, 4vw, 52px);
  margin: clamp(26px, 3.4vw, 40px) 0 0;
  padding-top: 20px;
  border-top: 1px solid var(--paper-16);
}
.factline__item { display: flex; flex-direction: column; gap: 6px; }
.factline dt {
  font-size: 10px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--paper-55);
}
.factline dd {
  margin: 0;
  font-family: var(--display);
  font-weight: 300;
  font-size: clamp(19px, 1.8vw, 24px);
  line-height: 1;
  color: var(--brass-light);
}

/* on ivory grounds */
.section:not(.on-green) .factline { border-top-color: var(--ink-14); }
.section:not(.on-green) .factline dt { color: var(--ink-72); }
.section:not(.on-green) .factline dd { color: var(--brass); }

/* In a page head the fact line follows a split row rather than a lede, so it
   needs a little more room above it and spreads across the full measure. */
.factline--head {
  margin-top: clamp(28px, 3.6vw, 44px);
  gap: 16px clamp(32px, 5vw, 72px);
}

/* At 320px a pair of values like "Twelve weeks" plus its neighbour exceeded
   the viewport. Let each item take a full row rather than overflow. */
@media (max-width: 380px) {
  .factline { gap: 14px 20px; }
  .factline__item { flex: 1 1 100%; }
  .factline dd { font-size: 18px; }
}

/* A single wide photograph with a caption beneath — the interim treatment
   while only one image exists. Wide and shallow so it reads as a plate in a
   book rather than a second portrait. */
.plate { margin: clamp(36px, 5vw, 64px) 0 0; }
/* 2:1 rather than 21:9 — the source is a portrait-orientation photograph, and
   an ultra-wide slice of it crops through the face however it is positioned. */
/* A 2:1 band. The ratio alone made it grow without limit once the measure
   became fluid — at 1552px wide the plate stood 776px tall and read as a wall
   rather than a band.

   The cap goes on the WIDTH, not the height: .photo is `height: 100%` of its
   parent, so a max-height here collapses it to nothing instead of shortening
   it. Constraining the width lets aspect-ratio derive a shorter height from it,
   which is what actually keeps the band a band. */
.plate .photo { aspect-ratio: 2 / 1; height: auto; }
.plate { max-width: 1120px; }
.plate__caption {
  display: flex;
  align-items: baseline;
  gap: 14px;
  margin-top: 16px;
}
.plate__rule { flex: 0 0 34px; height: 1px; background: var(--brass); }
.plate__caption span:last-child {
  font-size: 12px;
  letter-spacing: 0.02em;
  color: rgba(27, 42, 38, 0.62);
}

@media (max-width: 860px) {
  .plate .photo { aspect-ratio: 3 / 2; }
}

/* Three-up photo cluster at staggered vertical offsets. */
.cluster { display: flex; flex-wrap: wrap; gap: var(--col-gap); }
.cluster__item { flex: 1 1 240px; position: relative; }
.cluster__item:nth-child(2) { margin-top: clamp(0px, 4vw, 56px); }
.cluster__item:nth-child(3) { margin-top: clamp(0px, 2vw, 28px); }
.cluster__item img { width: 100%; aspect-ratio: 3 / 4; object-fit: cover; }

/* Sticky rail beside the FAQ. Released once the column stacks. */
@media (min-width: 900px) {
  .rail--sticky .rail__label { position: sticky; top: calc(var(--nav-h) + 42px); align-self: flex-start; }
}
