/* ==========================================================================
   editorial.css, part 2 of 2  (loads immediately after editorial.css)

   SPLIT FOR A REASON, DO NOT MERGE BACK. The dev server intermittently
   stops sending a file partway through - measured here cutting at 261,120
   bytes on every request for this file, which silently dropped the last
   34KB: 96 selectors, all of them the .clk chronograph on team.html and
   the .otn hiring section. editorial-2.css was split for the same reason
   and lost the entire .skyhero block until it was.

   Brace-depth-zero split, concatenates back byte for byte, cascade
   unchanged. Keep every stylesheet under ~200KB.
   ========================================================================== */


/* ==========================================================================
   Careers — "the bar"

   Not a split with a photo on one side. The section IS a filter: two things
   Marble does not care about are written out and then STRUCK THROUGH in
   front of you, leaving the one thing that counts.

   GRAMMAR: the only section on this homepage carried by KINETIC TYPE rather
   than a camera. `.wall` travels X, `.worlds` pushes Z, `.lp` holds still
   while planes separate, `.forge` turns an object, `.rise` climbs Y. A sixth
   spatial rig would be repetition; type doing the work is not.

   CONTRAST NOTE: the negations are --ink, not --vein, precisely BECAUSE they
   get dimmed after the strike. --ink at 0.6 still clears 6:1; --vein would
   have landed near 2.8:1. Struck-out copy is still copy.
   ========================================================================== */

.hire {
  position: relative;
  isolation: isolate;
  overflow-x: clip;
  padding-block: var(--section);
  /* no ground of its own: the site has ONE, and it is fixed. See .ground. */
}
.hire__grain {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  opacity: 0.45;
  /* no grain of its own: .grain::after covers the whole site */
  background: none;
  background-size: 3px 3px;
}

.hire__head {
  position: relative;
  z-index: 2;
  margin-bottom: clamp(1.8rem, 1.44rem + 2.52vw, 3.6rem);
}
.hire__title {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(2.1rem, 1.2rem + 4.2vw, 5rem);
  line-height: 1.02;
  letter-spacing: -0.026em;
  color: var(--ink);
}
.hire__title > span { display: block; overflow: hidden;
  padding-top: 0.16em; padding-bottom: 0.22em;
  margin-top: -0.16em; margin-bottom: -0.17em; }
.hire__title em { font-style: italic; color: var(--gold-light); }

/* ---- the filter ---- */
.hire__filter { position: relative; z-index: 2; }

.hneg {
  position: relative;
  display: block;
  width: fit-content;
  max-width: 100%;
  margin-bottom: clamp(0.9rem, 0.75rem + 0.9vw, 1.5rem);
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(1.15rem, 0.9rem + 1.4vw, 2.05rem);
  line-height: 1.28;
  letter-spacing: -0.01em;
  /* --ink on purpose: these get dimmed after the strike, and --vein could
     not survive that and still clear AA */
  color: var(--ink);
}
.hneg__t { display: block; }
/* the line that crosses it out. GSAP owns scaleX; CSS ships it drawn so a
   no-JS visitor simply reads two plain statements. */
.hneg__strike {
  position: absolute;
  left: 0;
  right: 0;
  top: 52%;
  height: 1px;
  background: linear-gradient(90deg, var(--gold), var(--gold-light));
  transform-origin: left;
  opacity: 0;
}

.hyes {
  margin-top: clamp(2rem, 1.5rem + 2.5vw, 3.75rem);
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(1.6rem, 1rem + 2.8vw, 3.4rem);
  line-height: 1.08;
  letter-spacing: -0.022em;
  color: var(--ink);
  max-width: 22ch;
}
.hyes > span { display: block; overflow: hidden; padding-bottom: 0.04em; }
.hyes em { font-style: italic; color: var(--gold-light); }

/* ---- the fork ---- */
.hire__fork {
  position: relative;
  z-index: 2;
  margin-top: clamp(2.24rem, 1.6rem + 2.56vw, 4.48rem);
  overflow: clip;
}
.hire__band {
  position: absolute;
  inset: 0;
  z-index: 0;
}
.hire__band img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: brightness(0.42) saturate(0.7) contrast(1.06);
  will-change: transform;
}
.hire__scrim {
  position: absolute;
  inset: 0;
  background:
    linear-gradient(90deg, rgba(6, 6, 8, 0.9) 0%, rgba(6, 6, 8, 0.6) 46%, rgba(6, 6, 8, 0.88) 100%),
    linear-gradient(180deg, var(--obsidian), transparent 24%, transparent 76%, var(--obsidian));
}
.hire__fork-inner {
  position: relative;
  z-index: 2;
  padding-block: clamp(2.32rem, 1.74rem + 2.9vw, 4.64rem);
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  gap: clamp(1.5rem, 1rem + 3vw, 4rem);
  align-items: center;
}
.hfork {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(1.25rem, 0.9rem + 1.7vw, 2.35rem);
  line-height: 1.16;
  letter-spacing: -0.018em;
}
.hfork--no { color: var(--vein); }
.hfork--yes { color: var(--ink); text-align: right; }
.hfork--yes em { font-style: italic; color: var(--gold-light); }
.hfork__seam {
  width: 1px;
  align-self: stretch;
  background: linear-gradient(180deg, transparent, var(--gold) 22%, rgba(156, 120, 72, 0.28) 74%, transparent);
  transform-origin: center;
}

.hire__out {
  position: relative;
  z-index: 2;
  margin-top: clamp(2.16rem, 1.8rem + 2.16vw, 3.6rem);
}

@media (max-width: 860px) {
  .hire__fork-inner {
    grid-template-columns: 1fr;
    gap: clamp(1.25rem, 1rem + 2vw, 2rem);
  }
  .hfork--yes { text-align: left; }
  .hfork__seam { width: 100%; height: 1px; align-self: auto;
    background: linear-gradient(90deg, transparent, var(--gold) 22%, rgba(156, 120, 72, 0.28) 74%, transparent); }
  .hire__scrim {
    background:
      linear-gradient(180deg, rgba(6, 6, 8, 0.86), rgba(6, 6, 8, 0.7) 50%, rgba(6, 6, 8, 0.9)),
      linear-gradient(180deg, var(--obsidian), transparent 20%, transparent 80%, var(--obsidian));
  }
}

@media (prefers-reduced-motion: reduce) {
  .hire__band img { transition: none; }
}

/* ==========================================================================
   THE CHANNELS — "whose door it is"   (what-we-do.html, section 03)

   History: a mirrored `.duo` card pair -> `.gates`, two doorways drawn in
   pure CSS that swung open -> `.chan`, one photographic field divided by a
   gold hairline that turned a corner -> this.

   THE LEAD LINE WAS ALREADY THE DESIGN: "Both begin with one of our people
   walking through a door. What changes is whose door it is." So the
   section is ONE FRAME that never moves, and the only thing that changes
   is what is behind it. Second time on this page that the approved copy
   held the composition - read the words before inventing a shape.

   THE FRAME IS A LOUVRE OF FOURTEEN SQUARE PRISMS. One face carries a
   company floor at first light, the face beside it carries a hand on a
   front door, and scrolling turns them from the first to the second.

   WHY A PRISM AND NOT A FLAP, and this is the whole construction: a
   two-sided flap passes through edge-on at the halfway point, which blacks
   the entire band out - the empty-screen failure this client has called
   out more than once. A square prism always has a face to the viewer, so
   the two worlds trade across a LIT CORNER instead of through a blackout.
   Face A sits at translateZ(pitch/2); face B is the same panel rotated 90
   degrees onto the side of the same prism. The slat turns NEGATIVE, so A
   goes away as B arrives.

   AT 45 DEGREES A SQUARE PRISM IS WIDER THAN ITS PITCH (its diagonal is
   root two times its side) and the slats overlap. That is left alone
   rather than spaced out: real corrugation looks exactly like that, and
   giving each prism the room never to touch its neighbour would leave
   gaps at rest, where the first photograph has to read whole.

   THE GRAMMAR IS TURNING IN PLACE, and it had to be. `.run` directly above
   cuts five openings on a diagonal and `.stop` directly below opens a rule
   outward from the centre, so this section can carry no travel at all -
   the slats turn together, and the only variation is a fixed, deliberately
   non-monotonic micro-offset per slat so the array reads hand-set.

   THE TWO WORLDS HAVE DIFFERENT LIGHT, and that is the honest difference
   between them: the office is a cool blue dawn, the doorstep is a warm
   lamp. `.addr__grade` crossfades between the two as the turn runs, so the
   section is lit by whichever world you are being shown.

   `--t` (0..90) is the turn and `--tp` is a separate pointer nudge, the
   two-number pattern this site uses everywhere a tween and a pointer would
   otherwise fight over one value. Neither is registered with @property:
   GSAP writes them every frame, so no interpolation is needed and the
   site-wide cost of an inherited registered property is avoided. The CSS
   value of --t is 34, so with no JS the louvre holds both photographs at
   an angle and every word still reads.
   ========================================================================== */

.addr {
  position: relative;
  overflow-x: clip;
}

.addr__head {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 0.9fr);
  gap: clamp(1.5rem, 1rem + 3vw, 4rem);
  align-items: end;
  margin-bottom: clamp(2rem, 1.5rem + 2.5vw, 3.75rem);
}
.addr__h {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(1.75rem, 1.35rem + 1.7vw, 2.6rem);
  line-height: 1.12;
  letter-spacing: -0.02em;
  color: var(--white);
}
.addr__h em { font-style: italic; color: var(--gold-light); }
.addr__lead {
  color: var(--vein);
  font-size: var(--text-lg);
  line-height: 1.7;
  max-width: 34rem;
}

/* ---- the band ---- */
.addr__band {
  /* The container's content edge. NOTE it resolves on whichever element
     READS it, so every consumer has to be absolutely positioned against
     the band - a trap this site has been caught by once already. */
  --edge: max(var(--gutter), calc((100% - var(--container) - 2 * var(--gutter)) / 2 + var(--gutter)));
  position: relative;
  /* Kept near the photographs' own proportion on purpose. At 128svh the
     band was much squarer than either frame and object-fit threw away a
     third of the doorstep, which is the one picture that has to read. */
  height: clamp(40rem, 112svh, 66rem);
  overflow: hidden;   /* the prisms overhang their own columns mid-turn */
}

/* ---- the louvre ---- */
.addr__louvre {
  --n: 14;
  --t: 34;    /* the turn, 0 = the company floor, 90 = the front door */
  --tp: 0;    /* the pointer's own nudge, never shared with --t */
  --pitch: calc(100vw / var(--n));
  position: absolute;
  inset: 0;
  z-index: 1;
  perspective: 2600px;
  transform-style: preserve-3d;   /* so the prisms occlude each other */
  background: var(--obsidian);
}

.addr__slat {
  position: absolute;
  top: 0;
  bottom: 0;
  left: calc(var(--i) * 100% / var(--n));
  width: calc(100% / var(--n));
  transform-style: preserve-3d;
  transform: rotateY(calc((var(--t) + var(--tp) + var(--o, 0)) * -1deg));
}

/* a pixel wider than the column on each side, so the sub-pixel difference
   between the band's real width and the 100vw --pitch can never open a
   hairline seam between two prisms */
.addr__face {
  position: absolute;
  inset: 0 -1px;
  overflow: hidden;
  backface-visibility: hidden;
}
.addr__face--a { transform: translateZ(calc(var(--pitch) / 2)); }
.addr__face--b { transform: rotateY(90deg) translateZ(calc(var(--pitch) / 2)); }

/* Each face carries the WHOLE photograph, sized to the band and pushed
   left by its own column, so the fourteen slices reassemble the picture
   exactly. main.css carries a global img { max-width: 100% } which
   silently clamps any deliberately oversized image - third time. */
.addr__face img {
  position: absolute;
  top: 0;
  left: calc(var(--i) * -100%);
  width: calc(var(--n) * 100%);
  max-width: none;
  height: 100%;
  object-fit: cover;
  display: block;
}
.addr__face--a img { object-position: 50% 44%; }
.addr__face--b img { object-position: 42% 44%; }   /* keeps the knocker clear of the type */

/* The light on a turning surface. Linear in --t rather than a cosine,
   which keeps the face that is turning away well clear of black - a face
   at 12 percent width is a hairline of picture, and if it is also crushed
   the whole band reads as bars rather than as a louvre.

   THE TWO PHOTOGRAPHS HAD TO BE BROUGHT TO THE SAME EXPOSURE, and this is
   the real reason the first pass read as bars. The doorway is a far darker
   frame than the company floor, so interleaving them straight put a bright
   slice beside a near-black one fourteen times over. The doorstep is
   therefore lifted hard - contrast BELOW 1 to raise its blacks, not just
   brightness, which only multiplies what is already there. Same lesson as
   the developing room and the divided field before it: on this library,
   assume a low-key frame needs a real lift, never a scrim. */
.addr__face--a { filter: brightness(calc(1.06 - 0.26 * var(--t) / 90)) saturate(0.94); }
.addr__face--b { filter: brightness(calc(1.14 + 0.22 * var(--t) / 90)) contrast(0.88) saturate(1.02); }

/* the leading corner catches the lamp as the prism comes round */
.addr__face::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
}
.addr__face--a::after {
  background: linear-gradient(90deg, rgba(4, 4, 8, 0.26), rgba(4, 4, 8, 0) 16%, rgba(255, 238, 206, 0.05) 88%, rgba(255, 242, 216, 0.34));
  opacity: calc(0.2 + 0.8 * var(--t) / 90);
}
.addr__face--b::after {
  background: linear-gradient(270deg, rgba(4, 4, 8, 0.24), rgba(4, 4, 8, 0) 18%, rgba(255, 238, 206, 0.05) 88%, rgba(255, 242, 216, 0.32));
  opacity: calc(1 - 0.8 * var(--t) / 90);
}

/* THE TWO WORLDS ARE LIT DIFFERENTLY AND THE SECTION FOLLOWS. Cool blue
   while the company floor is the one being shown, warm while the doorstep
   is. Plus the tonal fall the type needs to sit on. */
.addr__grade {
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  background:
    radial-gradient(64% 56% at 20% 14%, rgba(112, 146, 190, calc(0.13 * (1 - var(--t) / 90))), transparent 70%),
    radial-gradient(58% 54% at 80% 82%, rgba(192, 156, 96, calc(0.2 * var(--t) / 90)), transparent 72%),
    /* the band has to DISSOLVE into the page at both ends. A full-bleed
       photographic band that simply stops leaves a hard rule across the
       screen, and this section is not allowed to draw one. */
    linear-gradient(180deg, rgba(6, 6, 8, 0.98) 0%, rgba(6, 6, 8, 0.5) 7%, rgba(6, 6, 8, 0.1) 22%, rgba(6, 6, 8, 0.14) 58%, rgba(6, 6, 8, 0.55) 88%, rgba(6, 6, 8, 0.99) 100%);
}

/* ---- the words ----
   Each block carries its own pool of shade rather than sitting on a bar:
   a scrim with a hard edge across a photograph reads as a panel, and this
   section has no panels in it. z-index -1 inside an isolated block, so the
   pool sits under its own words and above the picture, with no positioning
   in JS. */
.addr__copy {
  position: absolute;
  z-index: 4;
  isolation: isolate;
}
.addr__copy::before {
  content: "";
  position: absolute;
  z-index: -1;
  inset: -2.6rem -3.4rem -3rem -3.4rem;
  pointer-events: none;
  background: radial-gradient(72% 62% at 34% 46%, rgba(4, 4, 7, 0.86), rgba(4, 4, 7, 0.52) 52%, rgba(4, 4, 7, 0) 78%);
}

.addr__kicker {
  display: flex;
  align-items: baseline;
  gap: 0.85rem;
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--ink);
}
.addr__idx {
  font-family: var(--font-display);
  font-weight: 500;
  letter-spacing: 0.1em;
  color: var(--gold-light);
}

.addr__ch,
.addr__say {
  margin-top: clamp(0.85rem, 0.7rem + 0.6vw, 1.25rem);
  font-family: var(--font-display);
  font-weight: 500;
  line-height: 1.2;
  letter-spacing: -0.014em;
  color: var(--white);
}
.addr__ch { font-size: clamp(1.35rem, 1.1rem + 1.1vw, 2rem); }
.addr__say { font-size: clamp(1.25rem, 1.05rem + 0.95vw, 1.8rem); }
.addr__ch em,
.addr__say em { font-style: italic; color: var(--gold-light); }

.addr__p {
  margin-top: clamp(0.85rem, 0.7rem + 0.5vw, 1.15rem);
  color: var(--ink);
  line-height: 1.75;
}
.addr__note {
  margin-top: clamp(0.8rem, 0.65rem + 0.5vw, 1.1rem);
  font-size: var(--text-sm);
  letter-spacing: 0.02em;
  color: var(--vein);
}
.addr__close {
  margin-top: clamp(1.1rem, 0.9rem + 0.7vw, 1.6rem);
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(1.05rem, 0.95rem + 0.5vw, 1.32rem);
  line-height: 1.35;
  color: var(--gold-light);
}

/* the standard, engraved rather than printed, at the point of the turn
   where neither world is the dominant one */
.addr__plaque {
  position: absolute;
  z-index: 4;
  isolation: isolate;
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(1.15rem, 0.95rem + 0.75vw, 1.62rem);
  line-height: 1.35;
  letter-spacing: -0.015em;
  color: var(--ink);
  text-shadow: 0 1px 0 rgba(0, 0, 0, 0.85), 0 0 26px rgba(4, 4, 7, 0.9);
}
.addr__plaque em { font-style: italic; color: var(--gold-light); }
/* the standard needs its own shade too: it lands exactly where the two
   worlds are woven, which is the busiest the picture ever gets */
.addr__plaque::before {
  content: "";
  position: absolute;
  z-index: -1;
  inset: -2.4rem -3.2rem;
  pointer-events: none;
  background: radial-gradient(70% 62% at 38% 50%, rgba(4, 4, 7, 0.9), rgba(4, 4, 7, 0.55) 50%, rgba(4, 4, 7, 0) 78%);
}
/* it lights only while neither world is the dominant one. The state is a
   class rather than a calc, because CSS has no abs() I can rely on here,
   and it is a transition on colour, which GSAP never touches. */
.addr__plaque { transition: color 0.6s ease, text-shadow 0.6s ease; }
.is-balanced .addr__plaque {
  color: var(--white);
  text-shadow: 0 1px 0 rgba(0, 0, 0, 0.85), 0 0 34px rgba(192, 156, 96, 0.42), 0 0 26px rgba(4, 4, 7, 0.9);
}

/* ---- the arrangement ----
   Not mirrored, and that is deliberate: one block is a heading over a
   paragraph at the top left, the other is a display statement over a line
   of small print at the bottom right, and the standard sits between them
   on the left. Two channels laid out as two matching halves would be the
   card pair this section was rebuilt twice to get away from. */
