/* ============================================================================
   96K AUTO CARE — sections.css
   The light website: everything after the walkthrough.

   Rule for this file: bright, airy, editorial. No card grids, no boxed
   services, no black-on-black stacking. Colour arrives as hairlines and a
   single burnished accent; the heavy lifting is done by type scale, negative
   space and deliberate asymmetry.
   ========================================================================= */

/* ==================================================== THE SECTION SYSTEM ==
   Everything below the hero belongs to one of four ZONES, and a zone is a run
   of sections sharing a ground:

       light   About · Services
       dark    Principles · Stats
       light   Experience · Testimonials
       dark    CTA · Footer

   That grouping is the point. The page previously alternated light and dark
   eight times, and eight flips is what made it read as a stack of unrelated
   rectangles rather than one document — however good each rectangle was.
   Four zones means three boundaries, and three is few enough to make each one
   an event.

   Sections inside a zone sit closer together (--zone-inner) than the distance
   across a boundary, so the eye groups them before it is told to.          */

.section {
  position: relative;
  padding-block: var(--section-y-lg);
  background: var(--color-bg);
}
.section--alt { background: var(--color-bg-alt); }

/* Rhythm. A section picks one of these and never writes its own padding. */
.section.section--md { padding-block: var(--section-y-md); }
.section.section--sm { padding-block: var(--section-y-sm); }

/* Continuing a zone rather than opening one: tighten the seam between them. */
.section.zone-mid { padding-top: var(--zone-inner); }
.section.zone-end { padding-bottom: var(--section-y-lg); }

/* ---- the three transitions ----------------------------------------------
   A zone does not begin at a straight edge; it RISES into the one above it on
   a single shallow arc, spanning the full width. Two 50% horizontal corner
   radii meet at the centre, so it is one continuous curve rather than two
   rounded corners — a panel line, not a bubble. The vertical radius is small
   against that width, which is what keeps it aerodynamic instead of playful.

   The rising section is pulled up by exactly its arc height and given that
   height back as a TRANSPARENT TOP BORDER — not as padding. Padding would
   have to name a value, and every section already varies its own padding by
   viewport height; overriding it here left one section with a 125px top and
   a 41px bottom on a short laptop. A border adds height without touching the
   padding at all, the background still paints beneath it (border-box), and
   border-radius is measured on the border box, so the arc is unaffected.   */
.section.zone-open {
  --zone-arc-h: clamp(26px, 3.4vw, 58px);
  border-radius: 50% 50% 0 0 / var(--zone-arc-h) var(--zone-arc-h) 0 0;
  border-top: var(--zone-arc-h) solid transparent;
  margin-top: calc(var(--zone-arc-h) * -1);
  z-index: 2;
  /* The arc clips the background, so anything decorative inside has to be
     clipped with it or it will hang over the curve. */
  overflow: hidden;
  isolation: isolate;
}

/* A hairline riding the arc — the only thing that makes the curve readable
   where the two grounds are close in value. Absolute insets resolve against
   the padding box, so it is lifted back onto the border box by the arc
   height to sit on the curve itself. */
.section.zone-open::before {
  content: "";
  position: absolute;
  top: calc(var(--zone-arc-h) * -1);
  left: 0;
  right: 0;
  height: var(--zone-arc-h);
  border-radius: inherit;
  border-top: 1px solid var(--zone-arc-line, rgba(255, 255, 255, 0.09));
  pointer-events: none;
  z-index: 3;
}
.section.zone-open--light { --zone-arc-line: rgba(13, 13, 15, 0.07); }

/* ---- the ribbon ---------------------------------------------------------
   One recurring object, three appearances. A long aerodynamic sweep — read it
   as a paint reflection, a PPF edge or a body contour depending on where it
   sits — drawn as two paths: a smoked band and a specular edge along its top.
   No colour of its own: it takes `color` from the zone and is drawn in the
   same ink as everything else.

   It is deliberately the only decorative motif on the page. The brief for the
   reference this came from is that its restraint is what reads as premium,
   and one object repeated is restraint; five different objects is not.     */
/* NO will-change here, deliberately. It reads as a free hint and is not: each
   one pins the element to its own compositor layer for the lifetime of the
   page, and the page had 31 of them — six card photographs, three
   full-width ribbons and four hero blocks among them. Layers that large cost
   memory continuously and cost the compositor on every single frame, whether
   or not anything is animating. The browser promotes what it needs on its
   own once a transform actually starts. */
.ribbon {
  position: absolute;
  /* base.css caps every svg at max-width:100%; this one is deliberately
     wider than its section so the sweep runs past both edges. */
  max-width: none;
  aspect-ratio: 1600 / 620;
  pointer-events: none;
  z-index: 0;
  width: min(160%, 2200px);
  height: auto;
  opacity: 0;                       /* revealed by the entrance             */
}
.ribbon__band { fill: currentColor; opacity: 0.055; }
.ribbon__edge { fill: none; stroke: currentColor; stroke-width: 1.1; opacity: 0.17; }

.ribbon--onDark { color: var(--color-secondary); }
.ribbon--onLight { color: var(--color-heading); }
.ribbon--onLight .ribbon__band { opacity: 0.038; }
.ribbon--onLight .ribbon__edge { opacity: 0.1; }

/* Placements. Each one starts inside a section and runs toward the next, so
   the boundary is crossed by something rather than merely abutted. */
.ribbon--a { left: -22%; bottom: -34%; transform: rotate(-4deg); }

@media (max-width: 900px) {
  /* Mobile keeps the zones and the arcs — they are structure — but drops the
     ribbon. On a narrow column it is clutter behind text, not depth. */
  .ribbon { display: none; }
  .section.zone-open { --zone-arc-h: clamp(18px, 5vw, 30px); }
}

@media (prefers-reduced-motion: reduce) {
  .ribbon { opacity: 0.55; transform: none !important; }
}

/* A whisper of brand tint, used where a section would otherwise read flat. */
.section--tint {
  background:
    radial-gradient(74% 52% at 84% 0%, var(--color-wash), transparent 62%),
    var(--color-bg);
}

.s-head {
  display: grid;
  gap: clamp(1rem, 2.2vw, 1.8rem);
  margin-bottom: clamp(2.5rem, 6vw, 5.5rem);
}
.s-title {
  font-size: var(--fs-h2);
  letter-spacing: -0.038em;
  text-transform: uppercase;
  max-width: 18ch;
}
.s-title em { font-style: normal; color: var(--color-muted); }

/* Shared caption used under every media block. */
.cap {
  display: flex;
  align-items: baseline;
  gap: 0.9em;
  margin-top: var(--s2);
  font-family: var(--font-mono);
  font-size: clamp(0.6rem, 0.72vw, 0.7rem);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--color-muted);
}
.cap b { font-weight: 500; color: var(--color-accent); }

/* ============================================================== 01 ABOUT == */
/* A two-column split on warm off-white. Everything reads down the left; one
   detailing image holds the right, with the badge floating off its
   lower edge. No stats, no cards, no dark panel. */

.about {
  padding-block: var(--section-y-lg);
  background: var(--color-bg-soft);
}

/* 46 / 54. The copy column takes the top of the range deliberately: at 1920+
   the container is capped at its max width, and at 44% the column is ~4px
   narrower than "Automotive care," needs at the heading's own maximum size —
   the line would wrap to a third line. 46% clears it. */
.about__grid {
  display: grid;
  grid-template-columns: minmax(0, 46fr) minmax(0, 54fr);
  /* 40-60px across the desktop range. The two columns should read as one
     composition; the old 86-112px opened a corridor between them. */
  column-gap: clamp(2rem, 3.4vw, 3.75rem);
  align-items: center;
}

/* ---- left: the whole story ---------------------------------------------- */
.about__copy {
  display: grid;
  justify-items: start;
  align-content: center;
  gap: clamp(1.5rem, 2.2vw, 1.15rem);
}

/* Each line is its own mask so the two can rise in sequence. The padding /
   negative-margin pair keeps the comma and any descender from being clipped
   by the mask's own overflow. */
/* .about__heading { margin-top: clamp(0.2rem, 0.9vw, 0.8rem); } */
.about__ln {
  display: block;
  overflow: hidden;
  padding-bottom: 0.14em;
  margin-bottom: -0.14em;
}
.about__ln > i { display: block; font-style: normal; }

.about__body { max-width: 500px; }

.about__copy .section-emphasis { margin-top: clamp(0.2rem, 0.8vw, 0.65rem); }

/* ---- right: the square ---------------------------------------------------- */
.about__media {
  position: relative;
  margin: 0;
  isolation: isolate;
}

.about__frame {
  position: relative;
  /* A controlled height, not a square. aspect-ratio tied the frame to the
     column width, so at 54% it stood ~200px taller than the copy beside it.
     Driven by width rather than height: the copy beside it barely changes
     with viewport height, so a vh-based frame drifted 100px+ taller at 1080.
     This holds a steady 35-40px overhang, which centring splits evenly. */
  height: clamp(520px, 30vw, 560px);
  overflow: hidden;
  border-radius: var(--r-lg);
  background: var(--color-dark);
  /* A hairline rather than a frame — it should read as an edge, not a border. */
  box-shadow: inset 0 0 0 1px var(--color-onDark-rule);
}

/* Fills the frame. The fixed 500px height here left 154px of bare frame
   background showing beneath the photograph. */
.about__frame img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* The frame is now wider than the source is proportionally tall, so cover
     crops a little off the top and bottom rather than the sides — the hand
     and towel sit centrally and stay whole. */
  object-position: 50% 50%;
}

/* ---- the floating badge -------------------------------------------------- */
/* Sits inside the image horizontally and overhangs it at the bottom, exactly
   as the reference sets it. */
.about__badge {
  position: absolute;
  right: 5%;
  bottom: -4.5%;
  z-index: 2;
  width: clamp(168px, 13.5vw, 205px);
  aspect-ratio: 1 / 1;
  display: grid;
  align-content: center;
  justify-items: center;
  gap: 0.34rem;
  padding: clamp(0.9rem, 1.5vw, 1.35rem);
  text-align: center;
  background: var(--color-dark-soft);
  border: var(--rule-onDark);
  border-radius: var(--r-md);
  box-shadow: 0 26px 50px -22px rgba(9, 9, 9, 0.6);
}

.about__badge svg {
  width: clamp(34px, 2.9vw, 44px);
  height: auto;
  margin-bottom: clamp(0.5rem, 1vw, 0.85rem);
  color: var(--color-onDark);
}

.about__badge b {
  font-size: clamp(0.66rem, 0.78vw, 0.76rem);
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--color-secondary);
}

.about__badge span {
  font-size: clamp(0.62rem, 0.72vw, 0.7rem);
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--color-onDark-soft);
}

.about__badge::after {
  content: "";
  width: 34px;
  height: 1px;
  margin-top: clamp(0.45rem, 0.9vw, 0.75rem);
  background: var(--color-onDark-rule);
  opacity: 1;
}

/* ---- stacked ------------------------------------------------------------- */
/* The image follows the copy, which is already the source order. */
@media (max-width: 900px) {
  .about__grid {
    grid-template-columns: 1fr;
    row-gap: clamp(2.4rem, 8vw, 3.6rem);
  }
  .about__copy { justify-items: start; }
  /* The body keeps its measure when stacked — a single column on a tablet is
     wide enough to run the line length past comfortable reading otherwise. */
  /* Capped at the source width so the photo is never scaled up past 1:1. */
  .about__media { max-width: 620px; width: 100%; }
  /* Back to the square. The desktop height exists only to match the column
     beside it; stacked there is nothing to match, and 520px against a 350px
     phone column turned the photo into a 2:3 portrait. */
  .about__frame { height: auto; aspect-ratio: 1 / 1; }
  .about__badge {
    width: clamp(140px, 34vw, 178px);
    right: 4%;
    bottom: -3.5%;
  }
}

@media (max-width: 420px) {
  .about__frame { border-radius: var(--r-lg); }
  .about__badge {
    width: 138px;
    right: 3.5%;
    bottom: -3%;
    gap: 0.28rem;
    padding: 0.85rem;
  }
  .about__badge svg { width: 30px; margin-bottom: 0.45rem; }
  .about__badge b { font-size: 0.62rem; letter-spacing: 0.12em; }
  .about__badge span { font-size: 0.58rem; letter-spacing: 0.12em; }
  .about__badge::after { width: 26px; }
}

/* =========================================================== 02 SERVICES == */
/* Six image cards, three across. Content sits on the photograph rather than
   beside it, so the picture carries the section and the type is the overlay
   — which is the whole reason this replaced a list-plus-one-image selector.

   Everything dimensional here is done with layers and light, not tilt. A card
   that rotates on hover announces itself as a widget; a card whose image
   drifts inside a fixed frame while the frame lifts a few pixels reads as
   depth and is much harder to notice doing it. There is a perspective on the
   grid and the lift uses translateZ, so the response is genuinely spatial —
   just at an amplitude that never becomes the point. */

.services {
  padding-block: var(--section-y-lg);
  background: var(--color-bg);
  /* The ribbon is deliberately wider than the section AND has to stay able to
     spill downward, so it slides under the dark panel that rises next — that
     overlap is the point of it. Only the horizontal overflow is cut; a plain
     overflow:hidden would clip both axes and take the spill with it. */
  overflow-x: clip;
  overflow-y: visible;
}

/* ---- the introduction ---------------------------------------------------
   Global classes only — .section-kicker, .section-heading, and one lede that
   matches About's measure. No section-specific heading styles. */
.svc__lead {
  max-width: 62ch;
  margin-bottom: clamp(2.4rem, 4.4vw, 4rem);
}
.svc__heading { margin-top: clamp(0.9rem, 1.6vw, 1.4rem); }
.svc__ln { display: block; overflow: hidden; }
.svc__ln > i { display: block; font-style: normal; }

.svc__lede {
  max-width: 62ch;
  margin-top: clamp(1rem, 1.8vw, 1.5rem);
  font-size: var(--fs-lead);
  line-height: 1.55;
  color: var(--color-text);
  text-wrap: pretty;
}

/* ---- the grid -----------------------------------------------------------
   Three across on desktop, and the perspective lives HERE rather than on each
   card: one shared vanishing point means the six cards read as a single plane
   being lit, instead of six independent objects each with their own camera. */
.svc__cards {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(1rem, 1.6vw, 1.6rem);
  perspective: 1400px;
  perspective-origin: 50% 40%;
}

/* Every card is the same shape, and the variation is in the FRAMING rather
   than the height. Varying the heights was the first attempt: a grid row is
   as tall as its tallest cell, so the shorter cards ended up with 52px of
   empty card below the photograph. Ragged bottoms would have fixed that and
   cost the clean grid.

   So the six differ by where each photograph is cropped instead — the centre
   column sits higher in frame, the last column lower. Same rectangle, six
   different compositions inside it, and the alignment is untouched. */
.svcard {
  position: relative;
  aspect-ratio: 4 / 5;
}
.svcard:nth-child(3n + 2) .svcard__img { object-position: 50% 34%; }
.svcard:nth-child(3n + 3) .svcard__img { object-position: 50% 62%; }

.svcard__link {
  /* Written by the pointer handler; 0 at rest, so with JS off or on a touch
     screen the card is simply flat. */
  --tx: 0deg;
  --ty: 0deg;
  --mx: 50%;
  --my: 50%;
  position: relative;
  display: block;
  height: 100%;
  border-radius: var(--r-lg);
  overflow: hidden;
  isolation: isolate;
  transform-style: preserve-3d;
  transform: translateZ(0);
  box-shadow:
    0 1px 2px rgba(13, 13, 15, 0.05),
    0 12px 26px -18px rgba(13, 13, 15, 0.4);
  transition:
    transform 0.42s var(--ease-out),
    box-shadow 0.62s var(--ease-out);
}

/* ---- the photograph ------------------------------------------------------
   Held slightly oversize and centred, so the parallax drift and the hover
   scale both have somewhere to move without ever exposing an edge. */
.svcard__media {
  display: block;
  position: relative;
  width: 100%;
  height: 100%;
  overflow: hidden;
  background: var(--color-dark-soft);
}
.svcard__img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transform: scale(1.06);
  transform-origin: 50% 45%;
  transition: transform 0.9s var(--ease-out);
}

/* ---- the scrim -----------------------------------------------------------
   Only where the type sits. It reaches ~58% up the card and is already fully
   transparent by half height, so the photograph is never flattened — the
   brief was a gradient behind the TEXT, not a darkened image. The second
   layer is a barely-there top vignette that keeps the number legible on the
   few frames that are bright at the top. */
.svcard__scrim {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    linear-gradient(to top,
      rgba(6, 6, 7, 0.94) 0%,
      rgba(6, 6, 7, 0.82) 18%,
      rgba(6, 6, 7, 0.3) 40%,
      rgba(6, 6, 7, 0) 60%),
    linear-gradient(to bottom, rgba(6, 6, 7, 0.3) 0%, rgba(6, 6, 7, 0) 26%);
  transition: opacity 0.62s var(--ease-out);
}

/* The sheen. A soft highlight that tracks the pointer across the card, which
   is what a curved painted panel does under a moving light — it is the one
   effect here that is specifically automotive rather than generically 3D.
   Very low opacity and screen-blended, so it lightens without tinting. */
.svcard__sheen {
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0;
  /* Plain alpha, not mix-blend-mode: screen. Blending forces the card to be
     composited against whatever is behind it, which disables the fast path
     for the whole stacking context; at these opacities white-over-photograph
     looks the same either way. */
  background: radial-gradient(38% 46% at var(--mx) var(--my),
    rgba(255, 255, 255, 0.22), rgba(255, 255, 255, 0.05) 45%, transparent 72%);
  transition: opacity 0.5s var(--ease-out);
}

/* A hairline inside the radius. It is what stops a pale image bleeding into
   the section ground, and it is the same rule token as everywhere else. */
.svcard__link::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  box-shadow: inset 0 0 0 1px rgba(243, 241, 237, 0.14);
  pointer-events: none;
}

/* ---- the copy ------------------------------------------------------------ */
.svcard__body {
  position: absolute;
  inset: auto 0 0 0;
  display: grid;
  gap: 0.5rem;
  padding: clamp(1.2rem, 1.7vw, 1.7rem);
  /* Lifted off the image plane so the hover translateZ separates type from
     photograph rather than moving the two together. */
  transform: translateZ(28px);
}

.svcard__num {
  font-size: var(--fs-label);
  font-weight: 500;
  letter-spacing: 0.24em;
  color: rgba(243, 241, 237, 0.6);
  transition: color 0.4s var(--ease-out);
}

.svcard__title {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(1.05rem, 1.35vw, 1.32rem);
  line-height: 1.16;
  letter-spacing: -0.022em;
  color: var(--color-secondary);
  text-wrap: balance;
}

.svcard__desc {
  max-width: 34ch;
  font-size: clamp(0.85rem, 0.92vw, 0.95rem);
  line-height: 1.5;
  color: rgba(243, 241, 237, 0.88);
  /* 0.84, not the 0.72 this started at. Averaged over each photograph the
     lighter value tested at 8:1, but a specular highlight under the copy —
     chrome, a work lamp, a wet panel — took the worst pixels to 2.2:1. The
     mean is not the number that matters when the background is a picture. */
}

.svcard__more {
  display: inline-flex;
  align-items: center;
  gap: 0.6em;
  margin-top: 0.35rem;
  font-size: var(--fs-label);
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(243, 241, 237, 0.82);
  transition: color 0.4s var(--ease-out);
}
.svcard__arrow {
  width: 22px;
  height: 11px;
  transition: transform 0.5s var(--ease-out);
}

/* ---- hover, on a fine pointer only --------------------------------------
   Five things move and none of them by much: the card lifts, the image grows
   2%, the scrim thins, the copy strengthens and the arrow steps 5px. The
   whole tile is the link, so this is decoration on top of an affordance that
   already works — nothing here carries information. */
@media (hover: hover) and (pointer: fine) {
  .svcard__link:hover,
  .svcard__link:focus-visible {
    transform: translate3d(0, -6px, 22px) rotateX(var(--tx)) rotateY(var(--ty));
    box-shadow:
      0 2px 4px rgba(13, 13, 15, 0.06),
      0 26px 46px -22px rgba(13, 13, 15, 0.5);
  }
  .svcard__link:hover .svcard__img,
  .svcard__link:focus-visible .svcard__img { transform: scale(1.085); }

  .svcard__link:hover .svcard__scrim,
  .svcard__link:focus-visible .svcard__scrim { opacity: 0.9; }

  .svcard__link:hover .svcard__sheen { opacity: 1; }

  .svcard__link:hover .svcard__num,
  .svcard__link:focus-visible .svcard__num { color: rgba(243, 241, 237, 0.78); }

  .svcard__link:hover .svcard__more,
  .svcard__link:focus-visible .svcard__more { color: var(--color-secondary); }

  .svcard__link:hover .svcard__arrow,
  .svcard__link:focus-visible .svcard__arrow { transform: translateX(5px); }
}

