/* ==========================================================================
   Macrotexture — landing page
   Extracted from "Macrotexture Landing.dc.html", option 4A.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Tokens
   -------------------------------------------------------------------------- */

:root {
  /* Surfaces */
  --canvas:       #EDE8EA;
  --surface:      #FFFFFF;

  /* Ink */
  --ink:          #0E0E0E;
  --muted:        #6C6469;

  /* Hairlines */
  --line:         #EDE8EA;
  --line-2:       #E1DADD;
  --line-3:       #E3DBDE;
  --rail-line:    #CFC6CA;

  /* Green — the one accent */
  --green:        #0E7C66;
  --green-600:    #0B6353;
  --green-700:    #0A5748;
  --green-800:    #0A4A3E;
  --green-900:    #084237;
  --green-950:    #04352C;
  --green-chip:   #0B3E33;
  --mint:         #17A98C;
  --mint-200:     #5AD3B4;
  --mint-100:     #8BE3C9;
  --mint-bg:      #E8F4F1;
  --mint-border:  #D3E9E3;
  --mint-tint:    #F1FBF8;
  --mint-edge:    #B7D8CF;

  /* Warm neutrals */
  --stone-100:    #F4EFF0;
  --stone-200:    #E2D9DC;
  --stone-300:    #E7E0E3;
  --stone-500:    #B9AEB3;

  /* Dark hero. The ridges step DOWN from the sky rather than up: light type
     crosses them, so they have to move away from the text colour. */
  --hero-ground:  #08120F;
  --hero-ink:     #F4F2ED;
  --hero-sub:     #9AAAA4;
  --hero-point:   #C6D4CE;
  --ridge-1:      #0B1A16;
  --ridge-2:      #081410;
  --ridge-3:      #060F0C;
  --ridge-4:      #040A08;
  --ridge-5:      #020605;
  --card-cream:   #F5F2EC;
  --card-ink:     #0A2A22;
  --card-chip:    #DFE6DC;

  /* Dark card */
  --dark-900:     #171717;
  --dark-800:     #212121;
  --dark-700:     #2B2B2B;
  --dark-600:     #3A3A3A;
  --dark-text:    #A5A0A2;

  /* Type */
  --font:         'Figtree', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --font-serif:   'Playfair Display', Georgia, serif;

  /* Rhythm */
  --pad:          44px;
  --radius-lg:    26px;
  --radius-md:    20px;
  --radius-sm:    14px;

  /* Motion */
  --ease-out:     cubic-bezier(.22, 1, .36, 1);
}

/* --------------------------------------------------------------------------
   2. Base
   -------------------------------------------------------------------------- */

*, *::before, *::after { box-sizing: border-box; }

html { scroll-behavior: smooth; }

body {
  margin: 0;
  background: var(--canvas);
  font-family: var(--font);
  color: var(--ink);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  /* Propagates to the viewport, so it already blocks user-initiated sideways
     scroll from the services contour bleed. It does not stop the document
     overflowing though — see the main rule below. */
  overflow-x: hidden;
}

/* The services contour field bleeds past its wrap on purpose (inset-inline:
   -12%). body's overflow-x above stops the user scrolling to it, but the
   document still measures 154px wider than the viewport and stays
   programmatically scrollable — a scrollIntoView or focus can shove the page
   sideways with no user-reachable way back. Clipping on main removes the
   overflow itself. main is full-bleed, so the visible overhang into the wrap
   margins is untouched.
   `clip` not `hidden`: clip creates no scroll container. Setting this on html
   instead would break the sticky .faq__aside; hidden here would too. */
main { overflow-x: clip; }

h1, h2, h3, p { margin: 0; }

img { max-width: 100%; display: block; }

a { color: inherit; text-decoration: none; }

.wrap {
  max-width: 1280px;
  margin-inline: auto;
  padding-inline: var(--pad);
}

.serif {
  font-family: var(--font-serif);
  font-style: italic;
  font-weight: 400;
  letter-spacing: -0.01em;
}

.eyebrow {
  font-size: 13px;
  font-weight: 700;
  letter-spacing: .18em;
  color: var(--green-600);
}

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

/* Focus — visible, on brand, never suppressed. */
:focus-visible {
  outline: 3px solid var(--green);
  outline-offset: 3px;
  border-radius: 4px;
}

/* --------------------------------------------------------------------------
   3. Motion primitives
   -------------------------------------------------------------------------- */

@keyframes mtx-sheen {
  from { background-position: 0% 50%; }
  to   { background-position: 100% 50%; }
}

@keyframes mtx-spin {
  to { transform: rotate(360deg); }
}

/* Scroll reveals. Long ease-out curve so things settle rather than snap. */
[data-reveal] {
  opacity: 0;
  transform: translateY(26px);
  transition: opacity .75s var(--ease-out), transform .75s var(--ease-out);
  transition-delay: var(--rd, 0ms);
}
[data-reveal].in { opacity: 1; transform: none; }

/* Service cards fly in from their side of the rail. */
[data-reveal][data-dir="l"] { transform: translateX(-64px) translateY(10px); }
[data-reveal][data-dir="r"] { transform: translateX(64px) translateY(10px); }
[data-reveal][data-dir].in  { transform: none; }

/* Staggered groups: JS stamps --i on each child. */
[data-stagger] > * {
  opacity: 0;
  transform: translateY(22px);
  transition: opacity .7s var(--ease-out), transform .7s var(--ease-out);
  transition-delay: var(--i, 0ms);
}
[data-stagger].in > * { opacity: 1; transform: none; }

/* A staggered container animates through its children, not as a block. */
[data-stagger][data-reveal] { opacity: 1; transform: none; transition: none; }

/* --------------------------------------------------------------------------
   3b. Boot skeleton
   -------------------------------------------------------------------------- */

@keyframes sk-shimmer {
  from { background-position: -160% 0; }
  to   { background-position: 260% 0; }
}

.boot {
  position: fixed;
  inset: 0;
  z-index: 100;
  background: var(--canvas);
  overflow: hidden;
  transition: opacity .5s ease;
}
.boot.is-done { opacity: 0; pointer-events: none; }

/* Backstop: if the load handler never runs, uncover the page anyway. */
.boot { animation: sk-failsafe 0s linear 6s forwards; }
@keyframes sk-failsafe { to { opacity: 0; visibility: hidden; } }

.boot__wrap {
  max-width: 1280px;
  margin-inline: auto;
  padding-inline: var(--pad);
}

.boot__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  padding-top: 40px;
}
.boot__nav { display: flex; gap: 8px; }

.boot__hero {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 440px;
  gap: 56px;
  padding-top: 104px;
  align-items: start;
}
.boot__copy { display: flex; flex-direction: column; gap: 18px; }

.sk {
  display: block;
  border-radius: 10px;
  background-color: #E3DDDF;
  background-image: linear-gradient(100deg,
    rgba(255, 255, 255, 0) 20%,
    rgba(255, 255, 255, .62) 42%,
    rgba(255, 255, 255, 0) 64%);
  background-size: 220% 100%;
  background-repeat: no-repeat;
  animation: sk-shimmer 1.5s ease-in-out infinite;
}

.sk--logo { width: 190px; height: 28px; }
.sk--pill { width: 118px; height: 46px; border-radius: 14px; }
.sk--cta  { width: 132px; background-color: #C9D8D2; }

.sk--h1    { height: 74px; border-radius: 14px; }
.sk--h1:nth-child(2) { width: 92%; }
.sk--short { width: 52%; }
.sk--sub   { width: 38%; height: 26px; margin-top: 10px; }

.sk--card {
  height: 560px;
  border-radius: var(--radius-lg);
  background-color: #C9D8D2;
}

@media (max-width: 900px) {
  .boot__hero { grid-template-columns: minmax(0, 1fr); gap: 40px; padding-top: 64px; }
  .sk--card { height: 420px; }
}
@media (max-width: 700px) {
  .boot__nav .sk--pill:nth-child(3) { display: none; }
  .sk--h1 { height: 46px; }
  .sk--logo { width: 150px; height: 24px; }
}

/* --------------------------------------------------------------------------
   4. Header
   -------------------------------------------------------------------------- */

.site-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  padding-top: 34px;
}

