/* ═════════════════════════════════════════════════════════════════════
   CoreWeave Webflow Motion Kit — cw-seams.css
   ═════════════════════════════════════════════════════════════════════
   PURPOSE
   The angled section-seam bend: a triangular wedge of the next section's
   colour that rises up into the section above as the boundary scrolls
   through the viewport. Scroll-driven, pure CSS — the animation runs on a
   `view()` timeline resolved by the compositor, no JavaScript. Chromium-only
   via the `@supports (animation-timeline: view())` guard; everywhere else
   (Safari, Firefox) the seam degrades to a flat section edge. Also carries
   the footer wordmark fade-in (.hf__word), which rides the same mechanism.

   REQUIRED MARKUP
   One <div> between two adjacent sections, with the colour variant for the
   section BELOW it:

     <section class="...">…</section>
     <div class="hp-seam hp-seam--grey-white"></div>   ← next section is white
     <section class="...">…</section>

   Variants:
     .hp-seam                     wedge paints --hp-grey  (default below-colour)
     .hp-seam--grey-white         wedge paints --hp-white
     .hp-seam--white-black        wedge paints #000 (use before the footer)
     .hp-seam--cta                the photograph-carrying seam above the CTA
                                  banner — needs an <img> child (same src as
                                  the banner's .hp-cta__shot)

   MODE SWITCHES — html[data-bend] and html[data-seam] are STATIC in this
   kit: set them once on the <html> tag (Webflow: Site settings → Custom code
   head snippet, or a body-embed script that sets them before paint). The
   original site swapped them live via bendmode.js; that switcher is not
   needed in production. Defaults baked here: data-bend="grow".
     data-bend="grow"    boundary arrives straight, bends to full angle as it
                         climbs (default — the keyframe name is the fallback)
     data-bend="fade"    boundary arrives at full angle, straightens as it
                         climbs; adds --hp-tail so the next section's ground
                         gets room to land on
     data-seam="overlap" the section above falls behind the scroll (max 360px)
                         while the next one rides over it — fade mode only;
                         grow mode switches the lag off itself

   Extracted verbatim from cw-landing.pages.dev/home.css, 2026-09-21.
   ═════════════════════════════════════════════════════════════════════ */

/* ── tokens the seam rules reference ──────────────────────────────────
   These live in home.css's page-wide :root; redefined here with their
   home.css values so this file is self-contained. */
:root {
  /* page colour tokens — override per section in Webflow if your palette
     differs */
  --hp-ink:        #02030b;
  --hp-grey:       #f2f2f3;   /* 5691:5901 (2026-09-21) */
  --hp-white:      #ffffff;

  /* The one number every section on the page keeps between its boundary and
     its content, at both ends: 124 at 1440, scaling down with the rest. */
  --hp-section-air: 80px;   /* 80 on a tablet, 120 at 1440, 160 past 1920; the phone block keeps 60 */

  /* Extra room under every block's content, on top of its own edge padding.
     In overlap mode the section below rides up over exactly this, so it is
     what the overlap eats instead of content. */
  --hp-tail: 0px;

  /* The CTA banner's height. A token rather than a number in one rule,
     because the seam above the banner has to size its half of the
     photograph by it — see .hp-seam--cta. */
  --hp-cta-h: clamp(420px, 60.42vw, 870px);

  /* The empty photograph the banner keeps under its copy for the seam below
     it to rise through. */
  --hp-cta-tail: var(--hp-section-air);

  /* …and what the section actually measures: the seam ABOVE the banner sizes
     its half of the photograph by the section's real height. */
  --hp-cta-box: calc(var(--hp-cta-h) + var(--hp-cta-tail));

  /* How deep a seam's bend goes, which is also the band's height.
     2026-09-21 (George): --hp-section-air rather than a vw of its own:
     80 / 120 / 160 up the ladder. (The older 14.55vw — 25°, 210 on a 1440
     screen — is what it replaces.) On :root rather than on .hp-seam because
     the CTA banner is sized by it too. */
  --hp-seam-swing: var(--hp-section-air);
}
/* the vertical rhythm climbs with the gutter */
@media (min-width: 1440px) { :root { --hp-section-air: 120px; } }
@media (min-width: 1920px) { :root { --hp-section-air: 160px; } }
/* the phone block pins the tokens outright */
@media (max-width: 720px) {
  :root {
    --hp-section-air: 60px;
    --hp-cta-h: 630px;
  }
  /* the banner is 630 in all, the photograph under the seam included */
  :root { --hp-cta-h: calc(630px - var(--hp-cta-tail)); }
}