.svcard__link:focus-visible { outline: 2px solid var(--color-secondary); outline-offset: 3px; }

/* ---- tablet: two across -------------------------------------------------- */
@media (max-width: 1100px) {
  .svc__cards { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  /* The tall card was the middle of a row of three; in a row of two that
     rhythm no longer exists, so every card returns to one aspect. */
  .svcard,
  .svcard:nth-child(3n + 2) { aspect-ratio: 4 / 3.4; }
}

/* ---- phone: one per row --------------------------------------------------
   One card per row, as specified — two columns at this width would put the
   description at about 16 characters a line. The perspective and the lift are
   dropped with the hover they belonged to; the image keeps its slight
   oversize so the composition is unchanged, it simply stops moving. */
@media (max-width: 700px) {
  .svc__cards {
    grid-template-columns: minmax(0, 1fr);
    perspective: none;
    gap: clamp(0.9rem, 3vw, 1.2rem);
  }
  .svcard,
  .svcard:nth-child(3n + 2) { aspect-ratio: 4 / 3.1; }
  .svcard__link { transform: none; box-shadow: 0 10px 22px -18px rgba(13, 13, 15, 0.45); }
  .svcard__sheen { display: none; }
  .svcard__body { transform: none; padding: clamp(1.05rem, 4.4vw, 1.35rem); }
  .svcard__desc { max-width: none; }
}

@media (prefers-reduced-motion: reduce) {
  .svcard__link,
  .svcard__img,
  .svcard__scrim,
  .svcard__arrow { transition: none; }
  .svcard__sheen { display: none; }
}


/* ==================================================== 03 THE 96K STANDARD == */
/* One compact full-screen composition. The car photograph washes in from the
   lower left behind the copy; one bordered panel of four equal rows holds the
   right. Dark graphite and ivory — no images anywhere else in
   the section, no cards, no icons.

   Nothing here is pinned and nothing reserves extra scroll distance: the
   section is sized to the viewport and behaves like any other section. */

.standard {
  position: relative;
  isolation: isolate;
  display: flex;
  align-items: center;
  /* Fits the viewport minus the fixed header, rather than forcing 100vh and
     overflowing it. */
  min-height: calc(100svh - var(--header-h));
  padding-block: var(--section-y-lg);
  background: var(--color-graphite-deep);
  overflow: hidden;
}

/* ---- the photograph, lower left ------------------------------------------ */
.std__bg {
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  overflow: hidden;
}

.std__bgImg {
  position: absolute;
  left: -4%;
  bottom: 0;
  /* Anchored to the LOWER left so the copy sits above it rather than across
     it — the reference puts the car under the text block, not behind it. */
  width: 54%;
  height: 54%;
  /* CONTAIN, not cover. The box is a percentage of the section in both axes,
     so its aspect ratio changes with the viewport while the photograph's
     does not — at 1440x760 the box became 829x257 against a 1600x1066
     source and cover threw away most of the car. Contain fits the whole
     vehicle into whatever box it is given and simply gets smaller. */
  object-fit: contain;
  object-position: left bottom;
  opacity: 0.72;
}

/* Two passes: horizontal, to dissolve the photograph into the graphite before
   it reaches the panel; vertical, to keep the copy off the brightest part of
   the car. Tuned to leave the headlight and the body reflections reading. */
.std__wash {
  position: absolute;
  inset: 0;
  background:
    /* 1 — readability. Heavy across the whole upper band where the kicker,
       heading, description and progress live, releasing only below them so the
       car reads in the lower third. This is the pass that was missing: the
       copy is on the LEFT, and the old wash was at its lightest there. */
    linear-gradient(to bottom,
      rgba(19, 19, 18, 0.95) 0%,
      rgba(19, 19, 18, 0.93) 30%,
      rgba(19, 19, 18, 0.86) 48%,
      rgba(19, 19, 18, 0.44) 64%,
      rgba(19, 19, 18, 0.3) 78%,
      rgba(19, 19, 18, 0.55) 100%),
    /* 2 — a soft pool of extra darkness directly behind the text column. */
    radial-gradient(120% 70% at 16% 34%,
      rgba(19, 19, 18, 0.72) 0%,
      rgba(19, 19, 18, 0.34) 45%,
      transparent 70%),
    /* 3 — dissolve into the graphite before the panel begins. */
    linear-gradient(90deg,
      rgba(19, 19, 18, 0.2) 0%,
      rgba(19, 19, 18, 0.34) 34%,
      rgba(19, 19, 18, 0.78) 62%,
      var(--color-graphite-deep) 86%);
}

/* ---- layout -------------------------------------------------------------- */
.std__grid {
  position: relative;
  z-index: 1;
  width: 100%;
  display: grid;
  grid-template-columns: minmax(0, 37fr) minmax(0, 63fr);
  column-gap: clamp(2rem, 4.5vw, 5rem);
  align-items: stretch;
  /* Gives the panel real height without a fixed pixel value, and without
     letting it exceed what the viewport can show. */
  min-height: min(720px, calc(100svh - var(--header-h) - 7rem));
}

/* ---- left ---------------------------------------------------------------- */
.std__intro {
  display: grid;
  /* Top-aligned, so the copy occupies the upper band and the car has the lower
     one to itself. Centred, it landed straight across the headlight. */
  align-content: start;
  justify-items: start;
  gap: clamp(0.7rem, 1.2vh, 1.1rem);
  padding-top: clamp(0.5rem, 3vh, 2.4rem);
}

/* The reference sets the kicker plain with a short rule beneath it, so
   the flanking rules the global component draws are dropped here. Type,
   tracking and colour are untouched. */
.std__kicker::before,
.std__kicker::after { display: none; }

.std__dash {
  display: block;
  width: 34px;
  height: 2px;
  background: var(--color-onDark);
  transform-origin: 0 50%;
}

.std__heading { margin-top: clamp(0.1rem, 0.5vh, 0.4rem); }
.std__ln {
  display: block;
  overflow: hidden;
  padding-bottom: 0.14em;
  margin-bottom: -0.14em;
}
.std__ln > i { display: block; font-style: normal; }

.std__lede {
  max-width: 400px;
  margin-top: clamp(0.3rem, 0.8vh, 0.7rem);
}

.std__progress {
  display: flex;
  align-items: center;
  gap: clamp(0.75rem, 1.4vw, 1.15rem);
  margin-top: clamp(0.6rem, 1.6vh, 1.4rem);
  font-size: clamp(0.68rem, 0.8vw, 0.78rem);
  font-weight: 600;
  letter-spacing: 0.2em;
  font-variant-numeric: tabular-nums;
  color: rgba(243, 241, 237, 0.38);
}
.std__progressNum { color: var(--color-onDark); }
.std__progressTrack {
  position: relative;
  width: clamp(90px, 11vw, 168px);
  height: 1px;
  background: rgba(243, 241, 237, 0.16);
}
.std__progressTrack > i {
  position: absolute;
  inset: 0;
  background: var(--color-onDark);
  transform: scaleX(0);
  transform-origin: 0 50%;
}
/* The travelling point of light on the rule. */
.std__progressTrack > i::after {
  content: "";
  position: absolute;
  right: -2px;
  top: 50%;
  width: 5px;
  height: 5px;
  margin-top: -2.5px;
  border-radius: 50%;
  background: var(--color-onDark);
  box-shadow: 0 0 10px 2px rgba(243, 241, 237, 0.4);
}

/* ---- right: four separated cards -----------------------------------------
   Was one bordered panel with the four rows sharing dividers. They are cards
   now, each with its own border and a real gap between them — a divider says
   "these are rows of one thing", a gap says "these are four things", and
   four principles are four things.

   Everything here is a step quieter than it was. The resting title was 0.5
   ivory at weight 600 and 2.15rem; against a near-black card that read as
   brighter and heavier than the composition wanted, so the whole set comes
   down in size and weight and the contrast between the live card and the
   other three does the work instead of raw brightness. */
.std__panel {
  height: 100%;
  /* No border and no fill of its own — it is only the track the cards sit
     in now. */
  overflow: visible;
}

.std__rows {
  height: 100%;
  margin: 0;
  padding: 0;
  list-style: none;
  display: grid;
  grid-template-rows: repeat(4, minmax(0, 1fr));
  /* A clear gap, not a hairline: this is what says four things rather than
     four rows of one thing. */
  gap: clamp(10px, 1vw, 16px);
}

.std__row {
  position: relative;
  display: grid;
  grid-template-columns: auto 1px minmax(0, 1fr);
  align-items: center;
  gap: clamp(1rem, 1.8vw, 1.8rem);
  padding: clamp(0.7rem, 1.5vh, 1.3rem) clamp(1.1rem, 2.2vw, 2.1rem);
  min-width: 0;
  border: var(--rule-onDark);
  border-radius: var(--r-md);
  background: rgba(255, 255, 255, 0.014);
  overflow: hidden;
  transition:
    border-color 0.4s var(--ease-out),
    background-color 0.4s var(--ease-out);
}

/* The live card: a brighter edge and a gradient in the TOP RIGHT corner,
   falling away to nothing by the middle of the card. */
.std__row.is-on {
  border-color: rgba(255, 255, 255, 0.22);
  background: rgba(255, 255, 255, 0.032);
}

.std__glow {
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0;
  /* Pure white, not the ivory used everywhere else. --color-secondary is a
     warmed plate colour (#f3f1ed); spread across a large soft gradient on a
     warm graphite ground it reads brown rather than as light. Hairlines are
     small enough to stay ivory; this is not. */
  background: radial-gradient(86% 128% at 100% 0%,
    rgba(255, 255, 255, 0.11), rgba(255, 255, 255, 0.035) 38%, transparent 66%);
  transition: opacity 0.45s var(--ease-out);
}
.std__row.is-on .std__glow { opacity: 1; }

/* ---- the ghost numeral ---------------------------------------------------
   Outlined, right of the card, and clipped by it. It is a texture in the
   surface, so it never goes above the resting title in strength. */
.std__ghost {
  position: absolute;
  right: clamp(0.6rem, 1.4vw, 1.4rem);
  top: 50%;
  transform: translateY(-50%);
  z-index: 0;
  font-family: var(--font-display);
  font-size: clamp(4.6rem, 7.2vw, 7.8rem);
  font-weight: 700;
  line-height: 0.8;
  letter-spacing: -0.05em;
  color: transparent;
  -webkit-text-stroke: 1px rgba(255, 255, 255, 0.085);
  pointer-events: none;
  user-select: none;
  transition: -webkit-text-stroke-color 0.4s var(--ease-out);
}
.std__row.is-on .std__ghost { -webkit-text-stroke-color: rgba(255, 255, 255, 0.17); }

/* ---- number, rule, copy --------------------------------------------------- */
.std__num {
  position: relative;
  z-index: 1;
  font-family: var(--font-display);
  font-size: clamp(1.25rem, 1.6vw, 1.7rem);
  font-weight: 600;
  line-height: 1;
  letter-spacing: -0.02em;
  color: rgba(243, 241, 237, 0.52);
  transition: color 0.34s var(--ease-out);
}
.std__row.is-on .std__num { color: rgba(243, 241, 237, 0.9); }

.std__rule {
  align-self: stretch;
  width: 1px;
  margin-block: clamp(0.35rem, 0.9vh, 0.7rem);
  background: rgba(243, 241, 237, 0.1);
  transition: background-color 0.34s var(--ease-out);
}
.std__row.is-on .std__rule { background: rgba(243, 241, 237, 0.2); }

.std__body {
  position: relative;
  z-index: 1;
  display: grid;
  gap: clamp(0.24rem, 0.6vh, 0.42rem);
  min-width: 0;
}

.std__title {
  font-family: var(--font-display);
  font-size: clamp(1.15rem, 1.5vw, 1.55rem);
  font-weight: 600;
  line-height: 1.14;
  letter-spacing: -0.024em;
  color: rgba(243, 241, 237, 0.56);
  transition: color 0.34s var(--ease-out);
}
.std__row.is-on .std__title { color: var(--color-secondary); }

.std__tag {
  font-size: clamp(0.84rem, 0.94vw, 0.94rem);
  font-weight: 500;
  line-height: 1.35;
  color: rgba(243, 241, 237, 0.56);
  transition: color 0.34s var(--ease-out);
}
.std__row.is-on .std__tag { color: rgba(243, 241, 237, 0.8); }

.std__text {
  max-width: 46ch;
  font-size: clamp(0.8rem, 0.88vw, 0.89rem);
  line-height: 1.55;
  color: rgba(243, 241, 237, 0.55);
  transition: color 0.34s var(--ease-out);
}
.std__row.is-on .std__text { color: rgba(243, 241, 237, 0.68); }

/* ---- shorter laptops -----------------------------------------------------
   Padding and the decorative number give way first; no content is hidden and
   the type scale is barely touched. */
@media (min-width: 901px) and (max-height: 850px) {
  .standard { padding-block: var(--section-y-md); }
  .std__grid { min-height: min(660px, calc(100svh - var(--header-h) - 5rem)); }
  .std__row { padding-block: clamp(0.5rem, 1.2vh, 1rem); }
  .std__ghost { font-size: clamp(5rem, 7.4vw, 7.6rem); }
  .std__rule { height: clamp(40px, 6vh, 62px); }
  /* The copy takes a larger share of a shorter section, so the car band
     recedes to keep the progress rule clear of it. */
  .std__bgImg { height: 50%; }
}

@media (min-width: 901px) and (max-height: 760px) {
  .standard { padding-block: var(--section-y-sm); }
  .std__grid { min-height: calc(100svh - var(--header-h) - 3.5rem); }
  .std__row { padding-block: 0.45rem; }
  .std__text { line-height: 1.5; }
  .std__ghost { font-size: 6rem; }
  .std__rule { height: 38px; }
  .std__lede { margin-top: 0.2rem; }
  .std__bgImg { height: 44%; }
}

/* ---- tablet -------------------------------------------------------------- */
@media (max-width: 1180px) and (min-width: 901px) {
  .std__grid { column-gap: clamp(1.5rem, 3vw, 2.5rem); }
  .std__row { gap: clamp(0.8rem, 1.6vw, 1.3rem); }
  .std__text { max-width: none; }
  .std__ghost { opacity: 0.05; }
}

/* ---- stacked -------------------------------------------------------------
   Mobile is not compressed to a viewport: the section grows naturally and the
   panel becomes a plain divided list. */
@media (max-width: 900px) {
  .standard {
    display: block;
    min-height: 0;
    padding-block: var(--section-y-md);
  }
  .std__grid {
    grid-template-columns: 1fr;
    row-gap: clamp(1.8rem, 6vw, 2.6rem);
    min-height: 0;
  }

  /* A backdrop, never competing with the words. */
  .std__bgImg {
    left: auto;
    right: -12%;
    top: 0;
    bottom: auto;
    width: 86%;
    height: 46%;
    object-position: right top;
    opacity: 0.5;
  }
  .std__wash {
    background:
      linear-gradient(to bottom,
        rgba(19, 19, 18, 0.72) 0%,
        rgba(19, 19, 18, 0.86) 34%,
        var(--color-graphite-deep) 62%);
  }

  .std__intro { align-content: start; }
  .std__lede { max-width: none; }

  .std__panel {
    height: auto;
    border: 0;
    border-radius: 0;
    background: none;
  }
  .std__rows {
    height: auto;
    grid-template-rows: none;
  }
  .std__row {
    padding: clamp(1.1rem, 4vw, 1.5rem);
    gap: clamp(0.8rem, 3.4vw, 1.2rem);
  }
  .std__glow { display: none; }
  .std__ghost { font-size: clamp(4rem, 17vw, 6rem); right: 0; opacity: 0.05; }
  .std__rule { height: clamp(38px, 9vw, 54px); }
  .std__text { max-width: none; }

  /* Every principle reads fully; nothing depends on hover. */
  .std__num { color: var(--color-onDark); }
  .std__title { color: var(--color-secondary); }
  .std__tag { color: rgba(243, 241, 237, 0.8); }
  .std__text { color: rgba(243, 241, 237, 0.68); }
}

@media (max-width: 420px) {
  .std__title { font-size: 1.3rem; }
  .std__num { font-size: 1.3rem; }
  .std__ghost { font-size: 4rem; }
}

/* ---- reduced motion ------------------------------------------------------ */
@media (prefers-reduced-motion: reduce) {
  .std__num { color: var(--color-onDark); }
  .std__title { color: var(--color-secondary); }
  .std__tag { color: rgba(243, 241, 237, 0.88); }
  .std__text { color: rgba(243, 241, 237, 0.74); }
  .std__num, .std__title, .std__tag, .std__text,
  .std__glow, .std__ghost, .std__rule, .std__row { transition: none; }
}

/* ======================================================== 04 IN NUMBERS == */
/* A transition strip, not a section with ambitions: one row, four stats, deep
   charcoal, no heading, no intro copy, no cards, no frame. Compact enough to
   read as a rule between two larger pieces of the page. */

.stats {
  position: relative;
  isolation: isolate;
  display: flex;
  align-items: center;
  /* Held in the strip range rather than sized by whatever the content wants. */
  min-height: clamp(220px, 26vh, 300px);
  padding-block: var(--section-y-md);
  /* Charcoal, but eased out of the graphite above it. The two dark sections
     are one zone and must not meet at a visible step — they are different
     surfaces of the same dark, not two panels butted together. */
  /* Flat. This carried a graphite-to-charcoal ramp down its top edge to
     blend with the Principles section that used to sit directly above it;
     About sits there now, so the ramp would be easing out of a colour that
     is no longer on screen. */
  background: var(--color-charcoal);
  overflow: hidden;
}

/* The hairline top and bottom edges, brightest at the centre. Not a frame —
   there is deliberately nothing down the sides. */
.stats__edge {
  position: absolute;
  left: 0;
  right: 0;
  height: 1px;
  background: linear-gradient(to right,
    transparent 0%,
    rgba(243, 241, 237, 0.14) 26%,
    rgba(243, 241, 237, 0.42) 50%,
    rgba(243, 241, 237, 0.14) 74%,
    transparent 100%);
  transform: scaleX(0);
  transform-origin: 50% 50%;
}
.stats__edge--top { top: 0; }
.stats__edge--bottom { bottom: 0; }

.stats__grid {
  --stats-sep: 0;              /* the entrance fades the separators in */
  width: 100%;
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
}

/* ---- one stat ------------------------------------------------------------ */
.stats__item {
  position: relative;
  display: flex;
  align-items: center;
  gap: clamp(0.7rem, 1.1vw, 1.05rem);
  /* Kept tight on purpose: the content column has to hold CLIENT SATISFACTION
     on one line, and at four columns every pixel of padding comes out of it. */
  padding-inline: clamp(0.35rem, 1vw, 1rem);
  min-width: 0;
}
.stats__item:first-child { padding-left: 0; }
.stats__item:last-child { padding-right: 0; }

/* Separator: a hairline that fades out at both ends. */
.stats__item:not(:last-child)::after {
  content: "";
  position: absolute;
  right: 0;
  top: 6%;
  bottom: 6%;
  width: 1px;
  opacity: var(--stats-sep);
  background: linear-gradient(to bottom,
    transparent 0%,
    var(--color-onDark-rule) 24%,
    var(--color-onDark-rule) 76%,
    transparent 100%);
}
/* The small point of light at its middle. A point, not an orb. */
.stats__item:not(:last-child)::before {
  content: "";
  position: absolute;
  right: -1px;
  top: 50%;
  width: 3px;
  height: 3px;
  margin-top: -1.5px;
  border-radius: 50%;
  opacity: var(--stats-sep);
  background: var(--color-onDark);
  box-shadow: 0 0 6px 1px rgba(243, 241, 237, 0.3);
}

/* ---- icon ---------------------------------------------------------------- */
.stats__disc {
  flex: none;
  display: grid;
  place-items: center;
  width: clamp(66px, 5vw, 78px);
  aspect-ratio: 1;
  border-radius: 50%;
  /* No ring, no border — just a disc a shade off the ground. */
  background: rgba(255, 255, 255, 0.035);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.05),
    inset 0 -1px 0 rgba(0, 0, 0, 0.35);
  color: var(--color-onDark);
  transition:
    transform 0.35s var(--ease-out),
    background-color 0.35s var(--ease-out),
    color 0.35s var(--ease-out);
}
.stats__disc svg {
  width: clamp(26px, 2.2vw, 32px);
  height: auto;
}

/* ---- content ------------------------------------------------------------- */
.stats__body {
  min-width: 0;
  transition: transform 0.35s var(--ease-out);
}

.stats__value {
  display: flex;
  align-items: baseline;
  gap: 0.04em;
  font-family: var(--font-sans);
  font-size: clamp(2.375rem, 3vw, 3.625rem);
  font-weight: 700;
  line-height: 1;
  letter-spacing: -0.022em;
  color: var(--color-secondary);
  font-variant-numeric: tabular-nums;
}
/* The symbol is dimmed — the figure itself stays full ivory and dominant. */
.stats__accent {
  font-size: 0.58em;
  font-weight: 700;
  letter-spacing: 0;
  color: rgba(243, 241, 237, 0.78);
}

