:root{
  --ink:#1E2B1A;
  --deep:#4A6741;
  --pist:#8DB96B;
  --light:#CBE0B4;          /* hairlines on cream — decorative only */
  --light-hi:#D8E9C6;       /* text on the green background — 4.96:1 */
  --card-txt:#E2F0D4;       /* text on the tinted card inside that band — 4.77:1 */
  --sep:#5F8F3C;            /* separator dots — 3.48:1 on cream */
  --cream:#F6F4EC;
  --white:#FFFFFF;
  --shell:#B08050;
  --danger:#A6412F;
  --ease:cubic-bezier(.22,1,.36,1);
  --maxw:1280px;
  --pad:clamp(20px,5vw,48px);   /* header, stage copy, sticky bar */
  --gut:clamp(20px,5.5vw,76px); /* side gutter for all page content */
}

*,*::before,*::after{box-sizing:border-box}
html{scroll-behavior:auto;-webkit-text-size-adjust:100%}
body{
  margin:0;
  background:var(--cream);
  color:var(--ink);
  font-family:Inter,-apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif;
  font-size:17px;
  line-height:1.55;
  -webkit-font-smoothing:antialiased;
  overflow-x:hidden;
  transition:background-color .35s linear;
}
img{max-width:100%;display:block}
a{color:inherit}

.skip{position:absolute;left:-9999px;top:0;z-index:200;background:var(--deep);color:var(--cream);padding:12px 18px;border-radius:0 0 4px 0;text-decoration:none}
.skip:focus{left:0}
.opt{text-transform:none;letter-spacing:0;opacity:.6;font-weight:400}

/* ---------- header ---------- */
.hdr{
  position:fixed;inset:0 0 auto 0;z-index:60;
  display:flex;align-items:center;justify-content:space-between;
  padding:18px var(--pad);
  transition:background-color .25s var(--ease),border-color .25s var(--ease),backdrop-filter .25s var(--ease);
  border-bottom:1px solid transparent;
}
.hdr.solid{background:rgba(246,244,236,.82);backdrop-filter:blur(12px);border-bottom-color:var(--light)}
.wordmark{display:block;text-decoration:none;line-height:0}
.wordmark img{display:block;height:28px;width:auto}
@media (max-width:767px){.wordmark img{height:24px}}
.hdr-right{display:flex;align-items:center;gap:20px;font-size:13px;letter-spacing:.06em}
.lang a{text-decoration:none;opacity:.55;transition:opacity .2s;display:inline-block;min-width:26px;min-height:26px;line-height:26px;text-align:center}
.lang a.on,.lang a:hover{opacity:1}
.lang span{opacity:.3;margin:0 2px}
.hdr .contact{text-decoration:none;border-bottom:1px solid currentColor;padding:4px 2px;display:inline-block;min-height:26px}
.hdr.on-green{color:var(--cream)}

/* ---------- scrolly ---------- */
/* 700vh, not 500: the holds in the frame map need scroll length to spend */
.scrolly{position:relative;height:700vh}
@media (max-width:767px){.scrolly{height:540vh}}
.sticky{
  position:sticky;top:0;height:100vh;height:100dvh;overflow:hidden;
  /* the picture fills the whole sticky viewport on a desktop; on a phone it
     becomes a band under the header (see the phone rules further down) */
  --bandtop:0px;--bandh:100%;
  --blockend:0px;        /* where the picture band ends, on a phone */
}
#seq,.lcp{position:absolute;left:0;right:0;top:var(--bandtop);height:var(--bandh);width:100%;display:block}
.lcp{object-fit:cover;z-index:0}
#seq{z-index:1}
/* A phone screen is far taller than the 16:9 footage. Fitting the whole frame
   inside it left a strip of cream above and below and a very small picture;
   a band of its own, filled edge to edge, is both bigger and tidier. */
@media (max-width:767px){
  .sticky{
    --bandtop:62px;--bandh:min(calc(100vw * .72),46dvh);
    --blockend:calc(var(--bandtop) + var(--bandh));
  }
}

/* preloader */
.pre{position:absolute;inset:0;z-index:9;display:flex;align-items:flex-end;justify-content:center;pointer-events:none}
.pre .bar{width:min(320px,60vw);height:2px;background:rgba(74,103,65,.16);margin-bottom:12vh;border-radius:2px;overflow:hidden}
.pre .bar i{display:block;height:100%;width:0%;background:var(--pist);transition:width .25s linear}
.loading .lcp{filter:blur(24px) saturate(.4);transform:scale(1.04)}
.lcp{transition:filter .6s var(--ease),transform .6s var(--ease)}
.ready .pre{opacity:0;transition:opacity .4s}

/* ---------- stages ---------- */
.stages{position:absolute;inset:0;z-index:3;pointer-events:none}
.stage{
  position:absolute;
  width:min(440px,74vw);
  opacity:0;
  will-change:opacity,transform,filter;
}
/* frosted panel — measured so cream text clears 4.5:1 even on the brightest frame */
.stage{
  background:rgba(30,43,26,.70);
  -webkit-backdrop-filter:blur(18px) saturate(1.05);
  backdrop-filter:blur(18px) saturate(1.05);
  border-radius:6px;
  padding:clamp(22px,2.4vw,32px) clamp(24px,2.8vw,38px);
}
.stage h1,.stage h2{
  margin:0 0 .45em;
  font-weight:600;
  letter-spacing:-.025em;
  line-height:1.08;
  font-size:clamp(1.7rem,3.5vw,2.7rem);
  color:var(--cream);
}
.stage p{margin:0;font-weight:400;color:var(--light-hi);font-size:clamp(.98rem,1.35vw,1.15rem);line-height:1.45}
/* applied only while the panel is actually moving: a filter, even at 0px,
   keeps the type on a raster layer of its own for the whole scroll */
.stage.vblur h1,.stage.vblur h2,.stage.vblur p{filter:blur(var(--vblur,0px))}
.stage .line{display:block;overflow:hidden}
.stage .line > span{display:block;transform:translateY(110%);transition:transform .7s var(--ease)}
/* the panels are click-through by default; the one carrying the button is not */
.stagebtn{margin-top:clamp(18px,2vw,26px);font-size:15px;padding:14px 26px}
.stage:has(.stagebtn){pointer-events:none}
.stage.in:has(.stagebtn){pointer-events:auto}
.stage .stagebtn{background:var(--cream);color:var(--deep);font-weight:600}
.stage .stagebtn:hover{background:var(--white)}
.stage.in .line > span{transform:translateY(0)}
.stage.in .line:nth-child(2) > span{transition-delay:.06s}
.stage.in p{transition-delay:.14s}