/* ── the seam band ────────────────────────────────────────────────────
   The vertex sits at 68.8% of the width — the same place in every reference
   frame. The band paints only the LOWER ground, and takes no room in the
   flow: the chord sits at the band's bottom edge and a negative top margin
   puts that edge exactly on the section boundary. */
.hp-seam {
  /* --hp-seam-swing is on :root — see the note there. */
  --hp-seam-below: var(--hp-grey);
  position: relative;
  height: var(--hp-seam-swing);
  /* out of the flow: the bend hangs up over the trailing padding of the
     section above, which is empty by construction */
  margin-top: calc(var(--hp-seam-swing) * -1);
  /* and it is paint, not surface. Hanging over the section above puts it on
     top of whatever is up there, and it was swallowing the clicks meant for
     the carousel controls — measured, the band covered the Next button of all
     three carousels over about 400px of scroll each. Nothing here is ever a
     target, so nothing here should be hit-tested. */
  pointer-events: none;
  /* No overflow here, and that is not tidiness: any overflow other than
     visible makes a box a scroll container, and view() resolves against the
     nearest ancestor one — the band would become its own scrollport, the
     ::after would fill it exactly, and the progress would never leave zero. */
}
.hp-seam::after {
  content: "";
  position: absolute;
  /* A pixel past the bottom on purpose. The band's height is a vw value and
     lands on a fractional pixel; the section below it starts on a rounded
     one, and the sliver between the two let the ground *behind* the band show
     through as a hairline — white against the footer's black, which is where
     it was impossible to miss. The overhang is the same colour as the section
     it overlaps, so it costs nothing and can never be seen. */
  inset: 0 0 -1px;
  background: var(--hp-seam-below);
  /* flat, for anything that cannot read the scroll */
  clip-path: polygon(0 100%, 68.8% 100%, 100% 100%);
}