@media (min-width: 901px) {
  .addr__plate { display: none; }

  .addr__copy--biz {
    top: clamp(2.5rem, 1.5rem + 4vw, 5.5rem);
    left: var(--edge);
    width: min(31rem, 40%);
  }
  .addr__copy--home {
    bottom: clamp(2.5rem, 1.5rem + 4vw, 5.5rem);
    right: var(--edge);
    width: min(29rem, 38%);
    text-align: right;
  }
  .addr__copy--home .addr__kicker { justify-content: flex-end; }
  .addr__copy--home::before {
    background: radial-gradient(72% 62% at 66% 54%, rgba(4, 4, 7, 0.86), rgba(4, 4, 7, 0.52) 52%, rgba(4, 4, 7, 0) 78%);
  }

  .addr__plaque {
    top: 50%;
    left: var(--edge);
    width: min(22rem, 32%);
    transform: translateY(-50%);
  }
}

/* ---- one column ----
   The louvre needs horizontal room to turn in and text over photography
   is the first thing to fail on a phone, so below 901px the prisms are
   dropped entirely and the two worlds are two plates. */
@media (max-width: 900px) {
  .addr__head { grid-template-columns: 1fr; gap: clamp(1rem, 0.85rem + 1vw, 1.5rem); }
  .addr__lead { max-width: 42rem; }

  .addr__band {
    height: auto;
    overflow: visible;
  }
  .addr__louvre,
  .addr__grade { display: none; }

  .addr__plate {
    position: relative;
    margin: 0 0 clamp(1.25rem, 1rem + 1.2vw, 1.9rem);
    overflow: hidden;
    aspect-ratio: 16 / 10;
    border-radius: 2px 16px 2px 16px;
    box-shadow: 0 26px 54px -34px rgba(0, 0, 0, 0.95);
  }
  .addr__plate::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 2;
    border-radius: inherit;
    padding: 1px;
    pointer-events: none;
    background: linear-gradient(150deg, rgba(192, 156, 96, 0.5), rgba(156, 120, 72, 0.1) 44%, rgba(192, 156, 96, 0.4));
    -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
            mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
    -webkit-mask-composite: xor;
            mask-composite: exclude;
  }
  .addr__plate img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
    filter: brightness(0.92) saturate(0.95);
  }
  .addr__plate--b img { object-position: 22% 46%; }

  .addr__copy,
  .addr__plaque {
    position: static;
    width: auto;
    max-width: 42rem;
    transform: none;
    text-align: left;
  }
  .addr__copy::before { display: none; }
  .addr__copy--home .addr__kicker { justify-content: flex-start; }
  .addr__plaque {
    margin-block: clamp(2rem, 1.6rem + 2vw, 3.25rem);
    text-shadow: none;
  }
  .addr__copy--biz { margin-bottom: clamp(1.5rem, 1.2rem + 1.5vw, 2.25rem); }

  /* the band's own children need the page gutter back, because the band
     itself is full bleed and carries no container */
  .addr__band > * {
    margin-inline: auto;
    max-width: calc(var(--container) + 2 * var(--gutter));
    padding-inline: var(--gutter);
  }
  .addr__plate { max-width: calc(var(--container) + 2 * var(--gutter)); }
}

@media (prefers-reduced-motion: reduce) {
  .addr__slat { transition: none; }
}

/* ==========================================================================
   THE ARGUMENT — "the table"   (what-we-do.html, section 01)

   History: an .ed--overlap split (a blank marble panel beside a bulleted
   list) -> .argue, a sticky linework plate beside an index of four claims
   -> this. The client asked for the section to look its best, to carry
   images and to be full of movement, so the plate and its four engraved
   emblems are gone.

   THE LEAD SENTENCE IS THE DESIGN. "Four reasons, and every one of them
   shows up on your side of the table." The four reasons are therefore
   dealt onto a table in front of the reader: four photographs, put down
   one at a time as you scroll, overlapping corner to corner until the set
   reads as one case rather than as four cards. The overlap is the whole
   point - four rectangles that do not touch are a grid.

   THE GRAMMAR IS PLACEMENT, and it was the movement still free. .run
   below cuts openings on a diagonal, .chan divides one photographic field,
   .stop opens a rule outward from the centre, the hero uncovers two
   plates with a clip sweep, and on other pages the site travels, pushes,
   climbs, develops, registers and strikes through. Nothing has ever put
   an object DOWN in front of the reader.

   ONE LIGHT SOURCE, HONESTLY OBEYED. The lamp is top right; every shadow
   falls down and to the left, and every plate takes its sheen from that
   same corner. Physical consistency is the only reason four rectangles
   read as objects on a surface rather than as four floating cards, and it
   is why the lamp BREATHES rather than travels - a light that moved would
   put every hand-set shadow out of step with it.

   GEOMETRY IS DATA, NOT STYLING. Every plate and every block of type is
   placed with --x / --y / --w as percentages of the field, and the field
   is held to an aspect ratio, so the whole composition scales as one
   object. Change a number and the overlaps move; they are tuned against
   measured boxes at 1081 / 1200 / 1280 / 1440 / 1728.

   NOTHING IS EVER HIDDEN. --tin (the landing) has an initial value of 1,
   so with no JS, no CDN or reduced motion every plate is already down,
   every claim reads in full, and the only thing missing is the movement.
   ========================================================================== */

/* --tin  : 0 = in the air, 1 = landed. GSAP owns it, and only it.
   --tdy  : the depth drift, in px. A SECOND number so the landing and the
            parallax can never fight over one transform.
   --tlit : the lamp's intensity, fed into the gradient alphas rather than
            into opacity, which would clamp at 1 and show nothing.
   All three are inherits:false - a registered INHERITED property is
   computed on every element on all nine pages that load this file. */
@property --tin  { syntax: "<number>"; inherits: false; initial-value: 1; }
@property --tdy  { syntax: "<number>"; inherits: false; initial-value: 0; }
@property --tlit { syntax: "<number>"; inherits: false; initial-value: 1; }

.tbl {
  position: relative;
  overflow-x: clip;   /* the wide plates run off the right edge */
  isolation: isolate;
}

/* The lamp hangs off the SECTION, never off .container: a full-bleed wash
   started at the container edge leaves a hard seam down the side of the
   screen, which is a bug this site has already paid for once. */
.tbl__lamp {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background:
    radial-gradient(52% 40% at 82% 4%, rgba(192, 156, 96, calc(0.17 * var(--tlit))), transparent 72%),
    radial-gradient(88% 64% at 66% 22%, rgba(156, 120, 72, calc(0.06 * var(--tlit))), transparent 78%),
    linear-gradient(198deg, rgba(24, 21, 28, 0.5), rgba(6, 6, 8, 0) 44%);
}
.tbl__grain {
  position: absolute;
  inset: 0;
  z-index: 1;
  opacity: 0.4;
  pointer-events: none;
  /* no grain of its own: .grain::after covers the whole site */
  background: none;
}

/* ---- the table ---- */
.tbl__field {
  position: relative;
  z-index: 2;
  aspect-ratio: 1 / var(--fh, 1);
}

/* the pointer specular, a soft warm pass over the plates. It sits above
   the plates and below every piece of type, so it can never wash a word. */
.tbl__sheen {
  --tmx: 50;
  --tmy: 50;
  position: absolute;
  inset: -12%;
  z-index: 6;
  opacity: 0;
  pointer-events: none;
  background: radial-gradient(24% 20% at calc(var(--tmx) * 1%) calc(var(--tmy) * 1%), rgba(255, 238, 206, 0.11), transparent 66%);
}

/* ---- the plates ---- */
.tbl__piece {
  --x: 0;
  --y: 0;
  --w: 40;
  --ar: 3 / 2;
  --rot: 0deg;
  --ex: 0;      /* where it comes in from, px */
  --ey: 46;
  --erot: 2.4;  /* the extra tilt it carries in the air, deg */
  position: absolute;
  left: calc(var(--x) * 1%);
  top: calc(var(--y) * 1%);
  width: calc(var(--w) * 1%);
  margin: 0;
  /* CSS composes the landing, the drift AND the plate's own hand-set
     rotation into one transform, so GSAP never has to share a property
     with a static transform or with a transition. */
  transform:
    translate3d(calc(var(--ex) * (1 - var(--tin)) * 1px),
                calc((var(--tdy) + var(--ey) * (1 - var(--tin))) * 1px), 0)
    rotate(calc(var(--rot) + (1 - var(--tin)) * var(--erot) * 1deg))
    scale(calc(1 + (1 - var(--tin)) * 0.05));
  opacity: calc(0.06 + 0.94 * var(--tin));
}

.tbl__shot {
  position: relative;
  display: block;
  overflow: hidden;
  aspect-ratio: var(--ar);
  border-radius: 2px 16px 2px 16px;
  background: var(--obsidian-raised);
  /* the shadow lands with the plate, and it falls away from the lamp */
  box-shadow:
    calc(-12px * var(--tin)) calc(24px * var(--tin)) calc(34px + 30px * var(--tin)) -24px rgba(0, 0, 0, 0.95),
    calc(-3px * var(--tin)) calc(7px * var(--tin)) 18px -12px rgba(0, 0, 0, 0.8);
}
.tbl__shot img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transform: scale(1.02);
  /* the grade is low-key but never crushed: an unlit plate still has to
     look like a photograph, not like an empty rectangle */
  filter: brightness(0.82) saturate(0.9) contrast(1.05);
  transition: filter 0.75s var(--ease-out), transform 0.9s var(--ease-out);
}
.tbl__piece.is-lit .tbl__shot img {
  filter: brightness(1.06) saturate(1) contrast(1.02);
  transform: scale(1.06);
}

/* the site's standard 1px gold edge */
.tbl__shot::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 3;
  border-radius: inherit;
  padding: 1px;
  opacity: 0.68;
  pointer-events: none;
  background: linear-gradient(150deg, rgba(192, 156, 96, 0.55), rgba(156, 120, 72, 0.1) 42%, rgba(192, 156, 96, 0.06) 66%, rgba(192, 156, 96, 0.45));
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
          mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
          mask-composite: exclude;
  transition: opacity 0.6s ease;
}
.tbl__piece.is-lit .tbl__shot::before { opacity: 1; }

/* The sheen off the lamp, plus the shade the label sits in. Both come
   from the same corner: light falls in from the top right, so the top
   LEFT is the shaded one, and that is where the labels live. */
.tbl__shot::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  background:
    linear-gradient(214deg, rgba(255, 240, 214, 0.14), rgba(255, 240, 214, 0) 36%),
    linear-gradient(158deg, rgba(6, 6, 8, 0.82), rgba(6, 6, 8, 0.1) 30%, rgba(6, 6, 8, 0) 46%),
    linear-gradient(0deg, rgba(6, 6, 8, 0.34), rgba(6, 6, 8, 0) 22%);
}

/* THE LABEL SITS AT THE TOP, and that is geometry rather than taste: the
   cascade runs down and to the left, so every plate lands across the
   BOTTOM corner of the one before it. A label set at the foot of a print
   is covered by the next print; a label at its head never can be. */
.tbl__cap {
  position: absolute;
  z-index: 4;
  left: clamp(0.9rem, 0.7rem + 0.7vw, 1.5rem);
  top: clamp(0.75rem, 0.6rem + 0.6vw, 1.2rem);
  display: flex;
  align-items: baseline;
  gap: 0.7rem;
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--ink);
}
.tbl__cap b {
  font-family: var(--font-display);
  font-weight: 500;
  letter-spacing: 0.1em;
  color: var(--gold-light);
}

/* ---- the type ---- */
.tbl__head,
.tbl__claim,
.tbl__close {
  position: absolute;
  left: calc(var(--x) * 1%);
  top: calc(var(--y) * 1%);
  width: calc(var(--w) * 1%);
  z-index: 8;
}

.tbl__head { --x: 0; --y: 0; --w: 42; }
.tbl__h {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(1.75rem, 1.35rem + 1.7vw, 2.6rem);
  line-height: 1.12;
  letter-spacing: -0.02em;
  color: var(--white);
}
.tbl__h em { font-style: italic; color: var(--gold-light); }
.tbl__lead {
  margin-top: clamp(1rem, 0.85rem + 0.5vw, 1.4rem);
  color: var(--vein);
  font-size: var(--text-lg);
  line-height: 1.7;
}

.tbl__serial {
  display: block;
  font-family: var(--font-display);
  font-size: var(--text-sm);
  letter-spacing: 0.12em;
  line-height: 1;
  color: var(--gold-shadow);
  transition: color 0.5s ease;
}
.tbl__claim.is-read .tbl__serial { color: var(--gold-light); }

.tbl__title {
  margin-top: 0.75rem;
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(1.18rem, 1rem + 0.75vw, 1.62rem);
  line-height: 1.24;
  letter-spacing: -0.012em;
  color: var(--ink);
  transition: color 0.5s ease;
}
.tbl__claim.is-read .tbl__title { color: var(--white); }

/* the sentence backing a claim is never dimmed and never hidden: it is
   the argument, and only the emphasis is allowed to move */
.tbl__note {
  margin-top: 0.6rem;
  color: var(--vein);
  line-height: 1.7;
}

/* the conclusion. It is set at the plate tier of the page's type ladder,
   under the section h2 at 2.6rem, and it is deliberately the thing that
   fills the corner of the table the cascade left empty. */
.tbl__close {
  --x: 0; --y: 86; --w: 30;
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(1.4rem, 1.05rem + 1.3vw, 2.3rem);
  line-height: 1.3;
  letter-spacing: -0.014em;
  color: var(--ink);
}

/* ---- the arrangement ----
   Four plates cascading down and to the right, each one landing across
   the corner of the one before it, with the type filling the pockets
   they leave. The last claim crosses to the right of the field on
   purpose: three claims down one edge is a column, and a column beside
   pictures is the layout this section was rebuilt to get away from. */
@media (min-width: 1081px) {
  /* Every plate lands ACROSS the corner of the one before it, and the
     vertical steps are tuned so the cascade leaves no hole in the middle
     of the table - a gap between two plates is a dead rectangle, which is
     this client's oldest complaint about this site. */
  .tbl__piece--a { --x: 56; --y: 2;  --w: 44; --ar: 16 / 10; --rot: -0.7deg; --ex: -36; --ey: 42; --erot: 2.6;  z-index: 2; }
  .tbl__piece--b { --x: 40; --y: 24; --w: 20; --ar: 4 / 5;   --rot: 1.2deg;  --ex: 30;  --ey: 48; --erot: -3;   z-index: 3; }
  .tbl__piece--c { --x: 52; --y: 40; --w: 48; --ar: 16 / 9;  --rot: -1deg;   --ex: -30; --ey: 44; --erot: 2.2;  z-index: 4; }
  .tbl__piece--d { --x: 31; --y: 58; --w: 26; --ar: 1 / 1;   --rot: 1.5deg;  --ex: 28;  --ey: 50; --erot: -2.8; z-index: 5; }

  /* three claims run down the left edge and the fourth crosses to the
     right, because three is a column and four would be a list */
  .tbl__claim--a { --x: 0;  --y: 22; --w: 30; }
  .tbl__claim--b { --x: 0;  --y: 43; --w: 29; }
  .tbl__claim--c { --x: 0;  --y: 64; --w: 27; }
  .tbl__claim--d { --x: 62; --y: 72; --w: 36; }
  .tbl__close    { --x: 0;  --y: 86; --w: 30; }
}

/* The plates are sized in % of the field's WIDTH, but the type is not -
   it wraps to more lines as the column narrows. So the field is given a
   little more height as it gets narrower, in steps small enough that no
   breakpoint produces a visible jump in the section's height. */
@media (min-width: 1400px) { .tbl__field { --fh: 0.96; } }
@media (min-width: 1250px) and (max-width: 1399px) { .tbl__field { --fh: 1.04; } }
@media (min-width: 1081px) and (max-width: 1249px) { .tbl__field { --fh: 1.14; } }

/* ---- one column ----
   Below 1081 the field stops being a table and becomes a plain reading
   order: head, plate, claim, plate, claim. Nothing is repositioned,
   because source order was written for this. The plates keep their
   unequal widths and sides but are deliberately NOT alternated - a strict
   left/right zigzag is the template rhythm this site keeps rejecting. */
@media (max-width: 1080px) {
  .tbl__field { aspect-ratio: auto; }
  .tbl__head,
  .tbl__claim,
  .tbl__close {
    position: static;
    width: auto;
    max-width: 42rem;
  }
  .tbl__piece {
    position: relative;
    width: 100%;
    max-width: 40rem;
    transform: none;
    opacity: 1;
    margin-top: clamp(2.25rem, 1.8rem + 2vw, 3.5rem);
  }
  .tbl__claim { margin-top: clamp(1.4rem, 1.1rem + 1.2vw, 2rem); }
  .tbl__close { margin-top: clamp(2.5rem, 2rem + 2.5vw, 4rem); }
  /* the portrait and the square are capped hard: at 1080 a 4/5 plate run
     to the full column is 880px of photograph on its own */
  .tbl__piece--b { width: 66%; max-width: 24rem; margin-left: auto; }
  .tbl__piece--d { width: 58%; max-width: 21rem; }
  .tbl__sheen { display: none; }
  .tbl__lead { max-width: 42rem; }
}

@media (max-width: 560px) {
  .tbl__piece--b { width: 88%; }
  .tbl__piece--d { width: 82%; }
  .tbl__cap { letter-spacing: 0.14em; gap: 0.55rem; }
}

@media (prefers-reduced-motion: reduce) {
  .tbl__shot img,
  .tbl__shot::before,
  .tbl__serial,
  .tbl__title { transition: none; }
}

/* ==========================================================================
   SERVICES — "the run"   (what-we-do.html, section 02)

   History: five stacked numbered rows (.svc-list) -> .cab, a horizontal
   case of five marble bays -> this. The client asked for the section to
   look its best, to carry images and to be full of motion, and the
   cabinet had no photograph anywhere in it.

   THE SHAPE IS A DESCENDING RUN. Five openings fall down the page on a
   switchback: the eye travels right across the top two, turns at the
   third and comes back down the left. It is the shape of a route, which
   is the thing a representative actually walks.

   THEY ARE OPENINGS, NOT PRINTS, and that distinction is the only reason
   this can sit directly under section 01. The table above puts
   photographs ON a surface, with cast shadows, tilt and overlap; these
   are cut INTO the page — a gold edge on the light side, black on the
   other two, no shadow, no rotation, and the picture travelling behind
   the hole as you scroll. You look THROUGH these rather than at them.

   NOTHING IS HIDDEN. All five names and all five sentences are on the
   page at once at every width, which is what a buyer scanning a services
   page needs and what the cabinet got right.

   Every opening is a different size and proportion, the copy swings from
   the right of the composition to the left halfway down, and each
   engraved numeral straddles a DIFFERENT edge of its own opening.

   --rin (0 shut, 1 open) and --rdy (the drift of the picture behind the
   opening) are UNREGISTERED on purpose: GSAP writes them every frame so
   nothing needs interpolating, and a registered INHERITED property costs
   a recalc on all nine pages that load this file. Both rest at their
   finished value, so no JS, a dead CDN and reduced motion all render an
   open run with every photograph in place.
   ========================================================================== */

