/* =========================================================================
   shift-anim.css — the before/after transition from home-v3.

   The scroll-snap track is replaced by a single stage whose text swaps. On
   change the two sides part outward and fade, the arrow eases down, the
   words are replaced at the midpoint, and everything returns. The movement
   is the thing that reads as "before becomes after", which the sideways
   track never actually said -- it only moved you between two pairs.

   Timings and easing are home-v3's, unchanged: .4s on the statements,
   .35s on the arrow, both cubic-bezier(.16,1,.3,1), with the swap at 260ms
   so it lands while the words are invisible.

   The trade is swipe: a track could be dragged, a stage cannot. The tabs
   are buttons, so keyboard and click both still work.
   ========================================================================= */

.hx-stage{
  position:relative;
  display:grid;grid-template-columns:1fr auto 1fr;align-items:center;gap:44px;
  padding:78px var(--hx-inset) 0;
  min-height:220px;
}

.hx-stage .hx-side--b{align-items:flex-end;text-align:right}
.hx-stage .hx-side--a{align-items:flex-start;text-align:left}

.hx-stage .hx-line{
  transition:
    opacity .4s cubic-bezier(.16,1,.3,1),
    transform .4s cubic-bezier(.16,1,.3,1);
}
.hx-stage.is-changing .hx-side--b .hx-line{opacity:0;transform:translateX(-18px)}
.hx-stage.is-changing .hx-side--a .hx-line{opacity:0;transform:translateX(18px)}

.hx-stage .hx-arrow svg{transition:transform .35s cubic-bezier(.16,1,.3,1)}
.hx-stage.is-changing .hx-arrow svg{transform:scale(.8)}

/* The tags hold still. Only the statements move, so the labels stay as
   fixed points to read the change against. */

/* ------------------------------- weight -------------------------------
   800 is the logo's weight and nothing else's. The hero's offering titles
   already sit at 700 at the same 35px; the section heading and the
   statements were still at 800, which put them level with the wordmark.
   Sizes were already matched -- heading and offering title both compute to
   35px with -1.225px tracking -- so only the weight moves. */
.lf-block .hx-head,
.lf-block .hx-line{font-weight:700}

/* ------------------------------ scale up ------------------------------
   The section heading and the hero's offering titles share one value, so
   they stay identical: 35px -> 42px at 1440. Raising only the section
   heading would have made it outrank the hero, which is the thing the
   whole page is built around. */
.lf-block{--hx-max:clamp(26px,2.95vw,42px)}
.lf-block .n12-services strong{font-size:var(--hx-max)}
/* The numeral's box is one of those lines tall, so it centres on the
   title's FIRST line. It has to be set here, beside the font-size it
   depends on: hero-v1.css sizes this box from its own
   clamp(23px,2.5vw,35px), which this rule overrides at higher
   specificity -- so the numeral was being centred in a 33px box beside a
   39.9px line, and sat 7px high. .95 is .n12-services strong's
   line-height. */
.lf-block .n12-services b{height:calc(var(--hx-max) * .95)}

/* The wordmark goes up with them, to keep the gap it had before the headers
   grew: it was 42 against 35, so 52 against 42 holds the same ratio. Weight
   and tracking already separate it; this puts the size back too. */
/* Closing the gap to the line. The padding was only half the story -- the
   stage also carried min-height:220px with the row centred inside it, so
   most of the space above the quotes was centring slack rather than
   padding, and cutting the padding alone barely moved it. The min-height
   comes down to just clear two lines, which is all it was ever guarding
   against. */
.lf-block .hx-stage{padding-top:56px;min-height:96px}

/* ---------------------- three gaps, made equal ----------------------
   The hero fills the viewport and its panel is centred over the FULL
   height, with the header sitting on top of it rather than above it. So
   the space below the nav and the space below the CTAs were never going to
   match: they differed by exactly the nav's own offset, 59px, which is why
   one measured 106 and the other 165.

   Padding the panel by that offset makes it centre in the space BELOW the
   header instead, and the two gaps then come out equal at any viewport
   height rather than only at this one. */
.lf-block .n12-panel{padding-top:59px}