.hp-seam--grey-white { --hp-seam-below: var(--hp-white); }
.hp-seam--white-black { --hp-seam-below: #000; }

/* The break that fades arrives at its full angle the moment the boundary
   touches the foot of the screen, so the next section's ground is already
   deep into this one before the reader has had a chance to look at what is
   down there. It gets more tail to land on — one token, and every block that
   a seam follows picks it up through the rule below. The break that grows
   arrives straight and needs none of it.
   2026-09-15: in the window's height, not in pixels — tied to the same unit
   as the lag, what it covers is the same share of the window at any size. */
:root[data-bend="fade"] { --hp-tail: max(0px, calc(60vh - var(--hp-section-air))); }

/* Every block a seam follows closes on --hp-section-air plus the tail.
   (home.css also zeroes the bottom padding of last blocks that bring their
   own — carousel feet, the forge loop; those page-specific exceptions live
   with their section modules, not here.) */
section:has(+ .hp-seam) { padding-bottom: calc(var(--hp-section-air) + var(--hp-tail)); }

/* ── the seam that carries the banner's photograph ───────────────────
   Every other seam paints a flat colour, because the section under it is a
   flat colour. The CTA banner is a photograph, so this one clips a picture
   instead. The clip-path and its animation move off the ::after and onto the
   element itself, because the picture is a child and a parent's clip-path
   clips its descendants. The element keeps the band's exact box, so `view()`
   resolves over the same window the other seams use.
   The 1px is the same overhang the ::after carried, given back as a negative
   margin so the layout is unmoved. */
.hp-seam--cta {
  height: calc(var(--hp-seam-swing) + 1px);
  margin-bottom: -1px;
  background: var(--hp-ink);   /* what shows until the photograph is decoded */
  clip-path: polygon(0 100%, 68.8% 100%, 100% 100%);
}
/* The banner lays a 60% black wash over its photograph; the wedge has to lay
   the same one over its half of it. The ::after is the wash rather than the
   flat colour it paints on every other seam — it is the last box in the
   element, so it is over the <img> without either of them needing a z-index. */
.hp-seam--cta::after {
  inset: 0;
  background: rgba(0, 0, 0, .6);
}
/* The picture's box is the wedge plus the banner, pinned to the wedge's top —
   exactly the box .hp-cta__shot is given in the CTA module, so the same
   `cover` crop lands in both and the join is invisible. */
.hp-seam--cta > img {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: calc(100% + var(--hp-cta-box));
  object-fit: cover;
}
/* …and the bend that rises through the banner's tail is cut to fit it:
   exactly as deep as the empty band it rises through, so nothing of the
   banner is ever under it. (Companion rule in the CTA section module:
   `.hp-cta:has(+ .hp-seam) { min-height: var(--hp-cta-box);
    padding-bottom: calc(var(--hp-cta-tail) - var(--hp-gutter)); }`.) */
.hp-cta + .hp-seam { --hp-seam-swing: var(--hp-cta-tail); }

/* ── the scroll-driven bend (Chromium; flat edge elsewhere) ───────────── */
@supports (animation-timeline: view()) {
  .hp-seam::after {
    animation: hp-seam-grow linear both;   /* the name is swapped per version */
    animation-timeline: view();
    animation-range: contain 0% exit 100%;
  }
  /* Two versions of the break, chosen by html[data-bend].

     grow: the boundary arrives straight and bends further the higher it
           climbs, reaching full angle as it leaves the top.
     fade: it arrives already at full angle and straightens as it climbs,
           flat by the time it reaches the top.

     Both run over the same window: `contain 0%` is the instant the band's
     bottom edge — the boundary itself — reaches the foot of the screen, and
     `exit 100%` is the instant it reaches the top. `cover` would have
     started the bend a band's height early, with the wedge poking into view
     before the boundary. */
  :root[data-bend="grow"] .hp-seam::after { animation-name: hp-seam-grow; }
  :root[data-bend="fade"] .hp-seam::after { animation-name: hp-seam-fade; }

  /* the picture-carrying seam bends on the element, not on the ::after */
  .hp-seam--cta {
    animation: hp-seam-grow linear both;
    animation-timeline: view();
    animation-range: contain 0% exit 100%;
  }
  :root[data-bend="grow"] .hp-seam--cta { animation-name: hp-seam-grow; }
  :root[data-bend="fade"] .hp-seam--cta { animation-name: hp-seam-fade; }

  @keyframes hp-seam-grow {
    from { clip-path: polygon(0 100%, 68.8% 100%, 100% 100%); }
    to   { clip-path: polygon(0 100%, 68.8% calc(100% - var(--hp-seam-swing)), 100% 100%); }
  }
  @keyframes hp-seam-fade {
    from { clip-path: polygon(0 100%, 68.8% calc(100% - var(--hp-seam-swing)), 100% 100%); }
    to   { clip-path: polygon(0 100%, 68.8% 100%, 100% 100%); }
  }
}

/* ── overlap mode: the last block slows down and the next one rides over it ─
   Geometry identical to the plain mode — same band, same bend, same spacing.
   The only difference is that the section above falls behind the scroll
   while the one below is arriving, so the two overlap by however far it has
   fallen.

   z-index rather than document order: a transform promotes its element into
   the positioned layer, where it would otherwise paint over the sections
   that follow it. Everything from the first seam down is lifted with it, and
   among equals the document order decides again. */
:root[data-seam="overlap"] .hp-seam,
:root[data-seam="overlap"] .hp-seam + :is(section, footer) { z-index: 1; }
:root[data-seam="overlap"] .hp-seam + :is(section, footer) { position: relative; }

@supports (animation-timeline: view()) {
  :root[data-seam="overlap"] section:has(+ .hp-seam) {
    /* THE KNOB: the speed the section holds while the one below it is coming
       up the screen. Not a speed it falls to — a speed it is at, from the
       first pixel of the next section to the last.

       The window is one viewport of scroll, so a section moving at S covers
       S viewports while the page covers one, and the difference is what the
       next section rides over: (1 - S) × 100vh. */
    --hp-seam-slow: .6;
    /* …and never further than 360, whatever the window. The lag is in vh, so
       a tall window fell further behind — 1040px on a 2560 × 1300 screen —
       and the bend below climbed over the last rows of the section. 360 is
       inside the ~390 of clear room every section keeps above the bend's
       apex, so the ride-over still reads and no longer covers text.
       (2026-09-15: was .2 uncapped — 80vh.) */
    --hp-seam-lag: min(calc((1 - var(--hp-seam-slow)) * 100vh), 360px);
    animation: hp-seam-lag linear both;
    animation-timeline: view();
    /* Named ranges only, no calc. `contain 0%` is the instant this section's
       bottom edge — which is the next section's top edge — reaches the foot
       of the window: the first pixel of the next section. `exit 100%` is the
       instant that same edge reaches the top. Between them the edge crosses
       exactly one viewport, whatever the section's height.

       This used to be `exit calc(100% - 100vh) exit 100%`, which is the same
       window arithmetically but asks the engine to resolve a percentage of a
       phase against a viewport unit. If that calc does not resolve, both ends
       collapse onto `exit 100%`, the range has zero length, and the animation
       sits on its `fill` value — translateY(0) — for the whole page. Which is
       indistinguishable from no animation at all. */
    animation-range: contain 0% exit 100%;
  }
  /* Two keyframes and linear, which is what a constant speed is: the moment
     a pixel of the next section shows, this one is already at its held speed. */
  @keyframes hp-seam-lag {
    from { transform: translateY(0); }
    to   { transform: translateY(var(--hp-seam-lag)); }
  }

  /* …but only under the break that fades. Grow already spends that window
     doing something: it arrives flat and bends to full angle as it climbs,
     and the angle is the event. Holding the section back at the same time
     gives the eye two things changing at once and the bend stops reading as
     the cause.

     (0,3,1) over the (0,2,1) that sets it, so this is a clean switch-off, not
     a competing value. The knob above stays exactly as it was. */
  :root[data-seam="overlap"][data-bend="grow"] section:has(+ .hp-seam) {
    animation: none;
    transform: none;
  }
}

/* A bend tied to the scroll is the kind of movement that reads worst when
   movement is unwelcome, so it flattens rather than slows — and the parallax
   goes with it. */
@media (prefers-reduced-motion: reduce) {
  .hp-seam::after, .hp-seam--cta { animation: none; }
  :root[data-seam="overlap"] section:has(+ .hp-seam) { animation: none; transform: none; }
}

/* ── footer wordmark ─────────────────────────────────────────────────
   The base sizing rule for the wordmark <img> (from the footer block of
   home.css) plus its light-up. */
.hf__word { width: 100%; height: auto; margin-top: 34px; }

/* The wordmark lights up as the reader arrives at it: black while it is
   coming into view, white by the time the page has nothing left to give.

   Driven by the scroll position itself rather than by script — a view()
   timeline is resolved by the compositor, so this costs nothing on the main
   thread.

   The hold to 45% is the point of it: on a straight ramp the mark is already
   half-lit early; held, it is genuinely black until the reader is nearly at
   the end.

   Guarded, and the initial opacity lives inside the guard: without support
   there is no timeline to run the animation, and an unguarded `opacity: 0`
   would leave the mark invisible for good. */
@supports (animation-timeline: view()) {
  .hf__word {
    opacity: 0;
    animation: hf-word-in linear both;
    animation-timeline: view();
    /* from its top edge entering the foot of the window to its bottom edge
       clearing it — which, being the last thing on the page, is the bottom */
    animation-range: entry 0% entry 100%;
  }

  @keyframes hf-word-in {
    0%   { opacity: 0; }
    45%  { opacity: 0; }
    100% { opacity: 1; }
  }

  @media (prefers-reduced-motion: reduce) {
    .hf__word { opacity: 1; animation: none; }
  }
}

/* ═════════════════════════════════════════════════════════════════════
   USAGE (Webflow)
   1. Set the modes once on <html> via Site settings → Custom code (head):
        <script>
          document.documentElement.dataset.bend = 'grow';
          document.documentElement.dataset.seam = 'overlap';
        </script>
      (Or bake the attributes into the html tag if your export allows:
       <html data-bend="grow" data-seam="overlap">.)
      Omit data-seam for the simpler no-overlap mode. data-bend="grow" is
      the baked default — without the attribute the seams still grow.
   2. Between every pair of adjacent sections, add one div:
        <div class="hp-seam hp-seam--grey-white"></div>
      choosing the variant whose colour matches the section BELOW the seam
      (default: --hp-grey; --grey-white → white; --white-black → black).
   3. Above the CTA banner, use the photograph seam instead:
        <div class="hp-seam hp-seam--cta">
          <img src="(same image as the banner background)" alt="">
        </div>
      and give the banner section the companion sizing rule noted at
      `.hp-cta + .hp-seam` above.
   4. Sections that a seam follows must be plain flowing <section> elements
      (the `section:has(+ .hp-seam)` spacing rule relies on it), and no
      ancestor of the seams may create a scroll container (overflow other
      than visible), or the view() timelines never leave zero.
   ═════════════════════════════════════════════════════════════════════ */
