/* dark-sections.css — styles for the five sections that exist.

   Rebuilt 5 Aug when the page went from eleven sections to five. The old file
   carried rules for wwd / social / ads / track / board / journey / reserve /
   close, all deleted — and its .dev-laptop / .dev-phone selectors had already
   collided once with the hero device rig and silently stretched a figure from
   215px to 370px. Dead CSS is not free. */

/* ---------- motion primitives (motion.js writes this DOM) ---------- */
.line-mask{display:block;overflow:hidden}
.line{display:block;transform-origin:top left}
@media (min-width:601px){.line{will-change:transform}}
/* No-JS and reduced-motion readers get the finished page, never a blank one. */
html.motion-off [data-reveal],html.motion-off [data-lines] .line{opacity:1;transform:none}
[data-reveal]{will-change:opacity,transform}

/* ---------- hero: the dark panel ---------- */
/* Full-bleed ink. The renders are photographs of white screens, and on a white
   page they had nothing to push against — on this ground they carry their own
   light. It is also the only inverted section on the site, so the first screen
   reads as a front door instead of as band one of six. */
/* padding-top grew when the kicker pill came out — that line was doing the work
   of holding the headline off the sticky nav, and without it the H1 sat about
   12px under the bar. */
/* The hero is sized to the SCREEN, not to its contents. It was 1111-1116px tall
   against viewports of 720-900, so the laptop was cut off on every real laptop
   — the one thing the section exists to show. min-height:100svh plus a flex
   column lets the copy take what it needs and hands the rest to the render,
   which then scales to fit rather than overflowing. svh, not vh, because mobile
   vh is the pre-toolbar height and would put us right back over the fold. */
/* Ground, lightened (Sean, 6 Aug: "too dark — lighten it, especially around
   the edges"). Three moves, all in one paint stack:
   1. base raised #0B131B -> #10202F, still ink but visibly blue;
   2. a soft blue radiance pinned to EACH SIDE EDGE, so the panel is brightest
      exactly where it used to fall off to black;
   3. the bottom ~230px dissolve ink -> wash -> white, which IS the transition
      into the next section: the dark panel melts into the paper the promise
      is printed on instead of hitting it as a hard seam. The devices straddle
      the melt, so they read as floating above a lit ground. */