/* ...and the third gap, hero bottom to the section's first text, set to the
   135px the other two settle at. Those two are a proportion of viewport
   height and this one is a fixed padding, so they agree exactly at a 900px
   viewport and drift apart on a much taller or shorter one. */
/* 135 top AND bottom. The top is pinned by the hero relationship (nav to
   eyebrow, CTAs to hero bottom, hero bottom to this text are all 135), so
   the bottom matches it rather than the section being lopsided. */
.lf-block .hx{padding-top:135px;padding-bottom:135px}

/* The clay, in the hero. On the numerals: they are the same device as the
   section's 01-04, where clay already marks the active one, so the
   numbering reads as one system down the page. They are also small and
   repeated, which is what an accent wants to be -- it registers without
   competing with the photograph, and it leaves "book a call" as the
   highest-contrast thing in the hero, which is where it should be. */
.lf-block .n12-services b{color:var(--lf-accent)}

/* ------------------------- the small type -------------------------
   It had drifted into near-duplicates that read as mistakes rather than as
   a scale: 10px and 10.5px doing the same job, and 13.5 / 14 / 15 / 15.5
   across four neighbouring elements. Collapsed to three sizes, each one
   step up, so they hold their own against 42px headings.

     12px    every uppercase micro label (was 10 and 10.5)
     15px    nav, and the hero's numerals
     16px    the two actions, which sat at 15 and 14 side by side
     16.5px  the section intro */

.lf-block .n12-claim,
.lf-block .hx-eyebrow,
.lf-block .hx-tab small,
.lf-block .hx-stage .hx-tag{font-size:12px;letter-spacing:.17em}

.lf-block .n12-services b{font-size:15px}

.lf-block .n12-cta,
.lf-block .n12-help{font-size:16px}

.lf-block .hx-sub{font-size:15px}

/* ------------------------- section hierarchy -------------------------
   The heading was 42px, tied with the hero's offering titles and larger
   than its own section's content at 30px. Two things wrong with that: a
   section signpost was ranking level with the page's primary content, and
   inside the section the signpost was louder than the thing it points at.

   The statements are the payload here, so they lead: 34px against a 32px
   heading, both clearly under the hero's 42. The measure widens with them,
   or the longest statement tips onto a second line. */
/* One line. The 20ch measure it inherited was sized for the old 42px, and
   at 32px there is room for the whole thing -- but left free to wrap on
   narrow viewports rather than forced with nowrap. */
/* 32 was too quiet. 38 gives the section headings presence while still
   sitting clearly under the hero's 42px offering titles, which is the one
   rank that must not be tied. */
.lf-block .hx-head{font-size:clamp(26px,2.65vw,38px);max-width:none}
.lf-block .hx-line{font-size:clamp(22px,2.4vw,34px);max-width:34ch}

/* The stage does not take the content inset the heading does. It is a
   centred composition -- one side right-aligned into the arrow, the other
   left-aligned out of it -- so what it needs is room either side of the
   middle, not alignment with the column above.

   At 115px the side was 546px and the longest statement, "everyone knows
   where the business is going", measures 606px, so it wrapped. At 44px,
   which is the hero's own gutter, the side is 617px and it holds. Only the
   longest lines ever reach out that far; the rest stay near the centre. */
.lf-block .hx-stage{padding-left:var(--n12-gutter);padding-right:var(--n12-gutter)}

/* The arrow takes the accent; the labels go back to grey and white, so the
   before/after distinction is carried twice again -- once by the labels,
   once by the statements -- rather than resting on the statements alone. */
.lf-block .hx-stage .hx-arrow{color:var(--lf-accent)}
.lf-block .hx-stage .hx-side--b .hx-tag{color:rgba(246,241,234,var(--lf-dim-tag))}
.lf-block .hx-stage .hx-side--a .hx-tag{color:var(--n12-cream)}

