/* ==========================================================================
   Customers are searching — Figma frame-y 886→1779

   Layered on a pinned screen, not a static canvas:

     .gw-search__media    the footage, filling the pin edge to edge and top to
                          bottom — it is the screen, so it never letterboxes
     .gw-search__stage    heading, connectors and the five intent rows, on the
                          comp's 1440x813 canvas, centred in the space above
                          the bar
     .gw-search__footer   the black bar and the ball, sitting on the screen's
                          bottom edge, above the footage

   Two scaling units, never mixed up:
     --u   one comp pixel of WIDTH / SIZE. Drives x, widths, type, the ball.
     --vy  one comp pixel of HEIGHT. Equals --u normally; only while the pin is
           active on a short viewport does it compress, so the canvas seats
           above the bar without ever shrinking the type.
   Nothing here is a device pixel: every value is a multiple of one of the two.
   ========================================================================== */

.gw-search {
  position: relative;
  background: var(--gw-white);
  overflow: clip;            /* clip, not hidden: hidden would break position:sticky */
  container-type: inline-size;
}

.gw-search__pin {
  position: relative;
  overflow: clip;
  --u: 1px;                  /* exactly 1px at >=1440, so the canvas is pixel-exact */
  --vy: var(--u);
}
@container (max-width: 1439px) {
  .gw-search__pin { --u: calc(100cqw / 1440); }
}

/* ---- layer 0: the footage, filling the whole pin -------------------------
   Width is 100cqw rather than the stage's 1440 so it still bleeds edge to edge
   on wide screens — cqw, not vw, so a scrollbar can never push the page
   sideways. object-fit:cover means it fills whatever shape the pin is.       */
.gw-search__media {
  position: absolute;
  top: 0; bottom: 0;
  left: 50%;
  width: 100cqw;
  transform: translateX(-50%);
  overflow: hidden;
  z-index: 1;
  pointer-events: none;
}
.gw-search__video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 28% center;
}
/* the footage runs at full strength; only the text column gets a wash */
.gw-search__scrim {
  position: absolute;
  inset: 0;
  z-index: 1;
  background: linear-gradient(90deg,
    rgb(255 255 255 / 0) 0%,
    rgb(255 255 255 / 0) 42%,
    rgb(255 255 255 / 0.55) 56%,
    rgb(255 255 255 / 0.80) 68%,
    rgb(255 255 255 / 0.86) 100%);
}

/* ---- the comp canvas: 1440 x 813, everything above the bar ---------------- */
.gw-search__stage {
  position: relative;
  width: 100%;
  max-width: 1440px;
  margin-inline: auto;
  height: calc(813 * var(--vy));
  z-index: 2;
}
.gw-search__stage > * { position: absolute; }

