/*  Leaf & Bloom — The Grove
 *  ---------------------------------------------------------------------------
 *  The one moment on the site that could not be lifted from another brand,
 *  because it is a literal construction of THIS logo: the arch draws itself,
 *  the tree grows inside it, the tree fades, and the real bottle is standing
 *  where the tree was.
 *
 *  Driven entirely by CSS scroll-driven animations. No JavaScript, no library,
 *  no scroll listener — the compositor runs it, so it costs nothing on a
 *  mid-range Android.
 *
 *  THE TRAP, written down so it is not walked into again: view-timeline-name
 *  goes on the tall runway section, NEVER on the sticky stage inside it.
 *  view() resolved against a sticky child measures a box that stays pinned to
 *  the viewport, so progress saturates at frame one and nothing ever animates.
 *
 *  THE RULE THAT MAKES IT SAFE: the default, un-animated state of every layer
 *  IS the final frame. A browser without support, a reader with reduced motion,
 *  and a phone below 900px all get that composition, static — and it has to be
 *  good on its own, or the showpiece was designed wrong.
 *  ------------------------------------------------------------------------- */

.grove {
  position: relative;
  background: var(--c-ground);
  color: var(--c-on-dark);
  /* Static by default. The runway is only granted where the animation runs. */
  padding-block: var(--section-y-lg);
}

.grove__stage {
  display: grid;
  place-items: center;
  text-align: center;
  gap: var(--sp-6);
}

/*  Side by side once there is room.
 *
 *  Stacked, the art (560px) and the copy (~300px) came to more than a 900px
 *  viewport, so the pinned stage clipped the headline off at the bottom. Side
 *  by side the stage is only as tall as the taller column — and an asymmetric
 *  pair reads better than one more centred stack anyway. */
@media (min-width: 900px) {
  .grove__stage {
    grid-template-columns: minmax(0, 42%) minmax(0, 1fr);
    gap: clamp(var(--sp-8), 6vw, var(--sp-11));
    place-items: center;
    text-align: left;
  }
  .grove__copy { justify-self: start; max-width: 34ch; }
  .grove__title { margin-inline: 0; }
  .grove__body  { margin-inline: 0; }
}

/* -- the art ------------------------------------------------------------- */
.grove__art {
  position: relative;
  width: min(420px, 78vw);
  /*  Capped against the viewport as well as the container: on a short laptop
   *  screen a 3:4 box 420px wide is taller than the pinned stage can show. */
  max-height: 64vh;
  aspect-ratio: 3 / 4;
  display: grid;
  place-items: end center;
}

.grove__arch,
.grove__tree,
.grove__bottle {
  grid-area: 1 / 1;
  width: 100%;
  height: 100%;
}

/* The arch: a 1px gold stroke. Non-scaling so it stays a hairline at any size. */
.grove__arch { fill: none; stroke: var(--c-gold-line); stroke-width: 1.2; vector-effect: non-scaling-stroke; }
.grove__arch path,
.grove__arch line { stroke-dasharray: var(--len, 1200); stroke-dashoffset: 0; }

/* The tree: drawn, and by the end of the sequence it has handed over. */
.grove__tree { fill: none; stroke: var(--c-leaf); stroke-width: 1.6; vector-effect: non-scaling-stroke; opacity: 0; }

/*  The bottle: the real photograph, standing where the tree was.
 *
 *  It is clipped to the arch rather than dropped inside it as a rectangle.
 *  A photograph with its own marble background pasted into the arch reads as
 *  two images stacked; cut to the same shape, the arch becomes the window the
 *  product is standing in — which is the whole idea.
 *
 *  The radius matches the arch path in the SVG: the arc springs at 57% of the
 *  height, so the vertical radius is 43% and the horizontal is a half. */
.grove__bottle {
  align-self: end;
  justify-self: center;
  width: 73%;                 /* the arch's interior width: 220 of 300 units */
  height: 84%;
  object-fit: cover;
  object-position: center 42%;
  border-radius: 50% 50% 0 0 / 43% 43% 0 0;
  margin-bottom: 0;
}

/*  The Grove sits on the deep ground in both themes, where the plain gold
 *  measured 3.34:1. The bright gold is the one made for these grounds: 6.21. */
.grove__eyebrow { color: var(--c-gold-bright); }
.grove__line {
  font-family: var(--ff-display);
  font-style: italic;
  font-size: var(--fs-h2);
  color: var(--c-gold-line);
  line-height: var(--lh-snug);
}
.grove__title {
  font-family: var(--ff-display);
  font-size: var(--fs-h2-lead);
  font-weight: 500;
  color: var(--c-on-dark);
  line-height: var(--lh-tight);
  max-width: 16ch;
}
/*  The sentence sat directly under the last line of a 62px heading with no
 *  gap at all, so "you can read" and "Everything we make" read as one block.
 *  A real step between them, and the body a size up so it holds its own
 *  against the heading on a dark ground rather than whispering under it. */
.grove__body { margin-top: var(--sp-5); font-size: var(--fs-lead); line-height: var(--lh-copy); color: color-mix(in srgb, var(--c-on-dark) 82%, transparent); max-width: 40ch; }
.grove__cta { margin-top: var(--sp-6); }