.stats__label {
  margin-top: clamp(0.45rem, 0.9vh, 0.7rem);
  font-size: clamp(0.75rem, 0.9vw, 0.875rem);
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  line-height: 1.3;
  color: rgba(243, 241, 237, 0.72);
}

.stats__note {
  margin-top: clamp(0.5rem, 1vh, 0.8rem);
  padding-top: clamp(0.5rem, 1vh, 0.8rem);
  border-top: var(--rule-onDark);
  font-size: clamp(0.875rem, 1vw, 1rem);
  line-height: 1.45;
  color: rgba(243, 241, 237, 0.66);
}

/* ---- hover: desktop only, and barely there ------------------------------- */
@media (hover: hover) and (pointer: fine) {
  .stats__item:hover .stats__disc {
    transform: translateY(-3px);
    background: rgba(255, 255, 255, 0.055);
    color: #ffffff;
  }
  .stats__item:hover .stats__body { transform: translateX(2px); }
}

/* ---- tablet: two by two -------------------------------------------------- */
@media (max-width: 1024px) and (min-width: 561px) {
  .stats {
    min-height: 0;
    padding-block: var(--section-y-md);
  }
  .stats__grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    row-gap: clamp(1.8rem, 4vw, 2.6rem);
  }
  .stats__item { padding-inline: clamp(0.75rem, 2.5vw, 1.6rem); }
  /* Only the left-hand column carries a separator now. */
  .stats__item:nth-child(odd) { padding-left: 0; }
  .stats__item:nth-child(even) { padding-right: 0; }
  .stats__item:nth-child(even)::after,
  .stats__item:nth-child(even)::before { display: none; }
  .stats__item:not(:last-child)::after { display: block; }
  .stats__item:nth-child(3)::after,
  .stats__item:nth-child(3)::before { display: block; }
  /* A hairline between the two rows. */
  .stats__item:nth-child(1),
  .stats__item:nth-child(2) {
    padding-bottom: clamp(1.8rem, 4vw, 2.6rem);
    border-bottom: var(--rule-onDark);
  }
}

/* ---- phone: two by two, icon above ---------------------------------------
   Below this the pair of columns is too narrow to keep the icon beside the
   figure without squeezing both, so the item goes vertical instead. */
@media (max-width: 560px) {
  .stats {
    min-height: 0;
    padding-block: var(--section-y-sm);
  }
  .stats__grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    column-gap: clamp(0.9rem, 4vw, 1.4rem);
    row-gap: clamp(1.8rem, 7vw, 2.4rem);
  }
  /* Centred, not left-aligned. Once the item goes vertical the disc sits
     above the figure rather than beside it, and a left edge shared by a
     circle, a two-character numeral and a sentence is three different
     optical starts pretending to be one line. Centring gives the stack a
     single axis — and with the separators gone at this width, that axis is
     the only thing holding the four together. */
  .stats__item {
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: clamp(0.7rem, 3vw, 1rem);
    padding-inline: 0;
  }
  /* .stats__value is its own flex row (figure + suffix on a shared baseline),
     so text-align does not reach it — it needs the axis stated directly. */
  .stats__value { justify-content: center; }
  .stats__item::after,
  .stats__item::before { display: none; }
  .stats__disc { width: clamp(48px, 13vw, 58px); }
  .stats__disc svg { width: clamp(22px, 6vw, 26px); }
  .stats__value { font-size: clamp(1.85rem, 9vw, 2.4rem); }
  .stats__label { letter-spacing: 0.12em; font-size: 0.72rem; }

  /* The note's rule becomes a fixed centred mark rather than a full-width
     border. As a border it shrink-wrapped each note's own text, which gave
     the four stats rules of 129, 154, 120 and 123px — invisible while the
     column was left-aligned and ragged, but once centred the four are
     symmetrical and the eye compares them directly. One width for all four
     is the only version that reads as intended, and 40px matches the short
     rule the global .section-kicker already draws. */
  .stats__note {
    position: relative;
    font-size: 0.82rem;
    border-top: 0;
  }
  .stats__note::before {
    content: "";
    position: absolute;
    top: 0;
    left: 50%;
    width: 40px;
    height: 1px;
    margin-left: -20px;
    background: var(--color-onDark-rule);
  }
}

/* ---- reduced motion ------------------------------------------------------ */
@media (prefers-reduced-motion: reduce) {
  .stats__grid { --stats-sep: 1; }
  .stats__edge { transform: scaleX(1); }
  .stats__disc,
  .stats__body { transition: none; }
}

/* ============================================================ 07 PROCESS == */
/* THE EXPERIENCE — white, architectural, typographic.

   The four numerals are watermarks BEHIND the content rather than decoration
   beside it: the copy overlaps their lower half, which is what stops the
   columns reading as empty. No icons, no cards, no timeline, no rail. Only
   structural classes live here — every piece of type is a global class. */

.experience {
  position: relative;
  background: var(--color-bg);
  padding-block: var(--section-y-lg);
  overflow: hidden;
}

.exp__inner {
  display: grid;
  gap: clamp(2rem, 4.6vh, 3.6rem);
}

/* ---- head ---------------------------------------------------------------- */
.exp__head {
  position: relative;
  display: grid;
  justify-items: start;
  gap: clamp(0.7rem, 1.4vh, 1.1rem);
}

/* The reference sets the kicker with a single leading rule, so the trailing
   half of the global component is dropped here. Type is untouched. */
.exp__kicker::after { display: none; }

.exp__heading { margin-top: clamp(0.1rem, 0.4vh, 0.35rem); }
.exp__ln {
  display: block;
  overflow: hidden;
  padding-bottom: 0.14em;
  margin-bottom: -0.14em;
}
.exp__ln > i { display: block; font-style: normal; }

.exp__rule {
  display: block;
  width: clamp(30px, 3vw, 44px);
  height: 2px;
  margin-top: clamp(0.3rem, 0.8vh, 0.6rem);
  background: var(--color-accent);
  transform-origin: 0 50%;
}

.exp__lede { max-width: 460px; }

/* ---- the faint 96K, upper right ------------------------------------------ */
.exp__mark {
  position: absolute;
  right: 0;
  top: 50%;
  transform: translateY(-50%);
  display: grid;
  justify-items: end;
  gap: clamp(0.3rem, 1vh, 0.8rem);
  pointer-events: none;
  user-select: none;
  text-align: right;
}
.exp__mark b {
  display: block;
  font-family: var(--font-sans);
  font-size: clamp(5rem, 10vw, 11rem);
  font-weight: 300;
  line-height: 0.82;
  letter-spacing: 0.04em;
  color: var(--color-heading);
  opacity: 0.045;
}
.exp__mark span {
  display: block;
  font-size: clamp(0.6rem, 0.86vw, 0.82rem);
  font-weight: 400;
  letter-spacing: 0.42em;
  text-transform: uppercase;
  color: var(--color-heading);
  opacity: 0.09;
}

/* ---- the four columns ---------------------------------------------------- */
.exp__grid {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
}

.exp__step {
  position: relative;
  /* Space for the numeral above; the content lands across its lower half. */
  padding: clamp(4rem, 8vh, 6.8rem) clamp(1rem, 1.8vw, 1.9rem) 0;
  min-width: 0;
}
.exp__step:first-child { padding-left: 0; }
.exp__step:last-child { padding-right: 0; }

/* No separators. The four steps are held apart by the column gap and by
   the oversized numerals behind them, which is enough structure — the rules
   were drawing a table around content that reads perfectly well as four
   parallel columns without one. The padding they used to sit against is
   kept, so the rhythm is unchanged. */

.exp__num {
  position: absolute;
  left: clamp(0.7rem, 1.5vw, 1.6rem);
  top: clamp(-1.4rem, -1.4vh, -0.6rem);
  z-index: 0;
  font-family: var(--font-sans);
  font-size: clamp(7rem, 12.4vw, 14rem);
  font-weight: 600;
  line-height: 0.8;
  letter-spacing: -0.03em;
  color: var(--color-heading);
  opacity: 0.055;
  pointer-events: none;
  user-select: none;
  transition: opacity 0.3s var(--ease-out), transform 0.3s var(--ease-out);
}
.exp__step:first-child .exp__num { left: 0; }

/* One ink micro line, above the title. */
.exp__tick {
  position: relative;
  z-index: 1;
  display: block;
  width: clamp(28px, 2.6vw, 40px);
  height: 2px;
  background: var(--color-accent);
  transition: width 0.3s var(--ease-out);
}

.exp__title {
  position: relative;
  z-index: 1;
  margin-top: clamp(0.9rem, 1.8vh, 1.4rem);
  font-family: var(--font-sans);
  font-size: clamp(1.02rem, 1.28vw, 1.28rem);
  font-weight: 700;
  line-height: 1.24;
  letter-spacing: 0.005em;
  text-transform: uppercase;
  color: var(--color-heading);
  text-wrap: balance;
  transition: transform 0.3s var(--ease-out);
}

.exp__copy {
  position: relative;
  z-index: 1;
  margin-top: clamp(0.85rem, 1.7vh, 1.3rem);
  /* The padding stays; the rule that used to sit on it does not. */
  padding-top: clamp(0.85rem, 1.7vh, 1.3rem);
  max-width: 30ch;
  font-size: clamp(0.86rem, 0.96vw, 0.96rem);
  line-height: 1.62;
  color: var(--color-text);
  text-wrap: pretty;
  transition: transform 0.3s var(--ease-out);
}

/* The hover transitions below and the entrance both drive opacity/transform.
   Left together, every value GSAP writes per frame gets re-eased by the CSS
   transition and the entrance arrives late and smeared — so transitions are
   suppressed for the duration of the timeline and restored on completion. */
.experience.is-entering .exp__num,
.experience.is-entering .exp__tick,
.experience.is-entering .exp__title,
.experience.is-entering .exp__copy { transition: none; }

/* ---- hover: desktop only, and barely there ------------------------------- */
@media (hover: hover) and (pointer: fine) {
  .exp__step:hover .exp__num { opacity: 0.085; transform: translateY(-3px); }
  .exp__step:hover .exp__tick { width: clamp(38px, 3.4vw, 54px); }
  .exp__step:hover .exp__title,
  .exp__step:hover .exp__copy { transform: translateY(-2px); }
}

/* ---- shorter laptops -----------------------------------------------------
   Padding and the watermarks give way first. Nothing is hidden. */
@media (min-width: 901px) and (max-height: 820px) {
  .experience { padding-block: var(--section-y-md); }
  .exp__inner { gap: clamp(1.4rem, 3vh, 2.2rem); }
  .exp__step { padding-top: clamp(3rem, 6vh, 4.6rem); }
  .exp__num { font-size: clamp(6rem, 10vw, 10.5rem); }
  .exp__mark b { font-size: clamp(4.5rem, 8.5vw, 9rem); }
}

@media (min-width: 901px) and (max-height: 720px) {
  .experience { padding-block: var(--section-y-sm); }
  .exp__inner { gap: 1.35rem; }
  .exp__step { padding-top: 2.6rem; }
  .exp__num { font-size: clamp(5.2rem, 8.6vw, 8.6rem); }
  .exp__mark b { font-size: 7rem; }
  .exp__copy { line-height: 1.54; }
  .exp__title { margin-top: 0.75rem; }
}

/* ---- tablet: two by two -------------------------------------------------- */
@media (max-width: 1024px) and (min-width: 641px) {
  .experience { padding-block: var(--section-y-md); }
  .exp__grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    row-gap: clamp(2.2rem, 5vw, 3.4rem);
  }
  .exp__step { padding-inline: clamp(1.1rem, 3vw, 2rem); }
  .exp__step:nth-child(odd) { padding-left: 0; }
  .exp__step:nth-child(even) { padding-right: 0; }
  /* Only the right-hand column of each row carries a separator. */
  .exp__step:not(:first-child)::before { display: none; }
  .exp__step:nth-child(even)::before { display: block; }
  .exp__copy { max-width: none; }
  .exp__mark { position: static; transform: none; justify-items: start; text-align: left; margin-top: 0.4rem; }
  .exp__mark b { font-size: clamp(4rem, 11vw, 7rem); }
}

/* ---- stacked ------------------------------------------------------------- */
@media (max-width: 640px) {
  .experience { padding-block: var(--section-y-md); }
  .exp__inner { gap: clamp(1.6rem, 6vw, 2.2rem); }
  .exp__grid { grid-template-columns: 1fr; }

  .exp__step {
    padding: clamp(2.4rem, 11vw, 3.4rem) 0 clamp(1.5rem, 6vw, 2rem);
  }
  .exp__step:not(:first-child)::before {
    /* Nothing to redraw — the separators are gone at every width. */
    display: none;
  }
  .exp__step:last-child { padding-bottom: 0; }

  .exp__num {
    left: 0;
    top: clamp(0.6rem, 3vw, 1.2rem);
    font-size: clamp(4.6rem, 22vw, 7rem);
    opacity: 0.05;
  }
  .exp__copy { max-width: none; }

  .exp__mark { position: static; transform: none; justify-items: start; text-align: left; }
  .exp__mark b { font-size: clamp(3.6rem, 18vw, 5.5rem); }
  .exp__mark span { letter-spacing: 0.3em; }
  .exp__lede { max-width: none; }
}

@media (max-width: 400px) {
  .exp__title { font-size: 0.98rem; }
  .exp__num { font-size: 4.4rem; }
}

/* ---- reduced motion ------------------------------------------------------ */
@media (prefers-reduced-motion: reduce) {
  .exp__num, .exp__tick, .exp__title, .exp__copy { transition: none; }
}


/* ======================================================= 08 TESTIMONIALS == */
/* A centre-focused carousel on white. The card in the middle is the active
   one; the two beside it sit behind at reduced scale and slightly softer ink.

   Every slide is stacked in the SAME grid cell and positioned by transform.
   Three consequences, all of them wanted: the cards are automatically equal
   height (the cell is as tall as the longest quote), the centre card can
   overlap its neighbours, and nothing reflows when the carousel moves —
   only transform and opacity ever change.

   The four numbers below are the whole geometry. JavaScript reads them, so a
   breakpoint only has to restate these rather than re-implement anything. */

.vox {
  background: var(--color-bg);
  padding-block: var(--section-y-lg);
  overflow: hidden;
}

.vox__inner {
  --vox-card: 40;          /* card width, % of the viewport             */
  --vox-step: 34;          /* centre-to-centre gap, % of the viewport   */
  --vox-side-scale: 0.8;   /* side cards                                */
  --vox-side-alpha: 0.72;
  --vox-side-tilt: 0.8deg; /* barely a tilt; zero on the centre card    */

  display: grid;
  justify-items: center;
  gap: clamp(2.2rem, 4.5vh, 3.4rem);
}

/* ---- head ---------------------------------------------------------------- */
.vox__head {
  display: grid;
  justify-items: center;
  text-align: center;
  gap: clamp(0.7rem, 1.3vh, 1.1rem);
}
.vox__heading { margin-top: clamp(0.1rem, 0.4vh, 0.35rem); }
.vox__ln {
  display: block;
  overflow: hidden;
  padding-bottom: 0.14em;
  margin-bottom: -0.14em;
}
.vox__ln > i { display: block; font-style: normal; }
.vox__lede { max-width: 46ch; }

/* ---- carousel ------------------------------------------------------------ */
.vox__carousel {
  position: relative;
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: clamp(0.5rem, 1.6vw, 1.6rem);
}

.vox__viewport {
  position: relative;
  flex: 1 1 auto;
  min-width: 0;
  display: grid;
  /* Every slide shares this one cell. */
  grid-template-areas: "stack";
  perspective: 1400px;
}

.vox__slide {
  grid-area: stack;
  width: calc(var(--vox-card) * 1%);
  justify-self: center;
}

/* ---- card ---------------------------------------------------------------- */
/* White on white — the card is defined by its hairline and its depth, never
   by a fill. */
.vox__card {
  display: grid;
  justify-items: start;
  gap: clamp(0.9rem, 1.6vh, 1.4rem);
  height: 100%;
  margin: 0;
  padding: clamp(1.7rem, 2.6vw, 2.8rem);
  background: var(--color-bg);
  border: var(--rule);
  border-radius: var(--r-md);
}

.vox__mark {
  font-family: var(--font-sans);
  font-size: clamp(2.4rem, 3.4vw, 3.6rem);
  font-weight: 700;
  line-height: 0.6;
  color: var(--color-rule-soft);
  transition: color 0.5s var(--ease-out);
}

/* One size for every card. The side cards reach their smaller size through
   the 0.8 scale (26px -> ~21px), which lands in the intended range WITHOUT
   changing font-size — so nothing reflows, every card stays the same height,
   and the carousel cannot change height as the active card changes. */
.vox__quote p {
  font-family: var(--font-sans);
  font-size: clamp(1.25rem, 1.62vw, 1.62rem);
  font-weight: 400;
  line-height: 1.55;
  color: var(--color-text);
  text-wrap: pretty;
  transition: color 0.5s var(--ease-out);
}

.vox__rule {
  display: block;
  width: clamp(26px, 2.4vw, 34px);
  height: 1px;
  background: var(--color-rule);
}

.vox__who {
  display: grid;
  gap: 0.4rem;
}
.vox__name {
  font-size: clamp(0.75rem, 0.86vw, 0.86rem);
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--color-heading);
}
.vox__city {
  font-size: clamp(0.68rem, 0.78vw, 0.78rem);
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--color-muted);
}

/* ---- the active card ------------------------------------------------------
   Elevated, not floating: a stronger hairline, a soft shadow and one very thin
   ink line along the foot. */
.vox__slide.is-active .vox__card {
  border-color: rgba(13, 13, 15, 0.11);
  box-shadow: 0 18px 40px -28px rgba(13, 13, 15, 0.4);
}
.vox__slide.is-active .vox__card::after {
  content: "";
  position: absolute;
  left: clamp(1.7rem, 2.6vw, 2.8rem);
  right: clamp(1.7rem, 2.6vw, 2.8rem);
  bottom: 0;
  height: 2px;
  background: var(--color-heading);
}
.vox__card { position: relative; }

.vox__slide.is-active .vox__mark { color: var(--color-heading); }
.vox__slide.is-active .vox__quote p { color: var(--color-heading); }

/* ---- arrows -------------------------------------------------------------- */
.vox__arrow {
  flex: none;
  display: grid;
  place-items: center;
  width: clamp(40px, 3.4vw, 52px);
  aspect-ratio: 1;
  border-radius: 50%;
  border: var(--rule);
  background: var(--color-bg);
  color: var(--color-heading);
  transition:
    border-color 0.3s var(--ease-out),
    background-color 0.3s var(--ease-out);
}
.vox__arrow svg {
  width: clamp(17px, 1.4vw, 21px);
  height: auto;
  transition: transform 0.3s var(--ease-out);
}
@media (hover: hover) and (pointer: fine) {
  .vox__arrow:hover { border-color: var(--color-rule); background: rgba(13, 13, 15, 0.02); }
  .vox__arrow--prev:hover svg { transform: translateX(-3px); }
  .vox__arrow--next:hover svg { transform: translateX(3px); }
}

/* ---- pagination ---------------------------------------------------------- */
.vox__pager {
  display: flex;
  align-items: center;
  gap: clamp(0.8rem, 1.6vw, 1.3rem);
  font-variant-numeric: tabular-nums;
}
.vox__count {
  font-size: clamp(0.72rem, 0.82vw, 0.82rem);
  font-weight: 600;
  letter-spacing: 0.16em;
  color: var(--color-heading);
}
.vox__count--total { color: var(--color-muted); }
.vox__bar {
  width: 1px;
  height: 12px;
  background: var(--color-border);
}
.vox__dots {
  display: flex;
  align-items: center;
  gap: clamp(0.55rem, 1vw, 0.85rem);
}
.vox__dot {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  border: 1px solid var(--color-muted);
  background: transparent;
  transition: background-color 0.3s var(--ease-out), border-color 0.3s var(--ease-out);
}
.vox__dot.is-on {
  background: var(--color-heading);
  border-color: var(--color-heading);
}

/* ---- tablet: the centre card plus a glimpse either side ------------------ */
@media (max-width: 1023px) and (min-width: 641px) {
  .vox__inner {
    --vox-card: 62;
    --vox-step: 52;
    --vox-side-scale: 0.86;
    --vox-side-alpha: 0.55;
  }
}

/* ---- phone: exactly one card, no perspective ----------------------------- */
@media (max-width: 640px) {
  .vox { padding-block: var(--section-y-md); }
  .vox__inner {
    --vox-card: 100;
    --vox-step: 106;
    --vox-side-scale: 1;
    --vox-side-alpha: 0;
    --vox-side-tilt: 0deg;
  }
  .vox__viewport { perspective: none; }
  .vox__carousel { gap: 0; }
  /* The arrows tuck under the card rather than squeezing it. */
  .vox__arrow {
    position: absolute;
    bottom: -1.1rem;
    z-index: 4;
    width: 38px;
    background: var(--color-bg);
  }
  .vox__arrow--prev { left: 0; }
  .vox__arrow--next { right: 0; }
  .vox__card { padding: clamp(1.4rem, 6vw, 1.9rem); }
}