.run {
  position: relative;
  overflow-x: clip;   /* the numerals straddle their openings */
  isolation: isolate;
}

/* ---- masthead. The three sections around this one all open with a
   stacked eyebrow / headline, so this one sets the title and the index on
   ONE baseline instead. ---- */
.run__head {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: baseline;
  column-gap: clamp(1.25rem, 3vw, 3.5rem);
  margin-bottom: clamp(2.4rem, 1.9rem + 2.4vw, 4.2rem);
}
.run__eyebrow {
  grid-column: 2;
  grid-row: 1;
  justify-self: end;
  margin-bottom: 0;
}
.run__h {
  grid-column: 1;
  grid-row: 1;
  margin: 0;
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(1.75rem, 1.35rem + 1.7vw, 2.6rem);
  line-height: 1.12;
  letter-spacing: -0.02em;
  color: var(--white);
}
.run__h em { font-style: italic; color: var(--gold-light); }

/* ---- the field. Everything inside is placed as a percentage of it, so
   the composition is one hand-set drawing rather than a grid. --x and --w
   are percentages of the WIDTH; --y and --cy are percentages of the
   HEIGHT, so raising --fh where the type wraps spreads the run out
   instead of leaving slack at the bottom. ---- */
.run__field {
  --fh: 1.10;
  position: relative;
  aspect-ratio: 1 / var(--fh);
}

/* the wrapper generates no box at all: the opening and its words are one
   service but they sit at two unrelated positions in the composition */
.run__item { display: contents; }

/* the lead sits in the masthead, not in the field: the top right of the
   composition is a photograph, and a paragraph parked there was a void */
.run__lead {
  grid-column: 1;
  grid-row: 2;
  max-width: 34rem;
  margin: clamp(0.9rem, 0.7rem + 0.6vw, 1.4rem) 0 0;
  color: var(--ink);
  font-size: var(--text-lg);
  line-height: 1.62;
}

/* ---- the openings ---- */
.run__frame {
  --rin: 1;   /* 0 shut, 1 open. GSAP owns it, and only it. */
  --rdy: 0;   /* the drift of the picture behind the opening, in px */
  --rmx: 50;
  --rmy: 50;
  position: absolute;
  left: calc(var(--x) * 1%);
  top: calc(var(--y) * 1%);
  width: calc(var(--w) * 1%);
  aspect-ratio: var(--ar);
  margin: 0;
}

.run__shot {
  position: absolute;
  inset: 0;
  overflow: hidden;
  border-radius: 2px;
  background: var(--obsidian-raised);
  /* the light on this page comes from the upper left, so a cut takes a
     gold edge along its top and left and falls to black on the other two.
     That, and the absence of any drop shadow, is what makes these read as
     holes in the page rather than as objects lying on it. */
  box-shadow:
    inset 1px 1px 0 rgba(192, 156, 96, 0.36),
    inset -1px -1px 0 rgba(0, 0, 0, 0.72),
    inset 0 18px 28px -20px rgba(0, 0, 0, 0.92);
  /* the cut opens on a diagonal, which is the direction the run travels.
     At --rin 1 the last two points are exactly the box corners. */
  clip-path: polygon(
    0 0,
    calc(var(--rin) * 134%) 0,
    calc(var(--rin) * 134% - 34%) 100%,
    0 100%);
}

.run__shot img {
  position: absolute;
  inset: -8%;
  width: 116%;
  height: 116%;
  /* main.css carries a global img { max-width: 100% } that silently
     clamps any deliberately oversized image, which shows up as a strip of
     the frame's own background down one edge. */
  max-width: none;
  display: block;
  object-fit: cover;
  filter: brightness(0.84) contrast(1.02) saturate(0.94);
  transition: filter 0.6s var(--ease-out);
  /* CSS composes the drift and the entrance scale into ONE transform, so
     GSAP never shares a property with a transition. The picture travels
     down AND to the right: along the run, not across it. */
  transform:
    translate3d(calc(var(--rdy) * 0.55px), calc(var(--rdy) * 1px), 0)
    scale(calc(1 + (1 - var(--rin)) * 0.07));
}
.run__item:nth-child(2) .run__shot img { object-position: 50% 38%; }
.run__item:nth-child(5) .run__shot img { object-position: 50% 46%; }

/* a slow light crossing the opening on a long repeat, so the run is alive
   with no pointer anywhere near it. Opacity rests at 0 and initRun raises
   it, so with no JS there is no band frozen across a photograph. */
.run__pass {
  position: absolute;
  inset: 0;
  z-index: 1;
  opacity: 0;
  pointer-events: none;
  mix-blend-mode: screen;
  background-image: linear-gradient(104deg,
    transparent 40%,
    rgba(255, 238, 206, 0.07) 47%,
    rgba(255, 242, 214, 0.15) 50%,
    rgba(255, 238, 206, 0.07) 53%,
    transparent 60%);
  background-size: 260% 100%;
  background-repeat: no-repeat;
  background-position: calc(var(--rpx, -40) * 1%) 0;
}

/* the pointer specular, inside the opening so the cut clips it too */
.run__gleam {
  position: absolute;
  inset: 0;
  z-index: 2;
  opacity: 0;
  pointer-events: none;
  mix-blend-mode: screen;
  background: radial-gradient(40% 32% at calc(var(--rmx) * 1%) calc(var(--rmy) * 1%),
    rgba(255, 240, 212, 0.17), transparent 68%);
}

/* the numerals are the section's metalwork. Each one straddles a
   different edge of its own opening, so no two sit the same way. */
.run__num {
  position: absolute;
  left: calc(var(--nl) * 1%);
  top: calc(var(--nt) * 1%);
  z-index: 3;
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(2.3rem, 1.5rem + 2.6vw, 4.4rem);
  line-height: 0.86;
  letter-spacing: -0.03em;
  background: linear-gradient(166deg, rgba(246, 242, 234, 0.92), rgba(198, 160, 102, 0.84) 44%, rgba(128, 96, 56, 0.52));
  -webkit-background-clip: text;
          background-clip: text;
  color: transparent;
  /* one shadow on the whole figure guarantees it separates from any tone
     in the photograph it crosses, without retuning a single colour */
  filter: drop-shadow(0 2px 6px rgba(0, 0, 0, 0.88));
  /* NEVER transition opacity here: initRun animates opacity on this
     element, and a transition on the same property leaves it stuck at 0.
     Every state below dims with filter instead. */
  transition: filter 0.55s var(--ease-out);
}

/* ---- the words ---- */
.run__copy {
  position: absolute;
  left: calc(var(--cx) * 1%);
  top: calc(var(--cy) * 1%);
  width: calc(var(--cw) * 1%);
  z-index: 4;
}
.run__title {
  margin: 0 0 0.62rem;
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(1.1rem, 0.95rem + 0.62vw, 1.62rem);
  line-height: 1.16;
  letter-spacing: -0.012em;
  color: var(--white);
}
.run__note {
  margin: 0;
  color: var(--vein);
  font-size: var(--text-sm);
  line-height: 1.68;
}
.run__tick {
  display: block;
  width: 1.5rem;
  height: 1px;
  margin-top: clamp(0.85rem, 0.7rem + 0.5vw, 1.3rem);
  background: var(--gold-shadow);
  transition: width 0.5s var(--ease-out), background 0.5s ease;
}

/* ---- pointer. The opening and its words are one service, so JS lights
   both from either; the bare :hover below is the no-JS fallback and can
   never fight the classes because .is-lit excludes itself from the dim. ---- */
@media (hover: hover) and (pointer: fine) {
  .run__frame:hover .run__shot img {
    filter: brightness(1.06) contrast(1.04) saturate(1);
  }
  .run__field.is-hot .run__item:not(.is-lit) .run__shot img {
    filter: brightness(0.4) contrast(0.98) saturate(0.7);
  }
  .run__field.is-hot .run__item:not(.is-lit) .run__num {
    filter: brightness(0.44) drop-shadow(0 2px 6px rgba(0, 0, 0, 0.88));
  }
  .run__item.is-lit .run__shot img {
    filter: brightness(1.08) contrast(1.04) saturate(1);
  }
  .run__item.is-lit .run__num {
    filter: brightness(1.24) drop-shadow(0 2px 7px rgba(0, 0, 0, 0.9));
  }
  .run__item.is-lit .run__tick { width: 3.4rem; background: var(--gold-light); }
}

/* ---- the type wraps to more lines as the measure narrows, so the field
   gets taller in steps rather than in one jump ---- */
@media (max-width: 1399px) { .run__field { --fh: 1.17; } }
@media (max-width: 1240px) { .run__field { --fh: 1.26; } }
@media (max-width: 1140px) { .run__field { --fh: 1.36; } }

/* ---- Below 1081 the composition cannot hold: the switchback needs the
   horizontal room it is drawn in. Every width the absolute layout set has
   to be reset here, or a percentage meant for a 1440 field survives onto
   a phone as a smudge. ---- */
@media (max-width: 1080px) {
  .run__field {
    --fh: auto;
    aspect-ratio: auto;
    display: grid;
    gap: clamp(2rem, 1.3rem + 2.8vw, 3.4rem);
  }
  .run__frame,
  .run__copy {
    position: relative;
    left: auto;
    top: auto;
    width: auto;
  }
  .run__num { left: 0.5rem; top: -0.42em; }
}

/* ---- 641 to 1080: the run pairs off. Each picture shares a row with its
   words and the pair swaps sides down the set, so the tablet range stays
   a composition instead of becoming a column of five large photographs -
   which is also what keeps this section's height in step with the ones
   around it here. Rows are explicit because auto-placement will not put a
   copy block back into column 1 after its picture has taken column 2. ---- */
@media (min-width: 641px) and (max-width: 1080px) {
  .run__field {
    grid-template-columns: minmax(0, 1.06fr) minmax(0, 0.94fr);
    column-gap: clamp(1.4rem, 2.4vw, 2.6rem);
    align-items: center;
  }
  .run__copy { max-width: none; }

  .run__item:nth-child(1) .run__frame { grid-area: 1 / 1; }
  .run__item:nth-child(1) .run__copy  { grid-area: 1 / 2; }
  .run__item:nth-child(2) .run__frame { grid-area: 2 / 2; --ar: 1 / 1; }
  .run__item:nth-child(2) .run__copy  { grid-area: 2 / 1; }
  .run__item:nth-child(3) .run__frame { grid-area: 3 / 1; }
  .run__item:nth-child(3) .run__copy  { grid-area: 3 / 2; }
  .run__item:nth-child(4) .run__frame { grid-area: 4 / 2; }
  .run__item:nth-child(4) .run__copy  { grid-area: 4 / 1; }
  .run__item:nth-child(5) .run__frame { grid-area: 5 / 1; --ar: 3 / 2; }
  .run__item:nth-child(5) .run__copy  { grid-area: 5 / 2; }
}

/* ---- 640 and below: one column. The pictures are CAPPED rather than run
   full width - five full-bleed photographs stacked is height with nothing
   gained - and the caps plus an alternating side keep the set hand-set
   rather than listed. ---- */
@media (max-width: 640px) {
  /* the index drops onto its own line above the headline, so the lead has
     to move down a row with it or it prints on top of the h2 */
  .run__head { grid-template-columns: 1fr; row-gap: 0.75rem; }
  .run__eyebrow { grid-column: 1; grid-row: 1; justify-self: start; }
  .run__h { grid-column: 1; grid-row: 2; }
  .run__lead { grid-column: 1; grid-row: 3; }

  .run__copy { max-width: 30rem; }
  .run__frame { width: min(100%, 27rem); }

  .run__item:nth-child(2) .run__frame { --ar: 4 / 5; width: min(76%, 17rem); margin-left: auto; }
  .run__item:nth-child(2) .run__copy  { margin-left: auto; }
  .run__item:nth-child(3) .run__frame { width: min(96%, 26rem); }
  .run__item:nth-child(4) .run__frame { width: min(74%, 20rem); margin-left: auto; }
  .run__item:nth-child(4) .run__copy  { margin-left: auto; }
  .run__item:nth-child(5) .run__frame { --ar: 3 / 2; width: min(100%, 28rem); }
}

@media (prefers-reduced-motion: reduce) {
  .run__shot img,
  .run__num,
  .run__tick { transition: none; }
}

/* ==========================================================================
   HERO — "the cover sheet"   (what-we-do.html)

   The old hero was the common one: eyebrow, headline, one line of sub, a
   watermark at 5%. This is the cover of a capabilities document instead:
   a ruled masthead, the proposition, a short specification block, and a
   footer that names what you are about to scroll into.

   The visual half is the firm's own mark STRUCK AS AN OBJECT — lit from
   behind, standing on a plinth line between registration marks, with its
   reflection beneath and a specular pass travelling across the metal.
   Everywhere else on the site that file is a flat 5% watermark; here it
   is the thing itself, which is why the hero needs no photograph.

   THE ENTRANCE IS PURE CSS, keyed off the preloader's `is-loading` class
   on <html>. That class is added by an inline head script and removed by
   motion.js (with a 3.5s hard fallback), so the from-state only ever
   exists while the curtain is up. With no JS at all `is-loading` is never
   applied and the cover simply renders finished. GSAP adds the specular
   sweep and the parallax and nothing else.

   The section keeps the base .hero class on purpose: runIntro() splits
   `.hero h1` into masked lines and choreographs `.hero .eyebrow` and
   `.hero__sub`, so this cover still opens with the site's own hero
   signature rather than inventing a second one.
   ========================================================================== */

.hero--cover {
  min-height: min(84svh, 46rem);
  padding-top: clamp(3.77rem, 3.19rem + 1.508vw, 4.785rem);
  padding-bottom: clamp(2.5rem, 2rem + 2vw, 4rem);
  justify-content: stretch;
}

/* the light the whole sheet sits in */
.cover__field {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background:
    radial-gradient(38rem 30rem at 76% 42%, rgba(156, 120, 72, 0.15), transparent 66%),
    radial-gradient(46rem 26rem at 4% 0%, rgba(156, 120, 72, 0.07), transparent 62%),
    radial-gradient(60rem 24rem at 50% 118%, rgba(6, 6, 8, 0.9), transparent 64%);
}

.cover__inner {
  position: relative;
  z-index: 2;
  flex: 1;
  display: flex;
  flex-direction: column;
}

/* ---- the sheet itself ---- */
.cover__body {
  flex: 1;
  display: grid;
  /* the proposition needs the room: the mark reads at any size, a
     five-word line at 60px does not */
  grid-template-columns: 1.42fr 0.58fr;
  gap: clamp(2rem, 1rem + 3vw, 4rem);
  align-items: center;
  padding-block: clamp(1.75rem, 1.25rem + 2.4vw, 3.25rem);
}

.cover h1 {
  font-size: clamp(1.95rem, 1.45rem + 2.1vw, 3rem);
  line-height: 1.1;
  letter-spacing: -0.024em;
  margin-bottom: clamp(1.1rem, 0.9rem + 0.8vw, 1.6rem);
}
.cover h1 em { font-style: italic; color: var(--gold-light); }
.cover .hero__sub { max-width: 34rem; margin-bottom: 0; }

/* the specification block: this is where a buyer gets the commercial
   shape of the firm before scrolling once */
.cover__spec {
  margin-top: clamp(1.75rem, 1.4rem + 1.6vw, 2.75rem);
  max-width: 36rem;
}
.cover__row {
  display: grid;
  grid-template-columns: clamp(6rem, 5rem + 3vw, 8.5rem) minmax(0, 1fr);
  gap: clamp(0.75rem, 0.6rem + 0.6vw, 1.35rem);
  align-items: baseline;
}
.cover__row + .cover__row { margin-top: clamp(0.7rem, 0.6rem + 0.4vw, 1.05rem); }
.cover__row dt {
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--gold);
}
.cover__row dd {
  font-size: var(--text-sm);
  line-height: 1.5;
  color: var(--ink);
}

/* ---- the struck mark ---- */
.cover__object {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-self: center;
  width: min(100%, 26rem);
}
.cover__mark {
  position: relative;
  width: clamp(8rem, 5rem + 10vw, 13.5rem);
  aspect-ratio: 512 / 490;
}
.cover__halo {
  position: absolute;
  inset: -52%;
  z-index: 0;
  pointer-events: none;
  background: radial-gradient(50% 50% at 50% 48%, rgba(192, 156, 96, 0.26), rgba(156, 120, 72, 0.07) 46%, transparent 72%);
}
.cover__face {
  position: relative;
  z-index: 1;
  width: 100%;
  height: auto;
  filter: drop-shadow(0 26px 34px rgba(0, 0, 0, 0.75));
}
/* the specular pass, masked to the metal so the light only ever travels
   across the mark and never across the page behind it */
@property --gleam-x { syntax: "<percentage>"; inherits: false; initial-value: 118%; }

.cover__gleam {
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  opacity: 0;
  background-size: 240% 100%;
  background-repeat: no-repeat;
  background-position: var(--gleam-x) center;
  background-image: linear-gradient(104deg,
    transparent 38%,
    rgba(255, 245, 222, 0.42) 48%,
    rgba(255, 255, 255, 0.72) 50%,
    rgba(255, 245, 222, 0.42) 52%,
    transparent 62%);
  -webkit-mask-image: url("../assets/mark-512.png");
          mask-image: url("../assets/mark-512.png");
  -webkit-mask-size: 100% 100%;
          mask-size: 100% 100%;
  -webkit-mask-repeat: no-repeat;
          mask-repeat: no-repeat;
  mix-blend-mode: screen;
}

/* the reflection. The mask keeps the BOTTOM of the unflipped file, which
   after scaleY(-1) becomes the edge nearest the plinth. */
.cover__echo {
  width: clamp(8rem, 5rem + 10vw, 13.5rem);
  height: auto;
  margin-top: clamp(0.5rem, 0.4rem + 0.4vw, 0.9rem);
  opacity: 0.12;
  transform: scaleY(-1);
  filter: blur(1.5px) saturate(0.7);
  pointer-events: none;
  -webkit-mask-image: linear-gradient(to top, rgba(0, 0, 0, 1), transparent 48%);
          mask-image: linear-gradient(to top, rgba(0, 0, 0, 1), transparent 48%);
}

/* ---- entrance. Only exists while the curtain is up, so no-JS renders
   the finished cover and nothing can be left hidden. ---- */
.cover__spec,
.cover__object { transition: opacity 1s var(--ease-out), transform 1.1s var(--ease-out); }
.cover__row { transition: opacity 0.8s var(--ease-out), transform 0.8s var(--ease-out); }
.cover__row:nth-child(1) { transition-delay: 0.66s; }
.cover__row:nth-child(2) { transition-delay: 0.76s; }
.cover__row:nth-child(3) { transition-delay: 0.86s; }
.cover__object { transition-delay: 0.38s; }
.cover__spec { transition-delay: 0.56s; }