/* -- the scroll-driven version -------------------------------------------
 *  Everything above is the finished frame. Everything below only applies where
 *  the browser can run a scroll timeline AND the viewport is tall enough AND
 *  the reader has not asked for less motion.
 *  ---------------------------------------------------------------------- */
@supports (animation-timeline: view()) {
  @media (min-width: 900px) and (prefers-reduced-motion: no-preference) {

    /*  The runway. The timeline is named HERE, on the tall scrolling box —
     *  never on the sticky stage. */
    .grove {
      padding-block: 0;
      /*  The stage pins for one viewport and the sequence plays across the
          remaining screen. This was 200vh, which on a 1000px window left a
          900px corridor of nothing below the pinned stage — measured, the
          worst px-per-fact block on the homepage after the pull quotes, and
          the owner named it: "ya bhi bohut bara hy".

          175vh, not lower, and the number is set by a test rather than by
          taste: tools/test-grove.js asserts a runway over 1500px at its
          900px viewport, because below that the scroll-driven sequence has
          no room to play and the arch stroke never moves. 175vh is 1575px
          there — 75px of margin. 140vh was tried first and failed exactly
          that assertion at 1260px. Every keyframe is a percentage of the
          view-timeline, so the whole sequence simply plays proportionally
          faster; no step is lost. */
      height: 175vh;
      view-timeline-name: --grove;
      view-timeline-axis: block;
    }

    /*  The stage pins for exactly one viewport. Nothing pins longer: a section
     *  that holds the screen hostage past one screen-height is where scroll
     *  storytelling starts costing more than it gives. */
    .grove__stage {
      position: sticky;
      top: 0;
      height: 100vh;
      align-content: center;
    }

    /*  On the timing below. The stage is two columns: art on the left, words on
     *  the right. An earlier version held every word back to 62% of the runway
     *  so the picture could speak first — which read well on a laptop, where a
     *  reader crosses the runway in a second or two, and badly on anything
     *  larger. At 1920x1080 that is roughly 1,340px of scrolling with the whole
     *  right-hand column empty, and the section reads as a broken page rather
     *  than a held breath.
     *
     *  So the order still stands — arch, tree, bottle, words — but the heading
     *  now arrives alongside the tree instead of after it. Nothing waits on an
     *  empty half-screen, and the finished frame is held for the last third,
     *  which is the part worth looking at. */

    /* 1. The arch draws itself. */
    .grove__arch path,
    .grove__arch line {
      animation: grove-draw linear both;
      animation-timeline: --grove;
      animation-range: entry 12% contain 14%;
    }

    /* 2. The tree grows inside it, from the trunk up. */
    .grove__tree {
      animation: grove-grow linear both;
      animation-timeline: --grove;
      animation-range: contain 8% contain 34%;
    }

    /* 3. The tree hands over. */
    .grove__tree-out {
      animation: grove-fade linear both;
      animation-timeline: --grove;
      animation-range: contain 38% contain 50%;
    }

    /* 4. The real bottle is standing where the tree was. */
    .grove__bottle {
      animation: grove-arrive linear both;
      animation-timeline: --grove;
      animation-range: contain 40% contain 58%;
    }

    /* 5. The words, led by the heading, which comes in with the tree. */
    .grove__copy > * {
      animation: grove-rise linear both;
      animation-timeline: --grove;
      animation-range: contain 20% contain 38%;
    }
    .grove__copy > :nth-child(2) { animation-range: contain 28% contain 46%; }
    .grove__copy > :nth-child(3) { animation-range: contain 36% contain 54%; }
    .grove__copy > :nth-child(4) { animation-range: contain 44% contain 62%; }
  }
}

@keyframes grove-draw {
  from { stroke-dashoffset: var(--len, 1200); opacity: .35; }
  to   { stroke-dashoffset: 0; opacity: 1; }
}
@keyframes grove-grow {
  from { opacity: 0; clip-path: inset(100% 0 0 0); }
  to   { opacity: 1; clip-path: inset(0 0 0 0); }
}
@keyframes grove-fade {
  from { opacity: 1; }
  to   { opacity: 0; }
}
@keyframes grove-arrive {
  from { opacity: 0; transform: translateY(14px) scale(.97); }
  to   { opacity: 1; transform: none; }
}
@keyframes grove-rise {
  from { opacity: 0; transform: translateY(var(--rise-sm)); }
  to   { opacity: 1; transform: none; }
}

/*  Belt and braces. If any of the above ever runs where it should not, this
 *  puts every layer back to the finished frame rather than a half-drawn one. */
@media (prefers-reduced-motion: reduce) {
  .grove { height: auto; padding-block: var(--section-y-lg); }
  .grove__stage { position: static; height: auto; }
  .grove__arch path, .grove__arch line { stroke-dashoffset: 0; opacity: 1; }
  .grove__tree { opacity: 0; }
  .grove__bottle { opacity: 1; transform: none; }
  .grove__copy > * { opacity: 1; transform: none; }
}