@media (max-width: 400px) {
  .vox__card { padding: 1.25rem; }
  .vox__arrow { width: 34px; bottom: -0.9rem; }
}

/* ---- reduced motion ------------------------------------------------------ */
@media (prefers-reduced-motion: reduce) {
  .vox__mark, .vox__quote p, .vox__arrow, .vox__arrow svg, .vox__dot { transition: none; }
}


/* ================================================================= CLOSE == */
/* CTA and footer as ONE composition: four columns, a compact booking bar,
   one copyright line. The CTA was a separate full-height section above this
   and is now a ~120px bar inside it — the invitation and the directory were
   never two ideas and did not need two screens between them.

   Full bleed. The element itself carries the ground edge to edge; only the
   content is held by the shared .site-container, so the left rule of the
   brand column lines up with every other section on the page. */

.close {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  /* 66px top / 46px bottom at 1440 — the compact rhythm the brief asks for.
     --section-y-lg would have put 92px above the brand column and made the
     close read as another full section rather than the end of the page. */
  padding-block: var(--section-y-md) var(--section-y-sm);
  background: var(--color-charcoal);
  color: var(--color-onDark-soft);
  /* Light from the TOP LEFT, falling away on a diagonal. Two layers: a broad
     radial lift anchored off the top-left corner, and a linear pass across
     the same axis that gives the falloff a soft straight edge rather than a
     circular one — which is the difference between a corner glow and a panel
     catching light.

     Both are white at very low alpha over the charcoal, so the ground stays
     one colour and only its value moves. */
  background-image:
    radial-gradient(78% 116% at -6% -14%, rgba(255, 255, 255, 0.075), transparent 58%),
    linear-gradient(129deg, rgba(255, 255, 255, 0.05) 0%, rgba(255, 255, 255, 0.018) 26%, transparent 52%);
}

/* ---- the watermark -------------------------------------------------------
   Middle right, bled off the edge. Set in the same face as everything else
   and left at 3% — it is a texture in the surface, not a graphic sitting on
   it, and at any more it starts competing with the contact column beside it.
   aria-hidden, so it is never announced as a second heading. */
.close__mark {
  position: absolute;
  right: clamp(-1rem, -1.5vw, -0.4rem);
  top: 50%;
  z-index: -1;
  transform: translateY(-50%);
  font-family: var(--font-display);
  font-size: clamp(7rem, 15vw, 17rem);
  font-weight: 700;
  line-height: 0.78;
  letter-spacing: -0.04em;
  color: var(--color-secondary);
  opacity: 0.03;
  pointer-events: none;
  user-select: none;
}

.close__inner {
  display: grid;
  /* ~43px between the columns, the booking bar and the copyright line. */
  gap: clamp(2rem, 3vw, 2.9rem);
}

/* ---- the four columns ----------------------------------------------------
   Brand takes the widest track; the three lists share the rest evenly. The
   dividers are drawn as column borders rather than as elements, so they can
   never fall out of step with the grid. */
.close__top {
  display: grid;
  grid-template-columns: minmax(0, 1.35fr) repeat(3, minmax(0, 1fr));
  gap: clamp(1.6rem, 3vw, 3.2rem);
}
.close__top > * + * {
  padding-left: clamp(1.6rem, 3vw, 3.2rem);
  border-left: var(--rule-onDark);
}

/* ---- brand --------------------------------------------------------------
   Typographic, never the logo file. Set in Inter at the wordmark's own
   tracking so it inherits every type change the rest of the site gets. */
.foot__mark {
  display: grid;
  gap: 0.35rem;
  margin-bottom: clamp(1.2rem, 2vw, 1.7rem);
}
.foot__mark b {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: clamp(2.1rem, 3.1vw, 3rem);
  line-height: 0.9;
  letter-spacing: -0.045em;
  color: var(--color-secondary);
}
.foot__mark span {
  font-size: var(--fs-label);
  font-weight: 500;
  letter-spacing: 0.42em;
  text-transform: uppercase;
  /* 0.64, not 0.55. The brand column sits directly under the new top-left
     gradient, and against that lifted ground the lighter value measured
     4.04:1 — the gradient raises the background, so the text on top of it
     has to come up with it. */
  color: rgba(243, 241, 237, 0.64);
}

.foot__statement {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(1.05rem, 1.4vw, 1.35rem);
  line-height: 1.24;
  letter-spacing: -0.024em;
  color: var(--color-secondary);
}
.foot__ln { display: block; overflow: hidden; }
.foot__ln > i { display: block; font-style: normal; }

.foot__creed {
  margin-top: 0.85rem;
  font-size: var(--fs-label);
  font-weight: 500;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: rgba(243, 241, 237, 0.64);
}

/* ---- social -------------------------------------------------------------
   Thin monochrome circles. None of these accounts exists in the project yet,
   so they are spans with aria-disabled rather than anchors — the design is
   present and one href each makes them live, but nothing here pretends to
   lead somewhere it does not. */
.foot__socials {
  display: flex;
  gap: 0.65rem;
  margin-top: clamp(1.3rem, 2.2vw, 1.9rem);
}
.foot__soc {
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  border: var(--rule-onDark);
  color: rgba(243, 241, 237, 0.6);
  cursor: default;
  transition:
    border-color 0.4s var(--ease-out),
    color 0.4s var(--ease-out),
    transform 0.4s var(--ease-out);
}
.foot__soc svg { width: 19px; height: 19px; }

/* ---- the three lists ----------------------------------------------------- */
.foot__head {
  font-family: var(--font-body);
  font-size: var(--fs-label);
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--color-secondary);
  margin-bottom: clamp(1.1rem, 1.9vw, 1.6rem);
}

.foot__list { display: grid; gap: 0.15rem; }

.foot__link {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding-block: 0.5rem;
  font-size: clamp(0.88rem, 0.95vw, 0.97rem);
  color: rgba(243, 241, 237, 0.66);
  transition: color 0.35s var(--ease-out);
}
.foot__chev {
  flex: none;
  width: 8px;
  height: 12px;
  opacity: 0.34;
  transition: transform 0.4s var(--ease-out), opacity 0.4s var(--ease-out);
}

/* ---- contact ------------------------------------------------------------ */
.foot__contact {
  display: flex;
  align-items: center;
  gap: 0.85rem;
  padding-block: 0.5rem;
  font-size: clamp(0.88rem, 0.95vw, 0.97rem);
}
.foot__ico {
  display: grid;
  place-items: center;
  flex: none;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  border: var(--rule-onDark);
  color: rgba(243, 241, 237, 0.62);
}
.foot__glyph { width: 17px; height: 17px; }

/* Every contact value is still to be supplied. Marked rather than invented,
   and styled so it reads as a gap in the data and not as content. */
/* Contrast, not taste: 0.44 measured 4.02:1 on this charcoal and 0.34 on the
   legal line measured 2.88:1 — both below AA for real text, however quiet the
   role is meant to be. Raised until every string on this ground clears 4.5. */
.pending {
  color: rgba(243, 241, 237, 0.56);
  font-style: normal;
}

/* A contact row that has a real value in it. Brighter than .pending on
   purpose: one is a gap in the data and the other is the thing a visitor came
   to the footer to find, and they should not read as the same weight. 0.82 on
   this charcoal measures 10.3:1. */
.foot__value {
  color: rgba(243, 241, 237, 0.82);
  font-variant-numeric: tabular-nums;
  transition: color 0.35s var(--ease-out);
}
a.foot__value:hover,
a.foot__value:focus-visible { color: var(--color-secondary); }

/* ---- the booking bar -----------------------------------------------------
   ~120px. A thin-bordered transparent panel, not a filled block: it has to
   read as part of the footer surface rather than as a card dropped onto it,
   which is the difference between this and the section it replaced. */
.close__cta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: clamp(1.4rem, 3vw, 3rem);
  min-height: 120px;
  padding: clamp(1.1rem, 1.8vw, 1.6rem) clamp(1.4rem, 2.6vw, 2.4rem);
  border: var(--rule-onDark);
  border-radius: var(--r-lg);
  background: rgba(255, 255, 255, 0.022);
}

.close__ctaCopy {
  display: flex;
  align-items: center;
  gap: clamp(0.9rem, 1.6vw, 1.4rem);
  min-width: 0;
}
.close__ctaIco {
  display: grid;
  place-items: center;
  flex: none;
  width: 54px;
  height: 54px;
  border-radius: var(--r-md);
  border: var(--rule-onDark);
  color: rgba(243, 241, 237, 0.72);
}
.close__ctaIco svg { width: 22px; height: 22px; }

.close__ctaText { display: grid; gap: 0.3rem; min-width: 0; }
.close__ctaTitle {
  font-size: var(--fs-label);
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--color-secondary);
}
.close__ctaSub {
  font-size: clamp(0.86rem, 0.95vw, 0.96rem);
  color: rgba(243, 241, 237, 0.6);
}

.close__ctaActions {
  display: flex;
  align-items: center;
  gap: clamp(1rem, 2vw, 1.8rem);
  flex: none;
}
.close__ctaSep {
  width: 1px;
  align-self: stretch;
  margin-block: 0.4rem;
  background: rgba(243, 241, 237, 0.15);
}

.close__talk {
  display: inline-flex;
  align-items: center;
  gap: 0.85rem;
  font-size: var(--fs-label);
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: rgba(243, 241, 237, 0.78);
  transition: color 0.35s var(--ease-out);
}
.close__talkIco {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  border: var(--rule-onDark);
  transition:
    border-color 0.4s var(--ease-out),
    transform 0.4s var(--ease-out);
}
.close__talkIco svg { width: 19px; height: 19px; }

/* ---- copyright ----------------------------------------------------------- */
.close__base {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding-top: clamp(1.5rem, 2.4vw, 2.1rem);
  border-top: var(--rule-onDark);
}
.foot__legal {
  font-size: var(--fs-label);
  letter-spacing: 0.12em;
  color: rgba(243, 241, 237, 0.58);
}
.foot__legal--quiet {
  text-transform: uppercase;
  letter-spacing: 0.2em;
  color: rgba(243, 241, 237, 0.5);
}

/* ---- hover, fine pointers only ------------------------------------------- */
@media (hover: hover) and (pointer: fine) {
  .foot__link:hover { color: var(--color-secondary); }
  .foot__link:hover .foot__chev { opacity: 0.8; transform: translateX(3px); }

  .foot__soc:hover {
    border-color: rgba(243, 241, 237, 0.4);
    color: var(--color-secondary);
    transform: translateY(-2px);
  }

  .close__go:hover { transform: translateY(-2px); --btn-bg: #ffffff; }
  .close__go:hover .btn__arrow { transform: translateX(4px); }
  .close__talk:hover { color: var(--color-secondary); }
  .close__talk:hover .close__talkIco {
    border-color: rgba(243, 241, 237, 0.42);
    transform: scale(1.06);
  }
}

/* Primary: white on black. Set through the global .btn tokens rather than
   as a new component, so it inherits the shared padding, tracking and focus
   ring. Neither existing modifier fitted — --solid is ink-on-light and
   --onDark is an outline. */
.close__go {
  --btn-fg: var(--color-primary-dark);
  --btn-bg: var(--color-secondary);
  --btn-bd: var(--color-secondary);
  transition:
    transform 0.4s var(--ease-out),
    background-color 0.4s var(--ease-out);
}
.close__go .btn__arrow { transition: transform 0.4s var(--ease-out); }

/* Both actions are inert until a real contact route exists (sections.js).
   The cursor says so; nothing else about them changes. */
.close__go[aria-disabled="true"],
.close__talk[aria-disabled="true"] { cursor: default; }

/* ---- tablet: two columns -------------------------------------------------- */
@media (max-width: 1080px) {
  .close__top {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    row-gap: clamp(2rem, 4vw, 2.8rem);
  }
  /* The border-left trick only works on a single row. At two columns the
     dividers become one vertical rule between the pair and horizontal rules
     between the rows. */
  .close__top > * + * { padding-left: 0; border-left: 0; }
  .close__top > :nth-child(even) {
    padding-left: clamp(1.4rem, 3vw, 2.4rem);
    border-left: var(--rule-onDark);
  }
  .close__top > :nth-child(n + 3) {
    padding-top: clamp(1.8rem, 3.4vw, 2.4rem);
    border-top: var(--rule-onDark);
  }
}

/* ---- phone ---------------------------------------------------------------
   One column, no vertical dividers, and the booking bar stacks with both
   actions at full width. */
@media (max-width: 720px) {
  .close { padding-block: var(--section-y-md) var(--section-y-sm); }
  /* Behind a single stacked column it stops being texture and starts being
     a shape under the text. */
  .close__mark { display: none; }

  .close__top { grid-template-columns: minmax(0, 1fr); }
  .close__top > * + * {
    padding-left: 0;
    border-left: 0;
    padding-top: clamp(1.6rem, 6vw, 2.1rem);
    border-top: var(--rule-onDark);
  }
  .close__top > :nth-child(even) { padding-left: 0; border-left: 0; }

  .close__cta {
    flex-direction: column;
    align-items: stretch;
    min-height: 0;
    gap: 1.4rem;
    padding: clamp(1.3rem, 5vw, 1.7rem);
  }
  .close__ctaActions {
    flex-direction: column;
    align-items: stretch;
    gap: 1rem;
  }
  .close__ctaSep { display: none; }
  .close__go { justify-content: center; width: 100%; }
  .close__talk { justify-content: center; width: 100%; }

  .close__base { flex-direction: column; align-items: flex-start; gap: 0.5rem; }
}

@media (prefers-reduced-motion: reduce) {
  .foot__soc,
  .foot__chev,
  .close__talkIco,
  .close__go .btn__arrow { transition: none; }
}


/* ========================================================= NO-JS FALLBACK = */
/* Stacked panels only make sense when something can switch between them.
   Without JS they unstack into a plain, complete, readable list. */
/* Services needs nothing here any more: the markup renders the first service
   complete, and the second image slot is the only thing JavaScript hides. */
/* Testimonials needs nothing here either: the three cards are stacked in one
   grid cell only once JavaScript positions them, so without it they simply
   render in sequence and read as a list. The arrows and pager are inert. */
/* The slides share one grid cell, which only makes sense once JavaScript is
   positioning them. Without it the viewport unstacks into a plain column and
   the three testimonials simply read in sequence. */
.no-js .vox__arrow,
.no-js .vox__pager { display: none; }
.no-js .vox__viewport { display: block; perspective: none; }
.no-js .vox__slide { width: 100%; margin-bottom: var(--s4); }
.no-js .vox__slide:last-child { margin-bottom: 0; }

/* ============================================================ INNER PAGES == */
/* The shell every page that is not the homepage renders into. Structure only:
   these pages carry no design yet, and the rule here is that a visitor should
   meet a quiet, correctly-framed page rather than developer placeholder text.

   Three things have to be true for that to hold:

   the ground is light from the first paint. base.css paints html/body dark so
   the walkthrough never flashes white, and main.js only clears that once the
   hero has been scrolled past — a signal that never arrives on a page with no
   hero. `.is-page` says so up front.

   the content clears the fixed masthead, which is out of flow and would
   otherwise sit over the top of whatever gets designed in here.

   the page is tall enough to put the footer at the bottom of the viewport
   rather than half way up it. An empty <main> would collapse to nothing and
   leave the footer floating under the header.                               */

html:has(body.is-page),
body.is-page { background: var(--color-bg); }

.page-main {
  padding-top: var(--header-h);
  background: var(--color-bg);
}

/* Pure white, every section, on inner pages only.

   The About composition is a SHARED partial — the homepage needs it on the
   warm off-white that its light zone is built from, so this is scoped to
   .page-main rather than written onto .about. A global change here would
   silently repaint the homepage. */
.page-main .section,
.page-main .about { background: var(--color-bg); }

/* The services ribbon keeps overflow-y visible on the homepage ON PURPOSE: it
   spills downward and slides under the dark panel that rises next, and that
   overlap is the point of it. An inner page has no such panel — on
   services.php the section is followed straight by the footer, so the spill
   is 592px of vector painted where nothing can receive it. Clipped to the
   section here; the horizontal clip is unchanged. */
.page-main .services { overflow: clip; }

.page-placeholder {
  /* Empty on purpose. The height is what keeps the composition honest until
     there is something to put here; it comes out with the first real
     section. */
  min-height: max(38svh, 260px);
}

/* ============================================================ WHO WE ARE == */
/* Heading left, short copy right, three vertical cards below.

   Each card is ONE object: the photograph fills it edge to edge, a white wash
   covers the upper portion, and the numeral and copy are printed on that
   wash. The type is on the image, not in a panel above it — that overlap is
   the character of the composition, and a separated copy block underneath
   turned three editorial cards into three captioned thumbnails.

   What the card adds around that is an even shadow, so it still reads as a
   complete object standing on the page rather than a bleed.

   Nothing here declares a font, a heading size or a palette value. Every type
   style is a global class and every colour is a token.                       */

.who {
  padding-block: var(--section-y-lg);
  background: var(--color-bg);
}

/* ---- heading and intro --------------------------------------------------- */
.who__head {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.85fr);
  gap: clamp(1.6rem, 4vw, 4.5rem);
  align-items: end;
  margin-bottom: clamp(2.4rem, 4.4vw, 4rem);
}
.who__heading { margin-top: clamp(0.9rem, 1.6vw, 1.4rem); }
.who__ln { display: block; overflow: hidden; }
.who__ln > i { display: block; font-style: normal; }

.who__intro {
  display: grid;
  gap: clamp(0.7rem, 1.2vw, 1rem);
  max-width: 46ch;
  padding-bottom: clamp(0.2rem, 0.6vw, 0.5rem);
}

/* ---- the three cards ----------------------------------------------------
   One fixed aspect for all three. Because every card is the same shape and
   the copy is absolutely placed inside it, the numeral, the title and the
   point where the photograph emerges land on the same line in all three
   without any subgrid or height juggling. */
.who__panels {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(1.1rem, 2vw, 2rem);
}

.who__panel { position: relative; min-width: 0; }

.who__inner {
  position: relative;
  display: block;
  aspect-ratio: 3 / 4.4;
  border-radius: var(--r-lg);
  overflow: hidden;
  background: var(--color-bg);
  /* Even on all four sides. A shadow with a large Y offset pools under the
     card and leaves the top edge bare; a near-zero offset surrounds it. */
  box-shadow:
    0 0 0 1px rgba(13, 13, 15, 0.028),
    0 2px 6px rgba(13, 13, 15, 0.035),
    0 6px 30px rgba(13, 13, 15, 0.06);
  transition: transform 0.55s var(--ease-out), box-shadow 0.55s var(--ease-out);
}

/* ---- the photograph, filling the card ------------------------------------ */
.who__media {
  position: absolute;
  inset: 0;
  margin: 0;
  overflow: hidden;
}
.who__img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* The subject sits low in all three frames — the car body, the gloved hand,
     the rear of the finished car. Anchoring below centre keeps it whole and
     keeps it clear of the washed zone where the type lives. */
  object-position: 50% 68%;
  transform: scale(1.04);
  transition: transform 0.9s var(--ease-out);
}

/* ---- the wash ------------------------------------------------------------
   Opaque white behind the copy, then out quickly. This is what lets dark type
   sit on a photograph with no panel behind it. The fade begins just past the
   last line: held any longer it leaves a dead band of almost-white between
   the description and the point where the picture actually reads. */
.who__scrim {
  position: absolute;
  inset: 0;
  pointer-events: none;
  /* The fade starts as soon as the copy ends and finishes quickly.
     Previously it held near-opaque to 44% and did not clear until 66%,
     which left a long dead band of almost-white between the last line and
     the point where the photograph actually read. Opaque only as far as the
     text needs, then out. */
  background: linear-gradient(
    to bottom,
    #ffffff 0%,
    #ffffff 28%,
    rgba(255, 255, 255, 0.85) 32%,
    rgba(255, 255, 255, 0.4) 38%,
    rgba(255, 255, 255, 0) 46%
  );
}

/* ---- the copy, on the wash ----------------------------------------------- */
.who__body {
  position: absolute;
  inset: 0 0 auto 0;
  display: grid;
  /* FIXED first column, not auto. Inter's figures are proportional, so "01"
     measures narrower than "02" and "03" — an auto track then starts the copy
     at a different x in every card and gives each a different text measure. */
  grid-template-columns: clamp(3.6rem, 5.4vw, 5.6rem) minmax(0, 1fr);
  gap: clamp(0.7rem, 1.3vw, 1.2rem);
  align-items: start;
  padding: clamp(1.4rem, 2.2vw, 2rem) clamp(1.3rem, 2vw, 1.8rem) 0;
}

