/* ==========================================================================
   HERO
   Measured against a 1280 x 832 Figma frame. Every length is written as its
   design-pixel number multiplied by --u, so the numbers here match the design
   one for one and the whole composition scales as a unit.

   The copy is centred and the card deck is gone. At rest the call to action
   is only a button, standing on a floor of drifting suds. On scroll that same element
   becomes the squeegee: it stretches into a full-width blade, grows a handle
   proportioned to its new size, and pulls down the floor - clearing the suds
   and leaving the next section's background behind it. Nothing is ever
   duplicated on top of anything else, which is what keeps it in true at any
   zoom.
   ========================================================================== */

.hero {

  position: relative;
  display: flex;
  flex-direction: column;
  /* The pinned hero has to cover the window in BOTH mobile toolbar states.
     `svh` is the SMALL viewport - the height with the address bar showing - so
     a hero sized to it is pinned at that height, and the moment the bar
     retracts on the first scroll the window grows underneath it and the
     section behind shows through the strip it no longer reaches. `lvh` is the
     large viewport, so the hero covers with the bar retracted and simply runs
     a little under it while it is showing. svh first as the fallback for
     anything without lvh. */
  min-height: 100svh;
  min-height: 100lvh;
  /* The header is fixed chrome now and no longer a child here, so its height is
     reserved instead. `.hero__inner` centres itself with auto margins, and
     without this it would centre in the whole section and sit lower than the
     design has it. 20u of header padding plus a 55u mark. */
  padding-top: calc(75 * var(--u));
  overflow: hidden;
}

/* --------------------------------------------------------------------------
   Copy - centred in the space left by the header
   -------------------------------------------------------------------------- */

/* Deliberately no z-index: that would trap the copy and the button in one
   stacking context, and the paint has to slide between them - over the title,
   under the blade. Each child carries its own layer instead. */
.hero__inner {
  position: relative;
  margin-block: auto;
  padding-bottom: calc(60 * var(--u));   /* optical centre, not mathematical */
  text-align: center;
}

.hero__title {
  position: relative;
  z-index: 3;   /* under the paint, so the stroke wipes it */
  max-width: calc(680 * var(--u));
  margin-inline: auto;
  font-family: var(--font-body);
  font-weight: var(--fw-semibold);
  font-size: calc(65 * var(--u));
  line-height: 1;
  letter-spacing: 0.01em;
  color: var(--c-text);
  text-wrap: initial;
}

.hero__title em {
  font-family: var(--font-accent);
  font-style: italic;
  font-weight: var(--fw-bold);
  color: var(--c-primary);
}

.hero__subtitle {
  position: relative;
  z-index: 3;   /* under the paint, so the stroke wipes it */
  /* Left-aligned block, centred on the page - not centred text. */
  width: calc(275 * var(--u));
  margin: calc(32 * var(--u)) auto 0;
  font-size: calc(22 * var(--u));
  line-height: 1.05;
  letter-spacing: 0.05em;
  text-align: left;
  color: rgb(43 28 18 / 0.62);   /* 4.32:1 at 0.6, a hair under the 4.5 floor */
}

/* Flex rather than a text-aligned line box, so the row is exactly as tall as
   the tool, so the handle can hang off its bottom edge at `top: 100%`.
   Above the paint, because the button is the blade doing the painting. */
.hero__actions {
  position: relative;
  z-index: 5;
  display: flex;
  justify-content: center;
  margin-top: calc(51 * var(--u));
}

/* The tool. Only the wrapper travels, so the handle is welded to the blade by
   construction rather than by animating the same distance onto both. Its own
   box stays the button's size all the way through - the head is stretched with
   a transform, which leaves layout alone - so the handle stays centred on the
   screen without ever being measured. */
.hero__tool {
  position: relative;
  display: flex;   /* not a block: a line box would add descender space below
                      the button, and the handle hangs off `top: 100%` */
}

/* The handle. Hidden until the head stretches: at rest this is a button and
   nothing else.

   Proportioned against the blade's THICKNESS, not its length. A real squeegee's
   handle runs about 63% of its head, but that head is roughly 12 times longer
   than it is thick; ours spans the whole screen at 26 times, so 63% of length
   would be a handle taller than the viewport. Against thickness the reference
   works out at handle 8x, grip 1.8x, saddle 5x - which is what these numbers
   are, and why the tool still reads as the same object at any width.

   Centred by auto margins, deliberately not by translateX(-50%): GSAP bakes
   whatever transform it finds into pixels when it takes over, and a -50% frozen
   as px is correct at exactly one scale. The negative left/right give the auto
   margins room to centre a box wider than the button it hangs from - without
   them an over-wide absolute box gives up and aligns left. */