.is-loading .cover__spec { opacity: 0; transform: translateY(14px); }
.is-loading .cover__row { opacity: 0; transform: translateY(10px); }
.is-loading .cover__object { opacity: 0; transform: translateY(22px) scale(1.05); }

@media (max-width: 900px) {
  .hero--cover { min-height: 0; padding-bottom: clamp(2rem, 1.5rem + 2vw, 3rem); }
  .cover__body {
    grid-template-columns: 1fr;
    gap: clamp(2.5rem, 2rem + 3vw, 3.5rem);
    padding-block: clamp(2rem, 1.5rem + 2vw, 3rem);
  }
  .cover__object { order: 2; width: 100%; }
  .cover__mark, .cover__echo { width: clamp(8rem, 30vw, 12rem); }
  .cover .hero__sub, .cover__spec { max-width: 42rem; }
}

@media (max-width: 560px) {
  .cover__row { grid-template-columns: 1fr; gap: 0.15rem; }
}

@media (prefers-reduced-motion: reduce) {
  .cover__spec,
  .cover__object,
  .cover__row { transition: none; }
}

/* ==========================================================================
   WHAT WE DO — page rhythm and heading scale

   The client asked for less air between sections and a medium heading
   size across the whole page. Both are scoped to this page rather than
   changed on the shared tokens, so no other page moves: `--section` is
   redefined on <main class="wwd"> and cascades into every `.section`
   inside it, and the two sections that still use generic markup (the FAQ
   and the closing band) opt into the same scale with `.sec--md`.
   ========================================================================== */

.wwd {
  --section: clamp(3.5rem, 2.5rem + 4vw, 5.75rem);
  --section-sm: clamp(2.75rem, 2rem + 3vw, 4.25rem);
}

.sec--md h2 {
  font-size: clamp(1.75rem, 1.35rem + 1.7vw, 2.6rem);
  line-height: 1.12;
  letter-spacing: -0.02em;
}

/* ==========================================================================
   WHAT WE DO NOT DO — "where we stop"   (what-we-do.html, section 04)

   The previous build put this on a large plate with the excluded work
   sunk into it as slots. On screen it read as a card with dark boxes
   inside — the template look — so the whole container is gone. No card,
   no boxes, no panel. Just type, one rule, and light.

   THE SECTION IS A BOUNDARY. The three things outside our scope hang
   above one gold rule, each tethered to it by a hairline that reaches
   the line and stops. Below the rule, on lit ground, sits the one thing
   that is left. Outside is unlit and debossed, inside is lit. The rule
   is where we stop, and the composition argues that without a label
   having to explain it.

   Grammar check against the rest of the page: 01 is a sticky plate with
   a drawn figure, 02 is a case that assembles, 03 is a photographic field
   dividing in two. This is the only section carried by a single rule and
   by the difference between lit and unlit ground.
   ========================================================================== */

.stop { position: relative; overflow-x: clip; }

.stop__head { max-width: 46rem; margin-bottom: clamp(2.25rem, 1.85rem + 1.8vw, 3.25rem); }
.stop__h {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(1.75rem, 1.35rem + 1.7vw, 2.6rem);
  line-height: 1.12;
  letter-spacing: -0.02em;
  color: var(--white);
}
.stop__h em { font-style: italic; color: var(--gold-light); }
.stop__lead {
  margin-top: clamp(0.9rem, 0.75rem + 0.6vw, 1.4rem);
  color: var(--vein);
  font-size: var(--text-lg);
  line-height: 1.7;
  max-width: 38rem;
}

.stop__field { position: relative; }

.stop__label {
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--gold);
  margin-bottom: clamp(1.1rem, 0.9rem + 0.8vw, 1.75rem);
}

/* ---- outside: unlit, and hanging off the boundary ---- */
.stop__out {
  list-style: none;
  display: grid;
  /* One row, one item per column, however many items there are. This was
     `repeat(3, max-content)` with `align-items: start`, which only held
     while every phrase was three short words on one line: a fourth item
     wrapped onto a second grid row and left the first three tethers
     terminating in mid-air instead of on the rule, and a long phrase in
     column one blew the max-content track out. 1fr tracks plus the
     default stretch keep every item's bottom edge on the same line, so
     every tether still reaches the boundary and stops dead against it. */
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: clamp(1.25rem, 0.9rem + 2.2vw, 3rem);
}
.stop__item {
  position: relative;
  display: flex;
  align-items: baseline;
  gap: clamp(0.7rem, 0.55rem + 0.5vw, 1.05rem);
  /* the room the tether needs to reach the rule */
  padding-bottom: clamp(1.9rem, 1.5rem + 1.8vw, 3rem);
}
.stop__n {
  flex: none;
  font-family: var(--font-display);
  font-size: var(--text-sm);
  letter-spacing: 0.08em;
  color: var(--gold-shadow);
}
.stop__name {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(1.05rem, 0.95rem + 0.5vw, 1.4rem);
  line-height: 1.25;
  color: var(--vein);
  /* cut into the surface rather than sitting on it */
  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.05);
}
/* the hairline that reaches the boundary and stops dead against it */
.stop__tether {
  position: absolute;
  left: 0;
  bottom: 0;
  width: 1px;
  height: clamp(1.35rem, 1.05rem + 1.5vw, 2.35rem);
  transform-origin: top center;
  background: linear-gradient(180deg, transparent, rgba(156, 120, 72, 0.42) 42%, var(--gold));
}
/* the terminal: where it reaches the boundary and goes no further */
.stop__tether::after {
  content: "";
  position: absolute;
  left: -0.28rem;
  bottom: -1px;
  width: 0.62rem;
  height: 1px;
  background: var(--gold-light);
  box-shadow: 0 0 8px rgba(192, 156, 96, 0.6);
}

/* ---- the boundary ---- */
.stop__rule {
  position: relative;
  display: block;
  height: 1px;
  background: rgba(156, 120, 72, 0.14);
}
.stop__rule i {
  position: absolute;
  inset: 0;
  transform-origin: center;
  background: linear-gradient(90deg, rgba(156, 120, 72, 0.35), var(--gold-light) 16%, var(--gold-light) 84%, rgba(156, 120, 72, 0.35));
  box-shadow: 0 0 26px rgba(192, 156, 96, 0.55), 0 1px 0 rgba(192, 156, 96, 0.22);
}

/* ---- inside: lit ground, and the one thing that survives ---- */
.stop__in {
  position: relative;
  padding-top: clamp(2rem, 1.6rem + 2vw, 3.25rem);
}
.stop__in::before {
  content: "";
  position: absolute;
  z-index: -1;
  left: -8vw;
  right: -8vw;
  top: 0;
  height: clamp(12rem, 9rem + 12vw, 20rem);
  pointer-events: none;
  background: radial-gradient(72% 100% at 32% 0%, rgba(156, 120, 72, 0.16), rgba(156, 120, 72, 0.05) 52%, transparent 82%);
}
.stop__label--in { color: var(--gold-light); }
.stop__yes {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(1.5rem, 1.2rem + 1.6vw, 2.5rem);
  line-height: 1.16;
  letter-spacing: -0.02em;
  color: var(--white);
  max-width: 46rem;
  /* lit, where the three above it are not */
  text-shadow: 0 1px 0 rgba(0, 0, 0, 0.85), 0 12px 34px rgba(192, 156, 96, 0.09);
}
.stop__yes em { font-style: italic; color: var(--gold-light); }

@media (hover: hover) and (pointer: fine) {
  .stop__item .stop__name,
  .stop__item .stop__tether { transition: color 0.4s ease, background 0.4s ease; }
  .stop__item:hover .stop__name { color: var(--ink); }
  .stop__item:hover .stop__tether { background: linear-gradient(180deg, transparent, var(--gold-light) 38%, var(--gold-light)); }
}

@media (max-width: 860px) {
  .stop__out {
    grid-template-columns: 1fr;
    gap: 0;
  }
  /* stacked, only the last one still hangs off the boundary */
  .stop__item { padding-block: clamp(0.7rem, 0.6rem + 0.5vw, 1rem); }
  .stop__item:last-child { padding-bottom: clamp(2rem, 1.6rem + 2vw, 3rem); }
  .stop__item .stop__tether { display: none; }
  .stop__item:last-child .stop__tether { display: block; }
  .stop__in::before { left: -12vw; right: -12vw; }
}

@media (prefers-reduced-motion: reduce) {
  .stop__name,
  .stop__tether { transition: none; }
}
/* ==========================================================================
   HERO — "the count"   (results.html)

   History: the original hero was the common one (eyebrow, headline, sub, a
   watermark) with a four-across strip of numbers under it. That became
   `.rec`, which folded the four figures into the hero as its visual half,
   hand-set rather than gridded. This is the second rebuild: the client
   asked for a hero that carries images and real motion, and `.rec` had no
   image in it at all.

   THE PICTURE IS MADE OF THE NUMBER. A canvas draws EXACTLY 250 x 152 =
   38,000 marks, one for every customer acquired, and their density follows
   a photograph, so the image resolves out of the count itself. The marks
   land in random order while the counter rolls, so you watch the quantity
   accumulate and the picture arrive at the same time.

   THAT IS WHY IT BELONGS ON THIS PAGE AND NOWHERE ELSE. The page's promise
   is that every number is checkable, and here even the decoration is: the
   caption says the picture holds exactly 38,000 marks, and it does. The
   grid was chosen for that product, not for its proportions.

   NEW GRAMMAR, and by now that is the constraint rather than "make it
   move". `.forge` on the homepage is also a canvas, but it turns a 3D
   object; this one constitutes an image out of data and then stops. And
   the marks accumulate in RANDOM order rather than sweeping, because a
   left-to-right pass belongs to `.cab` and a develop belongs to `.latent`
   further down this same page. 38,000 marks were made at 38,000 different
   times in 38,000 different places, so random is also the true one.

   The canvas module lives in main.js, NOT motion.js: a hero's image
   cannot depend on a CDN. GSAP adds only parallax and a sheen. With no JS
   at all the plate falls back to the photograph itself, and the entrance
   is CSS keyed off `is-loading`, so nothing is ever left hidden.

   Keeps the base .hero class on purpose, like the what-we-do cover, so
   runIntro() still splits the h1 into masked lines.
   ========================================================================== */

.hero--tally {
  min-height: min(84svh, 46rem);
  padding-top: clamp(3.77rem, 3.19rem + 1.508vw, 4.785rem);
  padding-bottom: clamp(2.5rem, 2rem + 2vw, 3.5rem);
  justify-content: stretch;
}

.tally__wash {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background:
    radial-gradient(36rem 28rem at 74% 40%, rgba(156, 120, 72, 0.15), transparent 66%),
    radial-gradient(40rem 24rem at 0% 98%, rgba(156, 120, 72, 0.07), transparent 62%);
}

.tally__inner {
  position: relative;
  z-index: 2;
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
}
/* Two columns and two rows: the claim holds the top of the left column,
   the specification holds its foot, and the plate spans both rows on the
   right. That is what gives the hero an architecture rather than one
   full half and one empty one. */
.tally__body {
  display: grid;
  grid-template-columns: minmax(0, 0.92fr) minmax(0, 1.08fr);
  grid-template-rows: auto 1fr;
  column-gap: clamp(1.62rem, 1.008rem + 2.592vw, 3.6rem);
  row-gap: clamp(1.6rem, 1rem + 2vw, 3rem);
  align-items: start;
}
.tally__claim { grid-column: 1; grid-row: 1; max-width: 34rem; }
.tally__exhibit { grid-column: 2; grid-row: 1 / 3; }
.tally__spec { grid-column: 1; grid-row: 2; align-self: end; }
.tally h1 {
  font-size: clamp(1.95rem, 1.45rem + 2.1vw, 3rem);
  line-height: 1.1;
  letter-spacing: -0.024em;
  margin-bottom: clamp(1.1rem, 0.9rem + 0.8vw, 1.6rem);
}
.tally h1 em { font-style: italic; color: var(--gold-light); }
.tally .hero__sub { max-width: 31rem; margin-bottom: 0; }

/* ---- the exhibit ------------------------------------------------------- */
.tally__exhibit {
  max-width: 34rem;
  margin-left: auto;
}

.tally__plate {
  position: relative;
  width: 100%;
  aspect-ratio: 5 / 4;
  overflow: hidden;
  border-radius: 3px;
  background: var(--obsidian);
  border: 1px solid rgba(156, 120, 72, 0.2);
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.03) inset,
    0 34px 70px -34px rgba(0, 0, 0, 0.92);
}

/* the fallback: with no JS the plate simply shows the photograph */
.tally__source {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: brightness(0.88) contrast(1.06) saturate(0.85);
  transition: opacity 0.9s var(--ease-out);
}
.tally__plate.is-drawn .tally__source { opacity: 0; }

/* never seen; `display: none` is avoided deliberately so the browser
   still decodes it and drawImage has something to read */
.tally__seed {
  position: absolute;
  left: 0;
  top: 0;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}

.tally__canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 1;
}

/* a slow reflection travelling over the plate once the field is complete */
.tally__sheen {
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  opacity: 0;
  mix-blend-mode: screen;
  background: linear-gradient(104deg, transparent 38%, rgba(255, 244, 218, 0.075) 48%, transparent 60%);
  background-size: 320% 100%;
  background-position: 160% 0;
  transition: opacity 1.2s var(--ease-out);
}
.tally__plate.is-complete .tally__sheen { opacity: 1; }

/* the plate is lit from the same corner as everything else here */
.tally__plate::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 3;
  pointer-events: none;
  background: radial-gradient(120% 90% at 78% 8%, rgba(192, 156, 96, 0.1), transparent 64%);
  box-shadow: inset 0 0 80px -46px rgba(0, 0, 0, 0.85);
}

/* ---- the legend --------------------------------------------------------
   The figure and the sentence that makes it checkable. The label is not
   decoration: it states what the picture is made of, which is the only
   reason the picture is allowed to be here. */
.tally__legend {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  column-gap: clamp(1rem, 0.7rem + 1.2vw, 1.9rem);
  align-items: end;
  margin-top: clamp(0.95rem, 0.75rem + 0.8vw, 1.5rem);
}

.tally__fig {
  display: block;
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(2.3rem, 1.7rem + 2.7vw, 3.5rem);
  line-height: 0.9;
  letter-spacing: -0.03em;
  /* near-vertical ramp: an angled one drops the "+" into its dark stop */
  background: linear-gradient(179deg, rgba(250, 248, 242, 0.98), rgba(216, 180, 120, 0.96) 56%, rgba(180, 140, 84, 0.92));
  -webkit-background-clip: text;
          background-clip: text;
  color: transparent;
}

/* the counter module inserts an sr-only sibling next to any [data-count],
   so the figure is WRAPPED: an extra grid item here would push the meta
   column onto a second row */
.tally__meta { display: block; padding-bottom: 0.3rem; }
.tally__lbl {
  display: block;
  position: relative;
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  line-height: 1.5;
  color: var(--vein);
}
/* the confirmation mark lands once the last of the 38,000 is down */
.tally__mark {
  display: block;
  width: 1.6rem;
  height: 1px;
  margin-bottom: 0.6rem;
  background: var(--gold-light);
  box-shadow: 0 0 10px rgba(192, 156, 96, 0.45);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 0.75s var(--ease-out);
}
.tally__plate.is-complete ~ .tally__legend .tally__mark { transform: scaleX(1); }

.tally__note {
  display: block;
  margin-top: clamp(0.5rem, 0.4rem + 0.3vw, 0.75rem);
  font-size: var(--text-sm);
  line-height: 1.55;
  color: var(--ink);
  text-wrap: pretty;
}
.tally__note b { font-weight: 500; color: var(--gold-light); }

/* ---- the specification ------------------------------------------------
   The three supporting figures, at caption scale and attached to the
   plate as its specification. Deliberately NOT a four-across strip of
   equal cells: the widths are set by their own content, so they are
   unequal, and they read as furniture belonging to the exhibit above. */
.tally__spec {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: clamp(0.8rem, 0.5rem + 1vw, 1.5rem);
  padding-top: clamp(0.8rem, 0.65rem + 0.6vw, 1.15rem);
  border-top: 1px solid rgba(156, 120, 72, 0.22);
  max-width: 34rem;
}
.tspec { position: relative; }
.tspec + .tspec { padding-left: clamp(0.8rem, 0.5rem + 1vw, 1.5rem); }
.tspec + .tspec::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.15rem;
  bottom: 0.15rem;
  width: 1px;
  background: linear-gradient(180deg, transparent, rgba(156, 120, 72, 0.42), transparent);
}
.tspec__fig {
  display: block;
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(1.05rem, 0.92rem + 0.5vw, 1.4rem);
  line-height: 1;
  letter-spacing: -0.01em;
  background: linear-gradient(179deg, rgba(246, 244, 238, 0.95), rgba(206, 170, 112, 0.94) 58%, rgba(172, 132, 78, 0.9));
  -webkit-background-clip: text;
          background-clip: text;
  color: transparent;
}
.tspec__lbl {
  display: block;
  margin-top: 0.42rem;
  font-size: 0.66rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  line-height: 1.4;
  color: var(--vein);
}

/* ---- entrance ----------------------------------------------------------
   Keyed off the preloader class, so the from-state only exists while the
   curtain is up. With no JS the hero simply renders finished. GSAP never
   touches .tally__plate's transform, only the canvas inside it, because a
   CSS transition and a GSAP tween must never share a property. */
.tally__plate,
.tally__legend,
.tally__spec {
  transition: opacity 1s var(--ease-out), transform 1s var(--ease-out);
}
.tally__plate { transition-delay: 0.26s; }
.tally__legend { transition-delay: 0.46s; }
.tally__spec { transition-delay: 0.6s; }

.is-loading .tally__plate { opacity: 0; transform: translateY(26px) scale(0.985); }
.is-loading .tally__legend { opacity: 0; transform: translateY(18px); }
.is-loading .tally__spec { opacity: 0; transform: translateY(14px); }

@media (max-width: 980px) {
  .hero--tally { min-height: 0; }
  /* one column, and the source order takes over: claim, picture, then
     the supporting figures */
  .tally__body {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: none;
    row-gap: clamp(2rem, 1.6rem + 2vw, 3rem);
  }
  .tally__claim,
  .tally__exhibit,
  .tally__spec {
    grid-column: 1;
    grid-row: auto;
    align-self: auto;
  }
  .tally__claim { max-width: 42rem; }
  .tally .hero__sub { max-width: 42rem; }
  .tally__exhibit { margin-left: 0; max-width: 44rem; }
  .tally__spec { max-width: 44rem; }
}