.who__mark {
  font-family: var(--font-display);
  /* Equal-width figures, so the three numerals occupy the same box. */
  font-variant-numeric: tabular-nums;
  font-size: clamp(2.9rem, 4.6vw, 4.8rem);
  font-weight: 700;
  line-height: 0.78;
  letter-spacing: -0.05em;
  color: rgba(13, 13, 15, 0.1);
  user-select: none;
  transition: color 0.55s var(--ease-out);
}

/* The offset the composition is built on: the copy starts below the numeral's
   cap rather than level with it. */
.who__copy {
  display: grid;
  align-content: start;
  gap: clamp(0.4rem, 0.75vw, 0.65rem);
  padding-top: clamp(0.5rem, 0.95vw, 0.9rem);
}

.who__tick {
  width: clamp(20px, 2vw, 28px);
  height: 2px;
  background: var(--color-heading);
  transform-origin: left center;
}

.who__title {
  font-family: var(--font-display);
  font-size: clamp(0.86rem, 0.98vw, 0.98rem);
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--color-heading);
}

.who__text {
  font-size: clamp(0.78rem, 0.86vw, 0.87rem);
  line-height: 1.6;
  color: var(--color-text);
  text-wrap: pretty;
}

/* ---- hover, fine pointers only ------------------------------------------- */
@media (hover: hover) and (pointer: fine) {
  .who__panel:hover .who__inner {
    transform: translateY(-4px);
    box-shadow:
      0 0 0 1px rgba(13, 13, 15, 0.03),
      0 4px 10px rgba(13, 13, 15, 0.04),
      0 14px 44px rgba(13, 13, 15, 0.09);
  }
  .who__panel:hover .who__img { transform: scale(1.075); }
  .who__panel:hover .who__mark { color: rgba(13, 13, 15, 0.15); }
}

/* ---- tablet, then phone -------------------------------------------------- */
@media (max-width: 1100px) {
  .who__panels { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .who__inner { aspect-ratio: 3 / 3.9; }
}

@media (max-width: 860px) {
  .who__head {
    grid-template-columns: minmax(0, 1fr);
    align-items: start;
    gap: clamp(1.1rem, 3vw, 1.6rem);
  }
  .who__intro { max-width: none; padding-bottom: 0; }
}

/* ---- one column: height from the content, not from a ratio ---------------
   A fixed aspect-ratio derives the card's HEIGHT from its WIDTH, which works
   while three cards share a row and each is narrow. On one column the card is
   the full container — 532px wide at a 583px viewport — so the ratio made it
   611px tall while the copy still ended at 113px. The wash then had to run to
   62% to reach the photograph, leaving 266px of dead white between the last
   line and the picture, and the wider the phone the worse it got.

   So at this width the ratio is dropped. The card becomes two rows: the copy
   at its natural height, and a photo band that is a real measurement rather
   than a by-product of the card's width. The scrim stops being a full-card
   wash and becomes a short seam over the top of the photograph, which is all
   it was ever doing once the copy was clear of it. */
@media (max-width: 760px) {
  .who__panels { grid-template-columns: minmax(0, 1fr); }

  .who__inner {
    aspect-ratio: auto;
    display: grid;
    grid-template-rows: auto var(--who-photo);
    --who-photo: clamp(200px, 42vw, 300px);
  }

  /* Explicit rows: source order is media, scrim, body, and the scrim stays
     absolutely positioned so it never claims a track of its own. */
  .who__body {
    position: static;
    grid-row: 1;
    padding-bottom: clamp(1.1rem, 3vw, 1.5rem);
  }
  .who__media {
    position: relative;
    inset: auto;
    grid-row: 2;
  }

  /* The seam. Opaque where it meets the copy block, gone a third of the way
     down the photograph — enough that the two melt together instead of
     butting at a hard edge, and short enough that the picture still reads. */
  .who__scrim {
    inset: auto 0 0 0;
    height: var(--who-photo);
    background: linear-gradient(
      to bottom,
      #ffffff 0%,
      rgba(255, 255, 255, 0.6) 20%,
      rgba(255, 255, 255, 0.22) 34%,
      rgba(255, 255, 255, 0) 48%
    );
  }

  .who__mark { font-size: clamp(2.5rem, 10vw, 3.4rem); }
}

@media (prefers-reduced-motion: reduce) {
  .who__inner, .who__img, .who__mark { transition: none; }
}

/* ================================================================= WAVE === */
/* The seam between two WHITE sections.

   There is no colour change to work with, so the curve cannot be drawn as an
   edge between two grounds — it has to be drawn as light. The path is filled
   pure white on white; the only thing that renders is the drop-shadow cast
   upward from its own contour, which traces the wave and nothing else.

   drop-shadow(), not box-shadow: box-shadow follows the element rectangle and
   would lay a straight line across the page. A filter shadow follows the
   painted alpha, so it follows the curve.

   The band is pulled UP into the section above it, never down into the one
   below. The first version used a negative BOTTOM margin, which lifted Who We
   Are underneath the wave and painted the white path straight over its kicker
   and the first line of its copy. The space above is the previous section's
   bottom padding — empty by definition — so that is the only safe direction
   to borrow from. */

.wave {
  position: relative;
  z-index: 0;
  display: block;
  width: 100%;
  height: clamp(52px, 6vw, 92px);
  margin-top: calc(clamp(52px, 6vw, 92px) * -0.55);
  pointer-events: none;
  /* 12% at an 8px blur. Rendered to a canvas and measured, that puts the
     darkest point of the contour at 234/255 — a 21-level step, which is a
     legible fold on white without ever becoming a grey band. The first pass
     was 4% over 16px and measured 247: technically present, invisible in
     practice. On white a soft edge has to be TIGHTER, not fainter. */
  filter: drop-shadow(0 -3px 8px rgba(13, 13, 15, 0.12));
}
.wave svg {
  display: block;
  width: 100%;
  height: 100%;
}
.wave path { fill: var(--color-bg); }

@media (max-width: 760px) {
  .wave {
    height: clamp(30px, 9vw, 44px);
    margin-top: calc(clamp(30px, 9vw, 44px) * -0.55);
    filter: drop-shadow(0 -2px 6px rgba(13, 13, 15, 0.13));
  }
}

/* ---- the dark seam --------------------------------------------------------
   Into the founder note, the one dark section on a light page.

   Everything about the white-on-white fold above is a workaround for having
   no colour change to draw with. Here there IS one, so the curve is a real
   edge between two grounds — filled charcoal, and the drop-shadow comes OFF.
   Kept, it would lay a grey halo along a boundary that is already the highest
   contrast edge on the page.

   The shape is deliberately not the same S. That one crests left and troughs
   right, which reads as motion; this seam is the page settling into its
   close, so it is a single symmetric swell — one broad rise to the centre and
   an even fall to both edges.

   Pulled up further than the light wave (0.72 against 0.55) because it has a
   solid bottom edge to land on the founder's top edge, and every pixel it
   does not borrow from Philosophy's bottom padding is a pixel of empty white
   between the curve and the black. */
.wave--dark,
.wave--onDark {
  --wave-h: clamp(52px, 6.2vw, 96px);
  height: var(--wave-h);
  margin-top: calc(var(--wave-h) * -0.72);
  filter: none;
}
/* Charcoal rising into white — white section above, dark section below. */
.wave--dark path { fill: var(--color-charcoal); }
/* And the inverse, for a dark section above and a white one below. Same
   geometry and the same swell, so every ground change on the page reads as
   one language; only which side is filled changes. */
.wave--onDark path { fill: var(--color-bg); }

@media (max-width: 760px) {
  .wave--dark,
  .wave--onDark {
    --wave-h: clamp(34px, 9vw, 54px);
    height: var(--wave-h);
    margin-top: calc(var(--wave-h) * -0.72);
    filter: none;
  }
}

/* ========================================================== PHILOSOPHY === */
/* Statement left, four value rows right, over the light automotive ground.

   Every type style is a global class and every colour is a token. The
   reference's gold is carried across as ink at low alpha — the kicker, the
   arcs, the ticks and the dashes are all the same charcoal the rest of the
   site uses, at the weight the gold had.

   Nothing here is an overlay trick: the background is the supplied image at
   full strength. It can be, because it is genuinely faint — its darkest pixel
   across 1.37M samples is 206/255, which still leaves --color-text at 5.20:1.
   Dimming it further would only cost the hexagons and the car their edges. */

.philosophy {
  position: relative;
  /* Contains the -1 layer below, so it paints under this section's content
     and above its own background — and cannot fall behind the page. */
  isolation: isolate;
  background-color: var(--color-bg);
}

/* The ground. A layer rather than a background on the section itself, because
   it has to be masked at both ends: this section sits between two of the
   white-on-white waves, and a hard edge where the texture starts or stops
   would draw a straight line right where the fold is supposed to be the only
   thing you see. The mask lets it emerge and recede instead. */
.philosophy::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background-image: url("../images/about/philosophy-bg-1600.webp");
  background-size: cover;
  background-position: 50% 50%;
  background-repeat: no-repeat;
  -webkit-mask-image: linear-gradient(
    to bottom,
    transparent 0,
    #000 clamp(60px, 7vw, 110px),
    #000 calc(100% - clamp(90px, 10vw, 150px)),
    transparent 100%
  );
  mask-image: linear-gradient(
    to bottom,
    transparent 0,
    #000 clamp(60px, 7vw, 110px),
    #000 calc(100% - clamp(90px, 10vw, 150px)),
    transparent 100%
  );
}

.phil__grid {
  display: grid;
  /* The left column gives width back to the rows. With the three rules gone
     the statement is only type, and it was already capped by
     .section-description's 46ch long before the column ran out. */
  grid-template-columns: minmax(0, 0.62fr) minmax(0, 1fr);
  gap: clamp(2.4rem, 6vw, 6.5rem);
  align-items: center;
}

/* ---- left: the statement ------------------------------------------------- */
.phil__lead { min-width: 0; }

/* The same kicker-to-heading step Who We Are uses, now that no rule sits
   between them — two sections on one page open the same way. */
.phil__heading { margin: 0 0 0 0; margin-top: clamp(0.9rem, 1.6vw, 1.4rem); }
.phil__ln { display: block; overflow: hidden; }
.phil__ln > i { display: block; font-style: normal; }

/* The heading's second tone is the GLOBAL .section-heading-accent, unchanged
   — the same grey Who We Are sets "For a reason." in, two sections up. An
   earlier pass overrode it one step darker here because the ground's darkest
   pixel puts it at 2.87:1 against a 3:1 floor for large text; that bought
   0.13 of contrast at the cost of two headings on one page not matching,
   which is the more visible defect. The ground is 250 behind these words
   typically and 236 at its worst ~1%, so the shortfall is a sliver under one
   soft diagonal, not the field the type sits on. */

.phil__copy {
  display: grid;
  /* Tight. The paragraphs are three beats of one statement, not three
     separate blocks — the rule-and-dot separators that used to justify the
     wider step are gone. */
  gap: clamp(0.45rem, 0.75vw, 0.65rem);
  margin-top: clamp(1.2rem, 2vw, 1.8rem);
}

/* ---- right: the four rows -------------------------------------------------
   Named areas rather than bare tracks, so the phone layout is a two-line
   template rather than a pile of overrides. */
.phil__rows {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
}

.phil__row {
  position: relative;
  display: grid;
  grid-template-columns: auto auto minmax(0, var(--phil-titlew)) minmax(0, 1fr);
  grid-template-areas: "icon tick title body";
  align-items: center;
  column-gap: clamp(1rem, 1.9vw, 1.9rem);
  padding-block: clamp(1.15rem, 2vw, 1.7rem);
  --phil-titlew: clamp(84px, 8.6vw, 124px);
}

/* Between rows only, never under the last one. It rides the row's own fade
   because it is part of the row, so the entrance needs no separate beat. */
.phil__row + .phil__row {
  border-top: 1px solid rgba(13, 13, 15, 0.09);
}

/* ---- the icon holder ----------------------------------------------------- */
.phil__icon {
  grid-area: icon;
  position: relative;
  width: clamp(48px, 4.6vw, 66px);
  height: clamp(48px, 4.6vw, 66px);
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--color-bg);
  /* The only depth in the section, and all of it is white on white. */
  box-shadow:
    0 1px 2px rgba(13, 13, 15, 0.04),
    0 8px 22px rgba(13, 13, 15, 0.07),
    inset 0 1px 0 rgba(255, 255, 255, 0.9);
  color: var(--color-heading);
}
.phil__icon svg {
  width: 42%;
  height: 42%;
  display: block;
}

/* One quarter of a ring, off the holder's upper-left shoulder. Only the top
   border is coloured, which gives a 90 degree arc centred at 12 o'clock; the
   rotation swings it round to 10:30 where the reference puts it. */
.phil__arc {
  position: absolute;
  inset: -14%;
  border-radius: 50%;
  border: 1px solid transparent;
  border-top-color: rgba(13, 13, 15, 0.28);
  transform: rotate(-45deg);
}

.phil__tick {
  grid-area: tick;
  justify-self: center;
  width: 1px;
  height: clamp(26px, 2.8vw, 44px);
  background: rgba(13, 13, 15, 0.16);
  transform-origin: center;
}

.phil__title {
  grid-area: title;
  font-family: var(--font-display);
  font-size: clamp(0.72rem, 0.86vw, 0.84rem);
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--color-heading);
}

.phil__body {
  grid-area: body;
  display: grid;
  justify-items: start;
  gap: clamp(0.6rem, 1vw, 0.9rem);
}
.phil__text {
  font-size: clamp(0.78rem, 0.92vw, 0.9rem);
  line-height: 1.6;
  color: var(--color-text);
  /* Capping the MEASURE rather than the track, so the grid never depends on
     the length of one sentence. Widened with the column — at 26ch the
     descriptions were wrapping tighter than the space beside them warranted. */
  max-width: 36ch;
  text-wrap: pretty;
}
/* Sentence per line where the copy is written that way. */
.phil__text > span { display: block; }
.phil__row:nth-child(1) .phil__text > span,
.phil__row:nth-child(3) .phil__text > span { display: inline; }

.phil__dash {
  display: block;
  width: clamp(18px, 1.8vw, 26px);
  height: 1px;
  background: var(--color-rule);
  transform-origin: left center;
}

/* ---- stacked ------------------------------------------------------------- */
@media (max-width: 960px) {
  .phil__grid {
    grid-template-columns: minmax(0, 1fr);
    gap: clamp(2.2rem, 6vw, 3.4rem);
    align-items: start;
  }
}

@media (max-width: 760px) {
  /* Smaller file for the smaller box — the ground is decorative, and at this
     width the 1600 is four times the pixels the layout can show. */
  .philosophy::before {
    background-image: url("../images/about/philosophy-bg-900.webp");
    /* cover on a tall narrow box crops to the middle, which is the one part
       of this image that is empty. Anchoring left-of-centre and high keeps
       the hexagons and the car in frame. */
    background-position: 22% 18%;
  }

  /* Title above, copy below, icon holding the left of both. */
  .phil__row {
    grid-template-columns: auto auto minmax(0, 1fr);
    grid-template-areas:
      "icon tick title"
      "icon tick body";
    align-items: center;
    row-gap: clamp(0.45rem, 1.6vw, 0.7rem);
    column-gap: clamp(0.85rem, 3.4vw, 1.3rem);
  }
  .phil__text { max-width: none; }
}

@media (prefers-reduced-motion: reduce) {
  .phil__tick, .phil__dash { transform: none; }
}

/* ============================================================= FOUNDER === */
/* One black field, split down the middle by a hairline.

   THE DIVIDER IS A GRID TRACK, not an absolutely placed line at a guessed
   percentage. A 1px column sits between the two content columns, so the split
   is wherever the grid says the middle is and the three can never disagree.
   The line inside that track bleeds far past the row and the section clips
   it, which is what makes it run the full height of the field instead of the
   height of the content.

   THE SERIF IS DELIBERATE AND CONTAINED. The approved reference sets this
   section's display type in a serif; --font-serif is loaded at one weight and
   reaches exactly two elements, the heading and the watermark. Everything
   else — the kicker, the note, the attribution — stays on the site face and
   on the global classes.

   Colour is the --onDark family and nothing else: --color-secondary for the
   bright tier, --color-onDark-soft for the quiet one, --color-onDark-rule for
   every line.                                                               */

.founder {
  position: relative;
  isolation: isolate;
  /* The watermark bleeds off the bottom and the divider past both ends. */
  overflow: hidden;
  padding-block: clamp(4.5rem, 8vw, 8.5rem);
}

/* THE DOUBLED SELECTOR IS LOad-BEARING. Inner pages carry
   `.page-main .section { background: var(--color-bg) }` — two classes, and a
   SHORTHAND, so it outranks a single `.founder` and resets both background
   longhands to white. This is the one section on a light page that is dark,
   so it has to match that specificity to state it. `.founder.section` does
   that without depending on the page shell the way `.page-main .founder`
   would. */
.founder.section {
  /* The same charcoal as the footer directly below, so the page bottom is one
     continuous dark field rather than two blacks meeting in a band. */
  background-color: var(--color-charcoal);
  /* One low pass of light off the top, the same device the close uses. */
  background-image:
    radial-gradient(120% 74% at 50% -12%, rgba(255, 255, 255, 0.05), transparent 64%);
}

/* ---- the split ------------------------------------------------------------ */
.founder__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 1px minmax(0, 0.78fr);
  column-gap: clamp(1.8rem, 4.4vw, 3.4rem);
  align-items: start;
}

.founder__split {
  position: relative;
  width: 1px;
  align-self: stretch;
}
.founder__split > i {
  position: absolute;
  left: 0;
  width: 1px;
  /* Far past the row at both ends; the section clips it back to its edges. */
  top: -60vh;
  bottom: -60vh;
  background: var(--color-onDark-rule);
  transform-origin: center;
}

/* ---- left: the statement --------------------------------------------------
   Centred against the note, which is the taller column. The grid stays
   align-items:start so the divider can still stretch and the note can still
   begin at the top. */
.founder__lead {
  min-width: 0;
  align-self: center;
}

.founder__kicker { color: var(--color-onDark-soft); }

.founder__rule {
  display: block;
  width: clamp(26px, 2.6vw, 38px);
  height: 1px;
  margin-block: clamp(0.9rem, 1.5vw, 1.25rem);
  background: var(--color-onDark-rule);
  transform-origin: left center;
}
.founder__rule--wide { width: clamp(84px, 11vw, 168px); }

/* The one departure from the global heading, and it is scoped to this
   section: the reference sets it in the serif, larger and lighter. Family and
   size both come from tokens (--font-serif, --fs-h2); weight and tracking are
   the serif's own requirements — Playfair at 600 with Inter's -0.028em is a
   different typeface's settings on the wrong face. */
.founder__heading {
  margin: 0;
  font-family: var(--font-serif);
  font-size: var(--fs-h2);
  font-weight: 400;
  /* Measured off the reference: 60px of leading on a ~48px face is 1.25, not
     the 1.14 the sans headings use. It also costs less to contain — see the
     mask padding below. */
  line-height: 1.25;
  letter-spacing: -0.005em;
  /* Cancels the first line's mask padding, so the heading still starts where
     the rule above it says it does. */
  margin-top: -0.06em;
}
/* Brand yellow, like every other accent on a dark ground. The weight stays
   at 400 — this heading is set lighter than the rest by design. */
.founder__heading .section-heading-accent {
  font-weight: 400;
  color: var(--color-brand);
}
.founder__ln { display: block; overflow: hidden; }
.founder__ln > i {
  display: block;
  font-style: normal;
  /* Playfair's glyph box is ~1.33em against a 1.25 line-height, so ascenders
     AND descenders hang outside the line box and an overflow:hidden mask
     shears both. Padding gives the mask the room at both ends; the negative
     margin below takes the same amount back out of the leading, so the lines
     still sit as tightly as the reference sets them.

     BOTH ends matter — the first pass padded only the bottom, which fixed the
     p of "simple" and left the whole cap line shaved by 6px. */
  padding-block: 0.06em;
}
.founder__ln + .founder__ln { margin-top: -0.12em; }

/* ---- the watermark --------------------------------------------------------
   Set in the serif to match the heading, bled off the bottom-left, and left
   at 5% — on this ground that resolves to about #181818, which is the
   reference's embossed-into-the-black reading rather than a graphic on it.

   The value lives HERE and only here; the entrance reads it back. */
.founder__mark {
  position: absolute;
  /* Dead centre of the field, behind both columns and the divider. Safe as a
     CSS transform because the entrance only ever touches this element's
     opacity — it never writes a matrix here. */
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  z-index: -1;
  font-family: var(--font-serif);
  font-size: clamp(7rem, 25vw, 22rem);
  font-weight: 400;
  line-height: 0.78;
  letter-spacing: -0.01em;
  color: var(--color-secondary);
  opacity: 0.05;
  pointer-events: none;
  user-select: none;
}

/* ---- right: the note ------------------------------------------------------
   Starts at the top now. The drop that used to sit here was pushing the note
   down to meet a top-aligned statement; the statement is centred against the
   note instead, so the offset would only make the section taller. */