/* The tub sits dead centre and the frame is cover-cropped, so the clear band
   to its left narrows as the window does. The tub's printed logo starts at
   about (50vw - 4.44vh) — measured off the frame, not guessed — so cap the
   panel to stop short of it. Above ~1050px the 440px cap wins and nothing
   changes. */
.s1{left:var(--pad);bottom:15vh;width:min(440px,74vw,calc(50vw - 4.44vh - 88px))}
.s2{right:var(--pad);top:16vh;text-align:right}
.s3{left:50%;top:50%;transform:translate(-50%,-50%);width:min(820px,88vw);text-align:center;padding:clamp(30px,3.4vw,46px) clamp(28px,3.6vw,52px)}
.s3 h2{font-size:clamp(2rem,5.2vw,4rem);letter-spacing:-.04em}
.s3 p{font-size:clamp(1rem,1.5vw,1.25rem)}
.s4{left:var(--pad);top:16vh}

/* on phones the copy sits on plain cream under the picture band and needs no
   panel at all — and it hangs off the bottom of the band, not off the bottom
   of the screen, so it stays close to the picture and well clear of the
   scroll cue */
@media (max-width:767px){
  .stage{
    background:none;backdrop-filter:none;-webkit-backdrop-filter:none;
    padding:0;left:var(--pad);right:var(--pad);width:auto;
    top:calc(var(--blockend) + clamp(26px,7vw,44px));
    bottom:auto;transform:none;text-align:center;
  }
  .stage h1,.stage h2{color:var(--ink);font-size:clamp(1.6rem,7vw,2.1rem)}
  .stage p{color:var(--deep);font-size:1rem}
  /* On a phone the sticky bottom bar already carries the call to action, so the
     one inside the hero copy is hidden. It needs two classes to win: the base
     .btn rule is defined further down the file and would otherwise re-display
     it, which is how it ended up landing on the scroll cue. */
  .stage .stagebtn{display:none}
  .s3{padding:0}
  .s3 h2{font-size:clamp(1.9rem,8vw,2.4rem)}
}

/* stage indicator */
.ind{position:absolute;left:var(--pad);bottom:var(--pad);z-index:4;display:flex;flex-direction:column;gap:6px}
.ind i{display:block;height:2px;width:24px;background:var(--light);border-radius:2px;transition:width .35s var(--ease),background-color .35s var(--ease)}
.ind i.on{width:40px;background:var(--deep)}
.on-green .ind i{background:rgba(246,244,236,.35)}
.on-green .ind i.on{background:var(--cream)}

/* scroll cue */
.cue{position:absolute;left:50%;bottom:5vh;transform:translateX(-50%);z-index:4;font-size:11px;letter-spacing:.22em;text-transform:uppercase;opacity:.5;transition:opacity .5s;text-align:center}
.cue .arw{display:block;width:1px;height:26px;background:currentColor;margin:10px auto 0;transform-origin:top;animation:cue 1.8s var(--ease) infinite}
@keyframes cue{0%{transform:scaleY(0);opacity:0}40%{transform:scaleY(1);opacity:1}100%{transform:scaleY(1) translateY(26px);opacity:0}}

/* 16:9 footage cannot fill a phone screen, so there is always cream left over.
   Gathering the cue and the progress bars under the copy keeps the hero as one
   block below the header and leaves the spare room in a single piece at the
   bottom, which is where the next section rises into it. */
@media (max-width:767px){
  /* The cue's line animates 26px past the bottom of its own box, so the gap to
     the progress bars is measured from where the line actually reaches, not
     from the box. 159px below the cue puts the bars 80px clear of it. The
     offset shrinks on a short screen so the bars never fall off the bottom. */
  .cue{--cueoff:clamp(72px,17dvh,160px);top:calc(var(--blockend) + var(--cueoff));bottom:auto}
  .ind{
    --cueoff:clamp(72px,17dvh,160px);
    top:calc(var(--blockend) + var(--cueoff) + 159px);bottom:auto;
    left:50%;transform:translateX(-50%);
    flex-direction:row;gap:6px;
  }
  .ind i{width:18px}
  .ind i.on{width:30px}
}

/* ---------- generic sections ---------- */
.wrap{max-width:var(--maxw);margin:0 auto;padding-left:var(--gut);padding-right:var(--gut)}
section.band{padding:clamp(64px,11vw,120px) 0}
.reveal{opacity:0;transform:translateY(22px);transition:opacity .7s var(--ease),transform .7s var(--ease)}
.reveal.in{opacity:1;transform:none}