.hero{position:relative;overflow:hidden;color:#fff;
  background:
    radial-gradient(44% 58% at -5% 26%, rgba(90,156,224,.20), rgba(90,156,224,0) 64%),
    radial-gradient(44% 58% at 105% 26%, rgba(90,156,224,.20), rgba(90,156,224,0) 64%),
    linear-gradient(180deg,
      #10202F 0%, #10202F calc(100% - 258px),
      #22374F calc(100% - 196px), #48688C calc(100% - 142px),
      #7C9FC2 calc(100% - 96px), #C2D8EC calc(100% - 52px),
      #EDF4FB calc(100% - 22px), #FFFFFF 100%);
  padding-top:clamp(3.4rem,6.4vw,6rem);text-align:center;
  min-height:calc(100svh - var(--nav-h));display:flex;flex-direction:column}
/* the glow the rig stands in; sits behind everything, never intercepts a tap */
.hero::before{content:"";position:absolute;inset:-18% 8% 44%;
  background:radial-gradient(52% 50% at 50% 34%,
    rgba(90,156,224,.34), rgba(16,32,47,0) 72%);
  filter:blur(28px);pointer-events:none}
.hero-in{position:relative}

.kick{display:inline-flex;align-items:center;gap:9px;margin:0 0 clamp(14px,2vw,22px);
  font-size:10.5px;font-weight:800;letter-spacing:.18em;text-transform:uppercase;
  color:#9FC4EC;border:1px solid rgba(159,196,236,.34);border-radius:999px;
  padding:8px 15px}

/* line-height stays at 1.04. .line-mask is overflow:hidden, so anything tighter
   guillotines the descender on "Built and run for you." */
.hero .h-display{margin:0 auto;max-width:22ch;color:#fff;line-height:1.04;
  font-size:clamp(27px,4.9vw,59px)}
/* the second source line, coloured through the mask the splitter builds —
   splitLines() wipes inner markup, so a <span> here would not survive */
.hero .h-display .line-mask:nth-child(2) .line{
  background:linear-gradient(180deg,#8FC2F5,#3B8AE0);
  -webkit-background-clip:text;background-clip:text;color:transparent}

/* balance, not pretty: at 46ch this paragraph set three lines and left "of it."
   alone on the third. balance evens the measure instead. */
.hero-lede{margin:clamp(14px,1.8vw,22px) auto 0;font-size:clamp(15px,1.65vw,19px);
  font-weight:500;color:#A8B8C6;max-width:52ch;text-wrap:balance}
.hero-cta{margin-top:clamp(22px,2.8vw,34px);display:flex;flex-wrap:wrap;gap:12px;
  justify-content:center}
/* the white ghost button is invisible logic on ink */
.hero .btn.ghost{background:transparent;color:#CFE2F7;border-color:rgba(207,226,247,.38)}

/* the rig used to be followed by a Website/Booking/CRM line; with that gone the
   hero closes on the render, so the bottom padding moves onto the section */
.hero{padding-bottom:clamp(34px,4.4vw,64px)}

/* Short viewports. Fitting the whole hero above the fold on a 720px screen left
   the laptop only 215px wide, which is not a hero — it is a thumbnail. The copy
   gives space back instead: everything above the render tightens so the render
   itself stays the biggest thing in the section. Keyed on height, because that
   is the axis that is actually short — a 1280x720 laptop and a 1280x1024
   monitor need opposite treatments at identical widths. */
@media (max-height:820px) and (min-width:700px){
  .hero{padding-top:clamp(1.6rem,3vw,2.4rem);padding-bottom:clamp(20px,2.4vw,30px)}
  .hero .h-display{font-size:clamp(24px,3.4vw,40px)}
  .hero-lede{font-size:clamp(14px,1.3vw,16px);margin-top:10px}
  .hero-cta{margin-top:16px}
  .hero .btn{padding:13px 22px}
  .hd-rig-wrap{padding-top:14px}
  /* the matching --hd-chrome for this tier lives in devices.css, which loads
     after this file and would otherwise win on source order */
}


/* ---------- how it works: one machine ---------- */
.machine{list-style:none;counter-reset:m;display:grid;gap:0;margin-top:clamp(1.6rem,3vw,2.4rem)}
.mstep{position:relative;display:grid;grid-template-columns:auto 1fr;gap:clamp(16px,2.4vw,30px);
  padding:clamp(20px,2.6vw,30px) 0;border-top:1px solid var(--soft)}
.mstep:last-child{border-bottom:1px solid var(--soft)}
/* icon + number as one lead column, so the step reads icon-first at a glance
   and the number still carries the sequence */
.mlead{display:flex;flex-direction:column;align-items:center;gap:10px;padding-top:2px;
  min-width:3.2em}
/* The icons are set in a solid brand tile rather than left as 26px hairlines on
   white. A 1.75-weight outline at that size is the quietest mark in the whole
   section, which is backwards — these label the four things the machine does.
   Same gradient as the buttons, so the tiles read as brand furniture rather
   than as decoration, and the white stroke gains the contrast the blue-on-white
   version never had. */
/* .mtile/.mi deleted 6 Aug — the 52px gradient tile and its Lucide glyph were
   the rejected pattern. The numeral survives as a pipeline node (.mnum). */
/* no-JS and reduced-motion readers must see finished icons, not empty outlines */
html.motion-off [data-draw] *{stroke-dashoffset:0 !important}
.own{display:flex;align-items:flex-start;gap:14px}
/* the closing line is a statement, not a fifth step — smaller tile, and it sits
   on the wash rather than the full gradient so it cannot outrank the four */

.mbody{min-width:0}
.mstep h3{font-size:clamp(17px,2vw,21px);font-weight:800;letter-spacing:-.015em;margin-bottom:7px}
.mstep p{font-size:15px;font-weight:500;color:var(--muted);max-width:56ch}
.own{margin-top:clamp(1.6rem,3vw,2.2rem);font-size:clamp(15px,1.7vw,18px);font-weight:700;
  max-width:52ch}
/* No mobile narrowing of the lead column. It was tried and refuted: nothing
   overflows or collides, the measure is 292px (~38 characters) at 390px, and
   the 3.2em is what lets the numeral centre under the icon — which is the
   stated intent above, not slack. */

/* ---------- before / after ---------- */
/* Clean and direct: two shots, one rule between them, labels that say which is
   which and nothing else. No slider — a drag comparison hides half the argument
   until the reader interacts, and most never do. */
.ba{margin:clamp(1.4rem,2.6vw,2.2rem) 0 0}
.ba-pair{display:grid;grid-template-columns:1fr;gap:clamp(10px,1.4vw,16px)}
@media(min-width:760px){.ba-pair{grid-template-columns:1fr 1fr}}
.ba-side{display:flex;flex-direction:column;gap:10px;min-width:0}
/* the label sits ABOVE the frame. Floated on top it covered the client's own
   logo in the shot it was labelling, which is the one thing that proves both
   sides are the same company. */
.ba-shot{width:100%;height:auto;display:block;
  border:1px solid var(--soft);border-radius:var(--r)}
.ba-lbl{align-self:flex-start;
  font-size:10px;font-weight:800;letter-spacing:.16em;text-transform:uppercase;
  padding:6px 12px;border-radius:999px}
.ba-before{background:var(--slate);color:#fff}
.ba-after{background:var(--grad-blue);color:#fff}
.ba figcaption{margin-top:14px;font-size:14px;font-weight:600;color:var(--muted);
  max-width:62ch}

/* ---------- the work ---------- */
/* Dense and small ON PURPOSE. Every build shares a layout engine, so at large
   size the reader compares four designs and sees one template; at thumbnail
   size the same grid reads as brand variety and, above all, as COUNT. The
   number is the argument; the wall is its evidence. */
.proofstat{display:flex;align-items:baseline;gap:16px;margin:clamp(1.4rem,2.6vw,2rem) 0}
.proofstat .bignum{font-size:clamp(52px,7vw,86px)}
.proofstat .label{max-width:16ch;line-height:1.5}

.wall{list-style:none;display:grid;gap:clamp(8px,1vw,12px);
  grid-template-columns:repeat(2,1fr);margin-top:clamp(1rem,2vw,1.6rem)}
@media(min-width:520px){.wall{grid-template-columns:repeat(3,1fr)}}
@media(min-width:820px){.wall{grid-template-columns:repeat(4,1fr)}}
@media(min-width:1100px){.wall{grid-template-columns:repeat(5,1fr)}}
.wall li{margin:0;border:1px solid var(--soft);border-radius:9px;overflow:hidden;
  background:#fff;aspect-ratio:16/10;
  transition:transform .3s cubic-bezier(.34,1.4,.64,1),border-color .3s}
.wall li:hover{transform:translateY(-3px);border-color:var(--blue)}
.wall img{width:100%;height:100%;object-fit:cover;display:block}

/* the one tile that is an invitation rather than evidence */
.wall-you{border:1.5px dashed var(--edge) !important;background:var(--blue-wash) !important}
.wall-you a{display:flex;flex-direction:column;justify-content:center;gap:6px;
  height:100%;padding:12px;text-decoration:none;text-align:center}
.wall-you b{font-size:clamp(12px,1.3vw,14px);font-weight:800;letter-spacing:-.01em;line-height:1.25}
.wall-you span{font-size:9.5px;font-weight:800;letter-spacing:.11em;text-transform:uppercase;
  color:var(--blue)}

/* ---------- talk ---------- */
.talk-grid{display:grid;grid-template-columns:minmax(0,.9fr) minmax(0,1.1fr);
  gap:clamp(2rem,4vw,3.6rem);align-items:start}
@media(max-width:900px){.talk-grid{grid-template-columns:1fr}}
.talk-plate{padding:clamp(22px,3vw,32px)}
.doneh{font-size:clamp(20px,2.4vw,26px);font-weight:800;letter-spacing:-.02em;margin-bottom:8px}
.wa-fallback{display:inline-block;margin-top:16px;font-size:12.5px;font-weight:700;
  color:var(--muted-2);text-decoration:underline;text-underline-offset:3px}
@media(hover:hover) and (pointer:fine){.wa-fallback:hover{color:var(--blue)}}

/* ---------- booking: pick a time, then details ----------
   Our own flow, not an embed. Every label is written by booking.js in the
   visitor's timezone, so nothing here can assume a string width. */
.bk-tz{font-size:12px;font-weight:600;color:var(--muted-2);margin:0 0 14px}
.bk-tz:empty{display:none}
/* The day rail scrolls rather than wraps: fourteen days wrapped into rows made
   the plate taller than the section on a phone. */
.bk-days{display:flex;gap:8px;overflow-x:auto;padding-bottom:10px;
  scrollbar-width:thin;-webkit-overflow-scrolling:touch}
.bk-day{flex:0 0 auto;font:700 12px/1 var(--ff);color:var(--muted);white-space:nowrap;
  background:var(--plate);border:1.5px solid var(--soft);border-radius:999px;
  padding:9px 14px;cursor:pointer;transition:border-color .2s,color .2s}
.bk-day[aria-pressed="true"]{background:var(--grad-blue);border-color:transparent;color:#fff}
@media(hover:hover) and (pointer:fine){
  .bk-day:hover{border-color:var(--blue);color:var(--blue)}
  .bk-day[aria-pressed="true"]:hover{color:#fff}
}
.bk-times{display:grid;grid-template-columns:repeat(auto-fill,minmax(84px,1fr));
  gap:8px;margin-top:14px;max-height:232px;overflow-y:auto}
.bk-time{font:700 12.5px/1 var(--ff);color:var(--blue);background:var(--plate);
  border:1.5px solid var(--edge);border-radius:9px;padding:11px 6px;cursor:pointer;
  transition:background .2s,color .2s,border-color .2s}
@media(hover:hover) and (pointer:fine){
  .bk-time:hover{background:var(--grad-blue);border-color:transparent;color:#fff}
}
.bk-empty{font-size:14px;font-weight:500;color:var(--muted);margin:6px 0 0}
.bk-chosen{font-size:15px;font-weight:800;color:var(--text);margin:0 0 16px;
  letter-spacing:-.01em}
#bk-form .fgrid{margin-bottom:0}
.bk-actions{display:flex;flex-wrap:wrap;gap:10px}
.losslbl{color:var(--text);margin:0 0 8px}
/* ---------- calculator ---------- */
.calc-grid{display:grid;grid-template-columns:1fr 1fr;gap:clamp(22px,3.4vw,38px);align-items:start}
/* display:block is load-bearing. .crow is a <label>, so it defaults to inline —
   and an inline box that wraps draws its border-bottom on EVERY line fragment
   and drops vertical padding entirely. At 390px these rows split into 2-3
   fragments, so the single divider rule rendered as hairlines slicing through
   the label text. Measured: 2, 2 and 3 client rects before this line existed. */
.crow{display:block;padding:14px 0;border-bottom:1px solid var(--soft)}
/* The three control captions inherited .label at 10.5px/--muted-2, which made
   them smaller and fainter than the disclaimer underneath — the thing he is
   asked to operate was set quieter than the small print about it. */
.crow .label{font-size:12.5px;letter-spacing:.08em;color:var(--muted)}
.crow:last-of-type{border-bottom:0}
input[type="range"]{-webkit-appearance:none;appearance:none;width:100%;height:44px;
  background:transparent;--fill:35%}
input[type="range"]::-webkit-slider-runnable-track{height:6px;border-radius:3px;
  background:linear-gradient(90deg,var(--blue) var(--fill),#C3CDD8 var(--fill))}
input[type="range"]::-webkit-slider-thumb{-webkit-appearance:none;width:20px;height:20px;
  border-radius:50%;background:var(--blue);margin-top:-7px;border:2px solid #fff;
  box-shadow:0 0 0 1px var(--edge);cursor:pointer}
input[type="range"]::-moz-range-track{height:6px;border-radius:3px;background:#C3CDD8}
input[type="range"]::-moz-range-progress{height:6px;border-radius:3px;background:var(--blue)}
input[type="range"]::-moz-range-thumb{width:20px;height:20px;border:2px solid #fff;border-radius:50%;
  background:var(--blue);cursor:pointer}
/* neutral well = the without-us state; the ink figure carries the weight */
.calc-out{background:var(--plate-3);
  border:1px solid var(--soft);border-radius:var(--r);padding:clamp(18px,2.6vw,26px)}
.lostnum .bignum{font-size:clamp(44px,5.4vw,64px)}
.losty{font-size:14px;font-weight:600;color:var(--muted);margin:6px 0 16px}
.losty span{font-weight:800;color:var(--text)}
.cchart-shell{background:#FFFFFF;border:1px solid var(--soft);border-radius:10px;
  padding:14px}
.cchart{display:flex;flex-wrap:wrap;gap:4px}
.cblock{width:16px;height:22px;border-radius:4px;background:var(--grad-blue)}
/* a blue bar with a slate bite taken out of it — absence reads as loss more
   honestly than a second hue does */
.cblock.miss{background:var(--slate)}
/* 9.5px at .1em tracking wrapped both keys to two lines on a phone. 11px/.06em
   fits them on one line inside the 244px chart and is the smallest type in the
   section by intent rather than by accident. */
.ckey{display:flex;gap:12px;flex-wrap:wrap;margin-top:10px}
.ckey .k{font-size:11px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;
  white-space:nowrap;
  color:var(--muted-2);display:flex;align-items:center;gap:6px}
.ckey .k::before{content:'';width:9px;height:9px;border-radius:3px}
.ckey .k.b::before{background:var(--grad-blue)}
.ckey .k.miss::before{background:var(--slate)}
.rate{margin-top:14px;font-size:13px;font-weight:600;color:var(--muted)}
.rate b{color:var(--text);font-weight:800}
.fgrid{display:grid;grid-template-columns:1fr 1fr;gap:16px}
/* 16px is a hard floor, not a taste call: iOS Safari auto-zooms the page on
   focus for any input under 16px, and the reader then has to pinch back out
   mid-form. This was 15px. */
.field input{width:100%;margin-top:7px;padding:13px 14px;font-family:var(--ff);font-size:16px;
  font-weight:600;color:var(--text);background:#FFFFFF;
  border:1.5px solid var(--edge);border-radius:10px}
/* .16 blue on white is too faint to register as focus. Full-strength ring. */
.field input:focus{outline:none;border-color:var(--blue);
  box-shadow:0 0 0 2px var(--blue)}
.ferr{display:none;font-size:11px;font-weight:700;color:var(--text);margin-top:6px}
.field.bad input{border-color:var(--text);box-shadow:0 0 0 1px var(--text)}
/* focus must outrank the error state. Without this the one field he is being
   asked to correct is the one field with no focus ring, so after a failed
   submit he cannot see where the keyboard is typing. */
.field.bad input:focus{border-color:var(--blue);box-shadow:0 0 0 2px var(--blue)}
.field.bad .ferr{display:block}
.consent{font-size:12px;font-weight:500;color:var(--muted-2);margin:16px 0 18px;max-width:52ch}
.consent a{color:var(--muted)}
.foot-todo{margin-left:auto;opacity:.65}
/* honeypot: off-screen, never focusable, invisible to a real visitor */
.hp{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}
/* :not([hidden]) matters — .formerr shares .ferr's display:none, so it needs to
   set display back, but a bare display:block beats the hidden attribute and the
   send-failed line then shows to every visitor on load. */
.formerr:not([hidden]){display:block}
.formerr{margin:0 0 14px;font-size:13px}
.formerr a{color:var(--blue);text-decoration:underline;text-underline-offset:3px}
/* ---------- Philip pass (4 Aug) ---------- */
/* align-items:start, not center: on a phone this line wraps to three lines and
   a centred dot floats beside the MIDDLE one, reading as a stray mark rather
   than a bullet. The margin-top optically centres it on the first line's cap
   height (14px text, 1.5 line-height -> 21px box; (21-9)/2 = 6). */
.exclusive{display:flex;align-items:flex-start;gap:12px;font-size:14px;font-weight:700;
  line-height:1.5;letter-spacing:.04em;text-transform:uppercase;color:var(--text)}
.exdot{width:9px;height:9px;border-radius:50%;background:var(--blue);flex:0 0 auto;
  margin-top:6px}

/* mobile: one column everywhere, and the money panel leads so the phone reader
   opens the section on the figure rather than on three sliders */
@media(max-width:760px){
  .calc-grid{grid-template-columns:1fr}
  .calc-grid .calc-out{order:-1}
  .fgrid{grid-template-columns:1fr}
  /* The chart sits ABOVE the sliders once .calc-out is reordered, and it grows a
     row for every 12 jobs. Unreserved, dragging the top slider re-flowed the
     chart and shoved the slider 104px down the page mid-drag — measured, at
     jobs 4 -> 60 — so the control fled the thumb that was moving it.
     126px = 5 rows at the 60-job maximum (22px block + 4px gap, 12 per row).
     align-content is centre, not start: the box is sized for that maximum, so
     at typical values it is mostly empty. Centred, the marks read as a
     deliberate panel; top-aligned they read as a broken render. */
  .cchart{min-height:126px;align-content:center}
}
.calc-cta{margin-top:18px}
.chint{margin-top:14px;font-size:12px;font-weight:500;color:var(--muted-2);max-width:46ch}

/* ---------- footer ---------- */
.foot{margin-top:clamp(2.6rem,5vw,4rem);border-top:1px solid var(--soft);padding:22px 0}
.foot-row{display:flex;justify-content:space-between;align-items:center;gap:16px;
  font-size:12px;font-weight:600;color:var(--muted-2)}
/* padding, not font-size: the link was a 45x19 target at the very end of the
   page, under the 44px floor. */
.foot-row a{color:var(--muted-2);display:inline-block;padding:13px 0}

/* ---------- the booking flow, screen by screen ---------- */
/* overflow:hidden is load-bearing. .flow::before below is inset -4% on both
   sides, which is harmless while .wrap is capped at 1140 and centred, but
   between roughly 1000px and 1180px .wrap runs nearly edge-to-edge and the glow
   pushed the document 2px wider than the viewport. Clipping at the section is
   right: the glow is meant to pool under the phones, not to reach the bezel. */
#try{overflow:hidden}
/* The phones are rendered at a 15-degree yaw so the titanium rail and the real
   thickness are visible — dead-on they read as flat pictures of a screen. The
   rest of the lift is done here: a two-layer shadow that matches the render's
   own key light, a soft ground glow so the group sits ON the band rather than
   floating in front of it, and an out-of-phase float. */
.flow{list-style:none;position:relative;display:grid;gap:clamp(30px,3vw,36px);
  grid-template-columns:1fr;margin-top:clamp(1.8rem,3.4vw,2.8rem)}
@media(min-width:560px){.flow{grid-template-columns:repeat(2,1fr)}}
@media(min-width:1000px){.flow{grid-template-columns:repeat(4,1fr);gap:clamp(16px,1.8vw,24px)}}
/* the glow pool the row stands in */
.flow::before{content:"";position:absolute;left:-4%;right:-4%;top:6%;height:74%;
  background:radial-gradient(60% 52% at 50% 46%,
    rgba(22,104,196,.16), rgba(22,104,196,.06) 52%, rgba(22,104,196,0) 76%);
  filter:blur(18px);pointer-events:none;z-index:0}

.fstep{position:relative;z-index:1;display:flex;flex-direction:column;align-items:center;
  text-align:center}
.fshot{position:relative;width:100%;max-width:250px}
.fstep img{width:100%;height:auto;display:block;
  /* two layers: a tight contact shadow and a broad ambient one, both offset
     down-right to agree with the key light baked into the render */
  filter:drop-shadow(0 5px 8px rgba(15,26,36,.24))
         drop-shadow(6px 26px 38px rgba(15,26,36,.30));
  transition:transform .5s cubic-bezier(.22,1,.36,1)}
/* pointer-gated. On a phone this fires on tap and latches, so a picture that
   does nothing when pressed still answers the press — a false affordance,
   directly under a heading that promises taps. */
@media(hover:hover) and (pointer:fine){
  .fstep:hover img{transform:translateY(-8px) scale(1.02)}
}

@keyframes fFloat{0%,100%{transform:translate3d(0,0,0)}50%{transform:translate3d(0,-9px,0)}}
html.motion-on .fshot{animation:fFloat var(--ff,8s) var(--fd,0s) ease-in-out infinite}
@media (prefers-reduced-motion:reduce){.fshot{animation:none}}

.fnum{margin-top:22px;font-size:10px;font-weight:800;letter-spacing:.16em;color:var(--blue)}
/* No mobile override here on purpose. Two changes were tried and both were
   refuted on measurement: the caption already sits nearer its own phone
   (22px to the image vs a 30px grid gap — the apparent inversion was one
   frame of the float, which moves the phone and not the caption), and the
   glow pool is NOT invisible at this width — it contributes ~11-15/255 of
   centre-weighted vignette behind the upper captions. Opening the gaps also
   added 264px to the longest section on the page. */
.fstep h3{margin-top:8px;font-size:16px;font-weight:800;letter-spacing:-.01em}
/* balance, or step 04 leaves the single word "board." alone on a second line */
.fstep p{margin-top:5px;font-size:13.5px;font-weight:500;color:var(--muted);max-width:30ch;
  text-wrap:balance}
@media(min-width:1000px){
  .fstep:not(.is-last)::after{content:"";position:absolute;top:calc(50% - 46px);
    right:calc(-1 * clamp(8px,.9vw,12px) - 5px);width:clamp(16px,1.8vw,24px);height:1px;
    background:var(--edge)}
}
.flow-foot{position:relative;z-index:1;margin-top:clamp(1.8rem,3vw,2.6rem);
  font-size:13.5px;font-weight:600;color:var(--muted-2);text-align:center}

/* ---------- who you are dealing with ---------- */
.who-grid{display:grid;grid-template-columns:1fr;gap:clamp(24px,4vw,52px);align-items:start}
@media(min-width:820px){.who-grid{grid-template-columns:224px 1fr}}
.who-shot{margin:0;border-radius:var(--r-lg);overflow:hidden;background:var(--plate-3);
  max-width:224px}
.who-shot img{width:100%;height:auto;display:block}
.who-role{font-size:11px;font-weight:800;letter-spacing:.16em;text-transform:uppercase;
  color:var(--blue);margin:6px 0 16px}
.who-p{font-size:clamp(15px,1.6vw,17px);font-weight:500;color:var(--muted);
  max-width:52ch;margin-bottom:14px}
.who-cta{display:flex;flex-wrap:wrap;gap:12px;margin-top:20px}
/* Own flex item so the three icons wrap as one unit, never split — see the
   comment on the markup in precall/who.html. */
.who-social{display:flex;gap:12px}

/* ---------- what this fixes: seven vignettes + the iOS rail ----------
   Sean's seven points, his words (6 Aug, approved). Each vignette ENACTS its
   line — the search row climbs, the admin chips are struck through and swept
   out, the tangle resolves into one path, the dials counter-rotate, the ringing
   goes quiet, the weeks fill, one truck becomes a fleet. The pass before this
   put a single Lucide glyph beside each line and was rejected on sight; an icon
   that only sits next to a sentence decorates it.

   Everything hides behind html.motion-on, NOT plain opacity:0 — with JS absent
   or reduced-motion set, this section must arrive finished, never blank. */
.fixes-band{background:linear-gradient(180deg,#FFFFFF, #F7FAFE 60%, #FFFFFF)}
.fx-label{display:block;margin-bottom:12px}
.fx-h{max-width:24ch}
.fx-cols{display:grid;grid-template-columns:1fr;gap:clamp(28px,3.6vw,52px);
  margin-top:clamp(28px,3.6vw,46px)}
@media(min-width:1020px){.fx-cols{grid-template-columns:minmax(0,1fr) 372px}}
.fx-grid{display:grid;grid-template-columns:1fr;gap:clamp(22px,2.6vw,32px)}
@media(min-width:660px){.fx-grid{grid-template-columns:1fr 1fr}}

html.motion-on .fx{opacity:0;transform:translateY(24px);
  transition:opacity .6s cubic-bezier(.22,1,.36,1),transform .6s cubic-bezier(.22,1,.36,1)}
html.motion-on .fx.on{opacity:1;transform:none}
.fx h3{margin:14px 0 6px;font-size:17.5px;font-weight:800;letter-spacing:-.01em;line-height:1.25}
.fx p{margin:0;font-size:14.5px;line-height:1.62;color:var(--muted);max-width:46ch}
.fx.feat{grid-column:1/-1;display:grid;gap:20px;background:var(--blue-wash);border-radius:20px;
  padding:clamp(20px,2.8vw,32px)}
@media(min-width:660px){.fx.feat{grid-template-columns:280px 1fr;align-items:center}}
.feat h3{margin-top:0;font-size:clamp(19px,2.1vw,23px)}
.feat p{max-width:70ch}

.viz{position:relative;height:118px;border-radius:14px;
  background:linear-gradient(180deg,#F6FAFE,#EDF4FB);
  border:1px solid rgba(22,104,196,.12);overflow:hidden}

/* 1 - the ranking climbs to #1 */
.v1 .serp{position:absolute;inset:12px 14px}
.v1 .sr{position:absolute;left:0;right:0;height:26px;border-radius:7px;background:#fff;
  border:1px solid rgba(15,26,36,.10);display:flex;align-items:center;gap:8px;padding:0 9px}
.v1 .sr i{width:9px;height:9px;border-radius:3px;background:var(--slate);opacity:.55}
.v1 .sr b{height:6px;border-radius:3px;background:var(--slate);opacity:.35;flex:1}
.v1 .r1{top:0} .v1 .r2{top:32px}
.v1 .you{top:64px;border-color:var(--blue);box-shadow:0 6px 16px -8px rgba(22,104,196,.5);z-index:2}
.v1 .you b{background:var(--blue-bright);opacity:.55}
.v1 .you em{font-style:normal;font-size:9.5px;font-weight:800;letter-spacing:.1em;color:var(--blue)}
.v1 .rank{font-size:10px;font-weight:800;color:#fff;background:var(--grad-blue);border-radius:5px;
  padding:2px 5px;opacity:0;transform:scale(.5)}
html.motion-on .fx.on .v1 .you{animation:vRise .9s cubic-bezier(.3,1.4,.4,1) .35s forwards}
html.motion-on .fx.on .v1 .r1{animation:vDrop1 .9s cubic-bezier(.22,1,.36,1) .35s forwards}
html.motion-on .fx.on .v1 .r2{animation:vDrop2 .9s cubic-bezier(.22,1,.36,1) .35s forwards}
html.motion-on .fx.on .v1 .rank{animation:vPop .5s cubic-bezier(.3,1.6,.4,1) 1.15s forwards}
html.motion-off .v1 .you{top:0} html.motion-off .v1 .r1{top:32px}
html.motion-off .v1 .r2{top:64px} html.motion-off .v1 .rank{opacity:1;transform:none}
@keyframes vRise{to{top:0}} @keyframes vDrop1{to{top:32px}} @keyframes vDrop2{to{top:64px}}
@keyframes vPop{to{opacity:1;transform:scale(1)}}

/* 2 - the junk is struck through and swept out; the real job takes the centre */
.v2 .chip{position:absolute;font-size:10.5px;font-weight:700;padding:5px 10px;border-radius:999px;
  background:#fff;border:1px solid rgba(15,26,36,.14);color:var(--muted)}
.v2 .j1{top:12px;left:12px} .v2 .j2{top:14px;right:16px}
.v2 .j3{top:48px;left:8%} .v2 .j4{bottom:12px;left:14px}
.v2 .keep{left:50%;top:50%;transform:translate(-50%,-50%) scale(1.15);
  border-color:var(--blue);color:var(--blue-deep);font-weight:800;background:#fff;
  box-shadow:0 8px 20px -8px rgba(22,104,196,.45);font-size:12px}
html.motion-on .v2 .keep{transform:translate(-50%,-50%) scale(.6);opacity:0}
html.motion-on .fx.on .v2 .junk{animation:vSweep .7s cubic-bezier(.5,0,.8,.4) forwards}
html.motion-on .fx.on .v2 .j1{animation-delay:.4s}
html.motion-on .fx.on .v2 .j2{animation-delay:.55s}
html.motion-on .fx.on .v2 .j3{animation-delay:.7s}
html.motion-on .fx.on .v2 .j4{animation-delay:.85s}
html.motion-on .fx.on .v2 .keep{animation:vClaim .8s cubic-bezier(.3,1.5,.4,1) 1.1s forwards}
html.motion-off .v2 .junk{opacity:0}
@keyframes vSweep{40%{text-decoration:line-through;opacity:.8}
  to{transform:translateX(-70px) rotate(-6deg);opacity:0;text-decoration:line-through}}
@keyframes vClaim{to{opacity:1;transform:translate(-50%,-50%) scale(1.15)}}

/* 3 - the tangle resolves into one straight path */
.v3 svg{position:absolute;inset:0;width:100%;height:100%}
.v3 .tangle{stroke:var(--slate);stroke-dasharray:420;stroke-dashoffset:0;opacity:.5}
.v3 .clean{stroke:var(--blue);stroke-dasharray:220;stroke-dashoffset:0}
html.motion-on .v3 .tangle{stroke-dashoffset:420}
html.motion-on .v3 .clean{stroke-dashoffset:220}
html.motion-on .fx.on .v3 .tangle{animation:vDraw 1s cubic-bezier(.22,1,.36,1) .3s forwards}
html.motion-on .fx.on .v3 .clean{animation:vDraw .8s cubic-bezier(.22,1,.36,1) 1.25s forwards}
@keyframes vDraw{to{stroke-dashoffset:0}}

/* 4 - hours wind down while money winds up */
.v4{display:flex;align-items:center;justify-content:center;gap:34px}
.v4 .dial{position:relative;width:78px;text-align:center}
.v4 svg{width:64px;height:64px;transform:rotate(-90deg)}
.v4 circle{fill:none;stroke-width:7;stroke-linecap:round}
.v4 .track{stroke:rgba(15,26,36,.10)}
.v4 .arc{stroke-dasharray:163}
.v4 .hours{stroke:var(--slate);stroke-dashoffset:106}
.v4 .money{stroke:var(--blue);stroke-dashoffset:20}
html.motion-on .v4 .hours{stroke-dashoffset:24}
html.motion-on .v4 .money{stroke-dashoffset:122}
html.motion-on .fx.on .v4 .hours{animation:vHours 1.4s cubic-bezier(.22,1,.36,1) .4s forwards}
html.motion-on .fx.on .v4 .money{animation:vMoney 1.4s cubic-bezier(.22,1,.36,1) .55s forwards}
@keyframes vHours{to{stroke-dashoffset:106}}
@keyframes vMoney{to{stroke-dashoffset:20}}
.v4 .dlab{display:block;margin-top:4px;font-size:9px;font-weight:800;letter-spacing:.12em;
  text-transform:uppercase;color:var(--muted-2)}

/* 5 - the ringing goes quiet, 3 missed becomes 0 */
.v5{display:grid;place-items:center}
.v5 .disc{position:absolute;width:64px;height:64px;border-radius:50%;
  background:radial-gradient(circle,#fff, var(--blue-wash));border:1px solid rgba(22,104,196,.18)}
.v5 .ph{width:30px;height:30px;color:var(--blue-deep);z-index:2}
.v5 .ring{position:absolute;width:44px;height:44px;border-radius:50%;
  border:2px solid var(--slate);opacity:0}
.v5 .calm{border-color:var(--blue-bright)}
html.motion-on .fx.on .v5 .g1{animation:vRip 1.1s ease-out .3s 2}
html.motion-on .fx.on .v5 .g2{animation:vRip 1.1s ease-out .65s 2}
html.motion-on .fx.on .v5 .calm{animation:vCalm 2.6s ease-out 2.6s infinite}
@keyframes vRip{0%{opacity:.7;transform:scale(.6)}100%{opacity:0;transform:scale(1.9)}}
@keyframes vCalm{0%{opacity:.55;transform:scale(.6)}70%{opacity:0;transform:scale(1.6)}100%{opacity:0}}
.v5 .badge{position:absolute;top:12px;right:14px;font-size:10px;font-weight:800;padding:3px 9px;
  border-radius:999px}
.v5 .miss{background:#fff;border:1px solid var(--slate);color:var(--muted);opacity:0}
.v5 .zero{background:var(--grad-blue);color:#fff}
html.motion-on .v5 .miss{opacity:1}
html.motion-on .v5 .zero{opacity:0;transform:translateY(6px)}
html.motion-on .fx.on .v5 .miss{animation:vGone .5s ease .35s forwards}
html.motion-on .fx.on .v5 .zero{animation:vHere .5s cubic-bezier(.3,1.5,.4,1) 2.5s forwards}
@keyframes vGone{to{opacity:0;transform:translateY(-8px)}}
@keyframes vHere{to{opacity:1;transform:none}}

/* 6 - the weeks ahead fill, and keep filling */
.v6{display:flex;align-items:center;justify-content:center;gap:18px}
.v6 .wk{text-align:center}
.v6 .wlab{display:block;font-size:8.5px;font-weight:800;letter-spacing:.1em;
  text-transform:uppercase;color:var(--muted-2);margin-bottom:7px}
.v6 .slots{display:grid;gap:5px}
.v6 .slots i{width:56px;height:13px;border-radius:4px;background:var(--grad-blue);
  border:1px solid transparent;display:grid;place-items:center;
  font-size:9px;font-weight:800;color:#fff;font-style:normal}
html.motion-on .v6 .slots i{background:#fff;border-color:rgba(15,26,36,.12);color:var(--blue)}
html.motion-on .fx.on .v6 .slots i{animation:vFill .45s cubic-bezier(.22,1,.36,1) forwards}
html.motion-on .fx.on .v6 .wk:nth-child(1) i:nth-child(1){animation-delay:.35s}
html.motion-on .fx.on .v6 .wk:nth-child(1) i:nth-child(2){animation-delay:.5s}
html.motion-on .fx.on .v6 .wk:nth-child(1) i:nth-child(3){animation-delay:.65s}
html.motion-on .fx.on .v6 .wk:nth-child(2) i:nth-child(1){animation-delay:.85s}
html.motion-on .fx.on .v6 .wk:nth-child(2) i:nth-child(2){animation-delay:1s}
html.motion-on .fx.on .v6 .wk:nth-child(2) i:nth-child(3){animation-delay:1.15s}
html.motion-on .fx.on .v6 .wk:nth-child(3) i:nth-child(1){animation-delay:1.35s}
html.motion-on .fx.on .v6 .wk:nth-child(3) i:nth-child(2){animation-delay:1.5s}
html.motion-on .fx.on .v6 .wk:nth-child(3) i.more{animation:vMore 2s ease 1.7s infinite}
.v6 .slots i.more{background:#fff;border-color:rgba(15,26,36,.12);color:var(--blue)}
@keyframes vFill{to{background:var(--grad-blue);border-color:transparent;color:#fff}}
@keyframes vMore{0%,100%{transform:none}50%{transform:scale(1.18)}}

/* 7 - one truck becomes a fleet as the radius grows */
.v7{min-height:150px}
.v7 .radius{position:absolute;left:18%;top:50%;width:60px;height:60px;border-radius:50%;
  border:1.5px dashed rgba(22,104,196,.45);transform:translate(-50%,-50%) scale(1.9)}
.v7 .r2{border-style:solid;border-color:rgba(22,104,196,.20)}
html.motion-on .v7 .radius{opacity:0;transform:translate(-50%,-50%) scale(.5)}
html.motion-on .fx.on .v7 .radius{animation:vGrow 2.2s cubic-bezier(.22,1,.36,1) .4s forwards}
html.motion-on .fx.on .v7 .r2{animation:vGrow 2.2s cubic-bezier(.22,1,.36,1) .8s forwards,
  vBreath 5s ease-in-out 3s infinite}
@keyframes vGrow{to{opacity:1;transform:translate(-50%,-50%) scale(1.9)}}
@keyframes vBreath{0%,100%{transform:translate(-50%,-50%) scale(1.9)}
  50%{transform:translate(-50%,-50%) scale(2.02)}}
.v7 .tk{position:absolute;width:34px;height:34px;color:var(--blue-deep);top:50%;
  transform:translate(-50%,-50%)}
.v7 .t1{left:18%} .v7 .t2{left:47%} .v7 .t3{left:72%}
html.motion-on .v7 .t2,html.motion-on .v7 .t3{opacity:0;
  transform:translate(-50%,-50%) translateX(-26px)}
html.motion-on .fx.on .v7 .t2{animation:vJoin .7s cubic-bezier(.3,1.4,.4,1) 1.3s forwards}
html.motion-on .fx.on .v7 .t3{animation:vJoin .7s cubic-bezier(.3,1.4,.4,1) 1.6s forwards}
@keyframes vJoin{to{opacity:1;transform:translate(-50%,-50%)}}

/* ---------- the rail: bare iOS banners, no container ----------
   Sean, 6 Aug: "must look more natural, without a box around it, popping up as
   one scrolls through the section, fluidly." The panel, its heading and its
   subtitle are gone — a translucent card sitting inside ANOTHER bordered card
   reads as a screenshot of a phone rather than as notifications arriving. They
   now float directly on the section's own paper, each one arriving as its
   paired point scrolls in.

   Each banner also drifts on its own timing so the stack never reads as one
   rigid block; the offsets are per-child so they never sync up. */
.fx-rail{position:relative}
.rail-in{position:sticky;top:clamp(90px,14vh,150px);perspective:1000px;
  display:flex;flex-direction:column;gap:14px}
.notif{position:relative;transform-origin:top center;will-change:transform,opacity}
html.motion-on .notif{opacity:0;
  transform:perspective(1000px) rotateX(-38deg) translateY(-30px) scale(.92)}
html.motion-on .notif.on{animation:nIn .85s cubic-bezier(.22,1.3,.36,1) forwards}
@keyframes nIn{
  0%{opacity:0;transform:perspective(1000px) rotateX(-38deg) translateY(-30px) scale(.92)}
  55%{opacity:1;transform:perspective(1000px) rotateX(5deg) translateY(4px) scale(1.015)}
  100%{opacity:1;transform:none}}
/* the banner itself: real iOS material, and NOTHING behind it */
.ncard{display:flex;gap:10px;align-items:center;
  font-family:-apple-system,'SF Pro Text',var(--ff),sans-serif;
  background:rgba(252,252,254,.78);
  -webkit-backdrop-filter:blur(30px) saturate(1.8);backdrop-filter:blur(30px) saturate(1.8);
  border:.5px solid rgba(255,255,255,.9);border-radius:22px;padding:12px 14px;
  box-shadow:0 1px 0 rgba(255,255,255,.7) inset,
             0 10px 20px -8px rgba(15,26,36,.20),
             0 26px 48px -20px rgba(15,26,36,.34);
  transition:transform .35s cubic-bezier(.22,1,.36,1), box-shadow .35s}
/* drift: each banner on its own period so the stack breathes rather than marching */
html.motion-on .notif.on .ncard{animation:nDrift 7s ease-in-out infinite alternate}
.notif:nth-child(2) .ncard{animation-delay:-1.4s}
.notif:nth-child(3) .ncard{animation-delay:-2.9s}
.notif:nth-child(4) .ncard{animation-delay:-4.1s}
.notif:nth-child(5) .ncard{animation-delay:-5.6s}
@keyframes nDrift{from{transform:translateY(0)}to{transform:translateY(-4px)}}
/* hover: the banner lifts toward the reader, the way a real one does under a press */
@media(hover:hover) and (pointer:fine){
  .notif .ncard:hover{animation-play-state:paused;
    transform:translateY(-3px) scale(1.022);
    box-shadow:0 1px 0 rgba(255,255,255,.7) inset,
               0 14px 26px -8px rgba(15,26,36,.24),
               0 34px 60px -22px rgba(15,26,36,.40)}
}
.nicon{width:38px;height:38px;border-radius:10.5px;background:#fff;flex:0 0 auto;
  border:.5px solid rgba(15,26,36,.10);object-fit:contain;padding:5px;
  box-shadow:0 3px 8px -3px rgba(15,26,36,.25)}
.nb{min-width:0;flex:1}
.nrow{display:flex;align-items:baseline;justify-content:space-between;gap:10px}
.nrow b{font-size:15px;font-weight:600;letter-spacing:-.2px;color:#000}
.nrow time{font-size:13px;color:rgba(60,60,67,.6);white-space:nowrap}

.nb p{margin:1px 0 0;font-size:15px;letter-spacing:-.2px;line-height:1.33;color:rgba(0,0,0,.88);
  max-width:none}

/* ---------- hover: the vignettes answer the pointer ----------
   Sean, 6 Aug: "Make the artifacts interactive when you hover over them."
   Pointer-gated, because a touch device latches :hover on tap and would leave
   an artefact stuck mid-gesture. Each hover extends that artefact's OWN
   argument rather than applying a generic lift: the #1 row pushes further
   ahead, the kept job swells, the straight path runs its arrow again, the money
   dial climbs, the quiet phone stays quiet and its badge pulses, the weeks add
   one more, the fleet spreads wider. */
@media(hover:hover) and (pointer:fine){
  .fx .viz{transition:transform .4s cubic-bezier(.22,1,.36,1),
                      box-shadow .4s cubic-bezier(.22,1,.36,1),
                      border-color .4s}
  .fx:hover .viz{transform:translateY(-4px);border-color:rgba(22,104,196,.30);
    box-shadow:0 14px 30px -14px rgba(14,76,147,.42)}

  /* 1 - the winning row pushes further clear of the pack */
  .v1 .sr{transition:transform .45s cubic-bezier(.22,1,.36,1),box-shadow .45s}
  .fx:hover .v1 .you{transform:translateX(6px);
    box-shadow:0 10px 22px -8px rgba(22,104,196,.65)}
  .fx:hover .v1 .r1,.fx:hover .v1 .r2{transform:translateX(-4px);opacity:.75}

  /* 2 - the job you wanted takes even more of the frame */
  .v2 .keep{transition:transform .45s cubic-bezier(.3,1.4,.4,1),box-shadow .45s}
  .fx:hover .v2 .keep{transform:translate(-50%,-50%) scale(1.3);
    box-shadow:0 12px 26px -8px rgba(22,104,196,.6)}

  /* 3 - the straight path redraws; the tangle fades further back */
  .v3 .tangle{transition:opacity .45s}
  .fx:hover .v3 .tangle{opacity:.22}
  .fx:hover .v3 .clean{animation:vDraw .7s cubic-bezier(.22,1,.36,1) forwards}

  /* 4 - money keeps climbing, hours keep falling */
  .v4 .arc{transition:stroke-dashoffset .6s cubic-bezier(.22,1,.36,1)}
  .fx:hover .v4 .money{stroke-dashoffset:6}
  .fx:hover .v4 .hours{stroke-dashoffset:124}

  /* 5 - the calm ring breathes and the zero badge asserts itself */
  .v5 .disc,.v5 .zero{transition:transform .45s cubic-bezier(.3,1.4,.4,1)}
  .fx:hover .v5 .disc{transform:scale(1.12)}
  .fx:hover .v5 .zero{transform:scale(1.12)}

  /* 6 - one more week fills in */
  .v6 .slots i{transition:transform .35s cubic-bezier(.22,1,.36,1),
                          background .35s,color .35s,border-color .35s}
  .fx:hover .v6 .wk:nth-child(3) i.more{background:var(--grad-blue);
    border-color:transparent;color:#fff;transform:scale(1.12)}
  .fx:hover .v6 .slots i{transform:translateY(-1px)}

  /* 7 - the fleet spreads and the territory widens */
  .v7 .tk{transition:transform .5s cubic-bezier(.3,1.3,.4,1)}
  .fx:hover .v7 .t1{transform:translate(-50%,-50%) translateX(-8px)}
  .fx:hover .v7 .t3{transform:translate(-50%,-50%) translateX(8px)}
  .v7 .radius{transition:transform .6s cubic-bezier(.22,1,.36,1),opacity .6s}
  .fx:hover .v7 .r2{transform:translate(-50%,-50%) scale(2.15);opacity:.9}
}

/* ================= #how artefacts: one job through the pipeline =============
   Rebuilt 6 Aug. Base CSS is the FINISHED state; pre-states live only under
   html.motion-on and animations only under html.motion-on .mstep.on — so with
   JS off or reduced-motion set the reader gets five finished panels, never a
   blank or half-played one. Nothing here loops: four sequenced panels of
   ambient motion read as a loading state, not a machine. */
.mstep{align-items:center}
@media(min-width:900px){
  .mstep{grid-template-columns:auto minmax(0,1fr) minmax(270px,380px);
    column-gap:clamp(16px,2.4vw,30px)}
}
@media(max-width:899px){.mviz{grid-column:2/-1;margin-top:16px}}

/* the spine: the numeral becomes a node on a drawn pipe */
.mlead{position:relative;min-width:3.2em;padding-top:2px;flex-direction:row}
.mnum{display:grid;place-items:center;width:28px;height:28px;border-radius:50%;
  background:var(--grad-blue);color:#fff;font-size:12px;font-weight:800;letter-spacing:.04em}
.mstep::before{content:"";position:absolute;left:calc(1.6em - 1px);top:52px;bottom:0;width:2px;
  background:linear-gradient(180deg,var(--blue),rgba(22,104,196,.25));transform-origin:top}
html.motion-on .mstep::before{transform:scaleY(0)}
html.motion-on .mnum{background:var(--blue-wash);color:var(--muted-2)}
html.motion-on .mstep.on::before{animation:mSpine .42s cubic-bezier(.22,1,.36,1) forwards}
html.motion-on .mstep.on .mnum{animation:mNode .32s cubic-bezier(.3,1.5,.4,1) .18s forwards}
@keyframes mSpine{to{transform:scaleY(1)}}
@keyframes mNode{to{background:var(--grad-blue);color:#fff}}

/* the panel chassis — byte-identical to the fixes section so both read as one hand */
.mviz{position:relative;height:118px;border-radius:14px;
  background:linear-gradient(180deg,#F6FAFE,#EDF4FB);
  border:1px solid rgba(22,104,196,.12);overflow:hidden;
  transition:transform .22s cubic-bezier(.22,1,.36,1),border-color .22s,box-shadow .22s}
/* progress hairline: you are N of 4 through a machine */
.mviz::after{content:"";position:absolute;left:0;bottom:0;height:2px;background:var(--grad-blue);
  transform-origin:left}
.k1::after{width:25%}.k2::after{width:50%}.k3::after{width:75%}.k4::after{width:100%}
html.motion-on .mviz::after{transform:scaleX(0)}
html.motion-on .mstep.on .mviz::after{animation:mProg .7s cubic-bezier(.22,1,.36,1) 1.75s forwards}
@keyframes mProg{to{transform:scaleX(1)}}

/* the token: one job, born once, delivered once. Always on the same optical line. */
.job{position:absolute;top:32px;height:18px;border-radius:6px;padding:0 9px;
  background:var(--grad-blue);color:#fff;font:800 10.5px/18px var(--ff);white-space:nowrap;
  box-shadow:0 6px 14px -6px rgba(22,104,196,.55);will-change:transform}
.j-born{opacity:0} .j-move,.j-land{opacity:0}

/* ---- 01 they find you ---- */
.k1 .q{position:absolute;left:12px;right:12px;top:8px;height:20px;background:#fff;border-radius:8px;
  border:1px solid rgba(15,26,36,.10);display:flex;align-items:center;padding:0 8px;overflow:hidden}
.k1 .qclip{display:block;height:20px;overflow:hidden}
.k1 .qt{display:block;height:20px;font:600 10.5px/20px var(--ff);color:var(--muted-2);white-space:nowrap}
.k1 .surf{position:absolute;left:12px;right:12px;height:18px;border-radius:6px;background:#fff;
  border:1px solid var(--blue);display:flex;align-items:center;gap:6px;padding:0 5px 0 7px}
.k1 .s1{top:32px}.k1 .s2{top:56px}.k1 .s3{top:80px}
.k1 .ch{font:800 8.5px/1 var(--ff);letter-spacing:.09em;text-transform:uppercase;color:var(--muted-2)}
.k1 .surf b{flex:1;height:5px;border-radius:3px;background:var(--slate);opacity:.12}
.k1 .name{font:800 10.5px/1 var(--ff);color:#fff;background:var(--grad-blue);border-radius:5px;
  padding:3px 7px;white-space:nowrap}
html.motion-on .k1 .qt{clip-path:inset(0 100% 0 0)}
html.motion-on .k1 .surf{opacity:0;transform:translateX(10px);border-color:rgba(15,26,36,.10)}
html.motion-on .k1 .surf b{opacity:.3}
html.motion-on .k1 .name{opacity:0;transform:scale(.6)}
html.motion-on .k1 .j-born{opacity:0;transform:scale(.5);left:46%}
html.motion-on .mstep.on .k1 .qt{animation:mType .62s steps(16) .35s forwards}
html.motion-on .mstep.on .k1 .surf{animation:mSurf .30s cubic-bezier(.22,1,.36,1) forwards}
html.motion-on .mstep.on .k1 .s1{animation-delay:.55s}
html.motion-on .mstep.on .k1 .s2{animation-delay:.70s}
html.motion-on .mstep.on .k1 .s3{animation-delay:.85s}
html.motion-on .mstep.on .k1 .name{animation:mPop .40s cubic-bezier(.3,1.5,.4,1) forwards}
html.motion-on .mstep.on .k1 .s1 .name{animation-delay:.95s}
html.motion-on .mstep.on .k1 .s2 .name{animation-delay:1.15s}
html.motion-on .mstep.on .k1 .s3 .name{animation-delay:1.35s}
html.motion-on .mstep.on .k1 .j-born{animation:mBorn .45s cubic-bezier(.3,1.5,.4,1) 1.55s forwards,
  mExit .45s cubic-bezier(.22,1,.36,1) 2.00s forwards}
@keyframes mType{to{clip-path:inset(0 0 0 0)}}
@keyframes mSurf{to{opacity:1;transform:none;border-color:var(--blue)}}
@keyframes mPop{to{opacity:1;transform:none}}
@keyframes mBorn{to{opacity:1;transform:none}}
/* it leaves toward step 02 — parked clipped at the right edge, which is also
   the base (finished) position, so motion-off shows the same thing */
@keyframes mExit{to{left:100%;opacity:0}}

/* ---- 02 they book themselves in ---- */
.k2 .khead{position:absolute;left:12px;right:12px;top:8px;height:16px;display:flex;
  align-items:center;gap:8px}
.k2 .clock{font:800 10.5px/1 var(--ff);color:var(--blue-deep)}
.k2 .rang{display:flex;align-items:center;gap:4px;font:800 8.5px/1 var(--ff);
  letter-spacing:.08em;text-transform:uppercase;color:var(--muted-2)}
.k2 .rang svg{width:13px;height:13px;color:var(--slate);flex:0 0 auto}
.k2 .rang .slash{stroke-dasharray:26;stroke-dashoffset:0}
.k2 .cnt{margin-left:auto;background:var(--grad-blue);border-radius:5px;padding:0 6px;
  height:15px;overflow:hidden;display:block}
.k2 .cstrip{display:block;transform:translateY(-15px)}
.k2 .cstrip i{display:block;height:15px;font:800 10.5px/15px var(--ff);color:#fff;font-style:normal}
.k2 .slot{position:absolute;left:12px;right:12px;height:20px;border-radius:5px;background:#fff;
  border:1px solid rgba(15,26,36,.14);display:flex;align-items:center;padding:0 8px;overflow:hidden}
.k2 .sl1{top:30px}.k2 .sl2{top:54px}.k2 .sl3{top:78px}
.k2 .sl1,.k2 .sl2{background:repeating-linear-gradient(45deg,rgba(15,26,36,.05) 0 3px,transparent 3px 6px),#fff}
.k2 .st{font:700 10.5px/1 var(--ff);color:var(--muted-2)}
.k2 .fill{position:absolute;inset:0;background:var(--grad-blue);border-radius:4px;
  transform-origin:left;display:flex;align-items:center;gap:7px;padding:0 8px}
.k2 .fill b{font:800 10.5px/1 var(--ff);color:#fff}
.k2 .fill i{font:700 9px/1 var(--ff);color:rgba(255,255,255,.82);font-style:normal}
.k2 .hv-fill{position:absolute;inset:0;background:var(--grad-blue);border-radius:4px;
  transform:scaleX(0);transform-origin:left;transition:transform .26s cubic-bezier(.3,1.5,.4,1)}
html.motion-on .k2 .cstrip{transform:translateY(0)}
html.motion-on .k2 .fill{transform:scaleX(0)}
html.motion-on .k2 .fill i{opacity:0;transform:translateY(4px)}
html.motion-on .k2 .rang .slash{stroke-dashoffset:26}
html.motion-on .k2 .j-move{opacity:1;left:-46px}
html.motion-on .mstep.on .k2 .j-move{animation:mRide .50s cubic-bezier(.22,1,.36,1) forwards,
  mSeat .55s cubic-bezier(.22,1,.36,1) .50s forwards, mGone .2s linear 1.40s forwards}
html.motion-on .mstep.on .k2 .fill{animation:mFill .30s cubic-bezier(.3,1.5,.4,1) 1.05s forwards}
html.motion-on .mstep.on .k2 .fill i{animation:mPop .30s cubic-bezier(.22,1,.36,1) 1.40s forwards}
html.motion-on .mstep.on .k2 .cstrip{animation:mCount .30s cubic-bezier(.22,1,.36,1) 1.55s forwards}
html.motion-on .mstep.on .k2 .rang .slash{animation:mSlash .30s cubic-bezier(.22,1,.36,1) 1.70s forwards}
@keyframes mRide{to{left:34%}}
@keyframes mSeat{to{left:14px;top:79px}}
@keyframes mGone{to{opacity:0}}
@keyframes mFill{to{transform:scaleX(1)}}
@keyframes mCount{to{transform:translateY(-15px)}}
@keyframes mSlash{to{stroke-dashoffset:0}}

/* ---- 03 the job lands on your board ---- */
.k3 .board{position:absolute;left:10px;right:10px;top:8px;bottom:8px;background:#fff;
  border-radius:10px;border:1px solid rgba(15,26,36,.10);
  box-shadow:0 6px 16px -12px rgba(15,26,36,.25);padding:7px 9px}
.k3 .bhead{display:flex;align-items:center;justify-content:space-between;
  font:800 8.5px/1 var(--ff);letter-spacing:.09em;text-transform:uppercase;color:var(--muted-2)}
.k3 .bnew{display:flex;align-items:center;gap:4px;color:var(--blue)}
.k3 .bnew::before{content:"";width:6px;height:6px;border-radius:50%;background:var(--blue)}
.k3 .rec{position:relative;margin-top:6px;border-radius:8px;background:#fff;
  border:1px solid rgba(15,26,36,.10);padding:6px 8px 6px 11px;overflow:hidden}
.k3 .rec::before{content:"";position:absolute;left:0;top:0;bottom:0;width:3px;background:var(--grad-blue)}
.k3 .rl1{display:flex;align-items:baseline;justify-content:space-between;gap:8px}
.k3 .rl1 b{font:800 11px/1 var(--ff);color:var(--text)}
.k3 .val{font:800 11px/1 var(--ff);color:var(--text)}
.k3 .rl2{display:flex;align-items:center;gap:6px;margin-top:4px;white-space:nowrap}
.k3 .iss{font:600 10.5px/1 var(--ff);color:var(--muted)}
.k3 .win{font:700 10.5px/1 var(--ff);color:var(--blue)}
.k3 .src{margin-left:auto;font:800 9px/1 var(--ff);color:var(--blue);background:var(--blue-wash);
  border-radius:5px;padding:3px 6px}
.k3 .hist{position:absolute;left:9px;right:9px;height:8px;border-radius:4px;background:var(--slate);opacity:.3}
.k3 .h1{bottom:20px}.k3 .h2{bottom:8px}
html.motion-on .k3 .rec{opacity:0}
html.motion-on .k3 .j-land{opacity:1;left:-46px}
html.motion-on .mstep.on .k3 .j-land{animation:mArrive .45s cubic-bezier(.22,1,.36,1) forwards,
  mUnfold .40s cubic-bezier(.22,1,.36,1) .55s forwards, mGone .1s linear .95s forwards}
html.motion-on .mstep.on .k3 .rec{animation:mRecIn .35s cubic-bezier(.22,1,.36,1) .95s forwards}
@keyframes mArrive{to{left:19px}}
@keyframes mUnfold{to{width:calc(100% - 38px);height:44px;border-radius:8px;
  background:#fff;color:transparent;box-shadow:none}}
@keyframes mRecIn{to{opacity:1}}

/* ---- 04 we run all of it ---- */
.k4 .task{position:absolute;left:12px;right:12px;height:26px;background:#fff;border-radius:8px;
  border:1px solid rgba(15,26,36,.10);display:flex;align-items:center;gap:8px;
  padding:0 8px 0 11px;overflow:hidden}
.k4 .t1{top:26px}.k4 .t2{top:58px}
.k4 .state{position:absolute;left:0;top:0;bottom:0;width:3px;background:var(--grad-blue);
  transform-origin:left}
.k4 .tlab{font:700 10.5px/1 var(--ff);color:var(--text);white-space:nowrap;overflow:hidden;
  text-overflow:ellipsis}
.k4 .owns{margin-left:auto;position:relative;display:grid;place-items:center;min-width:54px;height:17px}
.k4 .own-us,.k4 .own-you{position:absolute;border-radius:5px;padding:2px 7px;white-space:nowrap;
  font:800 10.5px/1 var(--ff)}
.k4 .own-us{background:var(--grad-blue);color:#fff}
.k4 .own-you{background:#fff;border:1px solid var(--soft);color:var(--muted-2);opacity:0}
.k4 .hv-req{position:absolute;left:11px;background:#fff;border:1px solid var(--blue);border-radius:5px;
  padding:3px 7px;font:700 10.5px/1 var(--ff);color:var(--blue);white-space:nowrap;
  opacity:0;transform:translateX(-28px);transition:opacity .3s,transform .3s cubic-bezier(.22,1,.36,1)}
.k4 .login{position:absolute;left:12px;bottom:8px;display:flex;align-items:center;gap:7px}
.k4 .plate{position:relative;background:#fff;border:1px solid var(--soft);border-radius:6px;
  padding:4px 9px;opacity:.35;font:700 10.5px/1 var(--ff);color:var(--muted-2)}
.k4 .plate svg{position:absolute;inset:0;width:100%;height:100%;overflow:visible}
.k4 .plate .slash{stroke:var(--slate);stroke-width:1.5;stroke-linecap:round;
  stroke-dasharray:64;stroke-dashoffset:0}
.k4 .never{font:800 8.5px/1 var(--ff);letter-spacing:.09em;text-transform:uppercase;color:var(--muted-2)}
html.motion-on .k4 .state{transform:scaleX(0)}
html.motion-on .k4 .own-us{opacity:0;transform:scale(.6)}
html.motion-on .k4 .own-you{opacity:1}
html.motion-on .k4 .plate .slash{stroke-dashoffset:64}
html.motion-on .mstep.on .k4 .state{animation:mBar .42s cubic-bezier(.22,1,.36,1) forwards}
html.motion-on .mstep.on .k4 .t1 .state{animation-delay:.35s}
html.motion-on .mstep.on .k4 .t2 .state{animation-delay:.50s}
html.motion-on .mstep.on .k4 .own-you{animation:mYouOut .20s cubic-bezier(.22,1,.36,1) forwards}
html.motion-on .mstep.on .k4 .t1 .own-you{animation-delay:.75s}
html.motion-on .mstep.on .k4 .t2 .own-you{animation-delay:1.00s}
html.motion-on .mstep.on .k4 .own-us{animation:mPop .38s cubic-bezier(.3,1.5,.4,1) forwards}
html.motion-on .mstep.on .k4 .t1 .own-us{animation-delay:.82s}
html.motion-on .mstep.on .k4 .t2 .own-us{animation-delay:1.07s}
html.motion-on .mstep.on .k4 .plate .slash{animation:mSlash2 .32s cubic-bezier(.22,1,.36,1) 1.35s forwards}
@keyframes mBar{to{transform:scaleX(1)}}
@keyframes mYouOut{to{opacity:0;transform:translateY(-10px)}}
@keyframes mSlash2{to{stroke-dashoffset:0}}

/* ---- the closing deed: not a step ---- */
.kown{position:relative;margin-top:clamp(1.8rem,3.4vw,2.6rem);max-width:520px}
@media(max-width:779px){.kown .host,.kown .tether{display:none}}
.kown .deed{position:relative;background:#fff;border:2px solid var(--text);border-radius:10px;
  padding:11px 14px;
  display:flex;align-items:center;gap:12px;min-height:64px;
  transition:transform .22s cubic-bezier(.22,1,.36,1),box-shadow .22s}
.kown .dom{position:relative;font:800 12px/1 var(--ff);color:var(--text);white-space:nowrap}
.kown .uline{position:absolute;left:0;right:0;bottom:-4px;height:2px;background:var(--blue);
  transform-origin:left}
.kown .custs{display:flex;gap:4px;margin-left:auto}
.kown .custs i{width:16px;height:16px;border-radius:5px;background:var(--blue-wash);
  display:grid;place-items:center;font:800 9px/1 var(--ff);color:var(--blue);font-style:normal}
.kown .ccount{font:700 10.5px/1 var(--ff);color:var(--muted);white-space:nowrap}
.kown .stamp{position:absolute;right:12px;bottom:7px;background:#fff;font:800 8.5px/1 var(--ff);letter-spacing:.1em;
  text-transform:uppercase;color:var(--blue);border:1px solid var(--blue);border-radius:4px;
  padding:2px 5px;transform:rotate(-6deg);opacity:.5;transition:opacity .22s,transform .22s}
.kown .hv-grow{position:absolute;right:12px;top:8px;font:800 10.5px/1 var(--ff);color:var(--blue);
  opacity:0;transform:scale(.6);transition:opacity .3s,transform .3s cubic-bezier(.3,1.5,.4,1)}
.kown .tether{position:absolute;right:-30px;top:50%;width:26px;border-top:1px dashed var(--slate);opacity:0}
.kown .host{position:absolute;right:-86px;top:calc(50% - 11px);background:#fff;border:1px solid var(--soft);
  border-radius:5px;padding:4px 8px;font:700 10.5px/1 var(--ff);color:var(--muted-2);opacity:0}
html.motion-on .kown .deed{opacity:0}
html.motion-on .kown .custs i{opacity:0;transform:translateY(8px)}
html.motion-on .kown .uline{transform:scaleX(0)}
html.motion-on .kown .stamp{opacity:0;transform:rotate(-6deg) scale(1.25)}
html.motion-on .kown .tether,html.motion-on .kown .host{opacity:1}
html.motion-on .kown.on .deed{animation:mDeed .42s cubic-bezier(.22,1,.36,1) forwards}
html.motion-on .kown.on .custs i{animation:mPop .26s cubic-bezier(.22,1,.36,1) forwards}
html.motion-on .kown.on .custs i:nth-child(1){animation-delay:.42s}
html.motion-on .kown.on .custs i:nth-child(2){animation-delay:.49s}
html.motion-on .kown.on .custs i:nth-child(3){animation-delay:.56s}
html.motion-on .kown.on .custs i:nth-child(4){animation-delay:.63s}
html.motion-on .kown.on .tether{animation:mGone .2s linear .76s forwards}
html.motion-on .kown.on .host{animation:mLeave .40s cubic-bezier(.5,0,.8,.4) .76s forwards}
html.motion-on .kown.on .uline{animation:mUline .38s cubic-bezier(.22,1,.36,1) 1.20s forwards}
html.motion-on .kown.on .stamp{animation:mStamp .28s cubic-bezier(.3,1.5,.4,1) 1.40s forwards}
@keyframes mDeed{to{opacity:1}}
@keyframes mLeave{to{opacity:0;transform:translateX(52px)}}
@keyframes mUline{to{transform:scaleX(1)}}
@keyframes mStamp{to{opacity:.5;transform:rotate(-6deg) scale(1)}}
.own{margin-top:14px}
.how-cta{margin-top:clamp(2rem,3.6vw,2.8rem)}

/* ---- hover: each panel extends its own argument ----
   Never swaps animation-name (that re-fires from frame 0 on mouseleave).
   Hover touches only properties no forwards-keyframe holds, or dedicated
   .hv-* elements that carry no reveal animation at all. */
@media(hover:hover) and (pointer:fine){
  .mstep:hover .mviz,.mstep:focus-within .mviz{transform:translateY(-2px);
    border-color:rgba(22,104,196,.28);box-shadow:0 10px 24px -16px rgba(14,76,147,.45)}
  .mstep:hover .mnum{transform:scale(1.06);transition:transform .22s cubic-bezier(.22,1,.36,1)}
  .k1 .qclip{transition:transform .3s cubic-bezier(.22,1,.36,1)}
  .mstep:hover .k1 .qclip{transform:translateY(-20px)}
  .mstep:hover .k2 .sl1 .hv-fill{transform:scaleX(1)}
  .mstep:hover .k4 .hv-req{opacity:1;transform:translateX(0)}
  .kown:hover .deed{transform:translateY(-2px);box-shadow:0 10px 24px -16px rgba(14,76,147,.45)}
  .kown:hover .deed{border-color:var(--blue)}
  .kown:hover .hv-grow{opacity:1;transform:scale(1)}
}
@media(prefers-reduced-motion:reduce){
  html.motion-on .mviz *,html.motion-on .mstep::before,html.motion-on .kown *{animation:none !important}
}

/* ---------- WhatsApp floating launcher ----------
   Same bottom-right corner as .popup below, one z-index under it — on the
   pages that have both, dark.js hides this while the popup is open rather
   than fighting it with position math, since which one wins is a JS-timed
   decision (25s) and not something CSS can know on its own. */
.wa-float{position:fixed;right:20px;bottom:20px;z-index:59;
  width:56px;height:56px;border-radius:50%;
  display:flex;align-items:center;justify-content:center;
  background:linear-gradient(160deg,var(--blue-bright),var(--blue-deep));
  box-shadow:0 10px 24px -6px rgba(14,76,147,.55);
  transition:transform .18s ease,box-shadow .18s ease}
.wa-float[hidden]{display:none}
.wa-float-icon{width:26px;height:26px;color:#fff}
@media(hover:hover) and (pointer:fine){
  .wa-float:hover{transform:translateY(-2px);box-shadow:0 14px 28px -6px rgba(14,76,147,.6)}
}
@media(prefers-reduced-motion:reduce){.wa-float{transition:none}}

/* ---------- 15s email popup ----------
   Fixed corner card, independent of scroll position — this is not a section
   and carries no data-reveal/data-fx, it is timed from page load (see
   dark.js). Deliberately not a full-screen modal: no backdrop, nothing traps
   focus, and the rest of the page stays scrollable and clickable under it. */
.popup{position:fixed;right:20px;bottom:20px;left:20px;z-index:60;
  display:flex;justify-content:flex-end;pointer-events:none}
.popup[hidden]{display:none}
.popup-card{position:relative;width:100%;max-width:340px;background:var(--plate);
  border:1px solid var(--soft);border-radius:var(--r-lg);
  padding:clamp(16px,2.4vw,20px);box-shadow:0 20px 48px -16px rgba(15,26,36,.35);
  animation:popupIn .32s cubic-bezier(.22,1,.36,1);pointer-events:auto}
@keyframes popupIn{from{opacity:0;transform:translateY(18px)}to{opacity:1;transform:none}}
@media(prefers-reduced-motion:reduce){.popup-card{animation:none}}
.popup-close{position:absolute;top:11px;right:11px;width:26px;height:26px;
  display:grid;place-items:center;border:0;background:transparent;cursor:pointer;
  font-size:18px;line-height:1;color:var(--muted-2);border-radius:50%}
@media(hover:hover) and (pointer:fine){
  .popup-close:hover{background:var(--plate-2);color:var(--text)}
}
/* .popup-h/.popup-note: the done-state confirmation still uses these (heading +
   supporting line + full CTA) — only the ask-state collapsed to one line, below. */
.popup-h{font-size:clamp(19px,2.2vw,23px);font-weight:800;letter-spacing:-.02em;
  margin:0 0 8px;padding-right:24px}
.popup-note{font-size:14px;font-weight:500;color:var(--muted);margin:0 0 18px;max-width:38ch}
.popup-done .btn{width:100%;justify-content:center;margin-top:4px}

/* ask-state: one line, no field label — input+button share a row, flex
   stretch matches their heights without setting one explicitly. */
.popup-line{font-size:13.5px;font-weight:700;line-height:1.4;letter-spacing:-.005em;
  margin:0 0 12px;padding-right:22px;max-width:27ch}
.popup-row{display:flex;gap:8px}
.popup-row input{flex:1;min-width:0;padding:9px 11px;font-size:13px;font-weight:500;
  font-family:var(--ff);color:var(--text);border:1.5px solid var(--edge);
  border-radius:8px;background:var(--plate)}
.popup-row input:focus{outline:none;border-color:var(--blue)}
.popup-row .btn{flex:0 0 auto;padding:0 15px;font-size:10.5px}

/* ---------- what: "What is Kaiser Collective? / What we do / Who it's for" ----------
   Centred: the one section on this page whose immediate neighbour (the hero)
   is also centred, so this reads as the hero's landing rather than as a
   seventh left-aligned section. .wh-row is the one exception — a ruled row
   reads left, always, regardless of the section around it. */
.wh{text-align:center}
.wh-lead{margin-left:auto;margin-right:auto}

.wh-claims{display:flex;flex-wrap:wrap;justify-content:center;gap:.875rem 2.25rem;
  margin-top:1.875rem;padding-top:1.5rem;border-top:1px solid var(--soft)}
.wh-claim{display:flex;align-items:center;gap:.625rem}
.wh-claim svg{flex:none;width:22px;height:22px;color:var(--blue)}
.wh-claim span{font-size:.8125rem;font-weight:700;letter-spacing:.04em;color:var(--text)}

.wh-sec2{margin-top:clamp(3rem,5.4vw,4.4rem)}
.wh-list{max-width:38rem;margin:1.75rem auto 0;text-align:left}
.wh-row{display:grid;grid-template-columns:26px auto 1fr;column-gap:14px;
  align-items:center;padding:12px 0;border-top:1px solid var(--soft)}
.wh-row:last-child{border-bottom:1px solid var(--soft)}
.wh-row svg{width:22px;height:22px;flex:none}
.wh-row b{font-size:13px;font-weight:800;letter-spacing:-.005em;color:var(--text);
  white-space:nowrap}
.wh-row span{font-size:13.5px;font-weight:500;color:var(--muted);line-height:1.5}
@media(max-width:480px){
  .wh-row{grid-template-columns:22px 1fr;row-gap:2px}
  .wh-row span{grid-column:2}
}
.wh-more{margin:1.375rem 0 0;font-size:.85rem}
.wh-more a{color:var(--blue);text-decoration:none;border-bottom:1px solid var(--hair);
  padding-bottom:1px}
@media(hover:hover) and (pointer:fine){.wh-more a:hover{border-bottom-color:var(--blue)}}

.wh-sec3{margin-top:clamp(3rem,5.4vw,4.4rem)}
/* max-width is generous on purpose, not a measure like .wh-list's: ES labels
   ("BÚSQUEDAS, LLAMADAS, REFERIDOS", "1–25 CAMIONES") run wider than EN, and a
   tight cap here made the row wrap unevenly on the ES page well above the
   intentional 640px stacking breakpoint below. */
.wh-reach{display:flex;align-items:center;justify-content:center;
  gap:clamp(10px,2.4vw,26px);flex-wrap:wrap;margin:2.25rem auto 0;max-width:46rem}
.wh-node{display:flex;flex-direction:column;align-items:center;gap:9px}
.wh-node svg{width:40px;height:40px}
.wh-node span{font-size:10.5px;font-weight:800;letter-spacing:.09em;
  text-transform:uppercase;color:var(--muted-2);white-space:nowrap}
.wh-badge{margin-top:1px;font-size:9.5px;font-weight:800;letter-spacing:.08em;
  color:#fff;background:var(--grad-blue);padding:3px 8px;border-radius:999px}
.wh-cluster{display:flex;gap:7px}
.wh-cluster svg{width:22px;height:22px}
.wh-arrow{width:30px;flex:none}
.wh-arrow svg{display:block;width:100%;height:auto}
@media(max-width:640px){
  .wh-reach{flex-direction:column;gap:1.375rem}
  .wh-arrow{width:14px;height:26px;transform:rotate(90deg)}
}