.founder__note {
  min-width: 0;
}
.founder__note > p { max-width: 38ch; }
.founder__note > p + p { margin-top: clamp(0.9rem, 1.5vw, 1.3rem); }

/* The third paragraph is the one that lands. One step up the scale and one
   step up the ink — both existing tokens. */
.founder__lede {
  font-size: var(--fs-lead);
  color: var(--color-secondary);
  margin-top: clamp(1.5rem, 2.6vw, 2.4rem) !important;
}

.founder__by {
  display: grid;
  justify-items: start;
  gap: clamp(0.35rem, 0.7vw, 0.55rem);
}
/* The name is the section's third serif element, and the only italic one on
   the site. Real italic, not a synthesised slant — see head.php. Tracking
   comes down from the role's 0.22em because italic caps at that width stop
   reading as a name and start reading as spaced-out capitals. */
.founder__name {
  font-family: var(--font-serif);
  font-style: italic;
  font-size: clamp(0.92rem, 1.06vw, 1.06rem);
  font-weight: 400;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--color-secondary);
}
.founder__role {
  font-size: clamp(0.66rem, 0.78vw, 0.76rem);
  font-weight: 500;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--color-onDark-soft);
}

/* ---- stacked --------------------------------------------------------------
   The divider turns through ninety degrees with the layout: the same element,
   the same token, now a full-width rule between the statement and the note. */
@media (max-width: 860px) {
  .founder__grid {
    grid-template-columns: minmax(0, 1fr);
    row-gap: clamp(1.8rem, 6vw, 2.6rem);
    align-items: start;
  }

  .founder__split {
    width: auto;
    height: 1px;
    align-self: auto;
  }
  .founder__split > i {
    left: 0;
    right: 0;
    top: 0;
    bottom: auto;
    width: auto;
    height: 1px;
    transform-origin: left center;
  }

  .founder__note { padding-top: 0; }
  .founder__note > p { max-width: none; }

  /* Behind the note now rather than under the statement, and smaller, so it
     stays a texture on a screen this narrow instead of a shape. */
  .founder__mark {
    font-size: clamp(6rem, 34vw, 13rem);
    bottom: clamp(-2.4rem, -5vw, -1.2rem);
  }
}

@media (prefers-reduced-motion: reduce) {
  .founder__rule, .founder__split > i { transform: none; }
}

/* ============================================================= JOURNEY === */
/* Four milestones as one ascending staircase.

   THE CLIMB IS DERIVED, NOT AUTHORED. Every step shares one base height and
   adds --i risers to it, where --i is its index. Four nth-child lines set the
   index and nothing else; the heights, the year offsets and the entrance all
   read off the same number. A fifth milestone is one <li> and one line.

   The panels stand on a COMMON BASELINE (align-items: end) and grow upward,
   which is what makes the row of dark treads climb. Sizing them from the top
   instead would have staggered the bottoms and read as four loose cards.

   No card has an outline. The only line in the whole staircase is the dark
   tread across each panel's top, turning a short way down its left edge —
   the thickness of the step, not a border.                                  */

.journey { background: var(--color-bg); }

/* Always paints above the staircase. On a wide screen the two overlap
   vertically by design (see the pull-up below); the ink never collides, but
   if the copy ever grew this guarantees the heading is on top rather than
   behind a panel. */
.jrn__head { position: relative; z-index: 1; }

/* ---- heading -------------------------------------------------------------- */
.jrn__rule {
  display: block;
  width: clamp(26px, 2.6vw, 38px);
  height: 1px;
  margin-block: clamp(0.9rem, 1.5vw, 1.25rem);
  background: var(--color-rule);
  transform-origin: left center;
}

/* The GLOBAL heading, untouched — same face, size, weight and tracking as
   Who We Are and Our Philosophy. The reference sets this in a serif, but a
   section heading that differs from every other section heading on the page
   is the more visible defect; the serif stays where it belongs, on the
   founder note and on the oversized year watermarks below.

   Nothing here declares type. .jrn__ln is the same mask Who We Are uses, and
   it needs no padding because Inter's glyph box fits its line box. */
.jrn__heading { margin: 0; }
.jrn__ln { display: block; overflow: hidden; }
.jrn__ln > i { display: block; font-style: normal; }

.jrn__lede {
  margin-top: clamp(1.1rem, 1.8vw, 1.6rem);
  max-width: 42ch;
}

/* ---- the staircase --------------------------------------------------------
   The top padding is the tallest year's slot: step 04's numerals sit above
   its tread, which is the highest point in the section. */
.jrn__steps {
  list-style: none;
  margin: 0;
  padding: 0;
  /* Exactly the year's slot and no more. This padding is the only thing
     between the lede and the top of the staircase, and the one thing standing
     in it is type at 5% — so every pixel beyond what the numerals need reads
     as blank page. It was 148px against a year that is 84px tall. */
  padding-top: clamp(52px, 6.6vw, 100px);
  margin-top: clamp(1rem, 2vw, 2rem);
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  /* Nearly touching, so the four read as one flight rather than four objects
     in a row. */
  column-gap: clamp(3px, 0.6vw, 9px);
  align-items: end;

  /* The base is the FIRST step's natural height — content plus its foot — so
     step 01 has no dead space at all and each step above it carries only the
     riser it needs. At 22vw the base was 90px taller than anything standing
     in it, and that surplus was then inherited by all four. */
  --jrn-base: clamp(150px, 16vw, 240px);
  --jrn-rise: clamp(22px, 3vw, 44px);
  --jrn-tread: clamp(4px, 0.45vw, 6px);
}

.jrn__step {
  position: relative;
  /* Its own stacking context, so the year can sit at -1: above the panel's
     white but under the copy. */
  z-index: 0;
  min-width: 0;
  min-height: calc(var(--jrn-base) + var(--i) * var(--jrn-rise));
  background: var(--color-bg);
  border-top: var(--jrn-tread) solid var(--color-heading);
  border-radius: clamp(6px, 0.8vw, 10px) clamp(6px, 0.8vw, 10px) 0 0;
  /* Very subtle, and wide rather than dark — the steps should look lifted off
     the page, not drawn on it. */
  box-shadow:
    0 1px 2px rgba(13, 13, 15, 0.035),
    0 12px 34px rgba(13, 13, 15, 0.07);
  padding: clamp(1.3rem, 2vw, 1.9rem) clamp(1.1rem, 1.7vw, 1.6rem)
           clamp(1.8rem, 3vw, 2.8rem);
}

.jrn__step:nth-child(1) { --i: 0; }
.jrn__step:nth-child(2) { --i: 1; }
.jrn__step:nth-child(3) { --i: 2; }
.jrn__step:nth-child(4) { --i: 3; }

/* The tread turning the corner. An absolutely positioned child measures from
   the PADDING box, so top:0 is already below the border — this picks up
   exactly where the dark top edge stops and runs a short way down. */
.jrn__step::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  width: var(--jrn-tread);
  height: clamp(10px, 1.5vw, 20px);
  background: var(--color-heading);
}

/* ---- the year -------------------------------------------------------------
   Above the tread on a wide screen, left-aligned to its own step. Held to the
   step's width so it can never reach across into the next panel. */
.jrn__year {
  position: absolute;
  z-index: -1;
  left: 0;
  bottom: calc(100% + clamp(6px, 1vw, 14px));
  font-family: var(--font-serif);
  /* Sized by the WIDEST label, not the average. "TODAY" is five caps against
     four figures and measures ~3.2x its own font-size; at 7.2vw that put it
     11px past the right edge of step 04, which is the last panel in the row
     and has nothing but container padding beyond it. */
  font-size: clamp(2.1rem, 6.8vw, 6.2rem);
  font-weight: 400;
  line-height: 0.86;
  letter-spacing: -0.01em;
  text-transform: uppercase;
  white-space: nowrap;
  color: var(--color-wash);
  pointer-events: none;
  user-select: none;
}

/* ---- the milestone --------------------------------------------------------
   Content sits at the TOP of every panel, so the numbers, titles and copy all
   start the same distance below their own tread however tall the step is. */
.jrn__body {
  display: grid;
  justify-items: start;
  gap: 0;
}

.jrn__num {
  font-family: var(--font-display);
  font-variant-numeric: tabular-nums;
  font-size: clamp(0.72rem, 0.84vw, 0.84rem);
  font-weight: 500;
  letter-spacing: 0.12em;
  /* NOT --color-muted. That grey is tuned for large display type and measures
     3.41:1 on plain white at this size — under the 4.5:1 floor before the
     year is even behind it, and 3.05:1 once it is. The body token reads as
     the same quiet tier against the black title and clears both. */
  color: var(--color-text);
}
.jrn__tick {
  width: clamp(16px, 1.6vw, 24px);
  height: 1px;
  margin-block: clamp(0.6rem, 1vw, 0.9rem);
  background: var(--color-rule);
  transform-origin: left center;
}
/* The site face too. With the section heading back on Inter, a serif h3
   underneath it would read as a leftover rather than a decision. */
.jrn__title {
  font-family: var(--font-display);
  font-size: clamp(1.05rem, 1.35vw, 1.35rem);
  font-weight: 600;
  line-height: 1.24;
  letter-spacing: -0.02em;
  color: var(--color-heading);
}
.jrn__text {
  margin-top: clamp(0.75rem, 1.2vw, 1.05rem);
  font-size: clamp(0.82rem, 0.94vw, 0.95rem);
  line-height: 1.66;
  color: var(--color-text);
  text-wrap: pretty;
}

/* ---- wide: the staircase rises BESIDE the heading -------------------------
   In the reference the tallest step's tread sits above the lede's last line —
   the flight climbs into the heading's band on the right rather than starting
   underneath it, which is what stops a 250px void opening under the lede.

   Gated at 1200px because it depends on horizontal clearance that does not
   exist below it. The heading sets ~400px of ink at 40px; at 800px viewport
   step 03 begins at 402px and the two would collide. At 1200 step 03 begins
   at 603 against 473 of heading and lede, and the margin only grows from
   there. */
@media (min-width: 1200px) {
  .jrn__steps { margin-top: clamp(-130px, -8vw, -60px); }
}

/* ---- tablet --------------------------------------------------------------- */
@media (max-width: 1024px) {
  .jrn__steps {
    --jrn-base: clamp(200px, 26vw, 260px);
    --jrn-rise: clamp(24px, 3.4vw, 40px);
  }
  .jrn__year { font-size: clamp(1.9rem, 6.4vw, 3.6rem); }
}

/* ---- stacked --------------------------------------------------------------
   One column. The staircase idea survives as a progressive INDENT rather than
   a rise — each milestone steps a little further in than the one above it —
   and the year moves inside the panel, behind the copy, because a year
   floating above every step would only add four gaps to a long scroll. */
@media (max-width: 760px) {
  .jrn__steps {
    grid-template-columns: minmax(0, 1fr);
    row-gap: clamp(0.9rem, 3vw, 1.4rem);
    padding-top: 0;
    align-items: stretch;
    --jrn-indent: clamp(8px, 2.6vw, 18px);
  }

  .jrn__step {
    min-height: 0;
    /* The indent shrinks the panel rather than pushing it out of the
       container, so the staircase can never become horizontal overflow. */
    margin-left: calc(var(--i) * var(--jrn-indent));
    padding-block: clamp(1.2rem, 4.4vw, 1.6rem) clamp(1.3rem, 4.6vw, 1.7rem);
    box-shadow: 0 1px 2px rgba(13, 13, 15, 0.04), 0 8px 20px rgba(13, 13, 15, 0.055);
  }

  .jrn__year {
    left: auto;
    right: clamp(0.7rem, 3vw, 1.2rem);
    bottom: auto;
    top: 50%;
    transform: translateY(-50%);
    font-size: clamp(2.4rem, 15vw, 4.6rem);
  }

  .jrn__text { max-width: 34ch; }
}

@media (prefers-reduced-motion: reduce) {
  .jrn__rule, .jrn__tick { transform: none; }
}

/* ========================================================= SERVICE HERO === */
/* The service-detail opener: one full-bleed photograph, one left-to-right
   scrim, and the copy held to the dark half.

   THE SCRIM IS SIZED FROM THE PHOTOGRAPH, NOT BY EYE. This frame is not dark
   on the left — there is a sunset behind the tree and a wet floor throwing it
   back, and across the left 45% the 99th-percentile pixel is 247/255. White
   copy laid on that untreated measures under 1.5:1. The stops below hold
   ~0.62 alpha out to the 45% mark, which is what puts --color-secondary above
   4.5:1 on the brightest thing under it, and then fall away fast so the car
   and the mitt keep their contrast.

   Nothing here declares a font or a heading size: the kicker, heading and
   copy are the global classes in their --onDark form, and the CTA is .btn.   */

.svchero {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  display: grid;
  align-items: center;
  /* Fills most of the first viewport under the masthead — .page-main already
     reserves --header-h, so this measures the space that is actually left.
     Capped so it never becomes a poster on a tall monitor. */
  min-height: clamp(480px, calc(100svh - var(--header-h)), 820px);
  background-color: var(--color-dark);
}

.svchero__img {
  position: absolute;
  inset: 0;
  z-index: -2;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Set per page — every service photograph frames its subject differently,
     so the page states the crop and this is only the fallback. */
  object-position: var(--svchero-pos, 62% 50%);
}

.svchero__scrim {
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background: linear-gradient(
    to right,
    rgba(9, 9, 10, 0.94) 0%,
    rgba(9, 9, 10, 0.88) 22%,
    rgba(9, 9, 10, 0.74) 40%,
    rgba(9, 9, 10, 0.4) 54%,
    rgba(9, 9, 10, 0.12) 68%,
    rgba(9, 9, 10, 0) 80%
  );
}

.svchero__inner { width: 100%; }

.svchero__copy {
  display: grid;
  justify-items: start;
  /* The dark half. 46% of the container is ~42% of the viewport once the
     container's own padding is counted — the band the reference sets the copy
     in, and the band the scrim is built to cover. */
  max-width: min(46%, 620px);
  padding-block: clamp(2rem, 5vh, 4rem);
}

/* Full strength, not --color-onDark-soft. That 62% grey is tuned for a flat
   charcoal panel; here the kicker crosses a lit workshop window at 255, and
   at 62% it measured 2.91:1 on a phone. Opaque --color-secondary clears the
   same pixel without asking the scrim to swallow the detailing action. */
.svchero__kicker { color: var(--color-secondary); }

.svchero__heading {
  margin-top: clamp(1.1rem, 2.2vh, 1.7rem);
}
.svchero__ln { display: block; overflow: hidden; }
.svchero__ln > i { display: block; font-style: normal; }

.svchero__lede {
  margin-top: clamp(1.1rem, 2.2vh, 1.7rem);
  max-width: 40ch;
}

.svchero__cta {
  margin-top: clamp(1.6rem, 3.4vh, 2.6rem);
}
.svchero__arrow {
  width: clamp(18px, 1.5vw, 22px);
  height: auto;
  /* Its own transition, so the nudge is independent of .btn's colour fade. */
  transition: transform var(--dur) var(--ease-out);
}
@media (hover: hover) and (pointer: fine) {
  .svchero__cta:hover .svchero__arrow { transform: translateX(5px); }
  .svchero__cta:hover { transform: translateY(-1px); }
}
.svchero__cta { transition: transform var(--dur) var(--ease-out); }

/* ---- narrower desktops ----------------------------------------------------
   The copy column keeps its share of the frame, but the scrim has to reach
   further right as the text does. */
@media (max-width: 1100px) {
  .svchero__copy { max-width: min(54%, 560px); }
  /* The strong band has to reach as far as the COPY does, and here the copy
     runs to 54%. Held out to 52% then dropped: the previous ramp had already
     fallen to 0.69 by the time the lede's longest line ended, over a lit part
     of the frame, and that line measured 3.90:1. */
  .svchero__scrim {
    background: linear-gradient(
      to right,
      rgba(9, 9, 10, 0.94) 0%,
      rgba(9, 9, 10, 0.9) 30%,
      rgba(9, 9, 10, 0.82) 52%,
      rgba(9, 9, 10, 0.5) 66%,
      rgba(9, 9, 10, 0.16) 78%,
      rgba(9, 9, 10, 0) 90%
    );
  }
}

/* ---- phone ----------------------------------------------------------------
   A left-to-right scrim cannot work once the copy spans the width, so the
   gradient turns through ninety degrees: the frame stays open at the top
   where the car and the mitt are, and the ground darkens under the type.

   The photograph is NOT swapped — only the crop moves. Anchoring further
   right and higher keeps the mitt and the front of the car in a portrait
   frame instead of centring on the door. */
@media (max-width: 760px) {
  .svchero {
    min-height: clamp(520px, calc(100svh - var(--header-h)), 760px);
    align-items: end;
  }

  /* 86%, not 70%. At this aspect the crop takes the full HEIGHT of the frame
     and a 428px-wide window of it — at 70% that window ended at image x 1249
     and cut the mitt in half. 86% frames x 1008–1436: the headlight, the wet
     bonnet and the mitt whole. */
  .svchero__img { object-position: var(--svchero-pos-m, 86% 40%); }

  /* Light across the top third so the car and the mitt keep their contrast,
     then a hard ramp through the band the copy occupies. The ramp starts at
     46% because that is where the kicker's first line lands. */
  .svchero__scrim {
    background: linear-gradient(
      to bottom,
      rgba(9, 9, 10, 0.28) 0%,
      rgba(9, 9, 10, 0.38) 30%,
      rgba(9, 9, 10, 0.66) 46%,
      rgba(9, 9, 10, 0.84) 58%,
      rgba(9, 9, 10, 0.9) 74%,
      rgba(9, 9, 10, 0.94) 100%
    );
  }

  .svchero__copy {
    max-width: none;
    padding-block: clamp(1.6rem, 4vh, 2.4rem) clamp(2.2rem, 6vh, 3.4rem);
  }
  .svchero__lede { max-width: 42ch; }

  /* The ONLY place the global 40px heading is scaled, and it is scaled here
     because this heading is a two-line statement rather than a paragraph:
     each line lives in its own masked span, so a line that wraps does not
     read as a longer heading, it reads as the composition breaking.

     40px is simply wider than a phone. The longest line on the set — the
     ceramic page's "Bonded to the paint." — measures 367px at 40px, against
     a 280px column at 320 and 335px at 375; every one of the four heroes
     broke into four lines at 320. 9.3vw is the size at which THAT line
     still fits at 320, and it caps back at the authored 40px from 431px up,
     so nothing at or above a large phone changes and no heading outside
     this hero is touched. */
  .svchero__heading { font-size: clamp(1.8rem, 9.3vw, 2.5rem); }
}

@media (prefers-reduced-motion: reduce) {
  .svchero__arrow, .svchero__cta { transition: none; }
}

/* ====================================================== WHAT'S INCLUDED === */
/* Exterior and interior either side of a ghosted top-view car.

   ONE CONTAINER CARRIES THE DEPTH. .inc__shell holds the border, the radius
   and the only box-shadow in the section; every item inside it is flat and
   separated by a hairline. Shadowing the rows individually would turn one
   panel into eight cards, which is the thing this composition is not.

   The centre column sits between the two lists in SOURCE order, so the
   stacked layout reads exterior, centre, interior without reordering
   anything — the grid just becomes one column.

   Nothing here declares a font or a heading size. The only serif is the
   COMPLETE watermark, on the rule the founder note and the journey years
   already set: oversized decorative type is serif, everything read is Inter. */

.included { background: var(--color-bg); }

.inc__shell {
  background: var(--color-bg);
  border: var(--rule);
  border-radius: var(--r-lg);
  /* Wide and very low. The panel should lift off the page, not sit on a
     drawn edge. */
  box-shadow:
    0 1px 2px rgba(13, 13, 15, 0.03),
    0 14px 44px rgba(13, 13, 15, 0.06);
  padding: clamp(2rem, 4.4vw, 4rem) clamp(1.2rem, 3.4vw, 3.4rem)
           clamp(2.2rem, 4.6vw, 4.2rem);
}

/* ---- centred head --------------------------------------------------------- */
/* Opens exactly like every other section on the site: left aligned, no rule
   between the kicker and the heading. The reference centres this one and puts
   a hairline under the kicker, but a section opener that differs from every
   other section opener is the more visible defect — and the same hairline has
   now been pulled twice. The BODY stays symmetric; only the head aligns. */
.inc__head {
  display: grid;
  justify-items: start;
  text-align: left;
  margin-bottom: clamp(2rem, 4vw, 3.4rem);
}

.inc__heading { margin-top: clamp(0.9rem, 1.6vw, 1.4rem); }
.inc__ln { display: block; overflow: hidden; }
.inc__ln > i { display: block; font-style: normal; }

/* No max-width override — .section-description's own 46ch, the same measure
   Who We Are and Our Philosophy set their copy in. */
.inc__lede { margin-top: clamp(0.9rem, 1.6vw, 1.4rem); }

/* ---- the three columns ---------------------------------------------------- */
.inc__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 0.72fr) minmax(0, 1fr);
  gap: clamp(1.4rem, 3vw, 3rem);
  align-items: start;
}

