/* Hero — Figma 1:1271 (sticky video, 640x853) + 1:1276 (headline + testimonials) */

/* The page scrolls inside .scroll; the video is pinned to the top of it and the
   content rides over it, which is what the Figma frame Sticky-Video-hero means. */
.scroll { position: relative; }

/* How far down the page the clip sits. She read as too high against the
   headline, so the whole clip is dropped by this much: once in the flow, and
   again as the sticky offset so she holds the same height when pinned. The
   scrim lives inside the clip and travels with her; the veil and the blur stay
   anchored to the text, which does not move. */
:root { --hero-drop: 58px; }

/* Sticky-Video-hero (1:1271). The video is pinned while the headline and the
   testimonials ride over it, then the range ends and it scrolls away. */
.hero-sticky-range {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 100%; /* the shadow stays behind the page wherever you are */
  z-index: 0;
  pointer-events: none;
}

.hero-sticky {
  position: sticky;
  top: var(--hero-drop);
}

.hero-media {
  /* No `position` here. .hero-sticky sets `sticky` and this rule is declared
     after it at equal specificity, so a `relative` here silently wins and the
     clip stops being pinned — the content then scrolls past it instead of over
     it. A sticky element is already a positioning context, so the ::after
     below anchors to it with nothing added. */
  width: var(--column);
  height: 853px;
  margin: var(--hero-drop) auto 0;
  overflow: hidden;
  /* The clip is composited against a CSS-painted page grey inside its own
     isolated group, so the flat part of the video is replaced by exactly
     var(--grey-background-100) no matter how the display colour-manages it. */
  background: var(--grey-background-100);
  isolation: isolate;
  overflow: hidden;
}