/* ============================ the indicator ============================
   Was a solid block that slid between tabs, which is what read as blocky:
   the only thing moving was a rectangle, and it travelled sideways across
   dead tabs to get where it was going.

   Now it is a progress bar. The bar sits under the active tab and fills
   left to right over the dwell; when it is full the pair advances. So the
   line is telling you how long you have rather than just marking a place.

   It fills with scaleX rather than width, which the compositor can animate
   on its own without re-laying out the row every frame -- that is most of
   the smoothness.

   It runs regardless of the pointer. Hovering used to freeze it, which
   read as the thing getting stuck rather than as a considerate pause.

   The four segments divide the FULL screen width rather than the tabs'
   inset, so the run reaches both edges: 01 starts at the left edge and 04
   finishes at the right. The cost is that a segment no longer sits exactly
   under its tab's text -- the tabs are an inset 4-column grid, the segments
   are plain quarters -- so the bar reads as progress across the section
   rather than as an underline, and the active tab is marked by its colour
   instead. */

.lf-block .hx-tabs{--hx-dwell:5200ms}

/* The rule is the whole screen now and never moves. One sweep crosses all
   four, so there is no per-tab slot to slide between -- the numbers change
   as the leading edge passes them. */
.lf-block .hx-rule{
  left:0;
  width:100%;
  transform:none;
  transition:none;
  background:none;               /* the fill carries the colour now */
  overflow:hidden;
}
/* The structure is the /automation proof strip's -- a body running up into a
   bright cream head, with a drop-shadow glow -- but on the clay rather than
   that strip's orange, which was too hot next to this ground. The body is
   #B28479 and only the last few percent goes to #E0D2C5, so the tip reads
   as light without the whole run reading as orange.

   Because the bar is scaled rather than clipped, the gradient compresses
   with it -- early on the whole ramp is squeezed into a few pixels and
   reads as a bright point, opening out into the full run as it fills. That
   is a side effect of scaling, but a useful one. */
.lf-block .hx-rule-fill{
  display:block;height:100%;width:100%;
  background:linear-gradient(90deg,
    rgba(178,132,121,.30) 0%,
    rgba(178,132,121,.68) 42%,
    rgba(178,132,121,.95) 78%,
    #E0D2C5 96%,
    rgba(224,210,197,.92) 100%);
  filter:drop-shadow(0 0 7px rgba(178,132,121,.42));
  transform:scaleX(0);
  transform-origin:left center;
}
.lf-block .hx-rule-fill{
  animation-timing-function:linear;
  animation-fill-mode:forwards;
}
/* Sweep: one run from the left edge to the right across all four.
   Drain: the trailing edge catches up and it leaves off the right. */
.lf-block .hx-tabs.is-filling .hx-rule-fill{animation-name:hx-sweep}
.lf-block .hx-tabs.is-exiting .hx-rule-fill{animation-name:hx-drain}

/* Held while the pointer is on a number. The bar is jumped to that number's
   mark and then frozen there, rather than frozen wherever the sweep had got
   to -- otherwise the line would be showing one number while another was
   lit. A paused animation is what makes this possible; a transition could
   not be stopped mid-flight. */
.lf-block .hx-tabs.is-held .hx-rule-fill{animation-play-state:paused}

@keyframes hx-sweep{from{transform:scaleX(0)}to{transform:scaleX(1)}}
@keyframes hx-drain{from{transform:scaleX(1)}to{transform:scaleX(0)}}

@media(prefers-reduced-motion:reduce){
  /* Nothing sweeps, so a full-width bar would say nothing -- it would just
     be a line. Drop it and let the active tab's colour do the marking. */
  .lf-block .hx-rule-fill{display:none}
}

@media(max-width:900px){
  .hx-stage{grid-template-columns:1fr;gap:18px;padding-top:52px;min-height:0}
  .hx-stage .hx-side--b,.hx-stage .hx-side--a{align-items:flex-start;text-align:left}
  .hx-stage .hx-arrow{transform:rotate(90deg)}
}

@media(prefers-reduced-motion:reduce){
  .hx-stage .hx-line,.hx-stage .hx-arrow svg{transition:none}
  .hx-stage.is-changing .hx-side--b .hx-line,
  .hx-stage.is-changing .hx-side--a .hx-line{opacity:1;transform:none}
  .hx-stage.is-changing .hx-arrow svg{transform:none}
}