.inc__col { min-width: 0; }

/* EXTERIOR above, then the count and its label on one baseline. */
.inc__colhead { margin-bottom: clamp(1rem, 2vw, 1.6rem); }

.inc__side {
  font-size: clamp(0.66rem, 0.78vw, 0.76rem);
  font-weight: 600;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--color-text);
}

.inc__count {
  display: flex;
  align-items: baseline;
  gap: clamp(0.6rem, 1.1vw, 1rem);
  margin-top: clamp(0.35rem, 0.7vw, 0.6rem);
}
.inc__count-n {
  font-family: var(--font-display);
  font-variant-numeric: tabular-nums;
  font-size: clamp(2.1rem, 3.4vw, 3.4rem);
  font-weight: 600;
  line-height: 1;
  letter-spacing: -0.03em;
  color: var(--color-heading);
}
.inc__count-l {
  font-size: clamp(0.66rem, 0.78vw, 0.76rem);
  font-weight: 600;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--color-text);
}

/* ---- the items -----------------------------------------------------------
   Number, hairline, copy. No background, no box — the only separation is the
   rule between rows, and the last row does not get one. */
.inc__list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.inc__item {
  display: grid;
  grid-template-columns: auto 1px minmax(0, 1fr);
  gap: clamp(0.75rem, 1.5vw, 1.25rem);
  align-items: stretch;
  padding-block: clamp(0.95rem, 1.8vw, 1.4rem);
}
.inc__item + .inc__item { border-top: var(--rule); }

.inc__num {
  font-family: var(--font-display);
  font-variant-numeric: tabular-nums;
  font-size: clamp(1.1rem, 1.5vw, 1.5rem);
  font-weight: 400;
  line-height: 1.1;
  letter-spacing: -0.02em;
  /* Quiet, but never below the body tier — --color-muted measures 3.41:1 at
     this size and is reserved for large display type. */
  color: var(--color-text);
  opacity: 0.55;
}

.inc__bar {
  width: 1px;
  background: var(--color-rule-soft);
  transform-origin: top center;
}

.inc__body { min-width: 0; }

.inc__title {
  font-family: var(--font-display);
  font-size: clamp(0.72rem, 0.84vw, 0.84rem);
  font-weight: 700;
  line-height: 1.3;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--color-heading);
}
.inc__text {
  margin-top: clamp(0.4rem, 0.7vw, 0.6rem);
  font-size: clamp(0.78rem, 0.88vw, 0.88rem);
  line-height: 1.62;
  color: var(--color-text);
  text-wrap: pretty;
}

/* ---- the centre ----------------------------------------------------------
   The car is a stroke drawing behind the word, both decorative. The column is
   a grid with one cell so the two stack on the same centre line. */
.inc__centre {
  position: relative;
  display: grid;
  justify-items: center;
  align-content: center;
  min-height: 100%;
  padding-block: clamp(1rem, 2.6vw, 2.6rem);
  pointer-events: none;
  user-select: none;
}

.inc__car {
  position: absolute;
  top: 50%;
  left: 50%;
  width: clamp(120px, 13vw, 200px);
  height: auto;
  transform: translate(-50%, -50%);
  color: var(--color-rule-soft);
}

.inc__word {
  position: relative;
  font-family: var(--font-serif);
  /* Sized to FIT THE CENTRE COLUMN, not picked by eye. COMPLETE sets about
   5.8x its own font-size in this face, and the centre track is ~20.6% of
   the viewport until the container caps at 1480 and then holds near
   295px. 4.4vw put the word 44px wider than its column at 900 and 72px
   wider at 1440, spilling it across both lists. */
  font-size: clamp(1.6rem, 3.2vw, 3rem);
  font-weight: 400;
  line-height: 1;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--color-rule-soft);
  text-align: center;
}
.inc__sub {
  position: relative;
  margin-top: clamp(0.8rem, 1.6vw, 1.5rem);
  font-size: clamp(0.62rem, 0.74vw, 0.72rem);
  font-weight: 600;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: var(--color-muted);
  text-align: center;
}

/* ---- tablet --------------------------------------------------------------- */
@media (max-width: 1024px) {
  .inc__grid { gap: clamp(1rem, 2.4vw, 2rem); }
  .inc__car { width: clamp(100px, 12vw, 150px); }
}

/* ---- stacked --------------------------------------------------------------
   One column, and the centre becomes a divider between the two lists rather
   than a backdrop behind them: the car shrinks and fades, and COMPLETE sits
   on it at a size that belongs to a phone. */
@media (max-width: 860px) {
  .inc__grid {
    grid-template-columns: minmax(0, 1fr);
    gap: clamp(1.6rem, 5vw, 2.4rem);
  }

  .inc__centre {
    /* The car is the constrained thing here, so the band is sized FROM it:
       one variable drives the drawing's height and the floor this block
       needs to hold it. Sizing the car by width instead left it 5px
       taller than the band, crossing the hairlines into both lists. */
    --inc-car-h: clamp(88px, 25vw, 130px);
    min-height: calc(var(--inc-car-h) + clamp(3.2rem, 12vw, 5.2rem));
    padding-block: clamp(1.6rem, 6vw, 2.6rem);
    border-block: var(--rule);
  }
  .inc__car {
    /* Sized on its HEIGHT, the axis that runs out first. */
    height: var(--inc-car-h);
    width: auto;
    /* Fainter via COLOUR, never opacity. The entrance fades this element
       with autoAlpha, which writes opacity:1 inline on completion and
       would silently discard an authored 0.5 — the same way it once blew
       out the founder watermark. Colour is a channel GSAP never touches. */
    color: var(--color-wash);
  }
  .inc__word { font-size: clamp(1.7rem, 9vw, 2.6rem); }

  .inc__count-n { font-size: clamp(1.7rem, 7vw, 2.4rem); }
}

@media (prefers-reduced-motion: reduce) {
  .inc__bar { transform: none; }
}

/* ======================================================= WHY IT MATTERS === */
/* Five reasons strung along one timeline.

   ONE RAIL, NOT FIVE SEGMENTS. A single element spans the row and the dots
   sit on it, which is what keeps them on one axis however unevenly the copy
   below them wraps, and what lets the entrance draw the line once rather than
   animating five pieces into alignment.

   On a phone that rail turns ninety degrees — same element, same token, one
   vertical line with the dots on it — and the numerals move out from behind
   the copy to beside it, where a 90px numeral has room to be faint without
   sitting under the text.

   Nothing here declares a font or a heading size.                           */

.why { background: var(--color-bg); }

/* ---- head ----------------------------------------------------------------- */
.why__head {
  display: grid;
  justify-items: center;
  text-align: center;
  /* The track below opens its own space for the numerals, so this only has
     to be the gap between the copy and the top of those. 6vw here plus the
     track's 6vw put 173px of mostly empty page between the lede and the
     rail. */
  margin-bottom: clamp(1.6rem, 3vw, 2.8rem);
}
.why__kicker { justify-content: center; }
.why__heading { margin-top: clamp(0.9rem, 1.6vw, 1.4rem); }
.why__ln { display: block; overflow: hidden; }
.why__ln > i { display: block; font-style: normal; }
.why__lede { margin-top: clamp(1rem, 1.8vw, 1.6rem); }

/* ---- the timeline --------------------------------------------------------- */
.why__track {
  position: relative;
  /* The numerals sit above the rail and are bled off the top of the row, so
     the track opens the space they need. */
  padding-top: clamp(52px, 5.4vw, 82px);
}

.why__rail {
  position: absolute;
  left: 0;
  right: 0;
  top: clamp(52px, 5.4vw, 82px);
  height: 1px;
  background: var(--color-rule-soft);
  transform-origin: left center;
}

/* THREE SHARED ROWS — tick, title, copy — carried into every column by
   subgrid. Left to itself each item sized its own rows, so a one-line title
   started its paragraph higher than a two-line one and the five columns read
   as five different objects. This is what puts them on one line. */
.why__items {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  grid-template-rows: auto auto auto;
}

.why__item {
  position: relative;
  min-width: 0;
  grid-row: span 3;
  display: grid;
  grid-template-rows: subgrid;
  padding: clamp(1.5rem, 2.6vw, 2.2rem) clamp(0.9rem, 1.6vw, 1.6rem) 0;
}

/* Where subgrid is unavailable, reserve the two lines the longest title needs
   so the paragraphs still line up. */
@supports not (grid-template-rows: subgrid) {
  .why__items { grid-template-rows: none; }
  .why__item { grid-row: auto; display: block; }
  .why__title { min-height: calc(1.45em * 2); }
}
/* Hairline between columns, never a box. */
.why__item + .why__item { border-left: var(--rule); }

/* Bled up over the rail, behind nothing — the row's top padding is its
   space. */
.why__num {
  position: absolute;
  top: calc(clamp(52px, 5.4vw, 82px) * -1);
  left: clamp(0.9rem, 1.6vw, 1.6rem);
  font-family: var(--font-serif);
  font-variant-numeric: tabular-nums;
  font-size: clamp(3rem, 5.2vw, 5.6rem);
  font-weight: 400;
  line-height: 1;
  letter-spacing: 0.01em;
  color: var(--color-wash);
  user-select: none;
}

/* Sits ON the rail: the row's top padding is the rail's offset, so -50% of
   its own height puts its centre exactly on the line. */
.why__dot {
  position: absolute;
  top: 0;
  left: clamp(0.9rem, 1.6vw, 1.6rem);
  width: 9px;
  height: 9px;
  margin-top: -4.5px;
  border-radius: 50%;
  background: var(--color-heading);
}

.why__tick {
  display: block;
  width: clamp(18px, 1.8vw, 26px);
  height: 2px;
  margin-bottom: clamp(0.7rem, 1.2vw, 1rem);
  background: var(--color-heading);
  transform-origin: left center;
}

.why__title {
  font-family: var(--font-display);
  font-size: clamp(0.72rem, 0.84vw, 0.84rem);
  font-weight: 700;
  line-height: 1.45;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--color-heading);
}
.why__text {
  margin-top: clamp(0.7rem, 1.2vw, 1rem);
  font-size: clamp(0.78rem, 0.88vw, 0.88rem);
  line-height: 1.62;
  color: var(--color-text);
  text-wrap: pretty;
}

/* ---- the closing note -----------------------------------------------------
   A hairline frame and one small ink square. No fill behind the copy, so it
   reads as a note on the page rather than a second panel. */
.why__note {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: center;
  gap: clamp(1.1rem, 2.2vw, 2rem);
  margin-top: clamp(3rem, 5.5vw, 5rem);
  padding: clamp(1rem, 1.8vw, 1.5rem) clamp(1.2rem, 2.2vw, 1.9rem);
  border: var(--rule);
}

.why__badge {
  display: grid;
  place-items: center;
  width: clamp(46px, 4.4vw, 62px);
  height: clamp(46px, 4.4vw, 62px);
  background: var(--color-heading);
  color: var(--color-secondary);
}
.why__badge svg { width: 46%; height: 46%; display: block; }

.why__note-t {
  font-family: var(--font-display);
  font-size: clamp(0.78rem, 0.92vw, 0.92rem);
  font-weight: 700;
  line-height: 1.35;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-heading);
}
.why__note-s {
  margin-top: clamp(0.3rem, 0.6vw, 0.5rem);
  font-size: clamp(0.78rem, 0.88vw, 0.88rem);
  line-height: 1.6;
  color: var(--color-text);
}

/* ---- the rail turns ninety degrees ---------------------------------------- */
@media (max-width: 980px) {
  .why__track {
    padding-top: 0;
    --why-rail-x: clamp(26px, 7vw, 44px);
  }

  .why__rail {
    left: var(--why-rail-x);
    right: auto;
    top: 0;
    bottom: 0;
    width: 1px;
    height: auto;
    transform-origin: center top;
  }

  .why__items { grid-template-columns: minmax(0, 1fr); grid-template-rows: none; }
  .why__item { grid-row: auto; display: block; }

  .why__item {
    padding: 0 0 clamp(1.8rem, 5vw, 2.6rem) calc(var(--why-rail-x) + clamp(1rem, 3.4vw, 1.6rem));
    border-left: 0;
  }
  .why__item:last-child { padding-bottom: 0; }

  /* Beside the copy now, not over it. */
  .why__num {
    position: absolute;
    top: -0.12em;
    left: 0;
    width: var(--why-rail-x);
    font-size: clamp(1.5rem, 6vw, 2.1rem);
    text-align: left;
    transform: translateX(calc(-100% - clamp(0.5rem, 2vw, 0.9rem)));
  }

  .why__dot {
    top: 0.6em;
    left: var(--why-rail-x);
    margin-top: 0;
    margin-left: -4.5px;
  }

  .why__note {
    grid-template-columns: minmax(0, 1fr);
    justify-items: start;
    gap: clamp(0.9rem, 3vw, 1.2rem);
  }
}

/* Below this the numerals have nowhere to go beside a rail, so they lead the
   copy instead and the rail carries only the dots. */
@media (max-width: 560px) {
  .why__track { --why-rail-x: clamp(18px, 6vw, 28px); }
  .why__num {
    position: static;
    display: block;
    width: auto;
    transform: none;
    margin-bottom: clamp(0.4rem, 1.6vw, 0.6rem);
    font-size: clamp(1.4rem, 8vw, 2rem);
  }
  .why__dot { top: 0.9em; }
}

@media (prefers-reduced-motion: reduce) {
  .why__rail, .why__tick { transform: none; }
}

/* ======================================================= WHAT TO EXPECT === */
/* A sticky statement on the left, a read-through spine on the right.

   THE SPINE IS AN INSTRUMENT, NOT A DIVIDER. It carries a node per stage, a
   fill that tracks how far down the section you are, and an active state that
   travels with you — which is what makes the sticky heading worth having,
   because it stays with the stage you are reading and the counter beside it
   says which one.

   THE INACTIVE STATE NEVER GOES BELOW THE BODY TIER. Dimming unread rows to
   --color-muted would read beautifully and measure 3.41:1, under the floor
   for this size. So the state moves between --color-text and
   --color-heading — a clear shift that leaves every row legible whether it is
   the one being read or not.

   Nothing here declares a font or a heading size. The stage indices use
   --font-serif, on the rule the rest of the site follows: oversized
   decorative figures are serif, everything that is read is Inter.           */

.expect { background: var(--color-bg); }

.xpc__grid {
  display: grid;
  grid-template-columns: minmax(0, 0.82fr) minmax(0, 1fr);
  gap: clamp(2rem, 5.5vw, 6rem);
  align-items: start;
}

/* ---- left: the statement -------------------------------------------------- */
.xpc__lead {
  position: sticky;
  /* Clears the fixed masthead, plus air. */
  top: calc(var(--header-h) + clamp(1.4rem, 3vw, 2.6rem));
  align-self: start;
  min-width: 0;
}

.xpc__heading { margin-top: clamp(0.9rem, 1.6vw, 1.4rem); }
.xpc__ln { display: block; overflow: hidden; }
.xpc__ln > i { display: block; font-style: normal; }

.xpc__lede { margin-top: clamp(1rem, 1.8vw, 1.6rem); }

/* The counter. Serif figures, a hairline between them, and only the first
   number changes — the total is fixed, so it is set once in the markup. */
.xpc__count {
  display: flex;
  align-items: center;
  gap: clamp(0.6rem, 1.1vw, 0.95rem);
  margin-top: clamp(1.6rem, 3vw, 2.6rem);
}
.xpc__count-n,
.xpc__count-t {
  font-family: var(--font-serif);
  font-variant-numeric: tabular-nums;
  font-size: clamp(1.6rem, 2.4vw, 2.4rem);
  font-weight: 400;
  line-height: 1;
  letter-spacing: 0.01em;
}
.xpc__count-n { color: var(--color-heading); }
.xpc__count-t { color: var(--color-rule-soft); }
.xpc__count-r {
  width: clamp(20px, 2.2vw, 34px);
  height: 1px;
  background: var(--color-rule);
}

.xpc__mark {
  margin-top: clamp(1.3rem, 2.4vw, 2rem);
  color: var(--color-muted);
}

/* ---- right: the spine ----------------------------------------------------- */
.xpc__body {
  position: relative;
  min-width: 0;
  --xpc-rail: clamp(1.4rem, 3vw, 3rem);
  padding-left: var(--xpc-rail);
}

.xpc__spine {
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 1px;
  background: var(--color-rule-soft);
}
/* Ink over the hairline, scrubbed from the top as the section is read. */
.xpc__fill {
  position: absolute;
  inset: 0;
  display: block;
  background: var(--color-heading);
  transform-origin: center top;
}

.xpc__list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.xpc__row {
  position: relative;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: clamp(1rem, 2.4vw, 2.4rem);
  align-items: start;
  padding-block: clamp(1.6rem, 3vw, 2.6rem);
}
.xpc__row:first-child { padding-top: 0; }
.xpc__row:last-child { padding-bottom: 0; }
.xpc__row + .xpc__row { border-top: var(--rule); }

/* On the rail, level with the stage index's cap. */
.xpc__node {
  position: absolute;
  left: calc(var(--xpc-rail) * -1);
  top: clamp(1.6rem, 3vw, 2.6rem);
  width: 9px;
  height: 9px;
  margin-left: -4px;
  margin-top: 0.34em;
  border-radius: 50%;
  background: var(--color-bg);
  box-shadow: 0 0 0 1px var(--color-rule);
  transition: background var(--dur) var(--ease-out), box-shadow var(--dur) var(--ease-out);
}
.xpc__row:first-child .xpc__node { top: 0; }

.xpc__idx {
  font-family: var(--font-serif);
  font-variant-numeric: tabular-nums;
  font-size: clamp(1.5rem, 2.2vw, 2.2rem);
  font-weight: 400;
  line-height: 1;
  letter-spacing: 0.01em;
  color: var(--color-rule-soft);
  transition: color var(--dur) var(--ease-out);
}

.xpc__copy { min-width: 0; }

.xpc__title {
  font-family: var(--font-display);
  font-size: clamp(0.74rem, 0.88vw, 0.88rem);
  font-weight: 700;
  line-height: 1.3;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  /* The quiet end of the state is the BODY tier, never --color-muted. */
  color: var(--color-text);
  transition: color var(--dur) var(--ease-out);
}
.xpc__text {
  margin-top: clamp(0.6rem, 1.05vw, 0.95rem);
  font-size: clamp(0.9rem, 1.02vw, 1.02rem);
  line-height: 1.76;
  color: var(--color-text);
  max-width: 50ch;
  text-wrap: pretty;
}

/* ---- the stage being read ------------------------------------------------- */
.xpc__row.is-live .xpc__node {
  background: var(--color-heading);
  box-shadow: 0 0 0 1px var(--color-heading);
}
.xpc__row.is-live .xpc__idx { color: var(--color-text); }
.xpc__row.is-live .xpc__title { color: var(--color-heading); }

/* ---- stacked --------------------------------------------------------------
   The statement stops sticking — there is nothing beside it to stick against
   once the rows are underneath rather than alongside — and the counter goes
   with it, since nothing is tracking a column any more. */
@media (max-width: 900px) {
  .xpc__grid {
    grid-template-columns: minmax(0, 1fr);
    gap: clamp(1.8rem, 6vw, 2.8rem);
  }

  .xpc__lead {
    position: static;
    top: auto;
  }
  .xpc__count { display: none; }

  .xpc__body { --xpc-rail: clamp(1.1rem, 4.4vw, 1.8rem); }
  .xpc__row {
    grid-template-columns: auto minmax(0, 1fr);
    gap: clamp(0.8rem, 3.4vw, 1.4rem);
  }
  .xpc__idx { font-size: clamp(1.25rem, 5.4vw, 1.7rem); }
  .xpc__text { max-width: none; }
}

@media (prefers-reduced-motion: reduce) {
  .xpc__node, .xpc__idx, .xpc__title { transition: none; }
  .xpc__fill { display: none; }
}

/* ============================================================= BOOK (CTA) === */
/* The dark moment before the questions.

   THE CAR IS SIZED FROM THE SECTION'S CONTENT BOX, NOT BLED OFF IT. It is
   inset by the same --book-pad top and bottom as the copy, and its width
   follows from that height — so the whole car is in frame, and the space
   above it equals the space below it by construction rather than by a number
   that happens to look right.

   The first pass translated it 9% right and 16% down and let overflow:hidden
   take the rest, which cut the rear off one edge and the wheels off the
   other, and left the copy sitting high in a panel whose top and bottom
   readings did not match.

   Charcoal is --color-charcoal, the same ground the founder note and the
   footer use. The doubled selector is load-bearing: inner pages carry
   `.page-main .section { background: var(--color-bg) }`, two classes and a
   shorthand, which outranks a single `.book`.                              */