@media (max-width: 620px) {
  .tally__plate { aspect-ratio: 4 / 3; }
  .tally__legend {
    grid-template-columns: minmax(0, 1fr);
    row-gap: 0.7rem;
    align-items: start;
  }
  .tally__meta { padding-bottom: 0; }
  /* two fixed columns rather than a wrapping row: a wrapped flex line
     starts with a divider hanging off nothing */
  .tally__spec {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: clamp(1rem, 3vw, 1.4rem);
  }
  .tspec + .tspec { padding-left: 0; }
  .tspec + .tspec::before { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .tally__plate,
  .tally__legend,
  .tally__spec,
  .tally__source,
  .tally__sheen,
  .tally__mark { transition: none; }
  .tally__mark { transform: scaleX(1); }
}

/* ==========================================================================
   THE RULES — "the standard"   (results.html, section 01)

   Was a generic five/seven grid with a bulleted list. The content is a
   set of DEFINITIONS — the lead literally says "here is what ours mean"
   — so it is set as the clauses of a standard: a hanging gold clause
   figure, the rule at a reading size, and the term being defined marked
   with a fine gold underline that draws itself in.

   MARKING THE TERM IS THE VISUAL. It is the gesture you make when you
   define a word; it gives four otherwise even lines an irregular rhythm
   because the marked phrases are different lengths; and it is the only
   thing on this site that moves like a pen rather than like light. It is
   deliberately an UNDERLINE, not the strike-through the homepage careers
   filter uses — one defines, the other cancels.

   Two unequal columns with the right one dropped, so the four clauses
   fill the measure instead of leaving a dead column beside them. No
   bullets, no cards, no framing rules.
   ========================================================================== */

.rules__head {
  max-width: 44rem;
  margin-bottom: clamp(2.25rem, 1.85rem + 1.8vw, 3.25rem);
}
.rules__lead {
  margin-top: clamp(0.85rem, 0.7rem + 0.55vw, 1.25rem);
  color: var(--vein);
  font-size: var(--text-lg);
  line-height: 1.7;
  max-width: 36rem;
  text-wrap: pretty;          /* no single word left on the last line */
}

/* column-wise flow puts 01/02 in the left column and 03/04 in the right,
   and the right column is dropped so the two never line up */
.rules__set {
  list-style: none;
  display: grid;
  grid-template-columns: 1.08fr 0.92fr;
  grid-template-rows: auto auto;
  grid-auto-flow: column;
  column-gap: clamp(2rem, 1.25rem + 3.4vw, 5rem);
  row-gap: clamp(1.4rem, 1.15rem + 1.1vw, 2.1rem);
  align-items: start;
}
.rules__item:nth-child(3) { margin-top: clamp(0.7rem, 0.55rem + 0.7vw, 1.25rem); }

.rules__item {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  column-gap: clamp(0.9rem, 0.75rem + 0.7vw, 1.5rem);
  align-items: baseline;
}
.rules__no {
  font-family: var(--font-display);
  font-size: var(--text-sm);
  letter-spacing: 0.08em;
  color: var(--gold-shadow);
}
.rules__text {
  font-size: clamp(1rem, 0.94rem + 0.34vw, 1.2rem);
  line-height: 1.65;
  color: var(--ink);
  max-width: 30rem;
}

/* The defined term, and the mark under it.

   The mark is a BACKGROUND, not a positioned child. An absolutely
   positioned underline inside an inline element that wraps resolves
   against the union of its line fragments and renders at zero width -
   clause 03's term wraps, and its underline vanished. A background with
   box-decoration-break: clone gives every line fragment its own mark,
   and --mark drives how far it is drawn so GSAP can still animate it. */
@property --mark { syntax: "<number>"; inherits: false; initial-value: 1; }

.rules__key {
  font-weight: 500;
  color: var(--white);
  padding-bottom: 0.14em;
  background-image: linear-gradient(var(--gold-light), var(--gold-light));
  background-repeat: no-repeat;
  background-position: 0 100%;
  background-size: calc(var(--mark) * 100%) 1px;
  -webkit-box-decoration-break: clone;
          box-decoration-break: clone;
}

@media (max-width: 860px) {
  .rules__set {
    grid-template-columns: 1fr;
    grid-template-rows: none;
    grid-auto-flow: row;
    row-gap: clamp(1.5rem, 1.25rem + 1.2vw, 2.25rem);
  }
  .rules__item:nth-child(3) { margin-top: 0; }
  .rules__text { max-width: 42rem; }
}
/* ==========================================================================
   CASE STUDIES — "cut four ways"   (results.html, section 02)

   History: an `.ed` split whose media half was a blank marble panel, then
   `.quest`, which set the four questions at increasing size so reading
   down them built to "What is the number?". The crescendo worked, but it
   was type alone and the client asked for a section that carries images
   and real motion.

   ONE PHOTOGRAPH, CUT INTO FOUR UNEVEN PANELS. Each panel carries one of
   the four questions. The panels are adjacent slices of the SAME picture:
   every `.cut__shot` is exactly stage-sized and anchored to the stage's
   bottom-left, so the streets and rooflines run straight through the cuts
   and the four read as one image rather than as four cards. That is the
   whole reason this can be four of something without looking like a grid
   of four of something.

   THE SLICES DRIFT AT DIFFERENT RATES AS YOU SCROLL, so the picture is
   only in register for a moment in the middle of the section and slightly
   torn either side of it. That is the section's argument made mechanical:
   four answers, and the story only holds when all four line up. Nothing
   else on this site misregisters an image, and it is legible here only
   because this particular photograph has long continuous lines crossing
   every cut.

   The panels are hand-set: four different widths, four different heights,
   four different text depths, and the entrance wipes each one in from a
   DIFFERENT edge. Nothing about the set is repeated four times.

   Base CSS is the finished state — panels unclipped, shots in register —
   so no-JS, reduced motion and a dead CDN all render a whole picture.
   ========================================================================== */

.cuts { position: relative; overflow-x: clip; }

.cuts__head {
  max-width: 44rem;
  margin-bottom: clamp(2.25rem, 1.85rem + 1.8vw, 3.25rem);
}
.cuts__lead {
  margin-top: clamp(0.85rem, 0.7rem + 0.55vw, 1.25rem);
  color: var(--vein);
  font-size: var(--text-lg);
  line-height: 1.7;
  max-width: 36rem;
  text-wrap: pretty;
}

/* ---- the stage ---------------------------------------------------------
   Percentages of the stage, hand-set. The 0.5 unit between each --x and
   the previous --x + --w is the cut itself. */
.cuts__stage {
  position: relative;
  list-style: none;
  width: 100%;
  aspect-ratio: 2.18;
}

.cut {
  position: absolute;
  bottom: 0;
  left: calc(var(--x) * 1%);
  width: calc(var(--w) * 1%);
  height: calc(var(--h) * 1%);
  overflow: hidden;
  border-radius: 2px;
  background: var(--obsidian);
  clip-path: inset(0 0 0 0);
  box-shadow: 0 1px 0 rgba(255, 255, 255, 0.03) inset;
}

/* THE CONTINUITY MATH, and it is the point of the section: the shot is
   sized to the stage (100/--w of the panel's width, 100/--h of its
   height) and pushed left by the panel's own offset, so all four shots
   land on the same stage coordinates. Change one --x or --w and the
   picture breaks. */
.cut__shot {
  position: absolute;
  bottom: 0;
  left: calc(-100% * var(--x) / var(--w));
  width: calc(100% * 100 / var(--w));
  height: calc(100% * 100 / var(--h));
  /* slack, so a drifting slice never exposes the edge of the picture.
     It must exceed the largest DRIFT amplitude in initCuts: 3.1% of the
     stage against 3.75% of headroom each side. Origin is bottom-centre,
     so every shot scales identically about the same baseline and they
     stay registered with each other. */
  transform: scale(1.105);
  transform-origin: 50% 100%;
}
.cut__shot img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: brightness(0.98) contrast(1.04) saturate(0.9);
  transition: filter 0.55s var(--ease-out);
}

/* legibility for the question sitting on the photograph */
.cut::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background: linear-gradient(180deg,
    rgba(6, 6, 10, 0.42) 0%,
    rgba(6, 6, 10, 0) 18%,
    rgba(6, 6, 10, 0) 42%,
    rgba(6, 6, 10, 0.5) 68%,
    rgba(6, 6, 10, 0.86) 88%,
    rgba(6, 6, 10, 0.95) 100%);
}

.cut__no {
  position: absolute;
  z-index: 2;
  top: clamp(0.7rem, 1.2vw, 1.3rem);
  left: clamp(0.75rem, 1.3vw, 1.45rem);
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.24em;
  color: var(--gold-light);
  text-shadow: 0 1px 8px rgba(0, 0, 0, 0.8);
}

.cut__body {
  position: absolute;
  z-index: 2;
  inset: auto 0 0 0;
  padding-inline: clamp(0.75rem, 1.3vw, 1.45rem);
  /* a different depth per panel, so the four questions never sit on one
     tidy baseline */
  padding-bottom: calc(var(--pb) * 1%);
}
.cut__part {
  display: block;
  margin-bottom: clamp(0.4rem, 0.35rem + 0.2vw, 0.6rem);
  font-size: 0.64rem;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--gold-light);
}
.cut__q {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(0.98rem, 0.83rem + 0.6vw, 1.34rem);
  line-height: 1.24;
  letter-spacing: -0.012em;
  color: var(--white);
  text-wrap: pretty;
}
.cut__q em { font-style: italic; color: var(--gold-light); }

/* hover lands on FILTER only. GSAP owns every transform in this section,
   and a CSS transition must never share a property with a tween. */
@media (hover: hover) and (pointer: fine) {
  .cut:hover .cut__shot img { filter: brightness(1.06) contrast(1.02) saturate(1); }
  .cuts__stage:has(.cut:hover) .cut:not(:hover) .cut__shot img {
    filter: brightness(0.58) contrast(1.05) saturate(0.7);
  }
}

/* ---- the close --------------------------------------------------------- */
.cuts__close {
  margin-top: clamp(1.8rem, 1.4rem + 1.6vw, 3rem);
  max-width: 44rem;
}
.cuts__line {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(1.2rem, 1rem + 0.9vw, 1.7rem);
  line-height: 1.3;
  letter-spacing: -0.015em;
  color: var(--ink);
  text-wrap: pretty;
}
.cuts__line em { font-style: italic; color: var(--gold-light); }
.cuts__status {
  margin-top: clamp(0.7rem, 0.6rem + 0.4vw, 1rem);
  font-size: var(--text-sm);
  letter-spacing: 0.02em;
  color: var(--vein);
}

/* ---- responsive --------------------------------------------------------
   Below the stage width a 21%-wide panel cannot hold a question, so the
   four become stacked bands. The continuity math is dropped and each band
   keeps its own region of the picture through object-position instead. */
@media (max-width: 900px) {
  .cuts__stage {
    aspect-ratio: auto;
    display: grid;
    gap: clamp(0.5rem, 2vw, 0.9rem);
  }
  .cut {
    position: relative;
    left: auto;
    bottom: auto;
    width: 100%;
    height: auto;
    aspect-ratio: 16 / 9.6;
  }
  .cut__shot {
    position: absolute;
    inset: 0;
    left: auto;
    bottom: auto;
    width: 100%;
    height: 100%;
    transform: none;
  }
  .cut__shot img { object-position: calc(var(--x) * 1.15%) 50%; }
  .cut__body { padding-bottom: clamp(0.9rem, 3vw, 1.4rem); }
  .cut__q { font-size: clamp(1.05rem, 0.9rem + 1.1vw, 1.3rem); }
}

@media (max-width: 520px) {
  .cut { aspect-ratio: 4 / 3; }
}

@media (prefers-reduced-motion: reduce) {
  .cut__shot img { transition: none; }
}

/* ==========================================================================
   PROOF OVER PROMISES — "the developing room"   (results.html, section 03)

   Was a small centred type block: one line, a phone number, an email, on
   an empty ground. It said the right thing and showed nothing, which on a
   page whose whole subject is evidence made it the lightest thing here.

   "Proof" is a photographic word before it is a sales one. A proof is the
   print you pull to CHECK something before you commit to it, and a
   darkroom is lit amber on black, which is this brand's palette arriving
   for a reason instead of as decoration. So the section is a darkroom and
   the prints come up out of the dark as you read down the page.

   THE VERB IS DEVELOPMENT, and that is what keeps this section its own.
   Everything else on this site moves a camera, an object, a rule or type;
   here the primary animated property is FILTER. Light and chemistry do
   the work, and nothing has to travel for the section to feel alive.

   THE THIRD PRINT NEVER FINISHES. That is deliberate: the case studies in
   section 02 publish shortly, and a print still coming up in the tray
   says so better than a status badge does.

   THE FILTER LANDS ON THE IMAGE ELEMENT, NEVER ON A WRAPPER. Paper, slip
   and caption sit outside it, so no copy is ever dimmed by the develop
   state (this site has hit the dim-a-wrapper contrast trap three times).

   The close stays CENTRED, and it is still the only centred block on
   results.html: the bench above argues from the left, then the page stops
   and offers a hand in the middle. Every base value is the FINISHED state
   (--dv initial-value 1), so no-JS, reduced motion and a dead CDN all
   render fully developed prints.
   ========================================================================== */

/* --dv is the develop state (0 latent, 1 fixed). --hov is a SEPARATE hover
   lift. Two registered numbers rather than one, for the same reason the
   doorways on what-we-do use two: GSAP writes --dv every frame of the
   scrub while CSS transitions --hov, so a hover can never fight a scrub,
   and no CSS transition is ever put on the filter itself. */
@property --dv { syntax: "<number>"; inherits: true; initial-value: 1; }
@property --hov { syntax: "<number>"; inherits: true; initial-value: 0; }

.latent {
  position: relative;
  overflow-x: clip;
  /* the lamp hangs at one place and the cone has to leave from it, so both
     are measured off the same two numbers */
  --lamp-x: clamp(1.5rem, 9vw, 9rem);
  --lamp-w: 3.6rem;
  --lamp-h: clamp(4.5rem, 8vw, 7.5rem);
  --cone-w: clamp(13rem, 26vw, 26rem);
}

/* ---- the safelight ------------------------------------------------------
   One warm source hanging at the top right. The cord and the dome are small
   crisp objects; the cone and the pools are what the bench is lit by. */
.lat__safelight {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background:
    radial-gradient(34% 30% at 82% 2%, rgba(206, 166, 104, 0.2), rgba(156, 120, 72, 0.06) 46%, transparent 72%),
    radial-gradient(88% 52% at 64% 30%, rgba(146, 108, 58, 0.1), transparent 72%),
    radial-gradient(66% 42% at 18% 82%, rgba(128, 96, 48, 0.085), transparent 74%);
}
/* the cone the lamp throws. blurred, because a light edge in a dark room
   is not a straight line */
.lat__safelight::after {
  content: "";
  position: absolute;
  top: calc(var(--lamp-h) - 0.5rem);
  right: calc(var(--lamp-x) + var(--lamp-w) / 2 - var(--cone-w) / 2);
  width: var(--cone-w);
  height: clamp(15rem, 30vw, 30rem);
  clip-path: polygon(44% 0%, 56% 0%, 100% 100%, 0% 100%);
  background: linear-gradient(180deg, rgba(214, 172, 108, 0.24), rgba(192, 156, 96, 0.06) 44%, transparent 78%);
  filter: blur(16px);
}

.lat__lamp {
  position: absolute;
  top: 0;
  right: var(--lamp-x);
  z-index: 1;
  width: var(--lamp-w);
  height: var(--lamp-h);
  pointer-events: none;
}
/* the cord */
.lat__lamp::before {
  content: "";
  position: absolute;
  top: 0;
  left: 50%;
  width: 1px;
  height: calc(100% - 1.15rem);
  background: linear-gradient(180deg, transparent, rgba(156, 120, 72, 0.55));
}
/* the dome, the filament line under its lip, and the spill */
.lat__lamp::after {
  content: "";
  position: absolute;
  left: 50%;
  bottom: 0;
  width: var(--lamp-w);
  height: 1.4rem;
  transform: translateX(-50%);
  border-radius: 100% 100% 4px 4px / 100% 100% 4px 4px;
  background: linear-gradient(178deg, #1d1912 0%, #0d0b09 100%);
  border: 1px solid rgba(156, 120, 72, 0.5);
  border-bottom: 0;
  box-shadow:
    0 2px 3px -1px rgba(238, 206, 150, 0.75),
    0 8px 22px -4px rgba(214, 172, 108, 0.5),
    0 28px 60px -8px rgba(192, 156, 96, 0.3),
    0 70px 130px -20px rgba(156, 120, 72, 0.26);
}

.latent__inner {
  position: relative;
  z-index: 2;
}

/* ---- the head ---------------------------------------------------------- */
.lat__head { max-width: 42rem; }
.lat__lead {
  margin-top: clamp(0.9rem, 0.75rem + 0.6vw, 1.4rem);
  max-width: 34rem;
  color: var(--vein);
  font-size: var(--text-lg);
  line-height: 1.7;
  text-wrap: pretty;
}

/* ---- the bench --------------------------------------------------------- */
.lat__bench {
  margin-top: clamp(2.2rem, 1.5rem + 2.6vw, 4.2rem);
  display: grid;
  grid-template-columns: minmax(0, 1.6fr) minmax(0, 0.85fr);
  gap: clamp(1.1rem, 0.7rem + 1.4vw, 2.4rem);
  align-items: start;
}
/* the right side is dropped, so the bench never squares up */
.lat__col--r { margin-top: clamp(1.2rem, 0.4rem + 2.6vw, 3.4rem); }

/* ---- a print ------------------------------------------------------------
   Warm paper with a wide bottom margin, the way a print is actually
   trimmed, and the slip printed on that margin. Sizes, aspects and angles
   are hand-set per print: no two are the same object. */
.lprint {
  position: relative;
  padding: clamp(0.45rem, 0.35rem + 0.4vw, 0.8rem);
  background: linear-gradient(176deg, rgba(26, 24, 28, 0.96), rgba(11, 11, 15, 0.98));
  border: 1px solid rgba(156, 120, 72, 0.16);
  border-radius: 3px;
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.035) inset,
    0 30px 60px -32px rgba(0, 0, 0, 0.92);
}
/* the paper's rim brightens as the print comes up */
.lprint::after {
  content: "";
  position: absolute;
  inset: -1px;
  border-radius: inherit;
  pointer-events: none;
  border: 1px solid rgba(192, 156, 96, calc(0.04 + var(--dv) * 0.24));
}

.lprint__win {
  position: relative;
  overflow: hidden;
  border-radius: 2px;
  isolation: isolate;
  background: var(--obsidian);
}

/* THE develop state. It lands here and only here. */
.lprint__img {
  position: absolute;
  inset: -6% 0 auto 0;
  width: 100%;
  height: 112%;
  object-fit: cover;
  /* An undeveloped print is FLAT AND WARM, not black: density and contrast
     are what the developer builds. Crushing it to black instead read as an
     empty screen, which is this client's standing complaint. So brightness,
     contrast and saturation all RISE together and the safelight's sepia
     cast clears as they do. */
  filter:
    brightness(calc(0.2 + var(--dv) * (0.77 + var(--hov) * 0.16)))
    contrast(calc(0.58 + var(--dv) * 0.48))
    saturate(calc(0.2 + var(--dv) * (0.7 + var(--hov) * 0.15)))
    sepia(calc((1 - var(--dv)) * 0.45));
}