.logo {
  font-weight: 800;
  font-size: 26px;
  letter-spacing: -0.035em;
}

.site-nav {
  display: flex;
  align-items: center;
  gap: 8px;
}

.pill {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  font-size: 16px;
  font-weight: 600;
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--line-3);
  padding: 12px 20px;
  border-radius: var(--radius-sm);
  box-shadow: 0 1px 2px rgba(20, 10, 12, .05), inset 0 1px 0 #FFFFFF;
  transition: transform .25s var(--ease-out), box-shadow .25s ease,
              border-color .25s ease, color .25s ease;
}
.pill:hover {
  transform: translateY(-2px);
  box-shadow: 0 10px 20px -12px rgba(6, 58, 47, .45);
  border-color: var(--mint-edge);
  color: var(--green-600);
}

/* The spinning-gradient CTA. Pure CSS — the design doc drove this from JS. */
.cta {
  position: relative;
  display: inline-flex;
  padding: 2px;
  border-radius: var(--radius-sm);
  overflow: hidden;
  background: var(--green-800);
  margin-left: 4px;
  transition: transform .28s var(--ease-out), box-shadow .28s ease;
}
.cta__spin,
.cta__spin--fast {
  position: absolute;
  left: 50%; top: 50%;
  width: 240px; height: 240px;
  margin: -120px 0 0 -120px;
  transition: opacity .3s ease;
  pointer-events: none;
}
.cta__spin {
  background: conic-gradient(from 0deg,
    rgba(255,255,255,0) 0deg, rgba(139,227,201,.55) 34deg,
    rgba(255,255,255,.95) 66deg, rgba(139,227,201,.55) 98deg,
    rgba(255,255,255,0) 140deg, rgba(255,255,255,0) 360deg);
  animation: mtx-spin 3.2s linear infinite;
  opacity: 1;
}
.cta__spin--fast {
  background: conic-gradient(from 0deg,
    rgba(255,255,255,0) 0deg, rgba(139,227,201,.6) 30deg,
    #FFFFFF 62deg, rgba(139,227,201,.6) 94deg,
    rgba(255,255,255,0) 136deg, rgba(255,255,255,0) 360deg);
  animation: mtx-spin 1.15s linear infinite;
  opacity: 0;
}
.cta__inner {
  position: relative;
  display: flex;
  align-items: center;
  gap: 0;
  font-size: 16px;
  font-weight: 700;
  color: #FFFFFF;
  background: var(--green);
  padding: 11px 22px;
  border-radius: 12px;
  transition: background .22s ease, gap .28s ease;
  white-space: nowrap;
}
.cta__arrow {
  transition: opacity .24s ease, max-width .28s ease;
  opacity: 0;
  max-width: 0;
  overflow: hidden;
}
.cta:hover { transform: scale(1.045); box-shadow: 0 14px 28px -14px rgba(11, 99, 83, .85); }
.cta:hover .cta__spin        { opacity: 0; }
.cta:hover .cta__spin--fast  { opacity: 1; }
.cta:hover .cta__inner       { gap: 8px; background: var(--green-600); }
.cta:hover .cta__arrow       { opacity: 1; max-width: 16px; }

/* --------------------------------------------------------------------------
   5. Hero
   -------------------------------------------------------------------------- */

.hero {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 440px;
  gap: 56px;
  padding-block: 96px 110px;
  align-items: start;

  /* The hero owns the whole first screen. Its content is a fixed 735px, so on
     any window taller than ~815px the next section's heading was already on
     screen at first paint: 86px of it at 1440x900, 236px at 1680x1050, 266px at
     1920x1080. Only 1280x800 came out clean, which is the size everything got
     checked at.

     min-block-size, never height — on a short window the content still sets the
     height and nothing is clipped. 79px is the header, which measures 79 at
     every width where the hero runs two-up; below 901px it stacks to ~1140px
     and the rule is a no-op, so it is left to fall through rather than undone.

     svh after vh: on desktop they are the same number, but on mobile browsers
     vh is the LARGEST viewport (toolbars retracted), which would overshoot and
     reintroduce the gap it is here to close. */
  min-block-size: calc(100vh - 79px);
  min-block-size: calc(100svh - 79px);
  /* align-items keeps the two columns their natural height; align-content
     centres the row in the taller box, so the extra space is shared above and
     below instead of dumped under the CTA. */
  align-content: center;
}

.hero__copy {
  display: flex;
  flex-direction: column;
  gap: 26px;
  padding-top: 8px;
}

.hero__title {
  font-weight: 700;
  font-size: clamp(44px, 6.9vw, 88px);
  line-height: .96;
  letter-spacing: -0.045em;
}

.hero__sub {
  font-size: clamp(18px, 1.8vw, 22px);
  font-weight: 400;
  color: var(--muted);
}

/* Risk reversal. Darker than --muted on purpose: these are claims, not
   supporting text, even though they sit below the subhead. */
.hero__points {
  display: flex;
  flex-wrap: wrap;
  gap: 10px 22px;
  margin: 0;
  padding: 0;
  list-style: none;
}
.hero__points li {
  display: flex;
  align-items: center;
  gap: 9px;
  font-size: 17px;
  font-weight: 500;
  color: #2C2A2B;
}
.hero__points svg { flex: none; }

/* Two rungs: a call for the ready, an email for everyone else. */
.hero__actions {
  display: flex;
  align-items: center;
  gap: 22px;
  flex-wrap: wrap;
}
.hero__cta {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  background: var(--green);
  color: #FFFFFF;
  font-size: 18px;
  font-weight: 700;
  padding: 17px 30px;
  border-radius: var(--radius-sm);
  transition: transform .25s var(--ease-out), box-shadow .25s ease,
              background .22s ease;
}
.hero__cta:hover {
  background: var(--green-600);
  transform: translateY(-2px);
  box-shadow: 0 14px 28px -14px rgba(11, 99, 83, .85);
}
.hero__alt {
  font-size: 17px;
  font-weight: 600;
  color: var(--green);
  border-bottom: 1.5px solid rgba(14, 124, 102, .35);
  padding-bottom: 1px;
  transition: border-color .22s ease, color .22s ease;
}
.hero__alt:hover {
  color: var(--green-600);
  border-bottom-color: var(--green);
}

/* Booking card */
.booking {
  background: linear-gradient(150deg, var(--green) 0%, var(--green-700) 52%, var(--green-900) 100%);
  border-radius: var(--radius-lg);
  padding: 26px;
  display: flex;
  flex-direction: column;
  gap: 18px;
  color: #FFFFFF;
  box-shadow: 0 30px 60px -34px rgba(6, 58, 47, .75);
}

.booking__top {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.booking__status {
  display: flex;
  align-items: center;
  gap: 9px;
  background: var(--green-chip);
  padding: 9px 16px;
  border-radius: 999px;
  font-size: 14px;
  font-weight: 600;
}
.booking__dot {
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--mint-100);
  flex: none;
}

.booking__meta { font-size: 14px; font-weight: 600; }

.booking__headline {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding-top: 6px;
}
.booking__headline h2 {
  font-weight: 700;
  font-size: clamp(32px, 3.2vw, 40px);
  line-height: 1;
  letter-spacing: -0.04em;
}
.booking__headline p { font-size: 17px; font-weight: 500; }

.booking__slots {
  display: flex;
  flex-direction: column;
  gap: 7px;
}
.booking__label {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .14em;
}
.slot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 11px 14px;
  border-radius: 12px;
  background: rgba(255, 255, 255, .18);
  transition: background .25s ease;
  font-weight: 600;
}
.slot span:first-child { font-size: 15px; }
.slot span:last-child  { font-size: 14px; }

.booking__cta {
  display: block;
  background: #FFFFFF;
  color: var(--green-800);
  text-align: center;
  font-weight: 700;
  font-size: 18px;
  padding: 19px;
  border-radius: var(--radius-sm);
  transition: transform .25s ease, background .25s ease;
}
.booking__cta:hover { background: var(--mint-tint); transform: translateY(-2px); }