.hero__handle {
  position: absolute;
  top: 100%;
  left: -100%;
  right: -100%;
  display: block;
  width: calc(250 * var(--u));
  max-width: none;   /* the base reset caps svg at 100%, which would clamp the
                        handle to the button's width and letterbox the drawing */
  height: calc(408 * var(--u));
  margin-inline: auto;
  /* The button orange's own hue, deeper. The rust it replaced sat at hue 20
     against the button's 26 and read as a different material; this is the same
     colour in shadow, far enough from the blade (1.76:1) to read as its own
     part, and 5.0:1 against the cream it hangs over. */
  fill: #ae5109;
  opacity: 0;
}

/* At rest this is a button and nothing more; the rubber along its bottom edge
   reads as a button's own shadow until the moment it becomes a wiping edge. On
   scroll this very element stretches to full width and makes the stroke - there
   is no second blade to hand over to, and so nothing that can drift out of
   register with it when the page is zoomed. */
.hero__cta {
  position: relative;
  overflow: hidden;
  display: inline-block;
  padding: calc(10 * var(--u)) calc(31.7 * var(--u)) calc(14 * var(--u));
  border-radius: calc(5 * var(--u));
  background-color: var(--c-primary);
  color: var(--c-bg);
  font-weight: var(--fw-semibold);
  font-size: calc(25 * var(--u));
  line-height: 1;
  letter-spacing: 0.01em;
  transition: background-color 0.25s var(--ease-out);
}

/* Colour only. The lift this used to have was a transform, and the stretch
   leaves an inline transform on this element that a stylesheet cannot beat. */
.hero__cta:hover {
  background-color: #d76208;
}

.hero__cta::after {
  content: '';
  position: absolute;
  inset: auto 0 0 0;
  height: 22%;   /* the rubber; thins with the head as it stretches */
  background-color: #ae5109;   /* the handle's shade, so the tool reads as one piece */
}

/* --------------------------------------------------------------------------
   Suds - the wet floor the squeegee is there to clear
   Behind everything (z-index 1), so the copy reads over it and the stroke's
   paint (z-index 4) covers it completely. Bubbles are built in JS, which is
   also what keeps them out of a no-script page.
   -------------------------------------------------------------------------- */

.suds {
  position: absolute;
  inset: 0;
  z-index: 1;
  overflow: hidden;
  pointer-events: none;
}

/* A film of water rather than a hard edge - the bubbles sit in it. */
.suds::after {
  content: '';
  position: absolute;
  inset: 40% 0 0 0;
  background: linear-gradient(to bottom,
    rgb(242 110 9 / 0) 0%,
    rgb(242 110 9 / 0.035) 55%,
    rgb(242 110 9 / 0.07) 100%);
}

/* Highlight up and left, thin warm rim, soft bloom along the lower edge: enough
   to read as a soap bubble at 12px without competing with the headline. */
.suds__bubble {
  position: absolute;
  border-radius: 50%;
  background: radial-gradient(circle at 33% 29%,
    rgb(255 255 255 / 0.95) 0%,
    rgb(255 255 255 / 0.5) 36%,
    rgb(255 255 255 / 0.08) 66%,
    rgb(255 255 255 / 0) 78%);
  box-shadow:
    inset 0 0 0 1px rgb(242 110 9 / 0.18),
    inset 0 calc(-2 * var(--u)) calc(7 * var(--u)) rgb(255 255 255 / 0.65);
  will-change: transform, opacity;
}

/* --------------------------------------------------------------------------
   Squeegee - the paint only
   What the stroke has already wiped over. Anchored to the top of the glass,
   with its height driven in JS to the blade's own bottom edge. It sits between
   the copy (z-index 3) and the button-blade (z-index 5), so it covers the
   title, the subtitle and the logo on its way down while the blade stays in
   front of it. Height is the only measurement in the whole effect.
   -------------------------------------------------------------------------- */

.squeegee {
  position: absolute;
  inset: 0;
  z-index: 4;
  pointer-events: none;
}

/* Same colour as the next section, so the hand-off at the end of the pin is
   seamless. Zero height until the stroke starts, so nothing shows at rest. */
.squeegee__fill {
  position: absolute;
  inset: 0 0 auto 0;
  height: 0;
  background-color: var(--c-primary);
  will-change: height;
}

/* --------------------------------------------------------------------------
   Phones
   The squeegee stays - it is the signature moment and it works vertically.
   Only the type comes down: 65u is 47px at --u's floor, which is a lot of
   headline for a 360px window.
   -------------------------------------------------------------------------- */

@media (max-width: 700px) {
  .hero__title {
    max-width: none;
    padding-inline: calc(20 * var(--u));
    font-size: calc(48 * var(--u));
  }

  .hero__subtitle {
    width: auto;
    max-width: calc(320 * var(--u));
    text-align: center;
  }
}