/* film grain, moving. localised to the window, so it costs almost nothing */
.lprint__grain {
  position: absolute;
  inset: -30%;
  z-index: 2;
  pointer-events: none;
  opacity: calc(0.1 + var(--dv) * 0.14);
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  animation: lat-grain 760ms steps(3) infinite;
}
@keyframes lat-grain {
  0%   { transform: translate3d(0, 0, 0); }
  33%  { transform: translate3d(-2.2%, 1.6%, 0); }
  66%  { transform: translate3d(1.8%, -2.1%, 0); }
  100% { transform: translate3d(0, 0, 0); }
}

/* the wet sheen of a print still in the fixer */
.lprint__wet {
  position: absolute;
  inset: 0;
  z-index: 3;
  pointer-events: none;
  mix-blend-mode: screen;
  opacity: calc(0.2 + var(--dv) * 0.8);
  background: linear-gradient(108deg, transparent 36%, rgba(255, 244, 218, 0.085) 47%, rgba(255, 244, 218, 0.02) 54%, transparent 64%);
  background-size: 300% 100%;
  background-position: 150% 0;
}
/* a shallow bath edge, so the window reads as depth rather than a swatch */
.lprint__win::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 4;
  pointer-events: none;
  box-shadow:
    inset 0 0 0 1px rgba(0, 0, 0, 0.55),
    inset 0 -40px 60px -40px rgba(0, 0, 0, 0.8);
}

/* the loupe. JS enables it on fine pointers only. */
.lat__loupe {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 5;
  display: none;
  width: clamp(6.5rem, 10vw, 9.5rem);
  aspect-ratio: 1;
  border-radius: 50%;
  pointer-events: none;
  opacity: 0;
  -webkit-backdrop-filter: brightness(2.2) contrast(1.07) saturate(1.28);
  backdrop-filter: brightness(2.2) contrast(1.07) saturate(1.28);
  box-shadow:
    0 0 0 1px rgba(206, 168, 108, 0.62),
    0 0 0 6px rgba(6, 6, 8, 0.28),
    0 18px 40px -12px rgba(0, 0, 0, 0.7),
    inset 0 0 30px -6px rgba(0, 0, 0, 0.55);
}
.lprint.has-loupe .lat__loupe { display: block; }

/* ---- the slip printed on the bottom margin ----------------------------- */
.lprint__slip {
  display: flex;
  align-items: baseline;
  gap: clamp(0.6rem, 0.5rem + 0.4vw, 1rem);
  padding: clamp(0.6rem, 0.5rem + 0.35vw, 0.9rem) 0.15rem 0.1rem;
}
.lprint__code {
  flex: none;
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.26em;
  color: var(--gold);
  transform: translateY(-0.05em);
}
.lprint__cap {
  font-size: var(--text-sm);
  line-height: 1.5;
  color: var(--ink);
  text-wrap: pretty;
}
.lprint__cap--quiet { color: var(--vein); }

/* Hand-set geometry, and the three aspects are REAL FILM FORMATS rather
   than three arbitrary crops: 3:2 is 35mm, 5:4 is large format, 1:1 is
   6x6. That is what stops the set reading as one card at three sizes.
   Hover changes FILTER only, through --hov: GSAP owns every transform in
   this section, and the two must never share a property. */
.lprint--main { transform: rotate(-0.7deg); }
.lprint--main .lprint__win { aspect-ratio: 3 / 2; }
.lprint--main .lprint__cap { font-size: var(--text-base); }

.lprint--a {
  transform: rotate(1.2deg);
  margin-right: calc(-1 * clamp(0rem, 2.6vw, 3rem));
}
.lprint--a .lprint__win { aspect-ratio: 5 / 4; }

.lprint--b {
  transform: rotate(-1.5deg);
  width: min(100%, 21rem);
  margin-left: auto;
  margin-top: clamp(1.1rem, 0.8rem + 1.4vw, 2.4rem);
}
.lprint--b .lprint__win { aspect-ratio: 1 / 1; }

.lprint { transition: --hov 0.5s var(--ease-out), box-shadow 0.5s var(--ease-out); }
.lprint:hover,
.lprint:focus-within {
  --hov: 1;
  box-shadow: 0 1px 0 rgba(255, 255, 255, 0.05) inset, 0 34px 66px -30px rgba(0, 0, 0, 0.95);
}

/* ---- the note beside the bench ----------------------------------------- */
.lat__note {
  margin-top: clamp(1.5rem, 1.1rem + 1.4vw, 2.6rem);
  /* stepped in from the print above it, so the eye travels diagonally
     across the bench instead of down a column edge */
  margin-left: clamp(0rem, 5vw, 5.5rem);
  max-width: 30rem;
  padding-left: clamp(0.9rem, 0.7rem + 0.8vw, 1.5rem);
  border-left: 1px solid rgba(156, 120, 72, 0.4);
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(1.12rem, 0.98rem + 0.6vw, 1.45rem);
  line-height: 1.35;
  letter-spacing: -0.015em;
  color: var(--ink);
  text-wrap: pretty;
}
.lat__note em { font-style: italic; color: var(--gold-light); }

/* ---- the close ---------------------------------------------------------
   The page stops arguing. One short rule, the payoff line, and the number
   as the object of the section, lit from underneath. */
.lat__close {
  position: relative;
  z-index: 2;
  margin-top: clamp(2.4rem, 1.8rem + 2.2vw, 4rem);
  max-width: 46rem;
  margin-inline: auto;
  text-align: center;
}
.lat__pool {
  position: absolute;
  left: 50%;
  bottom: -18%;
  width: min(92vw, 54rem);
  height: 150%;
  z-index: -1;
  transform: translateX(-50%);
  pointer-events: none;
  background: radial-gradient(52% 58% at 50% 86%, rgba(156, 120, 72, 0.17), rgba(156, 120, 72, 0.05) 46%, transparent 74%);
}
.lat__rule {
  display: block;
  width: 4.5rem;
  height: 1px;
  margin: 0 auto clamp(1.4rem, 1.1rem + 1vw, 2.1rem);
  background: linear-gradient(90deg, transparent, rgba(156, 120, 72, 0.75), transparent);
}
.lat__line {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(1.35rem, 1.1rem + 1.2vw, 2rem);
  line-height: 1.2;
  letter-spacing: -0.018em;
  color: var(--ink);
}
.lat__line em { font-style: italic; color: var(--gold-light); }

.lat__act { margin-top: clamp(0.9rem, 0.7rem + 0.8vw, 1.5rem); }
.lat__alt { margin-top: clamp(0.8rem, 0.65rem + 0.55vw, 1.2rem); }

.lat__num {
  display: inline-flex;
  align-items: center;
  gap: clamp(0.6rem, 0.45rem + 0.6vw, 1rem);
  transition: filter 0.4s ease;
}
/* near-vertical ramp: a wide figure with "+" and brackets in it will drop a
   glyph into the dark stop of an angled gradient */
.lat__num-fig {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(1.8rem, 1.35rem + 2vw, 2.85rem);
  line-height: 1.1;
  letter-spacing: -0.02em;
  background: linear-gradient(179deg, rgba(250, 248, 244, 0.98), rgba(220, 186, 128, 0.96) 56%, rgba(180, 140, 84, 0.92));
  -webkit-background-clip: text;
          background-clip: text;
  color: transparent;
}
.lat__num svg {
  width: 0.55em;
  height: 0.55em;
  flex: none;
  color: var(--gold-light);
  opacity: 0;
  transform: translateX(-0.5em);
  transition: opacity 0.45s var(--ease-out), transform 0.45s var(--ease-out);
}
.lat__num:hover { filter: brightness(1.14); }
.lat__num:hover svg,
.lat__num:focus-visible svg { opacity: 1; transform: translateX(0); }

.lat__mail {
  font-size: var(--text-sm);
  letter-spacing: 0.06em;
  color: var(--vein);
  transition: color 0.4s ease;
}
.lat__mail:hover { color: var(--gold-light); }

/* ---- responsive --------------------------------------------------------
   Below the bench width the three prints go to one column, the drop and
   the bleed come off, and the loupe is dropped with the fine pointer. */
@media (max-width: 980px) {
  .lat__bench { grid-template-columns: minmax(0, 1fr); }
  .lat__col--r {
    margin-top: clamp(1rem, 2vw, 1.8rem);
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: clamp(1rem, 0.7rem + 1.2vw, 2rem);
    align-items: start;
  }
  .lprint--a { margin-right: 0; }
  .lprint--b {
    width: 100%;
    margin-left: 0;
    margin-top: clamp(1.6rem, 4vw, 3rem);
  }
  .lat__note { max-width: 34rem; margin-left: 0; }
}

@media (max-width: 620px) {
  .lat__col--r { grid-template-columns: minmax(0, 1fr); }
  .lprint--b { margin-top: clamp(1rem, 3vw, 1.6rem); }
  .lat__lamp { right: 0.75rem; width: 2.6rem; }
  .lat__lamp::after { width: 2.6rem; height: 1.05rem; }
  .lat__num-fig { font-size: clamp(1.5rem, 1.1rem + 2.8vw, 1.95rem); }
  .lat__mail { word-break: break-word; }
}

@media (prefers-reduced-motion: reduce) {
  .lprint__grain { animation: none; }
  .lat__loupe { display: none !important; }
  .lprint,
  .lat__num,
  .lat__num svg,
  .lat__mail { transition: none; }
  .lat__num svg { opacity: 1; transform: none; }
}

/* ==========================================================================
   TEAM HERO — "the lane"   (team.html)

   Was the shared `.hero--page`: eyebrow, headline, sub, a 5% mark
   watermark and a glow. `.hero--page` is untouched and still runs
   about / careers / contact / privacy / terms.

   THE CONSTRAINT SHAPED THE DESIGN. There is no photograph of Derrick and
   one must never be generated, and this page's own FAQ says it would
   rather show real people than stock headshots. So a team hero cannot be
   faces. What it can be is the STANDARD everyone on the floor is held to,
   and this firm's standard has a real source: the founder ran track, and
   section 01 says a stopwatch tells you the truth every single time.

   SO THE HERO IS A LANE. The photograph is the track at dawn, and gold
   hairlines continue its lane lines out of the picture and run underneath
   the type. Everyone gets a lane, everyone runs the same distance, and
   the clock does not care how you feel.

   THE STAGGER IS THE MOTION AND IT IS THE ARGUMENT. On a track the lanes
   start at different marks precisely so that every runner covers the same
   distance. Here each hairline enters from a different distance and they
   all land at the same instant, on the same duration. Different seats,
   one standard. The type keeps the site's own hero entrance (runIntro
   splits the h1 into masked lines), so the section has a unique
   composition and the shared signature, exactly like the what-we-do
   cover.

   THE LINES ARE NEVER DRAWN, they arrive. A 1px rule extending from one
   end belongs to `.cab` on what-we-do and a pen-like mark belongs to
   `.rules` on results; these are objects sliding into place out of the
   photograph, which is a different gesture and a different meaning.

   Entrance is CSS keyed off the preloader class, so the from-state only
   exists while the curtain is up and no-JS renders a finished hero.
   ========================================================================== */

/* proximity light. A registered number so the hairlines can be lit by the
   pointer without ever touching opacity, which the entrance owns. */
@property --lit { syntax: "<number>"; inherits: false; initial-value: 0; }

.hero--lane {
  min-height: min(88svh, 52rem);
  padding-top: clamp(3.77rem, 3.19rem + 1.508vw, 4.785rem);
  padding-bottom: clamp(2.5rem, 2rem + 2vw, 3.5rem);
  justify-content: stretch;
}

.lane__wash {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background:
    radial-gradient(38rem 26rem at 78% 34%, rgba(192, 156, 96, 0.14), transparent 66%),
    radial-gradient(44rem 24rem at 0% 96%, rgba(156, 120, 72, 0.07), transparent 62%);
}

/* ---- the lanes ---------------------------------------------------------
   FULL-BLEED, hung off the section and never off the .container: an
   overlay that starts at the container edge leaves a hard seam down the
   side of the screen (learned the hard way on the homepage wall).

   Uneven spacing on purpose. Real lanes are parallel and equal; seen from
   a low angle they open up as they come toward you, and that is what
   makes five hairlines read as a receding surface rather than as a
   ruled list. */
.lane__rules {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  overflow: hidden;
}
.lane__rule {
  position: absolute;
  left: 0;
  /* stop dead at the container's right edge, which is where the plate's
     right edge is. Running on to the viewport edge left a stray stub past
     the photograph and killed the read that the lines come OUT of it. */
  right: max(var(--gutter), calc((100% - var(--container) - 2 * var(--gutter)) / 2 + var(--gutter)));
  height: 1px;
  /* brightest at the right, where the photograph is: the lines read as
     the track's own, continuing out of the picture and dissolving as
     they run away from it */
  background: linear-gradient(90deg,
    transparent 0%,
    rgba(156, 120, 72, calc(0.06 + var(--lit) * 0.12)) 10%,
    rgba(176, 138, 84, calc(0.36 + var(--lit) * 0.34)) 40%,
    /* full brightness lands just before the plate covers the rest */
    rgba(226, 190, 126, calc(0.86 + var(--lit) * 0.14)) 64%,
    rgba(226, 190, 126, calc(0.9 + var(--lit) * 0.1)) 100%);
  box-shadow: 0 0 calc(6px + var(--lit) * 12px) rgba(192, 156, 96, calc(0.1 + var(--lit) * 0.45));
  transition: --lit 0.3s linear;
}
/* gaps 11.5, 13.5, 16.5, 24.5 - the ramp is the perspective */
.lane__rule--1 { top: 30%; }
.lane__rule--2 { top: 41.5%; }
.lane__rule--3 { top: 55%; }
.lane__rule--4 { top: 71.5%; }
.lane__rule--5 { top: 89.5%; }

.lane__inner {
  position: relative;
  z-index: 2;
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
}
.lane__body {
  display: grid;
  grid-template-columns: minmax(0, 1.06fr) minmax(0, 0.94fr);
  gap: clamp(1.62rem, 1.008rem + 2.592vw, 3.6rem);
  align-items: center;
}

.lane__claim { max-width: 34rem; }
.lane h1 {
  font-size: clamp(2.1rem, 1.55rem + 2.3vw, 3.25rem);
  line-height: 1.08;
  letter-spacing: -0.026em;
  margin-bottom: clamp(1.1rem, 0.9rem + 0.8vw, 1.6rem);
}
.lane h1 em { font-style: italic; color: var(--gold-light); }
.lane .hero__sub { max-width: 32rem; margin-bottom: 0; }

/* the page's position on headshots, said in the hero instead of buried in
   an accordion at the bottom */
.lane__note {
  margin-top: clamp(1.2rem, 0.95rem + 1vw, 1.9rem);
  padding-left: clamp(0.9rem, 0.7rem + 0.8vw, 1.4rem);
  border-left: 1px solid rgba(156, 120, 72, 0.4);
  max-width: 27rem;
  font-size: var(--text-sm);
  line-height: 1.6;
  color: var(--ink);
  text-wrap: pretty;
}

/* ---- the photograph ---------------------------------------------------
   The plate is opaque and sits ABOVE the hairlines, so the lines run
   under it and come out the other side. That occlusion is what makes the
   picture read as lying on the track rather than as a panel beside it. */
.lane__plate {
  position: relative;
  z-index: 1;
  width: min(100%, 30rem);
  margin-left: auto;
  aspect-ratio: 4 / 5;
  overflow: hidden;
  border-radius: 3px;
  background: var(--obsidian);
  border: 1px solid rgba(156, 120, 72, 0.22);
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.03) inset,
    0 38px 76px -34px rgba(0, 0, 0, 0.94);
}
.lane__shot {
  position: absolute;
  inset: -4% 0 -4% 0;
  width: 100%;
  height: 108%;
}
.lane__shot img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 40%;
  filter: saturate(0.86) contrast(1.05) brightness(0.94);
}
/* the same corner the rest of the page is lit from, plus a floor vignette
   so the plate sits into the dark instead of on top of it */
.lane__plate::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    radial-gradient(90% 60% at 62% 30%, rgba(192, 156, 96, 0.08), transparent 64%),
    linear-gradient(180deg, rgba(6, 6, 10, 0.3) 0%, transparent 22%, transparent 62%, rgba(6, 6, 10, 0.62) 100%);
}

/* the tell. It names what the hairlines are doing and it is true of both
   the track and the floor. */
.lane__tell {
  position: relative;
  z-index: 2;
  display: block;
  margin-top: clamp(1rem, 0.8rem + 0.7vw, 1.5rem);
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--gold);
}

/* ---- entrance ----------------------------------------------------------
   THE STAGGER: five different distances, ONE duration, no delays, so they
   set off from different marks and land together. That is what a stagger
   is for. */
.lane__rule,
.lane__plate,
.lane__note,
.lane__tell {
  transition: opacity 1.15s var(--ease-out), transform 1.15s var(--ease-out);
}
.lane__rule { transition: opacity 1.15s var(--ease-out), transform 1.15s var(--ease-out), --lit 0.3s linear; }
.lane__plate { transition-delay: 0.2s; }
.lane__note { transition-delay: 0.62s; }
.lane__tell { transition-delay: 0.74s; }

.is-loading .lane__rule { opacity: 0; }
.is-loading .lane__rule--1 { transform: translateX(150px); }
.is-loading .lane__rule--2 { transform: translateX(255px); }
.is-loading .lane__rule--3 { transform: translateX(120px); }
.is-loading .lane__rule--4 { transform: translateX(330px); }
.is-loading .lane__rule--5 { transform: translateX(200px); }
.is-loading .lane__plate { opacity: 0; transform: translateY(28px) scale(0.985); }
.is-loading .lane__note { opacity: 0; transform: translateY(16px); }
.is-loading .lane__tell { opacity: 0; transform: translateY(12px); }

@media (max-width: 980px) {
  .hero--lane { min-height: 0; }
  .lane__body {
    grid-template-columns: minmax(0, 1fr);
    gap: clamp(2.25rem, 1.75rem + 2.5vw, 3.25rem);
  }
  .lane__claim { max-width: 42rem; }
  .lane .hero__sub,
  .lane__note { max-width: 42rem; }
  .lane__plate { margin-left: 0; width: 100%; aspect-ratio: 5 / 4; }
  /* the hairlines cross the type once the columns stack, so they step
     back to a texture rather than a structure */
  .lane__rule { opacity: 0.32; }
  .is-loading .lane__rule { opacity: 0; }
}