.hero-media video,
.hero-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* The video is a subject on a flat light backdrop. `darken` clamps every pixel
     lighter than the page to the page colour, so the clip can never read as a
     lighter rectangle whatever the display does with the video's colour. */
  mix-blend-mode: darken;
  /* The sides are feathered so the 640 column draws no vertical boundary.
     The clip runs to full height: it used to fade out from 56% to 72%, which
     was there to hide the bottom edge of the baked overlay that used to be
     painted on top of it. That overlay is gone — a backdrop-filter blurs the
     clip in place now — so the fade did nothing but delete the very thing the
     filter is meant to blur, leaving flat grey to blur below 72%. That is why
     the blurred hero disappeared from the background. */
  -webkit-mask-image: linear-gradient(to right, transparent 0, #000 9%, #000 91%, transparent 100%),
                      linear-gradient(to bottom, transparent 0, #000 4%, #000 62%, rgba(0,0,0,0) 100%);
  -webkit-mask-composite: source-in;
  mask-image: linear-gradient(to right, transparent 0, #000 9%, #000 91%, transparent 100%),
              linear-gradient(to bottom, transparent 0, #000 4%, #000 62%, rgba(0,0,0,0) 100%);
  mask-composite: intersect;
}

/* The clip's last stretch is painted over with the page's own colour, from
   fully transparent to fully opaque. A mask can only fade the clip towards
   whatever is behind it, and whatever is behind it is never quite the page —
   the veil's fill sits in between. This ends ON #e7e7e7 rather than near it,
   so there is nothing left to see a difference against.

   It lives inside .hero-media, which is 853 tall with overflow hidden, so it
   travels with the pinned clip and stops with it. */
.hero-media::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 300px;
  pointer-events: none;
  background: linear-gradient(
    to bottom,
    rgba(231, 231, 231, 0) 0%,
    rgba(231, 231, 231, 0.85) 55%,
    var(--grey-background-100) 100%
  );
}

/* Gradiant (1:1273): 640x640 starting 221px down, transparent to page grey at
   70.787%. That is what dissolves her body into the background. */
.hero-scrim {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  top: 221px;
  width: var(--column);
  height: 640px;
  background: linear-gradient(
    to bottom,
    rgba(231, 231, 231, 0) 0%,
    rgba(231, 231, 231, 0.7) 70.787%  /* fitted against the Figma raster: neck/sweater within 3 */
  );
  pointer-events: none;
}

/* Background/Hero-Overlay (38:786), from Figma dev mode:
     background: linear-gradient(180deg, rgba(237,237,237,0) 0%, rgba(231,231,231,0.8) 5.82%);
     backdrop-filter: blur(50px);

   Split across two elements because the node is both page-tall and a filter,
   and those two want different things:

   - the range carries the fill. It is page-tall and static, so the 5.82% stop
     lands where Figma puts it, in page coordinates.
   - the child carries the blur. It is pinned and exactly one clip tall, so the
     filter never runs on a layer thousands of pixels high — which is the one
     real objection to backdrop-filter here, Chromium dropping hard-edged bands
     out of tall layers (LOG.md, 2026-08-08). One screen is safe.

   And the blur is a RAMP, not the flat blur(50px) dev mode prints: the effect
   in Figma is progressive, dev mode cannot express that, and taken literally
   it draws a hard edge across her where the filter starts. The ramp is built
   from layers inside this child — see progressive-blur.css.

   Painting the fill under the blur rather than over it is the one liberty
   taken. The fill is a smooth low-frequency wash, so blurring it changes
   nothing perceptible.

   NOTHING in this subtree may carry a mask, filter or opacity below 1: any of
   those makes the ancestor a backdrop root and the child's backdrop-filter
   then samples an empty backdrop and blurs nothing. That was the bug in the
   hero copy's blur, and the range used to carry a mask here for the same
   reason. The fill's own alpha ramp replaces it, which is what Figma does. */
.hero-veil-range {
  position: absolute;
  top: 420px;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 1;
  pointer-events: none;
  background: linear-gradient(
    180deg,
    rgba(237, 237, 237, 0) 0%,
    rgba(231, 231, 231, 0.55) 5.82%
  );
}

.hero-overlay {
  position: sticky;
  top: 0;
  /* 120 taller than the clip, deliberately. The clip's own bottom edge is a
     hard cut, and a blur only dissolves an edge it can sample across — if the
     layer stopped level with it, the edge would sit exactly on the layer
     boundary and stay crisp. Overshooting puts it inside the blurred region.
     The layer's own bottom edge is safe: below the clip the backdrop is flat
     page grey, and a blur of flat grey is flat grey. */
  margin-top: 300px;   /* begins where .veil-onset ends */
  height: 973px;
  /* the blur itself is a ramp of layers — see progressive-blur.css */
}


/* Hero-headline-testimonials (1:1276): sits over the video, blurred panel */
.hero-panel {
  position: relative;
  z-index: 2;
  width: 576px;
  display: flex;
  flex-direction: column;
  gap: var(--space-32);
  align-items: center;
  padding: var(--space-16);
  border-radius: 8px;
  /* No backdrop-filter here: in the Figma render the panel leaves no visible
     box, the softening comes from the Hero-Overlay behind it. */
}

.hero-headline {
  margin: 0;
  width: 100%;
  font-family: var(--font-headings);
  font-weight: var(--weight-book);
  font-size: var(--h1-size);
  line-height: var(--h1-line);
  color: var(--headline-ink);
  /* No white halo. The Figma puts a 34 blur behind this text — a 17px CSS
     radius — and it is deliberately not carried over: removed on the headlines
     first, then everywhere, because it reads as a smudge on a screen where in
     Figma it reads as separation. Whatever a text needs to sit on, it gets
     from what is behind it, not from a glow around each letter. */
}

.hero-testimonials {
  width: 100%;
  display: flex;
  flex-direction: column;
  gap: var(--space-16);
}

.testimonial-avatars {
  display: flex;
  gap: var(--space-16);
  align-items: flex-start;
}

/* Testimonial chip (36:705): 54px image inside a 4px ring */
.testimonial {
  position: relative;
  z-index: 0;
  display: flex;
  align-items: center;
  padding: var(--space-4);
  border: 1px solid var(--border-action);
  border-radius: var(--radius-full);
  flex-shrink: 0;
}

.testimonial img {
  width: 54px;
  height: 54px;
  border-radius: 100px;
  object-fit: cover;
  pointer-events: none;
}

/* Tooltip (41:820) — hidden in Figma, revealed on hover */
.testimonial-name {
  position: absolute;
  left: 50%;
  bottom: -34px;
  transform: translateX(-50%);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-4) var(--space-6);
  border-radius: var(--space-4);
  background: var(--surface-tooltip);
  backdrop-filter: blur(var(--blur-8));
  -webkit-backdrop-filter: blur(var(--blur-8));
  color: var(--primary-white);
  font-weight: var(--weight-regular);
  font-size: 14px;
  line-height: 18px;
  white-space: nowrap;
  opacity: 0;
  transition: opacity 260ms cubic-bezier(0.16, 1, 0.3, 1);
}

.testimonial:hover .testimonial-name,
.testimonial:focus-within .testimonial-name { opacity: 1; }

/* The hovered chip comes forward, otherwise the next avatar paints over its name */
.testimonial:hover,
.testimonial:focus-within { z-index: 5; }

.testimonial-name { z-index: 6; }

@media (prefers-reduced-motion: reduce) {
  .testimonial-name { transition-duration: 0.01ms; }
}

@media (max-width: 700px) {
  .hero-media { height: 70vh; }
  .hero-panel {
    width: 100%;
    margin-top: -220px;
    padding: var(--space-16);
  }
  .testimonial-avatars {
    gap: var(--space-6);
    overflow-x: auto;
    padding-bottom: var(--space-4);
  }
}

/* Hover zoom on the testimonial faces. Not in the Figma, added on request.
   The image scales inside a round clip so the ring itself never moves. */
.testimonial-media {
  display: block;
  width: 54px;
  height: 54px;
  border-radius: 100px;
  overflow: hidden;
  flex-shrink: 0;
}

.testimonial-media img {
  width: 100%;
  height: 100%;
  transition: transform 620ms cubic-bezier(0.16, 1, 0.3, 1);
  will-change: transform;
  transform: translateZ(0);
  backface-visibility: hidden;
}

.testimonial:hover .testimonial-media img,
.testimonial:focus-within .testimonial-media img {
  transform: scale(1.18) translateZ(0);
  transition-duration: 900ms;
}

@media (prefers-reduced-motion: reduce) {
  .testimonial-media img { transition: none; }
  .testimonial:hover .testimonial-media img,
  .testimonial:focus-within .testimonial-media img { transform: none; }
}