.booking__who {
  display: flex;
  align-items: center;
  gap: 13px;
  padding-top: 14px;
  border-top: 1px solid rgba(255, 255, 255, .22);
}
.booking__who div {
  display: flex;
  flex-direction: column;
  margin-right: auto;
}
.booking__who strong { font-size: 15px; font-weight: 700; }
.booking__who span   { font-size: 14px; }

/* --------------------------------------------------------------------------
   5b. Dark hero

   The header and the hero share one dark band. Neither is wrapped in a new
   element — each paints its own full-bleed background instead, so the document
   structure stays untouched and the two read as continuous because the colour
   matches exactly. Everything below the hero stays on the light canvas.

   This block sits after the rules it overrides on purpose. Order is doing the
   work here, not specificity.
   -------------------------------------------------------------------------- */

.site-header,
.hero { position: relative; }

.site-header::before,
.hero::before {
  content: "";
  position: absolute;
  inset-block: 0;
  left: 50%;
  transform: translateX(-50%);
  width: 100vw;
  background: var(--hero-ground);
  z-index: -3;
}

/* Header, inverted. */
.logo { color: var(--hero-ink); }
.pill {
  background: rgba(255, 255, 255, .07);
  border-color: rgba(255, 255, 255, .16);
  color: var(--hero-ink);
  box-shadow: none;
}
.pill:hover {
  background: rgba(255, 255, 255, .13);
  border-color: var(--mint-200);
  color: var(--mint-100);
}
.cta { background: var(--green-900); }
.cta__inner { background: var(--mint); color: #04241C; }
.cta:hover .cta__inner { background: var(--mint-200); }
.cta__arrow { stroke: #04241C; }

/* Hero copy on dark. */
.hero__title     { color: var(--hero-ink); }
.hero__sub       { color: var(--hero-sub); }
.hero__points li { color: var(--hero-point); }
.hero__points svg { stroke: var(--mint); }
.hero__cta {
  background: var(--mint);
  color: #04241C;
}
.hero__cta:hover {
  background: var(--mint-200);
  box-shadow: 0 14px 30px -14px rgba(23, 169, 140, .8);
}
.hero__cta svg { stroke: #04241C; }
.hero__alt {
  color: var(--mint-100);
  border-bottom-color: rgba(139, 227, 201, .40);
}
.hero__alt:hover {
  color: #FFFFFF;
  border-bottom-color: var(--mint-100);
}

/* The booking card becomes the bright object in the frame. A green card on a
   dark green ground competes with it instead of standing out. */
.booking {
  background: var(--card-cream);
  color: var(--card-ink);
  box-shadow: 0 40px 84px -38px rgba(0, 0, 0, .82);
}
.booking__status { background: var(--card-chip); }
.booking__dot    { background: var(--green); }
.slot            { background: rgba(10, 42, 34, .085); }
.booking__cta {
  background: var(--green-700);
  color: #FFFFFF;
}
.booking__cta:hover { background: var(--green-600); }
.booking__who      { border-top-color: rgba(10, 42, 34, .16); }
.booking__who span { opacity: .76; }

/* The environment itself. */
.scene {
  position: absolute;
  inset-block: 0;
  left: 50%;
  transform: translateX(-50%);
  width: 100vw;
  z-index: -2;
  overflow: hidden;
  pointer-events: none;
}
.scene__layer {
  position: absolute;
  inset: -6% -8%;
  will-change: transform;
}
/* The light source, and the only thing the ridges can be read against. It used
   to sit at top:56% — BELOW ridge-1's 48% edge — so the ridges occluded the
   glow instead of being silhouetted by it, and the whole hero measured 1.28:1
   from darkest pixel to lightest. Parallax on an invisible scene reads as no
   parallax at all. Raised above the ridgeline and strengthened; the ridges
   themselves stay near-black, so nothing moves toward the light type. */
.scene__glow {
  position: absolute;
  left: 62%;
  top: 38%;
  width: 112%;
  height: 62%;
  transform: translate(-50%, -50%);
  background: radial-gradient(closest-side,
    rgba(90, 211, 180, .40), rgba(90, 211, 180, .12) 55%, transparent 78%);
  filter: blur(34px);
}
.scene__ridge {
  position: absolute;
  left: -14%;
  right: -14%;
  border-radius: 50% 50% 0 0 / 100% 100% 0 0;
}

/* Crest light — the thing that makes the parallax perceivable.
   §12.1 raised the glow and took the hero's tonal range from 1.28:1 to ~1.9:1,
   but the range it opened belongs to the GLOW, which rides data-depth="0.06"
   (10.6px of travel over the whole hero) and has left the viewport by
   scrollY 100. The five ridges carry all the real travel — 35px to 176px — and
   every one of them sat at 1.01–1.07:1 against the ground. Measured: freezing
   all five layers at scrollY 400 changed the composited hero by a mean of
   1.5/255. The parallax ran; there was nothing in it the eye could track.

   The fix is an EDGE, not more fill. Perceived motion needs a trackable
   feature: a soft blob translating 30px is invisible, a hairline translating
   30px is unmissable. An inset box-shadow follows the border-radius, so it
   draws light along each ridge's elliptical crest — which is also what a real
   ridgeline does, catch the sky along its top edge and stay black below it.

   Crest THICKNESS follows distance — far ridges get a thick soft band that
   survives their own blur, near ones a hairline. Crest BRIGHTNESS does not: it
   is set by what sits in front of each ridge, because these lines cross the
   copy. Measured, one crest at a time, at 1440:

     ridge 1  crest y 430  bottom edge of the H1 (183–441)    .16  no cost
     ridge 2  crest y 504  inside the subhead (467–521)       .08  weakest block
     ridge 3  crest y 578  clear of all copy                  .30  free, so brightest
     ridge 4  crest y 652  dead centre of the alt CTA (640–662)
                           at .40 it alone cost that link 12.24:1 → 7.99:1    .18
     ridge 5  crest y 735  hero's bottom edge, below all copy .50  free

   So ridges 3 and 5 carry the effect and ridge 4 is deliberately the dimmest of
   the near ones — an exception with a measured reason, not a gradient. §12's
   rule still holds either way: the ridge bodies stay below the ground and only
   a few pixels per ridge move toward the light type.

   Net, A/B on one page load with only the box-shadow varying, 1440×900:
     visible parallax (hero pixels, live vs all layers frozen)
                              mean 1.479 → 2.653 /255   max 23 → 73
     H1 8.75 → 8.75 · subhead 7.38 → 7.18 · points 11.97 → 11.78
     secondary CTA 12.12 → 10.51.  All still at or above AAA. */
.scene__ridge--1 { top: 48%; height: 64%; background: var(--ridge-1); filter: blur(6px);
  box-shadow: inset 0 5px 0 rgba(90, 211, 180, .16); }
.scene__ridge--2 { top: 57%; height: 62%; background: var(--ridge-2); filter: blur(4px);
  box-shadow: inset 0 4px 0 rgba(90, 211, 180, .08); }
.scene__ridge--3 { top: 66%; height: 60%; background: var(--ridge-3); filter: blur(2.5px);
  box-shadow: inset 0 3px 0 rgba(90, 211, 180, .30); }
.scene__ridge--4 { top: 75%; height: 56%; background: var(--ridge-4); filter: blur(1px);
  box-shadow: inset 0 2px 0 rgba(90, 211, 180, .18); }
.scene__ridge--5 { top: 85%; height: 52%; background: var(--ridge-5);
  box-shadow: inset 0 1.5px 0 rgba(90, 211, 180, .50); }

/* Horizon haze. The hero's near-black used to butt straight into the canvas —
   a jump from L 0.004 to L 0.79 in one pixel row, which reads as a torn edge.
   Fading the scene out from BELOW the ridgeline removes the line entirely
   rather than softening one side of it. Sits above the ground (-3) and the
   ridges (-2) so it takes both down together; the last 150px of the scene is
   featureless near-black anyway, so nothing visible is lost. */
.hero::after {
  content: "";
  position: absolute;
  bottom: 0;
  left: 50%;
  transform: translateX(-50%);
  width: 100vw;
  height: 188px;
  /* Eased, not linear. A straight two-stop blend from near-black to the canvas
     spends its middle in flat neutral grey and reads as a smudge; these stops
     approximate an ease-in so the light arrives late, and the early ones carry
     a green cast so the haze stays in the scene's hue rather than going grey. */
  background: linear-gradient(180deg,
    transparent 0%,
    rgba(150, 190, 178, .05) 26%,
    rgba(198, 212, 206, .14) 46%,
    rgba(226, 224, 226, .34) 64%,
    rgba(237, 232, 234, .72) 84%,
    var(--canvas) 100%);
  z-index: -1;
  pointer-events: none;
}

/* Legibility scrim. Any mid-tone crossing the subhead destroys its contrast;
   this holds the copy column near the ground colour and fades out well before
   it reaches the card. */
.scene__scrim {
  position: absolute;
  inset: 0;
  background: linear-gradient(102deg,
    var(--hero-ground) 0%, var(--hero-ground) 24%, transparent 60%);
  opacity: .38;
}

/* Boot skeleton follows the hero down, or it flashes light before paint. */
.boot { background: var(--hero-ground); }
.sk {
  background-color: #14231E;
  background-image: linear-gradient(100deg,
    rgba(255, 255, 255, 0) 20%,
    rgba(255, 255, 255, .10) 42%,
    rgba(255, 255, 255, 0) 64%);
}
.sk--cta  { background-color: #1C3B33; }
.sk--card { background-color: #E4E0DA; }

/* --------------------------------------------------------------------------
   6. Portrait slots (were <image-slot> in the design doc)
   -------------------------------------------------------------------------- */

.portrait {
  display: block;
  object-fit: cover;
  background: var(--stone-200);
  flex: none;
}
.portrait--chip {
  width: 46px; height: 46px;
  border-radius: 50%;
}
.portrait--chip-lg {
  width: 56px; height: 56px;
  border-radius: 50%;
}
.portrait--full {
  width: 100%; height: 100%;
  border-radius: var(--radius-md);
}

/* Placeholder shown until a real photo is dropped in. */
.portrait:not([src]),
.portrait[src=""] {
  display: grid;
  place-items: center;
  color: var(--muted);
  font-size: 12px;
  font-weight: 600;
}

/* --------------------------------------------------------------------------
   7. Process — "How working with me actually goes"
   -------------------------------------------------------------------------- */

.process {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 56px;
  padding-bottom: 40px;
}

.process__title {
  text-align: center;
  font-weight: 700;
  font-size: clamp(32px, 4.9vw, 62px);
  line-height: 1.04;
  letter-spacing: -0.04em;
  max-width: 15em;
}

.process__grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 24px;
  width: 100%;
}

.pcard {
  border-radius: var(--radius-lg);
  padding: 26px;
  display: flex;
  flex-direction: column;
  gap: 20px;
  min-height: 420px;
}
.pcard--green { background: linear-gradient(160deg, var(--mint-200) 0%, var(--mint) 55%, var(--green) 100%); }
/* Deepened off the canvas and given an edge. The old stone ran #F4EFF0 →
   #E2D9DC against an #EDE8EA canvas — 1.06:1 at the top, so the card holding
   the fixed-price promise barely read as a container at all. The hairline does
   most of the work; on a light ground an edge separates better than tint. */
.pcard--stone {
  background: linear-gradient(160deg, #EDE6E8 0%, #D9CFD3 100%);
  border: 1px solid var(--rail-line);
}
/* The hero's dark, not a neutral grey. Dark means "hero" on this page now, and
   #2B2B2B sat 1.34:1 from --hero-ground while clashing with it in hue — close
   enough to compare, different enough to look wrong. The --dark-* tokens stay
   untouched: .tile--3 and three other rules still use them. */
.pcard--dark  { background: linear-gradient(160deg, var(--ridge-1) 0%, var(--hero-ground) 100%); color: #FFFFFF; }

.pcard__panel {
  background: #FFFFFF;
  border-radius: 18px;
  padding: 22px;
  display: flex;
  flex-direction: column;
  gap: 12px;
  color: var(--ink);
  /* The rows below stack on the PANEL's width, not the viewport's. The same
     card is 285px of usable panel at 1280 and 167px at 901, so a viewport
     media query would get this wrong in both directions. */
  container-type: inline-size;
}
.pcard__label {
  font-size: 13px;
  font-weight: 600;
  letter-spacing: .08em;
  color: var(--muted);
}
.pcard__row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  /* space-between alone lets a long label butt straight into its value once
     the two together fill the row. The gap guarantees they never touch; the
     value keeps its own width and the label is what gives. */
  gap: 16px;
  font-size: 15px;
  font-weight: 600;
  padding-bottom: 10px;
  border-bottom: 1px solid var(--line);
}
.pcard__row > span:last-child { flex: none; text-align: right; }
.pcard__row:last-child { padding-bottom: 0; border-bottom: 0; }

/* Widest label+value pair measures 255px. Below that the two cannot sit side
   by side without the label wrapping mid-phrase, so they stack instead —
   which is what happens in the three-column layout under ~1200px and on a
   phone. Label over value reads cleanly; a broken label does not. */
@container (max-width: 262px) {
  .pcard__row { flex-direction: column; align-items: flex-start; gap: 2px; }
  .pcard__row > span:last-child { text-align: left; }
}
.pcard__free { color: var(--green-600); }
.pcard__item { font-size: 15px; font-weight: 600; }

.pcard__quotes {
  border-radius: 18px;
  padding: 20px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  font-size: 15px;
  font-weight: 500;
  line-height: 1.5;
}
.pcard__quotes--onGreen {
  /* Darkened AWAY from the white type rather than toward it — same rule the
     hero ridges follow. The old translucent-white panel put white on an
     effective #3CB79E and measured 2.48:1, well under AA. This is 5.2:1. */
  background: rgba(4, 53, 44, .46);
  border: 1px solid rgba(255, 255, 255, .20);
  color: #FFFFFF;
}
.pcard__quotes--onStone {
  background: var(--mint-bg);
  border: 1px solid var(--mint-border);
  color: #3F4744;
}
/* A translucent lift rather than a solid panel, so the block sits ABOVE the
   ground the way the hero's layers do instead of beside it. */
.pcard__quotes--onDark {
  background: rgba(255, 255, 255, .05);
  border: 1px solid rgba(255, 255, 255, .14);
  color: #FFFFFF;
}

.pcard__assure {
  display: flex;
  align-items: center;
  gap: 8px;
  padding-top: 2px;
  font-size: 14px;
  font-weight: 700;
  color: var(--green-600);
  line-height: 1.45;
}
/* Same device on the dark card, where --green-600 would disappear. Mint at
   #5AD3B4 on --dark-800 measures 8.3:1. Ticks align to the first line because
   this answer runs to two. */
.pcard__assure--onDark {
  align-items: flex-start;
  color: var(--mint-200);
}
.pcard__assure--onDark svg { flex: none; margin-top: 3px; }

/* The step index. The number is not decoration — you cannot get a fixed price
   before the call, so the order carries information. The eyebrow names the
   stage, which the h3 alone does not. */
.pcard__step {
  align-self: flex-start;
  display: inline-flex;
  align-items: center;
  gap: 9px;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: .08em;
}
.pcard__step b {
  flex: none;
  width: 22px;
  height: 22px;
  border-radius: 999px;
  display: grid;
  place-items: center;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0;
}
.pcard--green .pcard__step   { color: var(--green-950); }
.pcard--green .pcard__step b { background: var(--green-950); color: #FFFFFF; }
.pcard--stone .pcard__step   { color: var(--ink); }
.pcard--stone .pcard__step b { background: var(--ink); color: #FFFFFF; }
.pcard--dark  .pcard__step   { color: var(--hero-point); }
.pcard--dark  .pcard__step b { background: #FFFFFF; color: var(--hero-ground); }

/* The one thing to do in the section. */
.pcard__rung {
  align-self: flex-start;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  margin-top: 2px;
  padding-bottom: 2px;
  font-size: 14px;
  font-weight: 700;
  color: #FFFFFF;
  text-decoration: none;
  border-bottom: 1.5px solid rgba(255, 255, 255, .55);
}
.pcard__rung:hover { border-bottom-color: #FFFFFF; }
/* The global focus ring is --green, which disappears on this card's ground. */
.pcard__rung:focus-visible { outline-color: #FFFFFF; }

.pcard__foot {
  margin-top: auto;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.pcard__foot h3 {
  font-weight: 700;
  font-size: clamp(24px, 2.2vw, 28px);
  letter-spacing: -0.03em;
}
.pcard__foot p {
  font-size: 17px;
  font-weight: 500;
  line-height: 1.45;
}
.pcard--green .pcard__foot p { color: var(--green-950); }
/* Not --muted (#6C6469): at 17px/500 on the stone ground that measured 4.15:1
   and failed AA. #54494F clears it on both the current and deepened grounds. */
.pcard--stone .pcard__foot p { color: #54494F; }
/* --hero-point, the hero's own body tone, rather than the grey card's
   --dark-text. 12.4:1 on --hero-ground. */
.pcard--dark  .pcard__foot p { color: var(--hero-point); }

/* --------------------------------------------------------------------------
   8. About — "Who you are dealing with"
   -------------------------------------------------------------------------- */

.about { padding-block: 20px 90px; }

.about__inner {
  background: var(--surface);
  border-radius: var(--radius-lg);
  padding: 40px;
  display: grid;
  grid-template-columns: 300px minmax(0, 1fr);
  gap: 44px;
  align-items: center;
}

.about__figure {
  position: relative;
  width: 300px;
  height: 320px;
}

.about__body {
  display: flex;
  flex-direction: column;
  gap: 20px;
}
.about__lede {
  font-size: clamp(20px, 2.1vw, 27px);
  line-height: 1.35;
  letter-spacing: -0.02em;
  max-width: 20em;
}
.about__note {
  font-size: 17px;
  line-height: 1.55;
  color: var(--muted);
  max-width: 34em;
}
.about__byline {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding-top: 4px;
}
.about__byline strong { font-size: 17px; font-weight: 700; }
.about__byline span   { font-size: 15px; color: var(--muted); }

.about__proof {
  display: flex;
  flex-wrap: wrap;
  gap: 14px 30px;
  padding-top: 16px;
  border-top: 1px solid var(--line);
}
.about__proof li {
  display: flex;
  align-items: center;
  gap: 9px;
  font-size: 15px;
  font-weight: 600;
}

/* --------------------------------------------------------------------------
   9. Benefits — "It is the no surprises kind of better"
   -------------------------------------------------------------------------- */

.benefits {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 22px;
  padding-bottom: 96px;
}
.benefits .eyebrow { color: var(--ink); font-weight: 600; letter-spacing: .18em; }

.benefits__title {
  text-align: center;
  font-weight: 700;
  font-size: clamp(32px, 5.2vw, 66px);
  line-height: 1.02;
  letter-spacing: -0.045em;
  max-width: 13em;
}
.benefits__lede {
  text-align: center;
  font-size: clamp(17px, 1.6vw, 20px);
  line-height: 1.5;
  color: var(--muted);
  max-width: 32em;
}

.benefits__grid {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 22px;
  width: 100%;
  padding-top: 34px;
}

.benefit {
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.benefit h3 {
  font-weight: 700;
  font-size: 20px;
  letter-spacing: -0.02em;
}
.benefit p {
  font-size: 16px;
  line-height: 1.45;
  color: var(--muted);
}

.tile {
  height: 150px;
  border-radius: var(--radius-md);
  background-size: 190% 190%;
  animation: mtx-sheen 16s ease-in-out infinite alternate;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 18px;
  overflow: hidden;
  transition: transform .38s var(--ease-out), box-shadow .38s ease;
}
.tile:hover {
  transform: translateY(-7px);
  box-shadow: 0 18px 34px -18px rgba(6, 58, 47, .55);
}
.tile--1 { background-image: linear-gradient(150deg, var(--mint-200), var(--green)); }
.tile--2 { background-image: linear-gradient(150deg, var(--green), var(--green-800)); animation-duration: 17s; }
.tile--3 { background-image: linear-gradient(150deg, var(--dark-700), var(--dark-900)); animation-duration: 18s; }
.tile--4 { background-image: linear-gradient(150deg, var(--mint), var(--mint-100)); animation-duration: 19s; }
.tile--5 { background-image: linear-gradient(150deg, var(--stone-200), var(--stone-500)); animation-duration: 20s; }

/* Text that swaps on tile hover. Two spans, not a JS textContent write. */
.swap > .swap__b { display: none; }
.tile:hover .swap > .swap__a { display: none; }
.tile:hover .swap > .swap__b { display: inline; }

/* Tile 1 — three avatars converge */
.tile__faces { display: flex; align-items: center; justify-content: center; }
.tile__face {
  width: 38px; height: 38px;
  border-radius: 50%;
  background: rgba(255, 255, 255, .32);
  transition: transform .45s var(--ease-out), opacity .35s ease;
}
.tile__face--l { margin-right: -12px; }
.tile__face--r { margin-left: -12px; }
.tile__face--c {
  width: 62px; height: 62px;
  background: #FFFFFF;
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1;
  box-shadow: 0 8px 18px -8px rgba(6, 58, 47, .6);
  transition: transform .45s var(--ease-out);
}
.tile--1:hover .tile__face--l { opacity: 0; transform: translateX(-26px); }
.tile--1:hover .tile__face--r { opacity: 0; transform: translateX(26px); }
.tile--1:hover .tile__face--c { transform: scale(1.14); }

/* Tile 2 — quote resolves */
.tile__quote {
  width: 100%;
  background: #FFFFFF;
  border-radius: 13px;
  padding: 13px 14px;
  display: flex;
  flex-direction: column;
  gap: 9px;
}
.tile__quote-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-size: 12px;
  font-weight: 700;
  color: var(--ink);
}
.tile__quote-head b { color: var(--green-600); font-weight: 700; }
.tile__stack { position: relative; height: 32px; }
.tile__skel, .tile__fill { position: absolute; inset: 0; display: flex; flex-direction: column; }
.tile__skel { gap: 7px; transition: opacity .3s ease; opacity: 1; }
.tile__skel i {
  height: 7px;
  border-radius: 99px;
  background: var(--line);
}
.tile__skel i:last-child { width: 70%; }
.tile__fill { gap: 4px; transition: opacity .3s ease .12s; opacity: 0; }
.tile__fill div {
  display: flex;
  justify-content: space-between;
  font-size: 11px;
  font-weight: 600;
  color: var(--ink);
}
.tile--2:hover .tile__skel { opacity: 0; }
.tile--2:hover .tile__fill { opacity: 1; }
.tile__lock {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 11px;
  font-weight: 600;
  color: var(--muted);
}

/* Tile 3 — backup stack lifts */
.tile__stack3 { position: relative; width: 124px; height: 96px; }
.tile__sheet {
  position: absolute;
  border-radius: 8px;
  transition: transform .45s var(--ease-out);
}
.tile__sheet--a { left: 12px; top: 6px;  width: 100px; height: 22px; background: rgba(255,255,255,.22); }
.tile__sheet--b { left: 6px;  top: 32px; width: 112px; height: 24px; background: rgba(255,255,255,.42); border-radius: 9px; }
.tile__sheet--c {
  left: 0; top: 60px; width: 124px; height: 28px;
  border-radius: 10px;
  background: #FFFFFF;
  display: flex;
  align-items: center;
  padding: 0 11px;
  gap: 7px;
  font-size: 11px;
  font-weight: 700;
  color: var(--dark-900);
}
.tile--3:hover .tile__sheet--a { transform: translateY(-10px); }
.tile--3:hover .tile__sheet--b { transform: translateY(-5px); }
.tile--3:hover .tile__sheet--c { transform: translateY(6px); }

/* Tile 4 — handover video plays */
.tile__player {
  width: 132px;
  background: #FFFFFF;
  border-radius: 12px;
  padding: 9px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.tile__screen {
  height: 60px;
  border-radius: 8px;
  background: var(--dark-900);
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
}
.tile__play { transition: opacity .25s ease; opacity: 1; }
.tile__playing {
  position: absolute;
  font-size: 11px;
  font-weight: 700;
  color: #FFFFFF;
  transition: opacity .25s ease;
  opacity: 0;
}
.tile__track {
  height: 5px;
  border-radius: 99px;
  background: var(--line);
  position: relative;
  overflow: hidden;
}
.tile__track i {
  position: absolute;
  left: 0; top: 0;
  height: 5px;
  border-radius: 99px;
  background: var(--green);
  width: 16%;
  transition: width 1.1s cubic-bezier(.4, 0, .2, 1);
}
.tile--4:hover .tile__play    { opacity: 0; }
.tile--4:hover .tile__playing { opacity: 1; }
.tile--4:hover .tile__track i { width: 100%; }

/* Tile 5 — 30 days of cover fill in.
   Was a 7-wide grid of 12px pips, which is a calendar, and 14 of them, which is
   a fortnight — under a caption reading "30 days of bug cover". Ten columns of
   8px instead: 30 pips land as three clean rows, and it stops reading as weeks.
   Measured before shipping, because .tile is height:150px with overflow:hidden
   and there were only 12.4px of headroom at 1280: the grid goes 28px -> 30px,
   so it costs 2 of them. */
.tile__cover {
  background: #FFFFFF;
  border-radius: 13px;
  padding: 12px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.tile__cover-label {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .08em;
  color: var(--muted);
}
.tile__days {
  display: grid;
  grid-template-columns: repeat(10, 8px);
  gap: 3px;
}
.tile__day {
  height: 8px;
  border-radius: 2px;
  background: var(--stone-300);
  overflow: hidden;
}
.tile__day i {
  display: block;
  width: 100%; height: 100%;
  border-radius: 3px;
  background: var(--green);
  opacity: 0;
  transition: opacity .16s ease var(--d, 0ms);
}
.tile--5:hover .tile__day i { opacity: 1; }
.tile__cover-foot {
  font-size: 11px;
  font-weight: 700;
  color: var(--dark-900);
}

/* --------------------------------------------------------------------------
   10. Proof — two result photos
   -------------------------------------------------------------------------- */

.proof {
  padding-block: 76px 120px;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 88px;
}

.proof__item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 26px;
  text-align: center;
}

.proof__frame {
  width: 100%;
  height: 300px;
  border-radius: 22px;
  overflow: hidden;
  background: var(--stone-200);
}
.proof__frame img {
  width: 100%; height: 100%;
  object-fit: cover;
}
/* Owned proof artwork. `slice` on the SVG is the object-fit: cover it replaces —
   the frame's aspect swings from ~1.57:1 at 1280 to ~1.12:1 at 375, so the
   400x300 viewBox is deliberately squarer than any of them and every element
   sits inside a 40px safe inset. Worst case crop measures 27px vertical on
   desktop, 32px horizontal on mobile, and nothing meaningful is near an edge. */
.proof__viz {
  width: 100%; height: 100%;
  display: block;
}

/* Proof artwork, animated.

   The base state of every element below is the FINISHED graphic and the
   entrance lives entirely inside the keyframes. That ordering is load-bearing:
   a visitor with JS off never gets `.in`, so an animation-first base state
   would leave two blank frames, and the global reduced-motion block at the
   bottom of this file crushes animation-duration to .001ms, which lands on the
   finished frame rather than on nothing.

   Triggered by `.proof.in` — the section already carries data-reveal, so the
   drawing starts when it scrolls into view instead of playing to an empty room.
   Each delay adds var(--i), the per-child stagger main.js stamps for
   [data-stagger], so a card's artwork starts after that card has faded up. */

@keyframes mtx-viz-draw { from { stroke-dashoffset: var(--dash); } to { stroke-dashoffset: 0; } }
@keyframes mtx-viz-fade { from { opacity: 0; } }
@keyframes mtx-viz-wipe { from { transform: scaleX(0); } to { transform: scaleX(1); } }
@keyframes mtx-viz-pop  { from { transform: scale(0); } to { transform: scale(1); } }

.proof.in .viz__line,
.proof.in .viz__arrow,
.proof.in .viz__head,
.proof.in .viz__tick {
  stroke-dasharray: var(--dash);
  animation: mtx-viz-draw var(--dur, .8s) var(--ease-out) both;
  animation-delay: calc(var(--i, 0ms) + var(--at, 0ms));
}
.proof.in .viz__area,
.proof.in .viz__mark,
.proof.in .viz__gap {
  animation: mtx-viz-fade var(--dur, .8s) ease both;
  animation-delay: calc(var(--i, 0ms) + var(--at, 0ms));
}
.proof.in .viz__bar,
.proof.in .viz__chip,
.proof.in .viz__pop {
  transform-box: fill-box;
  animation: var(--kf, mtx-viz-pop) var(--dur, .6s) var(--ease-out) both;
  animation-delay: calc(var(--i, 0ms) + var(--at, 0ms));
}

/* Card 1 — the index falls out, then comes back. Dash lengths are the measured
   path lengths plus a few units of slack so the stroke fully clears. */
.viz__line--was { --dash: 285; --dur: .85s; }
.viz__line--now { --dash: 235; --dur: .8s;  --at: 760ms; }
.viz__mark      { --dur: .5s;  --at: 900ms; }
.viz__area      { --dur: .9s;  --at: 1150ms; }
.viz__pop       { --dur: .5s;  --at: 1500ms; transform-origin: center; }
.viz__pop--glow { --at: 1560ms; }

/* Card 2 — what arrives, what actually gets paid, and the gap being chased. */
.viz__bar        { --kf: mtx-viz-wipe; --dur: .7s; transform-origin: left center; }
.viz__bar--paid  { --at: 180ms; }
.viz__gap        { --dur: .45s; --at: 720ms; }
.viz__arrow      { --dash: 110; --dur: .7s; --at: 980ms; }
.viz__head       { --dash: 30;  --dur: .22s; --at: 1620ms; }
.viz__chip       { --dur: .42s; --at: 1720ms; transform-origin: center; }
.viz__tick       { --dash: 24;  --dur: .3s; --at: 1900ms; }

.proof__quote {
  font-family: var(--font-serif);
  font-style: italic;
  font-weight: 400;
  font-size: clamp(26px, 3.4vw, 44px);
  line-height: 1.18;
  letter-spacing: -0.01em;
  max-width: 14em;
}
.proof__detail {
  font-size: 17px;
  line-height: 1.5;
  color: var(--muted);
  max-width: 26em;
}
.proof__credit {
  font-size: 12px;
  color: var(--muted);
  opacity: .75;
}
.proof__credit:empty { display: none; }
.proof__credit a { text-decoration: underline; text-underline-offset: 2px; }

/* --------------------------------------------------------------------------
   11. Services — the scroll rail
   -------------------------------------------------------------------------- */

.services {
  padding-bottom: 70px;
  display: flex;
  flex-direction: column;
  gap: 44px;
  position: relative;
  isolation: isolate;
}

/* Parallax contour field. Taller than the section so there is travel room, and
   masked open down the middle — the rail's node masks are canvas-coloured, so
   they would otherwise punch visible solid blocks through the texture. */
.services__bg {
  position: absolute;
  /* Full-bleed, and it has to be done WITHOUT transform: main.js owns this
     element's transform for the parallax and overwrites it every frame, so the
     usual left:50% + translateX(-50%) trick would be wiped on the first scroll.

     Was `inset-inline: -12%`, which is -12% of the 1280px wrap and therefore a
     FIXED 1587px however wide the window gets. Past that it stopped reaching
     the edges: 46px gutters at 1680, 166px at 1920, 486px at 2560. The mask
     below is percentage-based, so the element has to be exactly viewport-width
     for the two contour bands to stay pinned to the left and right edges. */
  left: calc(50% - 50vw);
  right: auto;
  width: 100vw;
  top: -12%;
  height: 124%;
  z-index: -1;
  pointer-events: none;
  /* Overall strength of the texture. The one number to nudge if it reads too
     hot or too faint — the section is fully exposed before the cards reveal. */
  opacity: .8;
  background: url("assets/contours.svg") center center / cover no-repeat;
  will-change: transform;
  -webkit-mask-image: linear-gradient(90deg,
    #000 0%, #000 30%, transparent 43%, transparent 57%, #000 70%, #000 100%);
  mask-image: linear-gradient(90deg,
    #000 0%, #000 30%, transparent 43%, transparent 57%, #000 70%, #000 100%);
}

.services__head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 40px;
  padding-inline: 4px;
}
.services__head h2 {
  font-weight: 700;
  font-size: clamp(30px, 4.9vw, 62px);
  line-height: 1.02;
  letter-spacing: -0.045em;
  max-width: 12em;
}
.services__head p {
  font-size: 18px;
  line-height: 1.5;
  color: var(--muted);
  max-width: 20em;
  padding-bottom: 8px;
}

.rail { position: relative; }

.rail__track {
  position: absolute;
  left: 50%; top: 34px;
  width: 2px;
  margin-left: -1px;
  background: var(--rail-line);
}
.rail__fill {
  position: absolute;
  left: 0; top: 0;
  width: 2px;
  height: 0;
  background: linear-gradient(var(--mint), var(--green));
}
.rail__head {
  position: absolute;
  left: -4px; top: 0;
  width: 10px; height: 10px;
  margin-top: -5px;
  border-radius: 50%;
  background: var(--mint);
  box-shadow: 0 0 0 5px rgba(23, 169, 140, .18), 0 0 16px rgba(23, 169, 140, .9);
  opacity: 0;
}

.rail__grid {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr) 112px minmax(0, 1fr);
  row-gap: 26px;
}

.rail__slot {
  display: flex;
  justify-content: center;
  padding-top: 30px;
}
.rail__marker { position: relative; width: 56px; height: 56px; }
.rail__mask {
  position: absolute;
  left: 50%;
  margin-left: -6px;
  top: -3px;
  width: 12px; height: 62px;
  background: var(--canvas);
}
.rail__bypass {
  position: absolute;
  left: -34px; top: -26px;
  pointer-events: none;
}
.rail__node {
  position: relative;
  z-index: 1;
  width: 56px; height: 56px;
  border-radius: 18px;
  background: linear-gradient(150deg, var(--mint), var(--green-800));
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 0 0 8px var(--canvas);
  filter: grayscale(.85) opacity(.45);
  transform: scale(.9);
  transition: filter .45s ease, transform .45s var(--ease-out), box-shadow .45s ease;
}
.rail__node.is-lit {
  filter: none;
  transform: scale(1);
  box-shadow: 0 0 0 8px var(--canvas),
              0 14px 24px -16px rgba(6, 58, 47, .9),
              inset 0 1px 0 rgba(255, 255, 255, .35);
}

.svc-card {
  background: var(--surface);
  border-radius: var(--radius-lg);
  padding: 32px;
  display: flex;
  flex-direction: column;
  gap: 16px;
  transition: transform .35s var(--ease-out), box-shadow .35s ease;
}
.svc-card:hover {
  transform: translateY(-5px);
  box-shadow: 0 26px 46px -32px rgba(6, 58, 47, .6);
}
.svc-card__num {
  display: flex;
  align-items: center;
  gap: 14px;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: .14em;
  color: var(--muted);
}
.svc-card__num i { height: 1px; flex: 1; background: var(--line); }
.svc-card h3 {
  font-weight: 700;
  font-size: clamp(24px, 2.4vw, 30px);
  letter-spacing: -0.035em;
}
.svc-card__desc {
  font-size: 16px;
  line-height: 1.55;
  color: var(--muted);
}
.svc-card__tags {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
.tag {
  font-size: 13px;
  font-weight: 600;
  color: var(--green-600);
  background: var(--mint-bg);
  border-radius: 999px;
  padding: 6px 12px;
}
.svc-card__out {
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding-top: 18px;
  border-top: 1px solid var(--line);
}
.svc-card__out-label {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .14em;
  color: var(--green-600);
}
.svc-card__out ul {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px 24px;
}
.svc-card__out li {
  display: flex;
  align-items: flex-start;
  gap: 9px;
  font-size: 15px;
  font-weight: 500;
  line-height: 1.45;
}
.svc-card__out svg { flex: none; margin-top: 4px; }

/* --------------------------------------------------------------------------
   12. Extras — "Plus the small stuff"
   -------------------------------------------------------------------------- */

.extras { padding-bottom: 90px; }

.extras__inner {
  background: var(--surface);
  border-radius: var(--radius-lg);
  padding: 40px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.extras__head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 30px;
  padding-bottom: 14px;
}
.extras__head h2 {
  font-weight: 700;
  font-size: clamp(24px, 2.4vw, 30px);
  letter-spacing: -0.035em;
}
.extras__head p { font-size: 17px; color: var(--muted); }
.extras__ask {
  font-size: 15px;
  font-weight: 600;
  color: var(--green-600);
  background: var(--mint-bg);
  border-radius: 999px;
  padding: 10px 18px;
  white-space: nowrap;
}

.extras__cols {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 0 44px;
}
.extras__col { display: flex; flex-direction: column; }
.extras__item {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 13px 0;
  border-bottom: 1px solid var(--line);
  font-size: 16px;
  font-weight: 500;
  transition: padding-left .25s ease;
}
.extras__item:hover { padding-left: 6px; }
.extras__item svg { flex: none; }

/* --------------------------------------------------------------------------
   13. FAQ
   -------------------------------------------------------------------------- */

.faq {
  padding-bottom: 90px;
  display: grid;
  grid-template-columns: 340px minmax(0, 1fr);
  gap: 56px;
  align-items: start;
}

.faq__aside {
  display: flex;
  flex-direction: column;
  gap: 18px;
  position: sticky;
  top: 40px;
}
.faq__aside h2 {
  font-weight: 700;
  font-size: clamp(30px, 4.4vw, 54px);
  line-height: 1.02;
  letter-spacing: -0.045em;
}
.faq__aside p {
  font-size: 17px;
  line-height: 1.55;
  color: var(--muted);
}
.faq__contact {
  display: flex;
  align-items: center;
  gap: 12px;
  background: var(--surface);
  border-radius: 16px;
  padding: 16px 18px;
  margin-top: 6px;
}
.faq__contact svg { flex: none; }
.faq__contact div { display: flex; flex-direction: column; }
.faq__contact strong { font-size: 15px; font-weight: 700; }
.faq__contact a { font-size: 15px; color: var(--green-600); }
.faq__contact a:hover { text-decoration: underline; }

.faq__list {
  background: var(--surface);
  border-radius: var(--radius-lg);
  padding: 34px 36px;
}

.faq__row { border-bottom: 1px solid var(--line); }
.faq__row:last-child { border-bottom: 0; }

.faq__q {
  appearance: none;
  width: 100%;
  background: none;
  border: 0;
  font: inherit;
  color: inherit;
  text-align: left;
  cursor: pointer;
  padding: 18px 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  font-weight: 700;
  font-size: 20px;
  letter-spacing: -0.02em;
  transition: padding-left .25s ease;
}
.faq__q:hover { padding-left: 6px; }

.faq__sign {
  width: 28px; height: 28px;
  border-radius: 50%;
  background: var(--mint-bg);
  color: var(--green-600);
  font-size: 17px;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
  flex: none;
}
.faq__sign::before { content: "+"; }
.faq__q[aria-expanded="true"] .faq__sign::before { content: "\2013"; }

.faq__a {
  font-size: 17px;
  line-height: 1.55;
  color: var(--muted);
  max-width: 46em;
  padding-bottom: 18px;
  transition: padding-left .25s ease;
}
.faq__a[hidden] { display: none; }
.faq__row:hover .faq__a { padding-left: 6px; }

/* --------------------------------------------------------------------------
   14. Final CTA
   -------------------------------------------------------------------------- */

.book { padding-bottom: 44px; }

.book__inner {
  background: linear-gradient(150deg, var(--green) 0%, var(--green-700) 52%, var(--green-900) 100%);
  border-radius: var(--radius-lg);
  padding: 52px;
  color: #FFFFFF;
  display: grid;
  grid-template-columns: minmax(0, 1fr) 420px;
  gap: 52px;
  align-items: center;
}

.book__copy {
  display: flex;
  flex-direction: column;
  gap: 22px;
}
.book__copy .eyebrow { color: #FFFFFF; }
.book__copy h2 {
  font-weight: 700;
  font-size: clamp(30px, 4.6vw, 56px);
  line-height: 1;
  letter-spacing: -0.045em;
}
.book__copy > p {
  font-size: 19px;
  line-height: 1.5;
  max-width: 26em;
}

.book__points {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding-top: 2px;
}
.book__points li {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 16px;
  font-weight: 500;
}

.book__who {
  display: flex;
  align-items: center;
  gap: 14px;
  padding-top: 12px;
  border-top: 1px solid rgba(255, 255, 255, .22);
  margin-top: 6px;
}
.book__who div { display: flex; flex-direction: column; }
.book__who strong { font-size: 16px; font-weight: 700; }
.book__who span   { font-size: 15px; }
.book__who a { text-decoration: underline; text-underline-offset: 3px; }

.picker {
  background: var(--surface);
  border-radius: var(--radius-md);
  padding: 26px;
  color: var(--ink);
  display: flex;
  flex-direction: column;
  gap: 16px;
  box-shadow: 0 28px 50px -30px rgba(4, 45, 37, .7);
}
/* Removed as dead with the hardcoded picker: .picker__head, __grid, __dow,
   __day(+--free/--sel), __times, __time(+--sel), __note. Nothing referenced
   them once the Cal embed replaced that markup. */

/* The embed target. Empty and zero-height until Cal renders into it, so the
   card collapses to just the link when the script never arrives. */
.picker__cal { width: 100%; }
/* Floor only, not a target. Cal sizes its own iframe and reports the height
   back, and measured across 375–1440 that lands between 300px and 571px — so
   300 never adds a pixel, it just stops the card collapsing in the moment
   between the iframe being inserted and Cal reporting its height. This was 460,
   which was taller than the iframe at most widths and was padding the card out
   with dead white space all on its own. */
.picker--cal.is-live .picker__cal { min-height: 300px; }
.picker--cal.is-live .picker__fallback { display: none; }
.picker__cal iframe { width: 100%; border: 0; display: block; }

/* Base state, and the whole booking path with JS off or Cal blocked. Styled as
   a real call to action rather than an apology, because for some visitors this
   IS the booking experience. */
.picker__fallback {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  text-align: center;
  padding: 12px 0 4px;
}
.picker__fallback strong { font-size: 17px; font-weight: 700; letter-spacing: -0.02em; }
.picker__fallback > span { font-size: 13px; color: var(--muted); }
.picker__fallback a { color: var(--green-600); text-decoration: underline; }
.picker__link {
  background: var(--green);
  color: #FFFFFF;
  text-decoration: none;
  font-weight: 700;
  font-size: 15px;
  padding: 13px 22px;
  border-radius: 999px;
}
.picker__link:hover { background: var(--green-700); }

/* --------------------------------------------------------------------------
   15. Footer
   -------------------------------------------------------------------------- */

.site-footer {
  padding-bottom: 44px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  font-size: 16px;
  color: var(--muted);
}
.site-footer strong {
  font-weight: 800;
  font-size: 20px;
  color: var(--ink);
  letter-spacing: -0.035em;
}
.site-footer a { color: var(--ink); }
.site-footer a:hover { text-decoration: underline; text-underline-offset: 3px; }

/* --------------------------------------------------------------------------
   16. Responsive
   -------------------------------------------------------------------------- */

@media (max-width: 1180px) {
  :root { --pad: 32px; }

  .hero { grid-template-columns: minmax(0, 1fr) 380px; gap: 40px; padding-block: 72px 88px; }
  .benefits__grid { grid-template-columns: repeat(3, 1fr); gap: 20px; }
  .proof { gap: 48px; padding-block: 60px 96px; }
  .book__inner { grid-template-columns: minmax(0, 1fr) 360px; gap: 40px; padding: 40px; }
  .faq { grid-template-columns: 280px minmax(0, 1fr); gap: 40px; }
  .about__inner { gap: 32px; padding: 32px; }
}

@media (max-width: 900px) {
  .site-header { flex-wrap: wrap; gap: 16px; }

  .hero {
    grid-template-columns: minmax(0, 1fr);
    gap: 40px;
    padding-block: 56px 72px;
  }

  /* Stacked, the copy runs the full width, so the scrim has to protect from
     the top down rather than from the left. */
  .scene__scrim {
    opacity: .58;
    background: linear-gradient(180deg,
      var(--hero-ground) 0%, var(--hero-ground) 30%, transparent 74%);
  }
  .scene__glow { left: 50%; top: 66%; }

  .process { gap: 40px; }
  .process__grid { grid-template-columns: 1fr; }
  .pcard { min-height: 0; }

  .about__inner { grid-template-columns: minmax(0, 1fr); }
  .about__figure { width: 100%; max-width: 320px; height: 340px; margin-inline: auto; }

  .proof { grid-template-columns: 1fr; gap: 56px; }

  /* No rail down here, so no centre channel to keep clear. */
  .services__bg {
    -webkit-mask-image: none;
    mask-image: none;
    opacity: .5;
  }

  /* The rail is a desktop device. Below this it becomes a plain stack. */
  .rail__track,
  .rail__slot { display: none; }
  .rail__grid { grid-template-columns: minmax(0, 1fr); }
  .rail__grid > [data-card] { grid-column: 1 !important; grid-row: auto !important; }
  [data-reveal][data-dir="l"],
  [data-reveal][data-dir="r"] { transform: translateY(14px); }

  .extras__cols { grid-template-columns: repeat(2, 1fr); gap: 0 32px; }

  .faq { grid-template-columns: minmax(0, 1fr); gap: 32px; }
  .faq__aside { position: static; }

  .book__inner { grid-template-columns: minmax(0, 1fr); }

  /* Once the panel stacks, the booking card would otherwise stretch to the full
     panel width, and Cal's iframe height scales with its width: measured 743px
     tall at a 756px-wide card at 900, down to 340px at 279px wide. The whole
     stacked band was running long, worst at the top of it.
     420px is not an arbitrary cap — it is exactly the width of the picker column
     in the two-up desktop grid above, so the card renders identically at every
     width instead of having a distinct tall personality between 900 and 480. */
  .picker { max-width: 420px; margin-inline: auto; width: 100%; }
}

@media (max-width: 700px) {
  :root { --pad: 20px; --radius-lg: 20px; }

  .site-header { padding-top: 24px; }
  .site-nav { width: 100%; flex-wrap: wrap; }
  .pill, .cta__inner { font-size: 15px; padding: 10px 16px; }
  /* Once the nav wraps, the CTA starts a row of its own — drop the inline
     offset so it lines up with the pill above it. */
  .cta { margin-left: 0; }

  .booking { padding: 22px; }

  .benefits__grid { grid-template-columns: repeat(2, 1fr); }
  .benefits { padding-bottom: 72px; }

  .about { padding-bottom: 64px; }
  .about__inner { padding: 24px; }
  .about__proof { gap: 12px 20px; }

  .proof__frame { height: 220px; }

  .services__head { flex-direction: column; align-items: flex-start; gap: 16px; }
  .services__head p { padding-bottom: 0; }
  .svc-card { padding: 24px; }
  .svc-card__out ul { grid-template-columns: 1fr; }

  .extras__inner { padding: 24px; }
  .extras__head { flex-direction: column; align-items: flex-start; gap: 14px; }
  .extras__cols { grid-template-columns: 1fr; gap: 0; }

  .faq__list { padding: 22px 24px; }
  .faq__q { font-size: 18px; gap: 16px; }

  .book__inner { padding: 28px; }
  .picker { padding: 20px; }

  .site-footer {
    flex-direction: column;
    align-items: flex-start;
    gap: 10px;
    font-size: 15px;
  }
}

@media (max-width: 460px) {
  .benefits__grid { grid-template-columns: 1fr; }
}

/* --------------------------------------------------------------------------
   17. Reduced motion
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }

  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }

  [data-reveal] { opacity: 1 !important; transform: none !important; }
  [data-stagger] > * { opacity: 1 !important; transform: none !important; }
  .rail__head { display: none; }
  .services__bg { transform: none !important; }
  .boot { display: none; }
}

/* --------------------------------------------------------------------------
   18. Print
   -------------------------------------------------------------------------- */

@media print {
  .cta, .rail__track, .rail__bypass { display: none; }
  [data-reveal] { opacity: 1 !important; transform: none !important; }
  .faq__a[hidden] { display: block !important; }
  body { background: #FFFFFF; }
}