@media (max-width: 560px) {
  .lane__plate { aspect-ratio: 1 / 1; }
  .lane__rule--5 { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .lane__rule,
  .lane__plate,
  .lane__note,
  .lane__tell { transition: none; }
}

/* ==========================================================================
   THE INSTRUMENT — team.html, Leadership (section 01)
   Replaces the .ed split (marble panel + copy column). .ed stays: about,
   careers and results still use it.

   THE GRAMMAR IS TIME. Every other section on this site moves because the
   reader scrolls. This one runs on real wall-clock time and keeps running
   when nobody is looking, which is the copy's argument made mechanical.
   The hand is driven from main.js so it survives a dead CDN; GSAP adds
   only the circling light, the plate drift and the pointer specular.

   Ticks are DASHED SVG CIRCLES, not sixty elements and not a
   conic-gradient: one node per ring, crisp at any size, and the dash
   period is literally the division count (60 minor, 12 major, 12 on the
   totalizer). A conic-gradient would have needed mask-composite to be cut
   into a ring, and where that is unsupported the fallback is a filled
   disc rather than nothing.
   ========================================================================== */

/* ALL THREE ARE inherits: false, AND THAT MATTERS BEYOND THIS PAGE. A
   registered custom property declared `inherits: true` is computed on every
   element in every document that loads this stylesheet, so a convenience
   here would have put a style-recalc cost on all nine pages. The specular
   pair is therefore set on .clk__glass itself rather than inherited down
   from .clk__inst. */
@property --clkp-y { syntax: "<number>"; initial-value: 0; inherits: false; }
@property --clk-gl { syntax: "<number>"; initial-value: 34; inherits: false; }
@property --clk-gly { syntax: "<number>"; initial-value: 20; inherits: false; }

.clk {
  position: relative;
  /* the case bleeds left of its column and the outer orbit runs past the
     stage; the section clips itself so neither can reach the page */
  overflow-x: clip;
}

.clk__amb,
.clk__vein {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
}

/* one warm pool, sitting under the instrument rather than centred on the
   section, so the light has a source */
.clk__amb {
  background: radial-gradient(42% 48% at 61% 54%, rgba(156, 120, 72, 0.13), transparent 64%);
  animation: clk-breathe 11s ease-in-out infinite;
}

.clk__vein {
  opacity: 0.5;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='760' height='620'%3E%3Cdefs%3E%3Cfilter id='v'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.009' numOctaves='4' seed='23' result='n'/%3E%3CfeDisplacementMap in='SourceGraphic' in2='n' scale='70'/%3E%3C/filter%3E%3C/defs%3E%3Cg filter='url(%23v)' fill='none' stroke='%239c7848'%3E%3Cpath d='M-40 520 C 120 430 210 470 330 340 S 470 190 520 130' stroke-width='1' opacity='0.16'/%3E%3Cpath d='M-30 210 C 110 250 200 180 320 240' stroke-width='0.7' opacity='0.11'/%3E%3C/g%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: left 12% top 30%;
}

@keyframes clk-breathe {
  0%, 100% { opacity: 0.78; }
  50%      { opacity: 1; }
}

.clk__grid {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: minmax(0, 0.86fr) minmax(0, 1.14fr);
  gap: clamp(1.92rem, 1.024rem + 2.816vw, 3.84rem);
  align-items: center;
}

/* ---- the type ---------------------------------------------------------- */

.clk__h {
  margin-top: clamp(1rem, 0.85rem + 0.6vw, 1.5rem);
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(2.05rem, 1.5rem + 2.4vw, 3.15rem);
  line-height: 1.06;
  letter-spacing: -0.015em;
  color: var(--ink);
}
.clk__h em { font-style: italic; color: var(--gold-light); }

.clk__lede {
  margin-top: clamp(1.1rem, 0.9rem + 0.9vw, 1.65rem);
  max-width: 32rem;
  color: var(--ink);
  font-size: var(--text-lg);
  line-height: 1.7;
}

.clk__body {
  margin-top: 0.95rem;
  max-width: 32rem;
  color: var(--vein);
  line-height: 1.75;
}

.clk__sign { margin-top: clamp(1.75rem, 1.4rem + 1.4vw, 2.6rem); }
.clk__sign-rule {
  display: block;
  width: 3.6rem;
  height: 1px;
  background: linear-gradient(90deg, var(--gold-light), transparent);
}
.clk__name {
  margin-top: 0.9rem;
  font-family: var(--font-display);
  font-size: clamp(1.35rem, 1.2rem + 0.6vw, 1.7rem);
  line-height: 1.1;
  color: var(--ink);
}
.clk__role {
  margin-top: 0.35rem;
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--gold);
}

.clk__act { margin-top: var(--space-4-5); }

/* ---- the stage --------------------------------------------------------- */

.clk__stage {
  position: relative;
  aspect-ratio: 1 / 0.9;
}

/* ---- the photographic plates -------------------------------------------
   Parallax is written to --clkp-y, never to `transform`, so the hand-set
   rotation can live in CSS on the same element without GSAP wiping it.
   Nothing here transitions transform. */
.clkp {
  position: absolute;
  margin: 0;
}
.clkp--main {
  top: 2%;
  right: 0;
  width: 74%;
  aspect-ratio: 3 / 2;
  transform: translateY(calc(var(--clkp-y) * 1px)) rotate(-0.7deg);
  z-index: 1;
}
.clkp--sub {
  bottom: 2%;
  right: 6%;
  width: 46%;
  aspect-ratio: 16 / 10;
  transform: translateY(calc(var(--clkp-y) * 1px)) rotate(1.1deg);
  z-index: 2;
}

.clkp__win {
  position: absolute;
  inset: 0;
  overflow: hidden;
  border-radius: var(--radius-sm);
  box-shadow:
    0 0 0 1px rgba(156, 120, 72, 0.22),
    0 34px 64px -32px rgba(0, 0, 0, 0.92);
  transition: filter 0.5s var(--ease-out), box-shadow 0.5s var(--ease-out);
}
.clkp__win img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: brightness(0.74) contrast(1.05) saturate(0.84);
}
.clkp__win::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    linear-gradient(180deg, transparent 44%, rgba(6, 6, 8, 0.78) 100%),
    radial-gradient(120% 90% at 18% 0%, rgba(156, 120, 72, 0.12), transparent 56%);
}

@media (hover: hover) {
  .clkp:hover .clkp__win {
    filter: brightness(1.14);
    box-shadow:
      0 0 0 1px rgba(192, 156, 96, 0.44),
      0 34px 64px -32px rgba(0, 0, 0, 0.92);
  }
}

.clkp__cap {
  position: absolute;
  left: 1.05rem;
  bottom: 0.85rem;
  z-index: 2;
  display: flex;
  align-items: center;
  gap: 0.55rem;
  font-size: 0.62rem;
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--ink);
  text-shadow: 0 1px 10px rgba(0, 0, 0, 0.95);
}
.clkp__cap::before {
  content: "";
  width: 1.1rem;
  height: 1px;
  background: var(--gold-light);
}
/* the case stands over this plate's bottom-left corner, so its caption
   goes to the far side rather than being read through a watch */
.clkp--main .clkp__cap {
  left: auto;
  right: 1.05rem;
  flex-direction: row-reverse;
}

/* ---- the chronograph ---------------------------------------------------- */

.clk__inst {
  position: absolute;
  left: -4%;
  bottom: 18%;
  width: 50%;
  aspect-ratio: 1;
  z-index: 3;
  transform: translateY(calc(var(--clkp-y) * 1px));
}

.clk__orbit {
  position: absolute;
  left: 50%;
  top: 50%;
  aspect-ratio: 1;
  border-radius: 50%;
  transform: translate(-50%, -50%);
  pointer-events: none;
}
.clk__orbit--far {
  width: 172%;
  border: 1px solid rgba(156, 120, 72, 0.09);
}
.clk__orbit--near {
  width: 126%;
  border: 1px dashed rgba(156, 120, 72, 0.2);
  animation: clk-orbit 96s linear infinite;
}
@keyframes clk-orbit {
  from { transform: translate(-50%, -50%) rotate(0deg); }
  to   { transform: translate(-50%, -50%) rotate(360deg); }
}

/* the case: brushed obsidian, a gold gradient ring cut by an excluded
   padding mask (the gradient-ring device), and real chronograph anatomy on the
   right flank so it reads as a made object rather than a widget */
.clk__case {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background:
    radial-gradient(120% 100% at 30% 6%, rgba(156, 120, 72, 0.17), transparent 56%),
    repeating-conic-gradient(from 0deg, rgba(255, 255, 255, 0.022) 0 1.1deg, rgba(0, 0, 0, 0) 1.1deg 2.6deg),
    radial-gradient(closest-side, #17161c 0%, var(--surface) 64%, var(--obsidian-raised) 100%);
  box-shadow:
    0 46px 80px -34px rgba(0, 0, 0, 0.9),
    0 0 90px -30px rgba(156, 120, 72, 0.35),
    inset 0 1px 0 rgba(255, 255, 255, 0.05);
}
.clk__case::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  padding: 1px;
  background: conic-gradient(from 200deg,
    rgba(192, 156, 96, 0.16),
    rgba(214, 182, 126, 0.92) 24%,
    rgba(128, 96, 48, 0.24) 52%,
    rgba(214, 182, 126, 0.72) 78%,
    rgba(192, 156, 96, 0.16));
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
          mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
          mask-composite: exclude;
  pointer-events: none;
}

/* crown and two pushers: centred, rotated about the case, then pushed out
   along their own local axis, so the radius is one number per part */
.clk__crown,
.clk__push {
  position: absolute;
  left: 50%;
  top: 50%;
  background: linear-gradient(90deg, #3c3126, #b9975d 42%, #6d5530 100%);
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.35);
  border-radius: 1px 2px 2px 1px;
}
.clk__crown {
  width: 7.5%;
  height: 5.5%;
  transform: translate(-50%, -50%) rotate(90deg) translateY(-954%);
}
.clk__push { width: 6%; height: 4%; }
.clk__push--a { transform: translate(-50%, -50%) rotate(60deg) translateY(-1300%); }
.clk__push--b { transform: translate(-50%, -50%) rotate(120deg) translateY(-1300%); }

.clk__face {
  position: absolute;
  inset: 7.5%;
  border-radius: 50%;
  overflow: hidden;
  background: radial-gradient(closest-side, var(--surface) 0%, var(--obsidian-raised) 72%, var(--obsidian) 100%);
  box-shadow:
    inset 0 0 44px rgba(0, 0, 0, 0.95),
    inset 0 0 0 1px rgba(156, 120, 72, 0.13);
}

.clk__eng {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}
.clk__num text {
  font-family: var(--font-display);
  font-size: 11px;
  fill: rgba(232, 232, 230, 0.8);
  text-anchor: middle;
  dominant-baseline: middle;
}
.clk__mark {
  font-family: var(--font-sans);
  font-size: 6.2px;
  font-weight: 600;
  letter-spacing: 2.6px;
  fill: rgba(192, 156, 96, 0.9);
  text-anchor: middle;
}
.clk__sub text {
  font-family: var(--font-sans);
  font-size: 5.2px;
  letter-spacing: 1.1px;
  fill: rgba(160, 160, 158, 0.75);
  text-anchor: middle;
}

/* the light that runs the chapter ring. ADDITIVE ONLY: opacity 0 at rest,
   so with GSAP absent the dial is simply a finished dial. One mask layer,
   no compositing, so it cannot degrade into a filled disc. */