/* buttons */
.btn{
  display:inline-block;border:0;cursor:pointer;
  background:var(--deep);color:var(--cream);
  font:inherit;font-weight:500;font-size:16px;
  padding:16px 30px;border-radius:999px;text-decoration:none;
  transition:transform .3s var(--ease),background-color .3s var(--ease);
}
.btn:hover{transform:scale(1.04);background:#3D5636}
/* square variant, used inside the bordered grid */
.btn.sq{border-radius:2px;padding:15px 28px;font-size:15px}
.btn.sq:hover{transform:none;background:#3D5636}

/* ---------- trust band ----------
   A deep green band. Cream-on-cream hairline cards read as nothing straight
   after the full-bleed trailer; the colour change is what gives the page a
   beat there. Cream on --deep measures 6.6:1, --light-hi 4.96:1. */
/* section.band, not .trust — `section.band` above outranks a bare class */
section.trust{
  background:var(--deep);color:var(--cream);
  padding:clamp(56px,8vw,92px) 0;
}
.trust :focus-visible{outline-color:var(--cream)}

.thead{text-align:center;max-width:660px;margin:0 auto clamp(46px,5vw,62px)}
/* a label, not the title — but big enough to read as deliberate */
.thead .k{
  font-size:13px;letter-spacing:.2em;text-transform:uppercase;
  color:var(--light-hi);margin:0 0 16px;font-weight:600;
}
.thead h2{
  margin:0;font-size:clamp(1.5rem,2.7vw,2.15rem);font-weight:600;
  letter-spacing:-.025em;line-height:1.18;color:var(--cream);
}

/* four across, and they stay four across a long way down */
.tgrid{
  display:grid;grid-template-columns:repeat(4,1fr);
  gap:clamp(12px,1.5vw,20px);
  list-style:none;margin:0;padding:0;
}
.tcard{
  position:relative;text-align:center;
  border:1px solid rgba(246,244,236,.22);
  background:rgba(246,244,236,.05);
  border-radius:3px;
  padding:clamp(34px,3vw,42px) clamp(13px,1.4vw,22px) clamp(20px,2vw,28px);
  transition:background-color .3s var(--ease),border-color .3s var(--ease);
}
.tcard:hover{background:rgba(246,244,236,.1);border-color:rgba(246,244,236,.4)}
.ticon{
  position:absolute;top:0;left:50%;transform:translate(-50%,-50%);
  width:46px;height:46px;border-radius:50%;
  background:var(--pist);color:var(--ink);
  display:grid;place-items:center;
}
.ticon svg{
  width:23px;height:23px;display:block;
  fill:none;stroke:currentColor;stroke-width:1.7;
  stroke-linecap:round;stroke-linejoin:round;
}
.tcard h3{margin:0 0 .45em;font-size:clamp(.92rem,1.15vw,1.02rem);font-weight:600;letter-spacing:-.01em;line-height:1.3;color:var(--cream)}
/* --light-hi is measured against the flat band; the card's translucent wash
   lifts the background a touch, so body copy needs the brighter token to keep
   4.5:1 (--light-hi would land at 4.43) */
.tcard p{margin:0;font-size:clamp(13px,1vw,14.5px);color:var(--card-txt);line-height:1.45}

@media (max-width:680px){.tgrid{grid-template-columns:1fr 1fr;gap:clamp(24px,4vw,32px)}}
@media (max-width:420px){.tgrid{grid-template-columns:1fr}}

/* ---------- tastes: curved 3D carousel ----------
   Tiles sit on an arc whose centre of curvature is in FRONT of the screen, so
   the outer tiles lean toward the viewer and the middle one faces straight on.
   JS writes each tile's transform; CSS only sets the stage and the skin. */
.arcsub{margin:0 auto clamp(20px,2.4vw,32px);max-width:40ch;text-align:center;
  font-size:clamp(15px,1.15vw,17px);color:var(--light-hi)}
.arc h2{margin:0 auto clamp(10px,1.2vw,16px);max-width:24ch;text-align:center;font-size:clamp(1.5rem,2.7vw,2.15rem);font-weight:600;letter-spacing:-.025em;line-height:1.18}

/* The section is a tall runway (.arcpin) with the whole block stuck to the
   viewport (.arcstick) while it passes. The page keeps scrolling normally —
   nothing swallows the wheel — but on screen only the ring moves, and the
   visitor can always scroll out the other side.

   .stagearc takes whatever height is left and centres the ring in it, so the
   tiles that swell toward the viewer have room instead of being clipped.
   The perspective is written by JS: it has to stay in step with the ring's
   radius, which follows the tile width. */
.arc{
  background:var(--deep);color:var(--cream);
  /* portrait tiles. The height cap matters as much as the width one: on a
     short laptop screen a tall tile leaves the swelling edges nowhere to go. */
  --tw:clamp(128px,16.5vw,300px);
  --th:calc(var(--tw) * 1.32);
  /* A tile is laid out at --sup times its final size and scaled back down in
     the transform. The browser rasterises the layer at the LAYOUT size, so a
     tile blown up 2.5x by the perspective was being stretched from a 1x
     bitmap — which is why the captions went soft at the edges. At --sup 2 the
     bitmap has twice the detail and the text stays crisp all the way round.
     Every fixed length inside a tile is multiplied by --sup for this to work. */
  --sup:2;
}
/* the runway is a fixed length, not a multiple of the viewport, so the ring
   turns at the same rate on a laptop and on a tall monitor */
.arcpin{position:relative;height:calc(100vh + 1400px)}
.arcstick{
  position:sticky;top:0;height:100vh;height:100dvh;
  display:flex;flex-direction:column;justify-content:center;
  padding:76px 0 26px;
  overflow:clip;             /* outer guard for the tiles that spill upward */
}
.arcstick > .wrap:first-child,.arcfoot{flex:none}
.stagearc{
  /* just enough room around the ring — the tall tiles spill past it anyway */
  flex:none;height:min(calc(var(--th) * 1.5),calc(100vh - 250px));
  display:grid;place-items:center;
  width:100%;max-width:2100px;align-self:center;
  perspective-origin:50% 50%;
  /* clipped left and right, open top and bottom: the tiles nearest the viewer
     are far taller than the middle ones and they have to be allowed to spill
     into the margin instead of being sliced off. They swell at the two far
     edges, where nothing else on the page sits. */
  overflow-x:clip;overflow-y:visible;
}
.ring{
  position:relative;width:100%;height:var(--th);
  margin:0;padding:0;list-style:none;
  transform-style:preserve-3d;
  cursor:grab;touch-action:pan-y;
}
.ring:active{cursor:grabbing}
.ring:focus-visible{outline:2px solid var(--cream);outline-offset:8px;border-radius:3px}

.tile{
  position:absolute;left:50%;
  width:calc(var(--tw) * var(--sup));height:calc(var(--th) * var(--sup));
  /* the oversized box is scaled back around its own centre, so it has to be
     offset to keep that centre on the ring's mid-line */
  top:calc(var(--th) * (1 - var(--sup)) / 2);
  margin-left:calc(var(--tw) * var(--sup) / -2);
  /* the slot keeps its full width so the arc geometry still meets edge to
     edge; the padding is what opens a seam between the pictures */
  padding:0 calc(clamp(5px,.55vw,9px) * var(--sup));
  transform-style:preserve-3d;
}
.tile figure{
  margin:0;width:100%;height:100%;position:relative;overflow:hidden;
  border-radius:calc(3px * var(--sup));background:var(--light);
  box-shadow:0 calc(10px * var(--sup)) calc(30px * var(--sup)) rgba(30,43,26,.14);
}
.tile img{width:100%;height:100%;object-fit:cover;display:block}
/* placeholder until a photo exists: the name carries the tile on its own */
.tile figure.ph{display:grid;place-items:center;padding:calc(18px * var(--sup));text-align:center}
/* --ink, not --deep: --deep on --light is 3.4:1 and this is normal-size text */
.tile figure.ph figcaption{
  position:static;background:none;padding:0;
  color:var(--ink);font-size:calc(clamp(.92rem,1.2vw,1.05rem) * var(--sup));font-weight:600;
  letter-spacing:-.01em;line-height:1.3;
}
.tile figcaption{
  position:absolute;inset:auto 0 0 0;
  padding:calc(26px * var(--sup)) calc(14px * var(--sup)) calc(12px * var(--sup));
  color:var(--cream);font-size:calc(14px * var(--sup));font-weight:600;text-align:center;
  background:linear-gradient(to top,rgba(30,43,26,.78),rgba(30,43,26,0));
}

.arc .btn{background:var(--cream);color:var(--deep);font-weight:600}
.arc .btn:hover{background:var(--white)}
.arc :focus-visible{outline-color:var(--cream)}
.arcfoot{margin-top:clamp(20px,2.6vw,34px);display:flex;align-items:center;justify-content:center;gap:clamp(12px,2vw,20px)}
.arcnav{
  appearance:none;width:46px;height:46px;padding:0;cursor:pointer;flex:none;
  background:none;border:1px solid var(--cream);border-radius:50%;color:var(--cream);
  display:grid;place-items:center;transition:background-color .2s,color .2s,opacity .2s;
}
.arcnav svg{width:19px;height:19px;fill:none;stroke:currentColor;stroke-width:1.7;stroke-linecap:round;stroke-linejoin:round}
.arcnav:hover:not(:disabled){background:var(--cream);color:var(--deep)}
.arcnav:disabled{opacity:.3;cursor:default}

/* Phones: a shorter runway and a narrower tile, so more than one fits. */
@media (max-width:640px){
  /* No pinning on a phone: a thumb can already swipe the ring sideways, and
     freezing the page under a scrolling finger feels broken. */
  .arcpin{height:auto}
  .arcstick{position:static;height:auto;padding:clamp(56px,11vw,96px) 0;overflow:visible}
  .arc{--tw:clamp(120px,min(38vw,24vh),190px)}
  .stagearc{height:calc(var(--th) * 1.5)}
}
/* keep the arrows on phones too — swipe alone is not a visible affordance */
@media (max-width:560px){
  .arcnav{width:42px;height:42px}
  .arcnav svg{width:17px;height:17px}
  .arcfoot{gap:10px}
}
/* no 3D and no drag: lay the tiles out as a plain scrollable row */
@media (prefers-reduced-motion:reduce){
  .arc{--sup:1}
  .arcpin{height:auto}
  .arcstick{position:static;height:auto;padding:clamp(64px,11vw,120px) 0}
  .stagearc{perspective:none!important;overflow-x:auto;display:block;padding-bottom:10px}
  .ring{width:auto;height:auto;display:flex;gap:16px;cursor:auto;padding:0 var(--gut)}
  .tile{position:static;left:auto;margin:0;flex:none;transform:none!important;opacity:1!important}
}

/* reasons ----------------------------------------------------------------
   Three notes pinned to the page. The rotation is small on purpose: enough to
   read as paper, not enough to look like an accident. The tilt lives in the
   reveal states too, otherwise the fade-in would straighten every card the
   moment it appeared. */
.reasons h2{
  margin:0 0 clamp(30px,3.6vw,48px);max-width:26ch;
  font-size:clamp(1.5rem,2.7vw,2.15rem);font-weight:600;
  letter-spacing:-.025em;line-height:1.18;
}
/* four notes, so a 2x2 board rather than a row of three and a stray fourth */
.rgrid{display:grid;grid-template-columns:repeat(2,1fr);gap:clamp(24px,3.2vw,44px)}

.rcell{
  --rot:0deg;
  position:relative;min-width:0;
  padding:clamp(46px,4vw,58px) clamp(22px,2.4vw,34px) clamp(26px,2.8vw,38px);
  background:var(--white);
  border:1px solid rgba(30,43,26,.10);
  border-radius:2px;
  box-shadow:0 2px 3px rgba(30,43,26,.05),0 16px 34px rgba(30,43,26,.10);
  transform:translateY(22px) rotate(var(--rot));
  opacity:0;
  transition:opacity .7s var(--ease),transform .7s var(--ease),box-shadow .3s var(--ease);
}
.rcell.in{opacity:1;transform:rotate(var(--rot))}
.rcell:nth-child(1){--rot:-1.5deg}
.rcell:nth-child(2){--rot:.9deg}
.rcell:nth-child(3){--rot:-.7deg}
.rcell:nth-child(4){--rot:1.2deg}
/* straighten under the cursor, the way you would square a note on a board */
.rcell.in:hover{transform:rotate(0deg) translateY(-4px);box-shadow:0 2px 3px rgba(30,43,26,.05),0 24px 44px rgba(30,43,26,.14)}

/* The pin is the head alone. A drawn shaft has to lean in perspective to look
   like anything, and at this size it read as a balloon string; the domed head
   with its own cast shadow says pushpin without the geometry. */
.rcell::after{
  content:'';position:absolute;left:50%;top:17px;pointer-events:none;
  width:17px;height:17px;margin-left:-8.5px;border-radius:50%;
  background:radial-gradient(circle at 33% 27%,#A8CE87,var(--deep) 74%);
  box-shadow:0 3px 6px rgba(30,43,26,.26),inset 0 -2px 3px rgba(30,43,26,.35);
}

.rcell h3{margin:0 0 .7em;font-size:clamp(1.1rem,1.7vw,1.35rem);font-weight:600;letter-spacing:-.015em;line-height:1.25}
.rcell p{margin:0;color:var(--deep);font-size:16px;line-height:1.55}

@media (max-width:820px){
  .rgrid{grid-template-columns:1fr;gap:clamp(22px,5vw,32px)}
  .rcell:nth-child(1){--rot:-1deg}
  .rcell:nth-child(2){--rot:.8deg}
  .rcell:nth-child(3){--rot:-.6deg}
  .rcell:nth-child(4){--rot:1deg}
}
@media (prefers-reduced-motion:reduce){
  .rcell{opacity:1;transform:rotate(var(--rot))}
  .rcell.in:hover{transform:rotate(var(--rot))}
}

/* ---------- tastes: curved 3D carousel ----------
   Tiles sit on an arc whose centre of curvature is in FRONT of the screen, so
   the outer tiles lean toward the viewer and the middle one faces straight on.
   JS writes each tile's transform; CSS only sets the stage and the skin. */
.arcsub{margin:0 auto clamp(20px,2.4vw,32px);max-width:40ch;text-align:center;
  font-size:clamp(15px,1.15vw,17px);color:var(--light-hi)}
.arc h2{margin:0 auto clamp(10px,1.2vw,16px);max-width:24ch;text-align:center;font-size:clamp(1.5rem,2.7vw,2.15rem);font-weight:600;letter-spacing:-.025em;line-height:1.18}

/* The section is a tall runway (.arcpin) with the whole block stuck to the
   viewport (.arcstick) while it passes. The page keeps scrolling normally —
   nothing swallows the wheel — but on screen only the ring moves, and the
   visitor can always scroll out the other side.

   .stagearc takes whatever height is left and centres the ring in it, so the
   tiles that swell toward the viewer have room instead of being clipped.
   The perspective is written by JS: it has to stay in step with the ring's
   radius, which follows the tile width. */
.arc{
  background:var(--deep);color:var(--cream);
  /* portrait tiles. The height cap matters as much as the width one: on a
     short laptop screen a tall tile leaves the swelling edges nowhere to go. */
  --tw:clamp(128px,16.5vw,300px);
  --th:calc(var(--tw) * 1.32);
  /* A tile is laid out at --sup times its final size and scaled back down in
     the transform. The browser rasterises the layer at the LAYOUT size, so a
     tile blown up 2.5x by the perspective was being stretched from a 1x
     bitmap — which is why the captions went soft at the edges. At --sup 2 the
     bitmap has twice the detail and the text stays crisp all the way round.
     Every fixed length inside a tile is multiplied by --sup for this to work. */
  --sup:2;
}
/* the runway is a fixed length, not a multiple of the viewport, so the ring
   turns at the same rate on a laptop and on a tall monitor */
.arcpin{position:relative;height:calc(100vh + 1400px)}
.arcstick{
  position:sticky;top:0;height:100vh;height:100dvh;
  display:flex;flex-direction:column;justify-content:center;
  padding:76px 0 26px;
  overflow:clip;             /* outer guard for the tiles that spill upward */
}
.arcstick > .wrap:first-child,.arcfoot{flex:none}
.stagearc{
  /* just enough room around the ring — the tall tiles spill past it anyway */
  flex:none;height:min(calc(var(--th) * 1.5),calc(100vh - 250px));
  display:grid;place-items:center;
  width:100%;max-width:2100px;align-self:center;
  perspective-origin:50% 50%;
  /* clipped left and right, open top and bottom: the tiles nearest the viewer
     are far taller than the middle ones and they have to be allowed to spill
     into the margin instead of being sliced off. They swell at the two far
     edges, where nothing else on the page sits. */
  overflow-x:clip;overflow-y:visible;
}
.ring{
  position:relative;width:100%;height:var(--th);
  margin:0;padding:0;list-style:none;
  transform-style:preserve-3d;
  cursor:grab;touch-action:pan-y;
}
.ring:active{cursor:grabbing}
.ring:focus-visible{outline:2px solid var(--cream);outline-offset:8px;border-radius:3px}

.tile{
  position:absolute;left:50%;
  width:calc(var(--tw) * var(--sup));height:calc(var(--th) * var(--sup));
  /* the oversized box is scaled back around its own centre, so it has to be
     offset to keep that centre on the ring's mid-line */
  top:calc(var(--th) * (1 - var(--sup)) / 2);
  margin-left:calc(var(--tw) * var(--sup) / -2);
  /* the slot keeps its full width so the arc geometry still meets edge to
     edge; the padding is what opens a seam between the pictures */
  padding:0 calc(clamp(5px,.55vw,9px) * var(--sup));
  transform-style:preserve-3d;
}
.tile figure{
  margin:0;width:100%;height:100%;position:relative;overflow:hidden;
  border-radius:calc(3px * var(--sup));background:var(--light);
  box-shadow:0 calc(10px * var(--sup)) calc(30px * var(--sup)) rgba(30,43,26,.14);
}
.tile img{width:100%;height:100%;object-fit:cover;display:block}
/* placeholder until a photo exists: the name carries the tile on its own */
.tile figure.ph{display:grid;place-items:center;padding:calc(18px * var(--sup));text-align:center}
/* --ink, not --deep: --deep on --light is 3.4:1 and this is normal-size text */
.tile figure.ph figcaption{
  position:static;background:none;padding:0;
  color:var(--ink);font-size:calc(clamp(.92rem,1.2vw,1.05rem) * var(--sup));font-weight:600;
  letter-spacing:-.01em;line-height:1.3;
}
.tile figcaption{
  position:absolute;inset:auto 0 0 0;
  padding:calc(26px * var(--sup)) calc(14px * var(--sup)) calc(12px * var(--sup));
  color:var(--cream);font-size:calc(14px * var(--sup));font-weight:600;text-align:center;
  background:linear-gradient(to top,rgba(30,43,26,.78),rgba(30,43,26,0));
}

.arc .btn{background:var(--cream);color:var(--deep);font-weight:600}
.arc .btn:hover{background:var(--white)}
.arc :focus-visible{outline-color:var(--cream)}
.arcfoot{margin-top:clamp(20px,2.6vw,34px);display:flex;align-items:center;justify-content:center;gap:clamp(12px,2vw,20px)}
.arcnav{
  appearance:none;width:46px;height:46px;padding:0;cursor:pointer;flex:none;
  background:none;border:1px solid var(--cream);border-radius:50%;color:var(--cream);
  display:grid;place-items:center;transition:background-color .2s,color .2s,opacity .2s;
}
.arcnav svg{width:19px;height:19px;fill:none;stroke:currentColor;stroke-width:1.7;stroke-linecap:round;stroke-linejoin:round}
.arcnav:hover:not(:disabled){background:var(--cream);color:var(--deep)}
.arcnav:disabled{opacity:.3;cursor:default}

/* Phones: a shorter runway and a narrower tile, so more than one fits. */
@media (max-width:640px){
  /* No pinning on a phone: a thumb can already swipe the ring sideways, and
     freezing the page under a scrolling finger feels broken. */
  .arcpin{height:auto}
  .arcstick{position:static;height:auto;padding:clamp(56px,11vw,96px) 0;overflow:visible}
  .arc{--tw:clamp(120px,min(38vw,24vh),190px)}
  .stagearc{height:calc(var(--th) * 1.5)}
}
/* keep the arrows on phones too — swipe alone is not a visible affordance */
@media (max-width:560px){
  .arcnav{width:42px;height:42px}
  .arcnav svg{width:17px;height:17px}
  .arcfoot{gap:10px}
}
/* no 3D and no drag: lay the tiles out as a plain scrollable row */
@media (prefers-reduced-motion:reduce){
  .arc{--sup:1}
  .arcpin{height:auto}
  .arcstick{position:static;height:auto;padding:clamp(64px,11vw,120px) 0}
  .stagearc{perspective:none!important;overflow-x:auto;display:block;padding-bottom:10px}
  .ring{width:auto;height:auto;display:flex;gap:16px;cursor:auto;padding:0 var(--gut)}
  .tile{position:static;left:auto;margin:0;flex:none;transform:none!important;opacity:1!important}
}

/* ---------- how it works: scroll timeline ----------
   A centre rail that fills as the section passes mid-viewport; steps alternate
   sides and light up as the fill reaches their number. */
.how h2{margin:0 0 clamp(44px,5vw,64px);font-size:clamp(1.5rem,2.7vw,2.15rem);font-weight:600;letter-spacing:-.025em;line-height:1.18}

.tl{position:relative;list-style:none;margin:0;padding:0;display:grid;gap:clamp(40px,6vw,86px)}
.rail{position:absolute;left:50%;top:0;bottom:0;width:1px;background:var(--light);transform:translateX(-.5px)}
.rail .fill{display:block;width:100%;height:0;background:var(--deep);transition:height .18s linear}

.step{
  position:relative;
  display:grid;grid-template-columns:1fr 1fr;
  gap:clamp(30px,5vw,72px);align-items:center;
}
.step .art{display:flex;justify-content:center}
.step .art svg{
  width:clamp(92px,10vw,132px);height:auto;
  fill:none;stroke:var(--pist);stroke-width:1.6;
  stroke-linecap:round;stroke-linejoin:round;
  transition:stroke .45s var(--ease);
}
.step.on .art svg{stroke:var(--deep)}

.step .n{
  display:inline-grid;place-items:center;
  width:34px;height:34px;border-radius:50%;
  font-size:14px;font-weight:600;line-height:1;
  background:var(--light);color:var(--deep);
  margin:0 0 18px;
  transition:background-color .45s var(--ease),color .45s var(--ease);
}
.step.on .n{background:var(--deep);color:var(--cream)}
.step h3{margin:0 0 .5em;font-size:clamp(1.05rem,1.6vw,1.25rem);font-weight:600;letter-spacing:-.015em}

/* step one's title is the call to action: outlined so it is unmistakably a
   control, but not a solid block that would break the set of three */
.step h3.has-btn{margin-bottom:.75em}
.steplink{
  display:inline-flex;align-items:center;gap:11px;
  padding:11px 20px;border:1px solid var(--deep);border-radius:2px;
  font-size:.94em;color:var(--ink);text-decoration:none;
  transition:background-color .25s var(--ease),color .25s var(--ease);
}
.steplink svg{
  width:17px;height:17px;flex:none;
  fill:none;stroke:currentColor;stroke-width:1.7;
  stroke-linecap:round;stroke-linejoin:round;
  transition:transform .25s var(--ease);
}
.steplink:hover{background:var(--deep);color:var(--cream)}
.steplink:hover svg{transform:translateX(3px)}
.step p{margin:0;color:var(--deep);font-size:15.5px;line-height:1.55;max-width:42ch}

/* odd steps: drawing left, words right. even steps: mirrored.
   nth-of-type, not nth-child: the rail span is .tl's first child and would
   shift every step to the wrong side. */
.step:nth-of-type(odd) .art{grid-column:1;grid-row:1}
.step:nth-of-type(odd) .txt{grid-column:2;grid-row:1}
.step:nth-of-type(even) .art{grid-column:2;grid-row:1}
.step:nth-of-type(even) .txt{grid-column:1;grid-row:1;text-align:right}
.step:nth-of-type(even) p{margin-left:auto}

@media (max-width:820px){
  /* rail moves to the left edge and every step reads the same way */
  .rail{left:17px}
  .step{grid-template-columns:1fr;gap:22px;padding-left:64px}
  /* matched specificity, or the desktop nth-of-type rules keep their columns */
  .step:nth-of-type(odd) .art,.step:nth-of-type(even) .art{
    justify-content:flex-start;grid-column:1;grid-row:2;
  }
  .step:nth-of-type(odd) .txt,.step:nth-of-type(even) .txt{
    grid-column:1;grid-row:1;text-align:left;
  }
  .step:nth-of-type(even) p{margin-left:0}
  .step .art svg{width:86px}
  .step .n{position:absolute;left:0;top:0;margin:0}
  .step p{max-width:none}
}

/* ---------- bordered grid: enquiry + footer ----------
   One continuous rule box. The form half sits in <main>, the brand and link
   halves in <footer>; they abut with no margin, so the borders read as a
   single frame across the boundary. */
section[id]{scroll-margin-top:88px}

.fgrid{padding:0}
.fgrid-top{padding-top:clamp(64px,11vw,120px)}
.ftr{padding-bottom:clamp(64px,11vw,120px);color:var(--ink)}

.frame{border:1px solid var(--deep)}
.frame-a{border-bottom:0}
/* stretch, not start: the dividing rule has to run the full height of the row */
.frame-b{display:grid;align-items:stretch;grid-template-columns:1fr 1.1fr;border-bottom:0}
.frame-b .cell-r{border-left:1px solid var(--deep)}
.frame .cell{padding:clamp(26px,3.4vw,48px);min-width:0}

/* headline band, then the form across the whole box: a form squeezed into one
   half leaves a void in the other, so it gets the full width instead */
.head{
  display:grid;grid-template-columns:1.15fr 1fr;gap:clamp(24px,4vw,64px);
  align-items:center;padding:clamp(26px,3.4vw,48px);
  border-bottom:1px solid var(--deep);
}
.head h2{margin:0 0 .5em;font-size:clamp(1.6rem,3vw,2.3rem);font-weight:600;letter-spacing:-.025em;line-height:1.15}
/* One short claim, set apart from the bullet list on the right: a rule and a
   heavier weight so it reads as a statement rather than body copy. */
.head .lead{
  margin:0;padding-top:14px;position:relative;
  color:var(--deep);font-size:clamp(16px,1.25vw,18px);font-weight:600;
  letter-spacing:-.01em;line-height:1.4;max-width:46ch;
}
.head .lead::before{
  content:'';position:absolute;left:0;top:0;width:40px;height:2px;background:var(--pist);
}
.formwrap{padding:clamp(26px,3.4vw,48px)}

/* what replaces the form once the request is through */
.fdone{padding:clamp(30px,4vw,56px) clamp(26px,3.4vw,48px);text-align:center;outline:none}
.fdone .tick{
  display:grid;place-items:center;width:58px;height:58px;margin:0 auto 22px;
  border-radius:50%;background:var(--pist);
}
.fdone .tick svg{width:30px;height:30px;fill:none;stroke:var(--ink);stroke-width:3.4;stroke-linecap:round;stroke-linejoin:round}
.fdone h3{margin:0 0 .5em;font-size:clamp(1.25rem,2vw,1.6rem);font-weight:600;letter-spacing:-.02em}
.fdone p{margin:0 auto;max-width:44ch;color:var(--deep);font-size:16px;line-height:1.55}
.fdone .fdone-links{margin-top:22px;display:flex;flex-wrap:wrap;gap:10px 26px;justify-content:center;font-size:15px}
.fdone .fdone-links a{color:var(--deep);text-decoration:none;border-bottom:1px solid var(--light)}
.fdone .fdone-links a:hover{border-bottom-color:var(--sep)}
/* the failure state keeps the form visible above it, so it reads as a notice */
.fdone.bad{padding-top:0;text-align:left}
.fdone.bad .tick{display:none}
.fdone.bad h3{color:var(--danger);font-size:clamp(1.05rem,1.5vw,1.2rem)}
.fdone.bad p,.fdone.bad .fdone-links{margin-left:0;justify-content:flex-start}

.pts{list-style:none;margin:0;padding:0}
.pts li{position:relative;padding-left:24px;margin:0 0 12px;font-size:15px;color:var(--deep)}
.pts li:last-child{margin-bottom:0}
.pts li::before{content:'';position:absolute;left:0;top:.62em;width:9px;height:9px;border:1px solid var(--sep);background:var(--pist)}
@media (max-width:860px){.head{grid-template-columns:1fr;gap:28px;align-items:start}}

/* brand half */
.frame-b .ftr-mark{height:76px;width:auto;margin:0 0 24px}
.claim{margin:0 0 .5em;font-size:clamp(1.05rem,1.7vw,1.3rem);font-weight:600;letter-spacing:-.015em;line-height:1.3}
.claim-sub{margin:0 0 28px;color:var(--deep);font-size:15px;max-width:38ch}

/* link columns */
.lnk{display:grid;grid-template-columns:repeat(3,1fr);gap:24px}
.lnk h3{margin:0 0 16px;font-size:11px;letter-spacing:.16em;text-transform:uppercase;color:var(--deep);font-weight:600}
.lnk ul{list-style:none;margin:0;padding:0}
.lnk li{margin:0 0 4px}
.lnk a{display:inline-flex;align-items:center;gap:9px;padding:4px 0;font-size:15px;text-decoration:none;min-height:24px}
/* the rule sits under the words only — an underline running beneath the icon
   reads as a box around it */
.lnk a span{border-bottom:1px solid transparent}
.lnk a:hover span{border-bottom-color:var(--sep)}
.lnk a[aria-current="page"]{color:var(--deep)}
.lnk a[aria-current="page"] span{border-bottom-color:var(--light)}
.lnk svg{
  width:17px;height:17px;flex:none;color:var(--deep);
  fill:none;stroke:currentColor;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;
}
.lnk svg.solid{fill:currentColor;stroke:none}

/* base bar */
.frame-c{display:flex;flex-wrap:wrap;justify-content:space-between;align-items:center;gap:8px 28px;padding:16px clamp(20px,3vw,32px);font-size:13px;color:var(--deep)}
.frame-c p{margin:0}
.frame-c .right{text-align:right}

@media (max-width:860px){
  .frame-b{grid-template-columns:1fr}
  .frame-b .cell-r{border-left:0;border-top:1px solid var(--deep)}
  .frame-c{justify-content:flex-start}
  .frame-c .right{text-align:left}
  .lnk{grid-template-columns:1fr 1fr}
}

/* The grid lives in .fields, not on the form itself: the error summary is a
   sibling of the grid, so it can appear without shifting the fixed row
   numbers below and colliding with the message field.
   row 1  company | contact | email
   row 2  phone   | city    | role
   row 3  volume  | message (2 cols, 2 rows)
   row 4  send    |                        */
.f{display:block}
.fields{display:grid;grid-template-columns:repeat(3,1fr);gap:18px 20px;align-items:start}
.fields .msg{grid-column:2/span 2;grid-row:3/span 2;align-self:stretch;display:flex;flex-direction:column}
.fields .msg textarea{flex:1}
.fields .send{grid-column:1;grid-row:4;align-self:end}
.f label{display:block;font-size:12px;letter-spacing:.08em;text-transform:uppercase;color:var(--deep);margin:0 0 7px}
.f input,.f select,.f textarea{
  width:100%;font:inherit;font-size:16px;color:var(--ink);
  background:var(--white);border:1px solid #7E9A66;border-radius:2px;
  padding:13px 14px;min-height:48px;transition:border-color .2s,box-shadow .2s;
}
.f textarea{min-height:120px;resize:vertical}
.f input:focus,.f select:focus,.f textarea:focus{border-color:var(--deep);box-shadow:0 0 0 1px var(--deep)}
.f .err{display:none;color:var(--danger);font-size:13.5px;margin:7px 0 0;font-weight:500}
.f .bad input,.f .bad select,.f .bad textarea{border-color:var(--danger);background:#FFF7F5}
.f .bad .err{display:block}
.hp{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}

/* focusable error summary */
.summary{display:none;margin:0 0 24px;border:1px solid var(--danger);border-radius:2px;padding:18px 20px;background:#FFF7F5}
.summary.show{display:block}
.summary h3{margin:0 0 10px;font-size:16px;font-weight:600;color:var(--danger)}
.summary ul{margin:0;padding-left:18px}
.summary li{margin:0 0 5px;font-size:14.5px}
.summary a{color:var(--danger)}

/* visible focus for everything, everywhere */
:focus-visible{outline:2px solid var(--deep);outline-offset:3px;border-radius:3px}
.on-green :focus-visible{outline-color:var(--cream)}
.summary a:focus-visible,.f input:focus-visible,.f select:focus-visible,.f textarea:focus-visible{outline-color:var(--danger)}
.done{padding:34px 0;font-size:clamp(1.1rem,2vw,1.5rem);font-weight:500;line-height:1.35}
@media (max-width:1024px){
  .fields{grid-template-columns:1fr 1fr}
  .fields .msg{grid-column:1/-1;grid-row:auto}
  .fields .msg textarea{min-height:130px}
  .fields .send{grid-column:1/-1;grid-row:auto}
}
@media (max-width:600px){
  .fields{grid-template-columns:1fr}
  .fields .msg{grid-column:1}
}


/* ---------- floating WhatsApp button ----------
   Site green rather than WhatsApp's own green: the glyph alone is recognisable,
   and a #25D366 disc would be the loudest thing on a cream page. */
.wa{
  position:fixed;z-index:75;
  right:clamp(16px,2.6vw,28px);bottom:clamp(16px,2.6vw,28px);
  width:56px;height:56px;border-radius:50%;
  display:grid;place-items:center;
  background:var(--deep);color:var(--cream);
  box-shadow:0 0 0 2px var(--cream),0 6px 20px rgba(30,43,26,.22);
  transition:transform .25s var(--ease),background-color .25s var(--ease),bottom .24s var(--ease);
}
.wa svg{width:29px;height:29px;display:block;fill:currentColor}
.wa:hover{transform:scale(1.07);background:#3D5636}
.wa:focus-visible{outline:2px solid var(--deep);outline-offset:3px}
/* the sticky bar would sit on top of it, so lift the button while it shows */
.mcta.show ~ .wa{bottom:calc(78px + env(safe-area-inset-bottom))}
@media (max-width:767px){.wa{width:52px;height:52px}.wa svg{width:27px;height:27px}}
@media (prefers-reduced-motion:reduce){.wa{transition:none}.wa:hover{transform:none}}

/* mobile sticky cta */
.mcta{position:fixed;left:0;right:0;bottom:0;z-index:70;padding:12px var(--pad) calc(12px + env(safe-area-inset-bottom));background:rgba(246,244,236,.9);backdrop-filter:blur(12px);border-top:1px solid var(--light);transform:translateY(120%);transition:transform .24s var(--ease);display:none}
.mcta .btn{display:block;text-align:center}
.mcta.show{transform:none}
@media (max-width:767px){.mcta{display:block}}

/* reduced motion */
@media (prefers-reduced-motion:reduce){
  .scrolly{height:auto}
  .sticky{position:static;height:auto;overflow:visible}
  #seq{display:none}
  .stages{position:static;pointer-events:auto}
  .stage{position:static;opacity:1;width:auto;transform:none;text-align:left;margin:0 auto;padding:36px var(--pad) 56px;max-width:var(--maxw)}
  .stage .line > span{transform:none}
  .ind,.cue,.pre{display:none}
  .rm-shot{display:block;width:100%}
  .reveal{opacity:1;transform:none}
}
.rm-shot{display:none}

/* ---------- text pages (privacy notice, product facts) ---------- */
/* No scroller, no canvas: these load in a fraction of the home page's time,
   which is the point — they exist to be read and to be crawled. */
body.plain{background:var(--cream)}
.doc{padding:clamp(104px,14vh,152px) 0 clamp(56px,9vh,96px)}
.doc .wrap{max-width:74ch}
.dockicker{
  margin:0 0 10px;font-size:12px;letter-spacing:.14em;text-transform:uppercase;
  color:var(--deep);opacity:.75;
}
.doc h1{
  font-size:clamp(28px,4.4vw,44px);line-height:1.14;letter-spacing:-.015em;
  margin:0 0 20px;font-weight:600;
}
.doc h2{
  font-size:clamp(20px,2.4vw,26px);line-height:1.25;letter-spacing:-.01em;
  margin:44px 0 12px;font-weight:600;
}
.doc h2 + p, .doc h2 + ul, .doc h2 + dl{margin-top:0}
.doc h3{
  font-size:17px;line-height:1.35;margin:26px 0 6px;font-weight:600;
  color:var(--deep);
}
.doc p{margin:0 0 14px}
.doc ul{margin:0 0 16px;padding-left:1.15em}
.doc li{margin:0 0 6px}
.doc dl{margin:0 0 18px;display:grid;grid-template-columns:minmax(0,15em) 1fr;gap:2px 22px}
.doc dt{font-weight:600}
.doc dd{margin:0}
.doc dl + h2{margin-top:40px}
@media (max-width:639px){
  .doc dl{grid-template-columns:1fr;gap:0}
  .doc dd{margin:0 0 12px;opacity:.9}
}
.doc a{color:var(--deep);text-underline-offset:3px}
.docback{margin:48px 0 0;padding-top:20px;border-top:1px solid var(--light)}
.docback a{text-decoration:none;border-bottom:1px solid currentColor;padding-bottom:2px}

.docftr{padding:0 0 clamp(28px,5vh,48px);font-size:13px}
.docftr .wrap{
  display:flex;flex-wrap:wrap;gap:8px 24px;justify-content:space-between;
  padding-top:18px;border-top:1px solid var(--light);opacity:.78;
}
.docftr p{margin:0}
.docftr a{color:inherit;text-decoration:none;border-bottom:1px solid transparent}
.docftr a:hover{border-bottom-color:currentColor}

/* the one note that carries a link onward to the long-form product page */
.rmore{margin:14px 0 0 !important;font-size:15px}
.rmore a{
  color:var(--deep);text-decoration:none;
  border-bottom:1px solid rgba(74,103,65,.35);padding-bottom:2px;
  transition:border-color .2s var(--ease);
}
.rmore a:hover{border-bottom-color:currentColor}