.book {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  --book-pad: clamp(3rem, 6vw, 6rem);
  padding-block: var(--book-pad);
  /* Enough height for the car to be worth showing; the copy is shorter than
     this, so the car is what sets the panel.

     The floor is 400, not 440, because the car's WIDTH is derived from this
     height (x1.5) — and on a narrow desktop a tall floor makes a wide car in
     a narrow section. At 440 the two crossed the copy at 920. */
  min-height: clamp(400px, 42vw, 620px);
  display: grid;
  align-content: center;
}

.book.section {
  background-color: var(--color-charcoal);
  background-image:
    radial-gradient(88% 96% at 14% 8%, rgba(255, 255, 255, 0.06), transparent 62%);
}

/* Inset by the same padding as the copy, top and bottom. No left, so the box
   shrink-wraps whatever width the image needs at that height. */
.book__media {
  position: absolute;
  z-index: -1;
  right: 0;
  top: var(--book-pad);
  bottom: var(--book-pad);
  pointer-events: none;
  /* A ceiling on the WIDTH as well as the height. The car's width is derived
     from the section's content height (x1.5), and on a narrow desktop that
     derivation outgrows the space beside the copy — at 920 it reached 55% of
     the section and left the copy 25px of air. Past this cap the car shrinks
     inside its box instead of crowding, which is the right thing to give up:
     the copy is the message, the car is the mood. */
  max-width: 46vw;
  /* THE SOURCE ASSET IS SLICED. The car touches the left edge of its own
     1600x1066 frame — 66% of that column is opaque — because the crop cuts
     straight through the front bumper and grille. Nothing about the layout
     can put the nose back, so the job is to stop the slice reading as a hard
     vertical edge standing in the middle of the panel.
     The car is near-black on near-charcoal, so a short fade on that edge
     reads as the car emerging from the dark rather than as a cut. The other
     three edges have real margins in the asset (110/14/16px) and are left
     alone. */
  -webkit-mask-image: linear-gradient(to right, transparent 0, #000 14%);
  mask-image: linear-gradient(to right, transparent 0, #000 14%);
  /* The wrapper carries the dimming: the image's opacity channel belongs to
     the entrance, and a fade that ends at 1 would override anything set
     here. */
  opacity: 0.9;
}
.book__car {
  display: block;
  height: 100%;
  width: auto;
  max-width: 100%;
  /* So the cap scales the picture rather than squashing it. */
  object-fit: contain;
  object-position: center right;
}

.book__grid { position: relative; }

.book__copy {
  display: grid;
  justify-items: start;
  max-width: min(46%, 620px);
}

.book__heading { margin-top: clamp(0.9rem, 1.6vw, 1.4rem); }
.book__ln { display: block; overflow: hidden; }
.book__ln > i { display: block; font-style: normal; }

.book__lede { margin-top: clamp(1rem, 1.8vw, 1.6rem); }

.book__cta { margin-top: clamp(1.6rem, 3vw, 2.4rem); }
.book__arrow {
  width: clamp(18px, 1.5vw, 22px);
  height: auto;
  transition: transform var(--dur) var(--ease-out);
}
.book__cta { transition: transform var(--dur) var(--ease-out); }
@media (hover: hover) and (pointer: fine) {
  .book__cta:hover .book__arrow { transform: translateX(5px); }
  .book__cta:hover { transform: translateY(-1px); }
}

/* ---- stacked --------------------------------------------------------------
   The car moves under the copy. Its slot is RESERVED in the section's bottom
   padding — width times the image's own 1066/1600 ratio — so it is fully in
   frame here too rather than being clipped by the edge it sits against. */
@media (max-width: 900px) {
  .book {
    --book-car-w: min(84%, 440px);
    min-height: 0;
    padding-bottom: calc(var(--book-pad) + var(--book-car-w) * 0.666 + 1.4rem);
  }

  .book__copy { max-width: none; }

  .book__media {
    right: auto;
    left: 50%;
    top: auto;
    bottom: var(--book-pad);
    width: var(--book-car-w);
    /* The desktop cap exists to stop the car crowding the copy BESIDE it.
       Stacked there is nothing beside it, and at 375 that 46vw was cutting
       the car down to 173px. */
    max-width: none;
    -webkit-mask-image: linear-gradient(to right, transparent 0, #000 16%);
    mask-image: linear-gradient(to right, transparent 0, #000 16%);
    transform: translateX(-50%);
    opacity: 0.55;
  }
  .book__car {
    width: 100%;
    height: auto;
  }
}

@media (prefers-reduced-motion: reduce) {
  .book__cta, .book__arrow { transition: none; }
}

/* ==================================================================== FAQ === */
/* Native disclosure, styled.

   <details>/<summary> carries the semantics: it opens without JavaScript,
   answers the keyboard, and reports its own expanded state. sections.js only
   intercepts the toggle to animate the panel — nothing here depends on it.

   No boxes and no shadows. The list is hairlines and space, which is what
   keeps six questions from reading as six cards.                            */

.faq { background: var(--color-bg); }

.faq__head {
  display: grid;
  justify-items: center;
  text-align: center;
  margin-bottom: clamp(2.2rem, 4.4vw, 3.6rem);
}
.faq__kicker { justify-content: center; }
.faq__heading { margin-top: clamp(0.9rem, 1.6vw, 1.4rem); }
.faq__ln { display: block; overflow: hidden; }
.faq__ln > i { display: block; font-style: normal; }

.faq__list {
  max-width: 880px;
  margin-inline: auto;
  border-top: var(--rule);
}

.faq__item { border-bottom: var(--rule); }

.faq__q {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: clamp(1.2rem, 2.4vw, 2.4rem);
  padding-block: clamp(1.1rem, 2vw, 1.6rem);
  cursor: pointer;
  list-style: none;
  /* The default disclosure triangle, in both engines. */
  -webkit-tap-highlight-color: transparent;
}
.faq__q::-webkit-details-marker { display: none; }
.faq__q::marker { content: ""; }
.faq__q:focus-visible {
  outline: 2px solid var(--color-focus);
  outline-offset: 3px;
}

.faq__q-t {
  font-family: var(--font-display);
  font-size: clamp(0.95rem, 1.12vw, 1.12rem);
  font-weight: 600;
  line-height: 1.5;
  letter-spacing: -0.01em;
  color: var(--color-heading);
  transition: color var(--dur) var(--ease-out);
}
@media (hover: hover) and (pointer: fine) {
  .faq__q:hover .faq__q-t { color: var(--color-text); }
}

/* Plus to minus: only the upright stroke moves. */
.faq__sign {
  position: relative;
  flex: 0 0 auto;
  width: clamp(13px, 1.2vw, 16px);
  height: clamp(13px, 1.2vw, 16px);
}
.faq__sign i {
  position: absolute;
  inset: 0;
  margin: auto;
  background: var(--color-heading);
}
.faq__sign-h { width: 100%; height: 1.5px; }
.faq__sign-v {
  width: 1.5px;
  height: 100%;
  transition: transform var(--dur) var(--ease-out), opacity var(--dur) var(--ease-out);
  transform-origin: center;
}
.faq__item[open] .faq__sign-v { transform: scaleY(0); opacity: 0; }

/* The panel is measured and animated by sections.js; with JS off it is simply
   shown by the browser. */
.faq__a { overflow: hidden; }
.faq__a-t {
  padding-bottom: clamp(1.2rem, 2.2vw, 1.8rem);
  padding-right: clamp(1.6rem, 3.4vw, 3.4rem);
  font-size: clamp(0.9rem, 1.02vw, 1.02rem);
  line-height: 1.76;
  color: var(--color-text);
  max-width: 68ch;
  text-wrap: pretty;
}

@media (prefers-reduced-motion: reduce) {
  .faq__q-t, .faq__sign-v { transition: none; }
}

/* ============================================================== CONTACT === */
/* Three sections: the dark opening that carries the details, the three steps,
   and the service index.

   The doubled `.contactlead.section` selector is load-bearing for the same
   reason it is on .book and .founder — inner pages carry
   `.page-main .section { background: var(--color-bg) }`, two classes and a
   shorthand, which outranks a single class. A single `.contactlead` here
   rendered white and took the copy with it.

   No section below declares a font size for a heading, a kicker or body copy.
   Those are the global classes, exactly as every other section on this site
   uses them. */

.contactlead {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  padding-block: clamp(3.4rem, 7vw, 7rem);
}
.contactlead.section {
  background-color: var(--color-charcoal);
  /* The same corner light .book uses, so the site's dark grounds are one
     surface treatment rather than several. */
  background-image:
    radial-gradient(88% 96% at 14% 8%, rgba(255, 255, 255, 0.06), transparent 62%);
}

.contactlead__grid {
  display: grid;
  gap: clamp(2.4rem, 5vw, 4.5rem);
  align-items: start;
}

.contactlead__heading { margin-top: clamp(0.9rem, 1.6vw, 1.4rem); }
.ctc__ln { display: block; overflow: hidden; }
.ctc__ln > i { display: block; font-style: normal; }

.contactlead__lede {
  margin-top: clamp(1rem, 1.8vw, 1.6rem);
  max-width: 52ch;
}

/* ---- the two details ---------------------------------------------------- */
/* Cards, not a list of rows: these two values are the reason the page exists,
   and on a phone they are the only thing above the fold. */
.contactlead__details {
  display: grid;
  gap: clamp(0.9rem, 1.6vw, 1.3rem);
}

.ctcd {
  display: grid;
  /* icon in its own column, everything else stacked beside it. The icon spans
     all three text rows so it reads as the card's mark rather than as a
     bullet against the label. */
  grid-template-columns: auto 1fr;
  grid-template-areas:
    "ico label"
    "ico value"
    "ico note";
  column-gap: clamp(0.9rem, 1.5vw, 1.2rem);
  row-gap: 0.3rem;
  padding: clamp(1.2rem, 2.2vw, 1.8rem) clamp(1.3rem, 2.4vw, 2rem);
  border: var(--rule-onDark);
  border-radius: var(--r-md);
  background: rgba(243, 241, 237, 0.035);
}

.ctcd__ico {
  grid-area: ico;
  align-self: start;
  display: grid;
  place-items: center;
  width: 42px;
  height: 42px;
  border-radius: 50%;
  border: var(--rule-onDark);
  color: rgba(243, 241, 237, 0.7);
}
.ctcd__ico svg { width: 19px; height: 19px; }

.ctcd__label {
  grid-area: label;
  font-size: clamp(0.64rem, 0.76vw, 0.74rem);
  font-weight: 600;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  /* 0.62 on this charcoal measures 6.4:1. */
  color: var(--color-onDark-soft);
}

/* The one place on this page that sets a size, because this is a value being
   displayed rather than a heading or body copy — it belongs to neither scale.
   Tabular figures so the phone number's digits sit on an even rhythm. */
.ctcd__value {
  grid-area: value;
  font-size: clamp(1.25rem, 2.1vw, 1.7rem);
  font-weight: 600;
  letter-spacing: -0.01em;
  font-variant-numeric: tabular-nums;
  color: var(--color-secondary);
}
/* The one action on this page, and on a phone it is a thumb target rather
   than a line of text. The glyphs are 32px tall on their own, which is under
   the 44px a finger actually wants — inline-flex with a min-height grows the
   hit area without moving the number off the card's baseline rhythm. */
.ctcd__value--link {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  text-decoration: none;
  transition: color var(--dur) var(--ease-out);
}

.ctcd__note {
  grid-area: note;
  margin-top: 0.15rem;
  font-size: clamp(0.82rem, 0.92vw, 0.92rem);
  line-height: 1.6;
  color: var(--color-onDark-soft);
}

/* ---- from tablet up: copy left, details right --------------------------- */
@media (min-width: 900px) {
  .contactlead__grid {
    grid-template-columns: minmax(0, 1fr) minmax(0, 0.86fr);
    align-items: center;
  }
}

/* ================================================== WHAT HAPPENS NEXT === */
/* Doubled, like every other section ground on this site: inner pages carry
   `.page-main .section { background: var(--color-bg) }`, two classes and a
   shorthand, which outranks a single class. */
.reach.section { background: var(--color-bg); }

.reach__head { margin-bottom: clamp(2.4rem, 4.4vw, 4rem); }
.reach__heading { margin-top: clamp(0.9rem, 1.6vw, 1.4rem); }
.reach__ln { display: block; overflow: hidden; }
.reach__ln > i { display: block; font-style: normal; }
.reach__lede { margin-top: clamp(1rem, 1.8vw, 1.5rem); max-width: 62ch; }

.reach__steps {
  display: grid;
  gap: clamp(1.4rem, 2.6vw, 2.2rem);
  counter-reset: none;
}

.rstep {
  display: grid;
  gap: 0.55rem;
  padding-top: clamp(1.1rem, 2vw, 1.5rem);
  /* A rule above each step rather than a box around it: the three read as one
     sequence that way, which is what they are. */
  border-top: var(--rule);
}

/* --color-text, not --color-muted. The muted grey is the site's tone for a
   numeral that is decoration — the oversized watermark figures — and at 12px
   it measured 3.39:1 on white, under the 4.5 floor for text this size. This
   is the same colour .inc__n sets for the same role. */
.rstep__n {
  font-size: clamp(0.7rem, 0.84vw, 0.8rem);
  font-weight: 700;
  letter-spacing: 0.22em;
  font-variant-numeric: tabular-nums;
  color: var(--color-text);
}

.rstep__title {
  font-size: var(--fs-h3);
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: -0.02em;
  color: var(--color-heading);
}

.rstep__body {
  font-size: var(--fs-body);
  line-height: 1.7;
  color: var(--color-text);
  max-width: 46ch;
  text-wrap: pretty;
}

@media (min-width: 860px) {
  .reach__steps { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

/* ====================================================== SERVICE INDEX === */
/* The six services as a plain index. Deliberately not the homepage's service
   cards: those are a showcase and this is a way out of a page a visitor
   landed on by accident. */
.svcindex.section { background: var(--color-bg-soft); }

.svcindex__head { margin-bottom: clamp(1.8rem, 3.4vw, 3rem); }
.svcindex__heading { margin-top: clamp(0.9rem, 1.6vw, 1.4rem); }
.svci__ln { display: block; overflow: hidden; }
.svci__ln > i { display: block; font-style: normal; }

.svcindex__list {
  display: grid;
  gap: 0;
  border-top: var(--rule);
}
.svci { border-bottom: var(--rule); }

.svci__link {
  display: flex;
  align-items: center;
  gap: clamp(0.9rem, 1.8vw, 1.5rem);
  padding-block: clamp(0.95rem, 1.7vw, 1.3rem);
  color: var(--color-heading);
  transition: color var(--dur) var(--ease-out);
}

/* Same reason as .rstep__n, and it matters more here: on the warm ground
   the muted grey measured 3.09:1. */
.svci__n {
  flex: none;
  font-size: clamp(0.7rem, 0.84vw, 0.8rem);
  font-weight: 700;
  letter-spacing: 0.22em;
  font-variant-numeric: tabular-nums;
  color: var(--color-text);
}

.svci__label {
  flex: 1 1 auto;
  font-size: clamp(1.02rem, 1.5vw, 1.28rem);
  font-weight: 600;
  letter-spacing: -0.015em;
}

.svci__chev {
  flex: none;
  width: 8px;
  height: 12px;
  color: var(--color-muted);
  transition: transform var(--dur) var(--ease-out), color var(--dur) var(--ease-out);
}

@media (min-width: 860px) {
  .svcindex__list { grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: clamp(2rem, 4vw, 4rem); }
  /* With two columns the top border would only cap the first cell of each
     column; each row carries its own instead. */
  .svcindex__list { border-top: 0; }
  .svci { border-top: var(--rule); border-bottom: 0; }
}

@media (hover: hover) and (pointer: fine) {
  .ctcd__value--link:hover { color: #ffffff; }
  .svci__link:hover .svci__chev { transform: translateX(4px); color: var(--color-heading); }
}

@media (prefers-reduced-motion: reduce) {
  .ctcd__value--link, .svci__link, .svci__chev { transition: none; }
}

@media (max-width: 760px) {
  /* The same clamp .svchero__heading carries, and the same numbers on purpose:
     this is the other place on the site where a heading is the page's opening
     statement rather than a section title, so the two should shrink
     identically. At 320 the accent line ran 287px into a 280px column.

     The section headings BELOW this one are deliberately left alone. Every
     approved section heading on the site already wraps at 320 — five of the
     ten lines on the Premium Wash page do — so scaling these two would make
     the contact page the odd one out rather than fixing anything. */
  .contactlead__heading { font-size: clamp(1.8rem, 9.3vw, 2.5rem); }
}

/* ============================================================================
   GALLERY — the uploaded work, on the home page and on its own page.

   Columns rather than a grid of equal boxes. Every picture keeps the shape it
   was shot at; a fixed grid would crop them all to one rectangle, which is the
   one thing a gallery must not do. Only the column count changes with width.

   The palette is the existing one — the warm off-white ground, the hairline,
   the heading tone. Nothing new is introduced here.
   ========================================================================= */

.gal { background: var(--color-bg-soft); }
.gal--full { padding-block: var(--section-y-md, 6rem); }

.gal__head { max-width: 62ch; }
.gal__lede { margin-top: var(--s3); }

/* ---- the set ------------------------------------------------------------ */
.gal__set {
  margin-top: clamp(2.2rem, 4vw, 3.4rem);
  column-count: 3;
  column-gap: clamp(0.75rem, 1.4vw, 1.15rem);
}
@media (max-width: 1100px) { .gal__set { column-count: 2; } }
@media (max-width: 640px)  { .gal__set { column-count: 1; } }

/* ---- one tile ----------------------------------------------------------- */
.gal__tile {
  position: relative;
  margin: 0 0 clamp(0.75rem, 1.4vw, 1.15rem);
  /* A tile must not be split down the middle by the column break. */
  break-inside: avoid;
  page-break-inside: avoid;
  overflow: hidden;
  background: var(--color-wash);
  border: 1px solid var(--color-rule-soft);
}

.gal__media {
  display: block;
  width: 100%;
  height: auto;
  background: var(--color-wash);
}

/* Only a tile whose proportion is actually recorded holds its shape ahead
   of loading. The rest size themselves to the picture, which is slower to
   settle but never crops it. */
.gal__tile--fixed .gal__media {
  aspect-ratio: var(--gal-ratio);
  object-fit: cover;
}

/* The still lift the rest of the site uses on a card, at the same weight. */
@media (hover: hover) and (pointer: fine) {
  .gal__tile:not(.gal__tile--video) .gal__media {
    transition: transform 0.7s cubic-bezier(0.22, 1, 0.36, 1);
  }
  .gal__tile:not(.gal__tile--video):hover .gal__media { transform: scale(1.03); }
}

/* ---- video -------------------------------------------------------------- */
.gal__media--video { background: var(--color-dark); }

/* A small corner mark so a video is identifiable at a glance in a set that
   mixes both kinds. The clip carries its own controls, so this is a label
   rather than a button and never takes the pointer. */
.gal__badge {
  position: absolute;
  inset-block-start: 0.75rem;
  inset-inline-start: 0.75rem;
  display: grid;
  place-items: center;
  width: 2.1rem;
  height: 2.1rem;
  border-radius: 50%;
  color: var(--color-onDark);
  background: rgba(9, 9, 9, 0.62);
  backdrop-filter: blur(6px);
  pointer-events: none;
}
.gal__badge svg { width: 0.95rem; height: 0.95rem; }

/* ---- caption ------------------------------------------------------------ */
.gal__cap {
  padding: var(--s2) var(--s2) calc(var(--s2) + 0.1rem);
  font-size: var(--fs-label);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--color-text);
  background: var(--color-bg);
  border-block-start: 1px solid var(--color-rule-soft);
}

/* ---- the link to the rest ----------------------------------------------- */
.gal__foot {
  margin-top: clamp(2rem, 3.4vw, 3rem);
  display: flex;
  justify-content: center;
}
.gal__more {
  display: inline-flex;
  align-items: center;
  gap: 0.7rem;
  padding-block-end: 0.45rem;
  font-size: var(--fs-label);
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--color-heading);
  text-decoration: none;
  border-block-end: 1px solid var(--color-rule);
  transition: gap 0.35s cubic-bezier(0.22, 1, 0.36, 1);
}
.gal__more:hover { gap: 1.05rem; }
.gal__arrow { width: 1.35rem; height: 0.7rem; }

/* ---- the link on from a shortened services row --------------------------
   The home page shows a handful of services and links on to the full list.
   Same treatment as the gallery's own link, so the two read as one pattern
   rather than two ideas. */
.svc__foot {
  margin-top: clamp(2rem, 3.4vw, 3rem);
  display: flex;
  justify-content: center;
}
.svc__more {
  display: inline-flex;
  align-items: center;
  gap: 0.7rem;
  padding-block-end: 0.45rem;
  font-size: var(--fs-label);
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--color-heading);
  text-decoration: none;
  border-block-end: 1px solid var(--color-rule);
  transition: gap 0.35s cubic-bezier(0.22, 1, 0.36, 1);
}
.svc__more:hover { gap: 1.05rem; }
.svc__moreArrow { width: 1.35rem; height: 0.7rem; }