.clk__run {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  opacity: 0;
  /* a comet, not a block: a short ramp into the head and a long tail out
     of it, or the leading edge reads as a chunk of gold sitting on the
     ticks rather than as light passing over them */
  background: conic-gradient(from -90deg,
    rgba(230, 203, 150, 0) 0deg,
    rgba(230, 203, 150, 0.72) 11deg,
    rgba(230, 203, 150, 0) 82deg);
  mix-blend-mode: screen;
  -webkit-mask-image: radial-gradient(closest-side, transparent 0 82%, #000 84% 95%, transparent 97%);
          mask-image: radial-gradient(closest-side, transparent 0 82%, #000 84% 95%, transparent 97%);
  pointer-events: none;
}

/* hands. JS writes only --sec / --lap; CSS owns the composition, so a
   tween and a transition never share a property. */
.clk__sweep {
  position: absolute;
  inset: 0;
  transform: rotate(calc(var(--sec, 0) * 1deg));
}
.clk__sweep i {
  position: absolute;
  left: 50%;
  top: 9%;
  bottom: 44%;
  width: 1.6px;
  margin-left: -0.8px;
  border-radius: 1px;
  /* the tail must NOT fall to --gold-shadow: at 1.6px wide that segment
     disappears against the face and the counterweight reads as a loose
     dot floating beside the pin */
  background: linear-gradient(180deg, #e6cb96 0%, var(--gold-light) 56%, var(--gold) 100%);
  box-shadow: 0 0 14px rgba(192, 156, 96, 0.5);
}
.clk__sweep i::after {
  content: "";
  position: absolute;
  left: 50%;
  bottom: 0;
  width: 5px;
  height: 5px;
  margin: 0 0 -2.5px -2.5px;
  border-radius: 50%;
  background: var(--gold-light);
}

.clk__lap {
  position: absolute;
  left: 50%;
  top: 68%;
  width: 22%;
  aspect-ratio: 1;
  transform: translate(-50%, -50%) rotate(calc(var(--lap, 0) * 1deg));
}
.clk__lap i {
  position: absolute;
  left: 50%;
  top: 12%;
  bottom: 50%;
  width: 1.2px;
  margin-left: -0.6px;
  background: linear-gradient(180deg, var(--gold-light), var(--gold-shadow));
}

.clk__pin {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 4.6%;
  aspect-ratio: 1;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: radial-gradient(circle at 36% 30%, #e2c894, #6d5228 62%, #241b12);
  box-shadow: 0 0 12px rgba(0, 0, 0, 0.8);
}

.clk__beat {
  position: absolute;
  left: 50%;
  top: 22%;
  width: 2.4%;
  aspect-ratio: 1;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: var(--gold-light);
  animation: clk-beat 1s infinite;
}
@keyframes clk-beat {
  0%, 46%   { opacity: 0.95; box-shadow: 0 0 10px rgba(192, 156, 96, 0.7); }
  47%, 100% { opacity: 0.16; box-shadow: none; }
}

/* the crystal. --clk-gl / --clk-gly are registered numbers GSAP writes on
   pointer move; the fixed diagonal band underneath means it is lit with
   no JS at all. */
.clk__glass {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  pointer-events: none;
  /* the specular is a plain property write from motion.js, NOT a tween, so
     a CSS transition here is safe. --clkp-y IS tweened and must never get
     one. */
  transition: --clk-gl 0.45s linear, --clk-gly 0.45s linear;
  background:
    radial-gradient(58% 52% at calc(var(--clk-gl) * 1%) calc(var(--clk-gly) * 1%),
      rgba(255, 255, 255, 0.11), rgba(255, 255, 255, 0.02) 46%, transparent 72%),
    linear-gradient(146deg, rgba(255, 255, 255, 0.06) 0 20%, transparent 33% 100%);
}

/* ---- the tell ---------------------------------------------------------- */

.clk__tell {
  position: relative;
  z-index: 1;
  margin-top: clamp(2.25rem, 1.6rem + 2.4vw, 3.5rem);
  display: flex;
  align-items: center;
  gap: 0.95rem;
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--vein);
}
.clk__tell::before {
  content: "";
  flex: 0 0 clamp(2rem, 6vw, 5rem);
  height: 1px;
  background: linear-gradient(90deg, transparent, var(--border-gold-strong));
}
.clk__elapsed {
  font-family: var(--font-display);
  font-size: 0.95rem;
  letter-spacing: 0.1em;
  font-variant-numeric: tabular-nums;
  color: var(--gold-light);
}

/* ---- narrower ----------------------------------------------------------- */

@media (max-width: 1080px) {
  .clk__grid {
    grid-template-columns: minmax(0, 1fr);
    gap: clamp(2.5rem, 2rem + 3vw, 3.75rem);
  }
  .clk__stage {
    aspect-ratio: 1 / 0.76;
    width: 100%;
    max-width: 46rem;
  }
  .clk__lede,
  .clk__body { max-width: 42rem; }
  .clk__inst { width: 44%; bottom: 14%; }
}

@media (max-width: 640px) {
  .clk__stage { aspect-ratio: 1 / 0.94; }
  .clkp--main { width: 84%; }
  .clkp--sub { width: 54%; right: 0; }
  /* -4%, not more: a circle sliced flat by the screen edge reads as a
     clipping bug rather than as a bleed */
  .clk__inst { width: 54%; left: -4%; bottom: 11%; }
  .clk__orbit--far { display: none; }
  .clk__tell { font-size: 0.64rem; gap: 0.7rem; }
  /* the plate is only ~300px wide here and the case stands under its
     bottom-left, so the caption has to shorten to clear it */
  .clkp__cap { font-size: 0.55rem; letter-spacing: 0.16em; }
  .clkp--main .clkp__cap::before { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .clk__amb,
  .clk__orbit--near,
  .clk__beat { animation: none; }
  .clkp__win { transition: none; }
  /* the hand is set once to the real time and then left alone, so a
     running counter beside it would be describing motion that is not
     happening */
  .clk__elapsed { display: none; }
}

/* ==========================================================================
   HOW THE TEAM IS BUILT — "one field"   (team.html, section 02)

   History: a 2x2 grid of four identical `.card card--tick` boxes -> `.seat`,
   one dominant seat panel with three supports converging on it -> this. The
   argument is unchanged and must stay: four equal boxes say four equal
   things, while the copy says the whole company exists to make one of them
   win. What changed is that the seat had become one very large, very dark
   rectangle with three ragged plates beside it.

   THE HEADLINE IS THE COMPOSITION. "Four functions. One field." is one
   rectangle, divided. Four photographs tile a single window with nothing
   between them but a gold hairline, so the four really are ONE FIELD rather
   than four cards on a page.

   AND THE LEAD IS THE MOTION. "Three of them exist so the fourth can win"
   is not stated and then illustrated, it happens: the whole division comes
   off ONE number, `--g`, and as you read, the main seam TRAVELS. The four
   begin as near-equal shares of the field and end with field sales holding
   most of it. The three do not shrink away, they give up ground. Nothing
   else on this site redivides a surface; 01 turns on its own clock, 03
   holds still, 04 spreads a pile of prints.

   THE WORDS DO NOT MOVE WITH THE PICTURES, and that is what makes the whole
   thing affordable: each note is anchored to its own pane's leading edge
   and carries its own scrim, so the field is redrawn UNDER the reading
   instead of reflowing it. No note ever has to be re-measured, and no note
   can lose its legibility to whichever photograph has arrived beneath it.

   NO TWO PANES ARE THE SAME SHAPE (a near-square, a wide strip, a small
   block, a tall slot) and no two notes are built the same way - 01 has an
   engraved mark in the opposite corner, 02 hangs its figure in the margin,
   03 sets its figure under a hairline at the foot, 04 has its numeral
   struck across the bottom of the pane. That is the lesson the previous
   version was rebuilt on: unequal sizing does not break a repeated
   component, a different internal structure does.

   `--g` and `--fl` are UNREGISTERED: GSAP writes them every frame so
   nothing needs interpolating, and a registered INHERITED property costs a
   recalc on all nine pages that load this file. Both rest at their finished
   value, so no JS, a dead CDN and reduced motion all render the field
   already argued and fully lit.
   ========================================================================== */

.fld { position: relative; overflow-x: clip; }

.fld__head {
  max-width: 46rem;
  margin-bottom: clamp(2.2rem, 1.7rem + 2.2vw, 3.6rem);
}
.fld__h {
  margin: 0.55rem 0 0;
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(1.75rem, 1.35rem + 1.7vw, 2.6rem);
  line-height: 1.12;
  letter-spacing: -0.02em;
  color: var(--white);
}
.fld__h em { font-style: italic; color: var(--gold-light); }
.fld__lead {
  margin: clamp(0.85rem, 0.7rem + 0.55vw, 1.25rem) 0 0;
  max-width: 34rem;
  color: var(--ink);
  font-size: var(--text-lg);
  line-height: 1.62;
}

/* ---- the field. One number divides it. `--v` is the main seam, and every
   pane edge is derived from it, so the whole redivision is a single scrub.
   `container-type` is here so the notes can size themselves in cqw - a
   width bound to the FIELD rather than to the pane it sits on is what stops
   the copy reflowing while the seam travels. ---- */
.fld__field {
  --g: 1;                                   /* 0 four near-equal shares, 1 the argued division */
  --v: calc(46 + 12 * var(--g));            /* the main vertical seam, % of width */
  --r: calc(100 - var(--v));                /* everything right of it */
  --fmx: 50;
  --fmy: 50;
  position: relative;
  container-type: inline-size;
  aspect-ratio: 1 / var(--ffh, 0.68);
}

/* the wrapper generates no box: a pane and its note are one function but
   they sit at two unrelated places in the composition */
.fld__unit { display: contents; }

/* ---- the four panes. Each one tiles a share of the field exactly, so the
   only thing between two photographs is their two hairlines. ---- */
.fld__pane {
  --fl: 1;      /* the light this pane has taken. GSAP owns it, and only it. */
  --fdy: 0;     /* the drift of the picture behind the aperture, px */
  position: absolute;
  margin: 0;
  overflow: hidden;
  background: var(--obsidian-raised);
  isolation: isolate;
}
.fld__pane--1 { left: 0; top: 0; width: calc(var(--v) * 1%); height: 100%; }
.fld__pane--2 { left: calc(var(--v) * 1%); top: 0; width: calc(var(--r) * 1%); height: 34%; }
.fld__pane--3 { left: calc(var(--v) * 1%); top: 34%; width: calc(var(--r) * 0.52%); height: 48%; }
.fld__pane--4 {
  left: calc((var(--v) + var(--r) * 0.52) * 1%);
  top: 34%;
  width: calc(var(--r) * 0.48%);
  height: 66%;
}

/* the hairline. It brightens as the pane takes its light, so the seams of
   the field come up with the photographs rather than being drawn on. */
.fld__pane::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 3;
  pointer-events: none;
  box-shadow:
    inset 0 0 0 1px rgba(192, 156, 96, calc(0.12 + 0.26 * var(--fl))),
    inset 0 1px 0 0 rgba(226, 196, 140, calc(0.06 + 0.2 * var(--fl)));
}

.fld__shot { position: absolute; inset: 0; overflow: hidden; }
.fld__shot img {
  position: absolute;
  inset: -6%;
  width: 112%;
  height: 112%;
  /* main.css carries a global img { max-width: 100% } which silently clamps
     any deliberately oversized image and shows as a strip of the frame's
     own background down one edge */
  max-width: none;
  display: block;
  object-fit: cover;
  /* NO transition on filter: it is computed from --fl, which GSAP writes
     every frame, and a transition would smear the whole scrub. Hover is
     handled by the two overlay layers below instead. */
  filter:
    brightness(calc(0.54 + 0.46 * var(--fl)))
    contrast(calc(0.94 + 0.08 * var(--fl)))
    saturate(calc(0.82 + 0.2 * var(--fl)));
  transform: translate3d(0, calc(var(--fdy) * 1px), 0);
}
/* the subject of each frame sits in a different place, and every pane
   re-crops as the seam travels, so each one is anchored by hand */
.fld__pane--1 .fld__shot img { object-position: 52% 38%; }
.fld__pane--2 .fld__shot img { object-position: 50% 48%; }
.fld__pane--3 .fld__shot img { object-position: 56% 44%; }
/* the client's room runs cooler than the other three; matching the exposure
   matters more than the geometry when photographs are shown side by side */
.fld__pane--4 .fld__shot img { object-position: 50% 64%; filter: brightness(calc(0.62 + 0.5 * var(--fl))) contrast(calc(0.9 + 0.08 * var(--fl))) saturate(calc(0.9 + 0.26 * var(--fl))) hue-rotate(-6deg); }

/* hover: a warm bloom on the pane under the pointer, and a veil on the
   others. Both are OVERLAY OPACITIES rather than filters, precisely so
   nothing GSAP drives ever carries a CSS transition. */
.fld__glow {
  position: absolute;
  inset: 0;
  z-index: 2;
  opacity: 0;
  pointer-events: none;
  mix-blend-mode: screen;
  transition: opacity 0.5s var(--ease-out);
  background:
    radial-gradient(46% 42% at calc(var(--fmx) * 1%) calc(var(--fmy) * 1%), rgba(255, 240, 212, 0.2), transparent 70%),
    linear-gradient(180deg, rgba(192, 156, 96, 0.07), transparent 60%);
}
.fld__veil {
  position: absolute;
  inset: 0;
  z-index: 2;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.5s var(--ease-out);
  background: rgba(6, 6, 8, 0.6);
}

/* the engraved marks. 01 sits in the corner of its pane opposite its own
   words; 04 is struck across the foot of its pane. */
.fld__mark {
  position: absolute;
  right: clamp(0.9rem, 2vw, 1.9rem);
  top: clamp(0.4rem, 1.4vw, 1.1rem);
  z-index: 2;
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(2.6rem, 1.7rem + 2.8vw, 4.2rem);
  line-height: 0.9;
  letter-spacing: -0.03em;
  background: linear-gradient(166deg, rgba(246, 242, 234, 0.9), rgba(198, 160, 102, 0.8) 44%, rgba(128, 96, 56, 0.48));
  -webkit-background-clip: text;
          background-clip: text;
  color: transparent;
  /* one shadow on the figure guarantees it separates from any tone in the
     photograph it crosses without retuning a single colour */
  filter: drop-shadow(0 2px 6px rgba(0, 0, 0, 0.85));
  pointer-events: none;
}
.fld__mark--foot {
  top: auto;
  right: auto;
  left: clamp(0.7rem, 1.6vw, 1.3rem);
  bottom: clamp(0.15rem, 0.6vw, 0.6rem);
  font-size: clamp(2.4rem, 1.5rem + 2.6vw, 3.8rem);
}

/* ---- the notes. Each one tracks the leading edge of its own pane, so the
   words travel with the seam, but every WIDTH is in cqw (a percentage of
   the FIELD, not of the pane) so no line ever rewraps while it moves. ---- */
.fld__note {
  position: absolute;
  z-index: 4;
  isolation: isolate;   /* keeps the scrim pseudo out of the panes' business */
}
/* every note carries its own scrim, so legibility can never depend on which
   photograph happens to be underneath it at a given point in the scrub */
.fld__note::before {
  content: "";
  position: absolute;
  inset: -1.1rem -1.7rem -1.3rem -1.3rem;
  z-index: -1;
  pointer-events: none;
  background:
    linear-gradient(180deg, rgba(6, 6, 8, 0) 0%, rgba(6, 6, 8, 0.74) 14%, rgba(6, 6, 8, 0.74) 84%, rgba(6, 6, 8, 0) 100%),
    radial-gradient(96% 84% at 24% 50%, rgba(6, 6, 8, 0.7), rgba(6, 6, 8, 0) 76%);
}
.fld__note--4::before {
  inset: -2.6rem -2.2rem -3rem -1.6rem;
  background:
    radial-gradient(64% 52% at 42% 50%, rgba(6, 6, 8, 0.9), rgba(6, 6, 8, 0.66) 58%, rgba(6, 6, 8, 0) 88%),
    radial-gradient(90% 74% at 40% 50%, rgba(6, 6, 8, 0.52), rgba(6, 6, 8, 0) 82%);
}

.fld__note--1 { left: 3.6%; top: 66%; width: 30cqw; }
.fld__note--2 { left: calc((var(--v) + 3.6) * 1%); top: 6%; width: 31cqw; }
.fld__note--3 { left: calc((var(--v) + 2.6) * 1%); top: 38%; width: 16cqw; }
.fld__note--4 {
  left: calc((var(--v) + var(--r) * 0.52 + 1.9) * 1%);
  top: 44%;
  width: 15cqw;
}

.fld__kicker {
  margin: 0 0 0.5rem;
  font-family: var(--font-sans);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--gold-light);
}
.fld__name {
  margin: 0 0 0.65rem;
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(1.15rem, 0.95rem + 0.7vw, 1.5rem);
  line-height: 1.16;
  letter-spacing: -0.012em;
  color: var(--white);
}
.fld__note--1 .fld__name { font-size: clamp(1.4rem, 1.1rem + 1.1vw, 2rem); }
.fld__copy {
  margin: 0;
  color: var(--vein);
  font-size: var(--text-sm);
  line-height: 1.68;
}
.fld__note--1 .fld__copy { color: var(--ink); font-size: var(--text-base); }

/* 02 hangs its figure in the margin */
.fld__fig {
  position: absolute;
  left: -2.5rem;
  top: -0.15rem;
  margin: 0;
  font-family: var(--font-display);
  font-size: 1.05rem;
  letter-spacing: 0.08em;
  color: var(--gold-shadow);
}
/* 03 sets its figure under a hairline at the foot */
.fld__foot {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  margin: clamp(0.9rem, 0.75rem + 0.5vw, 1.3rem) 0 0;
  font-family: var(--font-display);
  font-size: 1.05rem;
  letter-spacing: 0.08em;
  color: var(--gold-shadow);
}
.fld__rule { flex: 1; height: 1px; background: linear-gradient(90deg, rgba(156, 120, 72, 0.45), rgba(156, 120, 72, 0.08)); }

/* the verdict sits in the notch the three leave when the field is redivided */
.fld__verdict {
  position: absolute;
  left: calc((var(--v) + 2.6) * 1%);
  top: 84%;
  width: 19cqw;
  z-index: 4;
  margin: 0;
  font-family: var(--font-display);
  font-weight: 500;
  font-style: italic;
  font-size: clamp(1.1rem, 0.88rem + 0.78vw, 1.55rem);
  line-height: 1.28;
  letter-spacing: -0.01em;
  color: var(--gold-light);
}

@media (hover: hover) and (pointer: fine) {
  /* the CSS-only fallback: with no JS the pane under the pointer still
     lights. The class pair below is what couples a note to its own pane. */
  .fld__pane:hover .fld__glow { opacity: 1; }
  .fld__field:has(.fld__pane:hover) .fld__pane:not(:hover) .fld__veil { opacity: 1; }

  .fld__unit.is-lit .fld__glow { opacity: 1; }
  .fld__field.is-hot .fld__unit:not(.is-lit) .fld__veil { opacity: 1; }
}

/* ---- the type wraps to more lines as the measure narrows, so the field
   gets taller in steps rather than in one jump ---- */
@media (max-width: 1360px) { .fld__field { --ffh: 0.7; } }
@media (max-width: 1200px) { .fld__field { --ffh: 0.78; } }
@media (max-width: 1080px) { .fld__field { --ffh: 0.88; } }

/* ---- 900 and below the division cannot hold: four tiled photographs plus
   their words need the horizontal room the seam travels in. The field
   becomes a run of four bands, each keeping the PROPORTION of its own pane
   so the set still reads as four different shapes, with the words under
   each. Every absolute value the composition set has to be reset here. ---- */
@media (max-width: 900px) {
  .fld__field {
    --ffh: auto;
    aspect-ratio: auto;
    container-type: normal;
    display: grid;
    gap: clamp(1.9rem, 1.2rem + 2.6vw, 3rem);
  }
  .fld__pane,
  .fld__note,
  .fld__verdict {
    position: relative;
    left: auto;
    top: auto;
    width: auto;
    height: auto;
  }
  .fld__pane { aspect-ratio: 16 / 10; width: min(100%, 30rem); }
  .fld__pane--2 { aspect-ratio: 2 / 1; width: min(88%, 27rem); margin-left: auto; }
  .fld__pane--3 { aspect-ratio: 5 / 4; width: min(74%, 21rem); }
  .fld__pane--4 { aspect-ratio: 3 / 4; width: min(64%, 19rem); margin-left: auto; }
  .fld__note { max-width: 32rem; }
  .fld__note--2,
  .fld__note--4 { margin-left: auto; }
  .fld__note::before { inset: -0.9rem -1.2rem; background: none; }
  .fld__fig { position: relative; left: auto; top: auto; margin-bottom: 0.4rem; }
  .fld__verdict {
    max-width: 26rem;
    font-size: clamp(1.2rem, 1rem + 1.1vw, 1.65rem);
    margin-top: clamp(0.2rem, 1.5vw, 0.9rem);
  }
  .fld__mark { font-size: clamp(2.4rem, 1.6rem + 3.4vw, 3.4rem); }
}

/* ---- 641 to 900: the field pairs off. Each photograph shares a row with
   its words and the pair swaps sides down the set, so the tablet range
   stays a composition instead of becoming a column of capped photographs
   with half the measure empty beside each one - which is also what keeps
   this section's height in step with the ones around it here. Rows are
   explicit because auto-placement will not put a note back into column 1
   after its picture has taken column 2. ---- */
@media (min-width: 641px) and (max-width: 900px) {
  .fld__field {
    grid-template-columns: minmax(0, 1.04fr) minmax(0, 0.96fr);
    column-gap: clamp(1.4rem, 2.6vw, 2.4rem);
    align-items: center;
  }
  .fld__pane,
  .fld__note { width: auto; max-width: none; margin: 0; }
  .fld__pane { aspect-ratio: 4 / 3; }
  .fld__pane--2 { aspect-ratio: 16 / 10; }
  .fld__pane--3 { aspect-ratio: 5 / 4; }
  .fld__pane--4 { aspect-ratio: 5 / 6; }

  .fld__unit:nth-child(1) .fld__pane { grid-area: 1 / 1; }
  .fld__unit:nth-child(1) .fld__note { grid-area: 1 / 2; }
  .fld__unit:nth-child(2) .fld__pane { grid-area: 2 / 2; }
  .fld__unit:nth-child(2) .fld__note { grid-area: 2 / 1; }
  .fld__unit:nth-child(3) .fld__pane { grid-area: 3 / 1; }
  .fld__unit:nth-child(3) .fld__note { grid-area: 3 / 2; }
  .fld__unit:nth-child(4) .fld__pane { grid-area: 4 / 2; }
  .fld__unit:nth-child(4) .fld__note { grid-area: 4 / 1; }
  .fld__verdict { grid-area: 5 / 1 / 6 / -1; max-width: 30rem; }
}

@media (prefers-reduced-motion: reduce) {
  .fld__glow,
  .fld__veil { transition: none; }
}

/* ==========================================================================
   WHO WE HIRE — "out of turn"   (team.html, section 03)

   History: an `.ed--flip` split (copy beside a blank marble panel, because
   its image used data-src) -> "THE LINE", a queue of 18 identical marks
   with one gap in it, which the client rejected as meaningless and they
   were right -> a plain two-column split, copy left and one photograph
   right -> this. FOURTH version. If it is rejected too, ASK what
   specifically is wanted before building a fifth.

   WHAT WAS WRONG WITH THE SPLIT: it is the shape every site uses, and it
   left a 550x200 hole between the headline and the lede and another under
   it, while the room photograph sat so far down in the grade that it read
   as a smudge rather than a picture.

   THE HEADLINE IS THE MOTION. "Done waiting their turn" is not stated and
   then illustrated, it happens. The tower you are told to wait inside
   RECEDES - it shrinks, cools, dims and goes soft - while the doorstep
   ADVANCES, growing and warming until it crosses in front of the tower.
   ONE number, `--m`, drives every value in both, and the overtake IS the
   argument. Nothing else on this page moves that way: 01 turns on its own
   clock, 02 redivides a field, 04 spreads a pile of prints.

   THE WORDS DO NOT MOVE WITH THE PICTURES. Every block is fixed and
   carries its own scrim, so the frames travel underneath the reading
   rather than reflowing it. And the negations are set at display size
   ACROSS the picture on purpose - the fault the split had was a column of
   type beside an image, and the only way to not have that is for the type
   to cross the image.

   `--m` is UNREGISTERED: GSAP writes it every frame so nothing needs
   interpolating, and a registered INHERITED property costs a recalc on all
   nine pages that load this file. Its CSS value is 1, THE FINISHED STATE,
   so no JS, a dead CDN and reduced motion all render the overtake already
   made, both photographs in place and every word readable.
   ========================================================================== */

.otn { position: relative; overflow-x: clip; }

.otn__stage {
  --m: 1;             /* 0 the tower still holds the frame, 1 the doorstep has taken it */
  --oh: 0.60;
  position: relative;
  aspect-ratio: 1 / var(--oh);
}

/* ---- the two frames. Every value is interpolated in CSS from the single
   number, so a tween and a static geometry can never fight over one
   property, and there is no wrapper element for either of them. ---- */
.otn__frame {
  position: absolute;
  margin: 0;
  left: calc((var(--x0) + (var(--x1) - var(--x0)) * var(--m)) * 1%);
  top: calc((var(--y0) + (var(--y1) - var(--y0)) * var(--m)) * 1%);
  width: calc((var(--w0) + (var(--w1) - var(--w0)) * var(--m)) * 1%);
  aspect-ratio: var(--ar);
}

/* the tower: bigger, higher and warmer at the start, and it gives all of
   that up. The blur is the whole reason it reads as receding rather than
   merely shrinking. */
.otn__frame--wait {
  --x0: 42; --x1: 44;
  --y0: 0;  --y1: 4;
  --w0: 28; --w1: 22;
  --ar: 3 / 4;
  z-index: 2;
}
.otn__frame--wait .otn__shot img {
  object-position: 50% 42%;
  filter:
    brightness(calc(0.98 - 0.26 * var(--m)))
    saturate(calc(1 - 0.4 * var(--m)))
    contrast(calc(1 - 0.04 * var(--m)))
    hue-rotate(calc(var(--m) * -10deg))
    blur(calc(var(--m) * 1.9px));
}
.otn__frame--wait .otn__shot { box-shadow: inset 0 0 0 1px rgba(156, 120, 72, calc(0.3 - 0.18 * var(--m))); }

/* the doorstep: small, low and unlit at the start, and it ends in front */
.otn__frame--move {
  --x0: 76; --x1: 62;
  --y0: 40; --y1: 14;
  --w0: 18; --w1: 34;
  --ar: 5 / 6;
  z-index: 3;
}