/* ---- golf pattern (Figma 91:17 — x=-3, rel y=384, 1447x814) -------------- */
.gw-search__bg {
  position: absolute;
  top: calc(384 * var(--vy)); left: calc(-3 * var(--u));
  width: calc(1447 * var(--u)); height: calc(814 * var(--vy));
  overflow: hidden;
  /* Figma paints the pattern first, under a cut-out golfer, so it shows around
     him. Our stand-in is a filled video frame, so underneath it would vanish
     entirely — it rides on top instead and multiplies, which lets the dots read
     against the white ground while leaving the figure itself untouched. */
  z-index: 2;
  mix-blend-mode: multiply;
  pointer-events: none;
  /* Figma paints a white→transparent gradient over the pattern, top to bottom */
  -webkit-mask-image: linear-gradient(180deg, transparent 0%, #000 22%);
          mask-image: linear-gradient(180deg, transparent 0%, #000 22%);
}
.gw-search__bg img {
  width: 100%; height: 100%; object-fit: cover; opacity: 0.7;
  filter: invert(1) brightness(2.2) invert(1);   /* same lift as the hero */
}

/* ---- the designer's connectors ------------------------------------------
   Vectors 91:79, 91:80, 279:1246, 279:1247, 279:1248, traced from the render.
   preserveAspectRatio="none" makes the viewBox track --vy exactly, so a line
   stays glued to its row's centre even when the pin compresses vertically;
   non-scaling-stroke keeps the hairline a hairline while that happens.       */
.gw-search__links {
  top: 0; left: 0;
  width: calc(1440 * var(--u));
  height: calc(813 * var(--vy));
  z-index: 5;
  pointer-events: none;
  overflow: visible;
}
.gw-search__link {
  stroke: var(--gw-ink);
  stroke-width: 1;
  fill: none;
  vector-effect: non-scaling-stroke;
}

/* ---- heading (91:62 rel y=72, 91:63 rel y=197) --------------------------- */
.gw-search__head {
  top: calc(72 * var(--vy)); left: calc(298 * var(--u));
  width: calc(836 * var(--u));
  z-index: 6;
}
.gw-search__title {
  width: 100%;
  margin: 0;
  display: flex; flex-direction: column;
  text-align: center;
  font-family: var(--gw-font-display);
  font-weight: 400;
  font-size: calc(36 * var(--u));
  line-height: calc(50.4 * var(--u));
}
.gw-search__title-a { color: var(--gw-violet); }
.gw-search__title-b { color: var(--gw-black); }


/* ---- the five intent rows -----------------------------------------------
   Row n sits at 332 + 90n (the comp's exact pitch), is 40 tall, and starts at
   x=736. Inside it: a 2-wide violet rule, a 71-wide wash fading out under the
   first word, then the text at x=767. Rows are placed individually rather than
   with a flex gap so the pitch survives vertical compression untouched.      */
.gw-search__intents {
  top: 0;
  left: calc(736 * var(--u));
  width: calc(620 * var(--u));
  height: calc(813 * var(--vy));
  z-index: 6;
}
.gw-search__intent {
  position: absolute;
  left: 0;
  top: calc((332 + 90 * var(--i)) * var(--vy));
  height: calc(40 * var(--vy));
  width: 100%;
  display: flex;
  /* the comp seats its 26-tall text box 4 below the 40-tall bar, not centred —
     consistent across all five rows, so it is intent, not drift */
  align-items: flex-start;
  padding: calc(4 * var(--vy)) 0 0 calc(31 * var(--u));
  /* wash starts just past the rule and dies out at the group's 73 edge */
  background-image: linear-gradient(90deg, rgb(109 40 217 / 0.09), rgb(109 40 217 / 0));
  background-repeat: no-repeat;
  background-position: calc(2 * var(--u)) 0;
  background-size: calc(71 * var(--u)) 100%;
}
/* the violet rule */
.gw-search__intent::after {
  content: '';
  position: absolute;
  left: 0; top: 0;
  width: calc(2 * var(--u));
  height: 100%;
  background: var(--gw-violet);
}
/* the connector's terminating dot, carried by the row so the two can never
   drift apart (Figma draws it at x=704, i.e. 32 back from the group edge) */
.gw-search__intent::before {
  content: '';
  position: absolute;
  left: calc(-35 * var(--u));
  top: 50%;
  width: calc(6 * var(--u)); height: calc(6 * var(--u));
  margin-top: calc(-3 * var(--u));
  border-radius: 50%;
  background: var(--gw-ink);
}
.gw-search__intent-text {
  font-family: var(--gw-font-display);
  font-weight: 400;
  font-size: calc(20 * var(--u));
  line-height: calc(26 * var(--u));
  color: var(--gw-black);
  white-space: nowrap;
}

/* ---- the bottom bar: black bar (91:82) + ball (91:71), over the footage ---
   Both are centred off the canvas midline rather than transformed into place,
   because the scroll choreography owns their transform.                      */
.gw-search__footer {
  position: relative;
  width: 100%;
  height: calc(80 * var(--u));
  z-index: 7;
}
.gw-search__bar {
  position: absolute;
  left: 50%;
  margin-left: calc(-526.5 * var(--u));   /* 1053 wide, centred like the comp */
  width: calc(1053 * var(--u));
  height: 100%;
  display: flex; align-items: center; justify-content: center;
  padding: calc(24 * var(--u)) calc(10 * var(--u));
  background: var(--gw-black);
}
.gw-search__bar p {
  font-family: var(--gw-font-display);
  font-weight: 400;
  font-size: calc(36 * var(--u));
  line-height: calc(32 * var(--u));
  color: var(--gw-white);
  text-align: center;
}

.gw-search__ball {
  position: absolute;
  left: 50%;
  margin-left: calc(565 * var(--u));      /* comp x=1285 on the 1440 midline */
  top: calc(8 * var(--u));
  width: calc(70 * var(--u)); height: calc(70 * var(--u));
  --sphere-frames: 30;
}
/* the roll is scroll-linked, so no CSS animation on this one */
.gw-motion .gw-search__ball .gw-sphere__film { animation: none; }

/* ==========================================================================
   Motion layer — only when JS adds .gw-motion. No JS / reduced motion /
   ?nomotion all fall back to the fully-revealed comp above.
   ========================================================================== */

.gw-search.is-pinned { height: 440svh; }   /* room for the lead-in beat */
.gw-search.is-pinned .gw-search__pin {
  position: sticky;
  top: 0;
  height: 100svh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  /* reserve the bar's strip: the canvas centres in what is left, while the
     footer is positioned against the padding box and so still sits flush */
  padding-bottom: calc(80 * var(--u));
  /* the canvas has to seat above the bar; only then does it compress */
  --vy: min(var(--u), calc((100svh - 80px) / 813));
}
.gw-search.is-pinned .gw-search__footer {
  position: absolute;
  left: 0; right: 0; bottom: 0;
}

.gw-motion .gw-search__link {
  stroke-dasharray: 1;
  stroke-dashoffset: calc(1 - var(--draw, 0));
}

/* row, rule, wash and dot arrive together as one beat; the text carries the
   blur-and-slide so the dot does not smear with it */
.gw-motion .gw-search__intent {
  opacity: var(--reveal, 0);
  background-size: calc(71 * var(--u) * var(--reveal, 0)) 100%;
}
.gw-motion .gw-search__intent::after { transform: scaleY(var(--reveal, 0)); }
.gw-motion .gw-search__intent-text {
  opacity: calc(0.1 + 0.9 * var(--reveal, 0));
  filter: blur(calc((1 - var(--reveal, 0)) * 3px));
  transform: translateX(calc((1 - var(--reveal, 0)) * 28 * var(--u)));
  will-change: opacity, filter, transform;
}

.gw-motion .gw-search__bar {
  opacity: var(--bar, 0);
  transform: translateY(calc((1 - var(--bar, 0)) * 24 * var(--u)));
}
.gw-motion .gw-search__ball {
  opacity: var(--ball-in, 0);
  transform: translateX(calc(var(--ball-travel, 0) * var(--u)));
}

/* ==========================================================================
   Responsive: below 1200 the absolute canvas becomes an ordinary stacked
   block. Connectors are dropped — they only mean anything beside the footage.
   ========================================================================== */
@media (max-width: 1199px) {
  .gw-search.is-pinned { height: auto; }
  .gw-search.is-pinned .gw-search__pin,
  .gw-search__pin {
    position: static;
    height: auto;
    display: block;
    padding-bottom: 0;
    --vy: var(--u);
  }
  .gw-search__stage {
    width: 100%; height: auto;
    padding: clamp(2.5rem, 6vw, 4rem) var(--gw-gutter) clamp(2rem, 5vw, 3rem);
    display: flex; flex-direction: column; align-items: center;
    gap: clamp(1.5rem, 3.5vw, 2.5rem);
  }
  .gw-search__stage > * { position: static; }
  /* decorative layers must stay out of the flow — as a flex item the pattern
     would sit at the top of the column as a several-hundred-pixel spacer */
  .gw-search__bg {
    position: absolute;
    inset: 0;
    width: 100%; height: 100%;
  }
  .gw-search__links { display: none; }   /* nothing to point at once stacked */
  /* the side-to-side scrim only works beside the footage; stacked, the text sits
     over the golfer, so veil the whole frame and let him read as a ghost */
  .gw-search__scrim {
    background: linear-gradient(180deg,
      rgb(255 255 255 / 0.92) 0%,
      rgb(255 255 255 / 0.88) 45%,
      rgb(255 255 255 / 0.94) 100%);
  }
  .gw-search__video { object-position: 32% 25%; }

  .gw-search__head { width: 100%; max-width: 44rem; }
  .gw-search__title { font-size: clamp(1.5rem, 4.2vw, 2.25rem); line-height: 1.25; }

  .gw-search__intents {
    width: 100%; max-width: 44rem; height: auto;
    display: flex; flex-direction: column; gap: clamp(0.75rem, 2vw, 1.25rem);
  }
  .gw-search__intent {
    position: static;
    width: 100%; height: auto;
    min-height: 2.5rem;
    padding-left: 1.25rem;
    background-position: 2px 0;
    background-size: 4.4375rem 100%;
  }
  .gw-search__intent::after { width: 2px; }
  .gw-search__intent::before { display: none; }   /* no line to terminate */
  .gw-search__intent-text {
    font-size: clamp(1rem, 2.4vw, 1.25rem);
    line-height: 1.35;
    white-space: normal;
  }
  .gw-motion .gw-search__intent { background-size: calc(4.4375rem * var(--reveal, 0)) 100%; }
  .gw-motion .gw-search__intent-text { transform: translateX(calc((1 - var(--reveal, 0)) * 1.25rem)); }

  /* the bar stays a bottom bar, just a stacked one */
  .gw-search.is-pinned .gw-search__footer,
  .gw-search__footer {
    position: relative;
    height: auto;
    padding: 0 var(--gw-gutter) clamp(1.5rem, 4vw, 2.5rem);
    display: flex; flex-direction: column; align-items: center;
    gap: clamp(1rem, 2.5vw, 1.5rem);
  }
  .gw-search__bar {
    position: static;
    margin-left: 0;
    width: 100%; max-width: 1053px; height: auto;
    padding: clamp(1rem, 2.5vw, 1.5rem) 1.25rem;
  }
  .gw-search__bar p { font-size: clamp(1.125rem, 3vw, 1.625rem); line-height: 1.2; }
  /* keep it positioned: .gw-sphere's film is absolute inside it, and a static
     ball would let the film size itself against the section instead */
  .gw-search__ball {
    position: relative;
    top: auto; left: auto; margin-left: 0;
    width: 3.5rem; height: 3.5rem;
    align-self: flex-end;
  }
}
