/* ============================================================================
   ASTROVE — commerce layer
   ----------------------------------------------------------------------------
   The four blocks a first-time Indian DTC shopper meets before any brand story:

     .hero-shop     what this is, what it costs, how to buy it
     .proof-strip   five claims, no prose
     .shop          First Harvest Trio ₹599 + three SKUs at ₹225, Add to Cart
     .faq           crawlable question/answer pairs (FAQPage JSON-LD twin)

   Kept out of landing.css deliberately. landing.css is the editorial system and
   was pruned to pixel-parity on 2026-08-19; growing it again would undo that.
   These four blocks also map 1:1 onto Shopify sections, so they need to lift out
   of this file cleanly when the theme is built.

   Every colour here is a token from tokens.css. Nothing new is invented.
   ============================================================================ */

/* ============================================================================
   STOREFRONT SURFACES

   commerce.css is the storefront layer, and every ground it painted came from
   the v2 chromatic spine — which is hue-committed violet by design:

     --void-deep  #04020a   section grounds     measured chroma  8
     --void       #0a0417   shop canvas         measured chroma 19
     --void-lift  #150a28   SKU card bodies     measured chroma 30
     --line       rgba(239,222,255,.2)          a violet-tinted white
     --moon-dim   #a396b4   metadata type       a grey-LILAC

   That is a themed page, not a gallery. The hero already runs on neutral
   near-black; below it the site stepped back into purple, and the SKU card
   bodies were the most saturated surface on the page at chroma 30.

   These replace them. They are NEW names rather than a repoint of --void-*,
   because those tokens are also read by journey.css, process-engine.css and
   landing.css — sections outside this pass. Nothing here changes what any of
   them resolve to; only what the storefront asks for.

   The product supplies the colour. The interface does not.
   ============================================================================ */
:root {
  --store-canvas: #070709;          /* page + section grounds */
  --store-surface: #0d0d11;         /* cards and raised panels */
  --store-surface-2: #121216;       /* only where real elevation is needed */
  --store-hairline: #26212a;        /* borders and dividers */
  --store-hairline-strong: #3a373d; /* hover / emphasis borders */
  --store-metadata: #8a8280;        /* was --moon-dim, the lilac one */
  --store-ivory: #f2e9db;           /* primary type */
  --store-secondary: #b8b0a3;       /* softer warm grey */
  --store-gold: #e7a51a;            /* the one commerce accent */
}
/* ---------------------------------------------------------------------------
   SHARED CONTROLS
   Two buttons and a price. The rest of the site uses bespoke per-section
   controls; the commerce layer needs the opposite — one button that looks the
   same everywhere so "buy" is never a new visual puzzle.
   --------------------------------------------------------------------------- */
.c-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.6rem;
  padding: 0.95rem 1.75rem;
  border: 1px solid transparent;
  border-radius: var(--radius-pill);
  font-family: var(--font-ui);
  font-size: 0.9rem;
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  text-decoration: none;
  cursor: pointer;
  transition: transform var(--dur-fast) var(--ease-out),
              background-color var(--dur-fast) var(--ease-out),
              border-color var(--dur-fast) var(--ease-out),
              color var(--dur-fast) var(--ease-out);
}
.c-btn:active { transform: translateY(1px); }

.c-btn--primary {
  background: var(--nectar);
  color: var(--ink);
}
.c-btn--primary:hover { background: var(--moon); }

.c-btn--ghost {
  background: transparent;
  border-color: var(--store-hairline-strong);
  color: var(--moon);
}
.c-btn--ghost:hover {
  border-color: var(--nectar);
  color: var(--nectar);
}

.c-btn--block { width: 100%; }

.c-price {
  font-family: var(--font-ui);
  font-size: 1.35rem;
  font-weight: 500;
  color: var(--moon);
  letter-spacing: 0.01em;
}
.c-price small {
  display: block;
  font-size: 0.7rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--store-metadata);
  margin-top: 0.25rem;
}

/* ---------------------------------------------------------------------------
   HERO
   A macro texture shot at full bleed, and copy that names the product, the
   fruits, the price and the payment methods above the fold.

   The macro masters photograph the chunks on pale stone, so they cannot simply
   sit on the violet field — the beige would glare. The image is masked to
   transparent across its left third and multiplied slightly, which lets the
   texture emerge out of the dark rather than being pasted onto it.
   --------------------------------------------------------------------------- */
.hero-shop {
  position: relative;
  isolation: isolate;
  display: grid;
  align-items: center;
  min-height: min(92svh, 54rem);
  /* Trimmed from (header + 3rem) / 3.5rem. The argument is taller than the
     benefit copy it replaced, so the hero became content-driven rather than
     min-height-driven and measured 917px on a 900px laptop — everything
     readable was above the fold, but the next section was not even hinted at.
     Twenty px of padding buys back that hint. Air, not type: the brief is
     explicit that density is not to be solved by shrinking things. */
  padding: calc(var(--header-height) + 2.25rem) var(--gutter) 2.5rem;
  overflow: hidden;

  /* ========================================================================
     HERO COLOUR SYSTEM

     Declared HERE on the section and deliberately not promoted to :root. The
     rest of the site still runs on the v2 chromatic system; this is one
     section proving a more disciplined language before any of it propagates.
     Nothing outside .hero-shop reads a single one of these.

     A SYSTEM, NOT A PALETTE. Three tiers, and each one answers a different
     question:

       FOUNDATION  what is this surface, and how loud is this text?
       COMMERCE    one fixed colour, and it never moves. Gold means "spend
                   money here" — CTA, price, offer. If gold shifted with the
                   fruit it would stop meaning that and start meaning "mango".
       PRODUCT     which fruit is on screen. Small, contained, and confined to
                   the active SKU indicator.

     The failure this replaces: five accents live at once (amber category,
     amber CTA, saffron mango, magenta jamun, citrus pineapple), with pineapple
     sitting two hue-steps from the CTA so the eye could not tell a product
     state from a commerce action. Now the only gold objects above the fold are
     the buy button, the price, and mango — and mango is small text against a
     230px fill, which is a difference in kind.
     ======================================================================== */

  /* -- FOUNDATION ---------------------------------------------------------
     The ground has moved three times: #1b0442 (saturated violet) → #0a0417
     (obsidian, still violet-cast) → #050507 → #070709. Each step took hue out
     rather than putting a different one in. */
  --hero-canvas: #070709;              /* base black */
  --hero-canvas-rgb: 7, 7, 9;          /* the same colour, for scrim alphas */
  --hero-surface: #0d0d11;             /* raised surface — the nav bar */
  --hero-hairline: #26212a;            /* dividers */

  /* Three type weights, not two. The old pair forced the argument's body and
     the payment-methods line into the same grey, which is how a hero ends up
     looking like one flat block of text. */
  --hero-ivory: #f2e9db;               /* primary   — 16.7:1 */
  --hero-secondary: #b8b0a3;           /* secondary —  9.4:1 */
  --hero-muted: #8a8280;               /* metadata  —  5.4:1 */

  /* -- COMMERCE -----------------------------------------------------------
     One value, fixed across all three fruit states. */
  --hero-commerce: #e7a51a;            /* 9.4:1 on canvas, 8.9:1 for its label */

  /* -- PRODUCT ------------------------------------------------------------
     Active SKU text and its underline. Nothing else — these three values are
     read by exactly three selectors and the progress strip's leading segment.

     ALL THREE ARE SEPARATED FROM COMMERCE GOLD BY BOTH HUE AND VALUE, which is
     the correction this pass exists for. Measured against #e7a51a at hue 41deg
     and 9.4:1:

       mango      #c96b24   hue  26deg (15 apart)   5.4:1  (43% darker)
       jamun      #af6490   hue 325deg (76 apart)   4.8:1
       pineapple  #a7a84a   hue  61deg (20 apart)   8.0:1

     Mango is the one that had to move furthest. #d89a18 sat at hue 41 — the
     SAME hue as the buy button — and only 13% off its luminance, so the
     selected-mango state and the purchase action were one semantic colour
     wearing two hats. Alphonso copper keeps the fruit (a ripe Alphonso IS this
     colour under its skin) while being unmistakably not a button.

     Pineapple moved for the opposite reason: olive #6f8742 solved the collision
     but solved it by going military. Dried-leaf citron keeps the green lean
     that separates it from gold, and gets its life back.

     Jamun is #af6490, not the originally specified #8a4a6f. That value measures
     3.15:1 on this canvas and this is the one word that tells the customer
     which product is on screen — it cannot sit below the legibility floor.
     #af6490 is the same hue lifted to 4.84:1: still a deep mulberry, still
     nowhere near the cosmetic pink it replaced. */
  --fruit-mango: #c96b24;              /* 5.4:1 — Alphonso copper */
  --fruit-jamun: #af6490;              /* 4.8:1 — see note above */
  --fruit-pineapple: #a7a84a;          /* 8.0:1 — dried-leaf citron */

  background: var(--hero-canvas);
  color: var(--hero-ivory);
}

/* The CTA takes the hero's commerce token rather than the global --nectar —
   scope discipline: the hero's colour system is complete and self-contained,
   and when the global pass happens the two should converge rather than one
   having quietly inherited the other. */
.hero-shop .c-btn--primary { background: var(--hero-commerce); }
.hero-shop .c-btn--primary:hover { background: var(--hero-ivory); }

.hero-shop__field {
  position: absolute;
  inset: 0;
  z-index: -1;
}
.hero-shop__field img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 68% 50%;
  /* Fade the plate out to the left so the headline sits on clean field. */
  -webkit-mask-image: linear-gradient(to right, transparent 4%, #000 46%);
  mask-image: linear-gradient(to right, transparent 4%, #000 46%);
  /* Was 0.92. The 8% was buying separation from a violet ground that no longer
     exists — against obsidian the photograph does not need to be dimmed to sit
     on it. Photography is the energy in this composition; taking a tenth of it
     away to make room for a background colour was the wrong trade. */
  opacity: 1;
}
/* The Navier-Stokes field. It does not blend with the plate — it DRAWS the
   plate, refracted through its own velocity field, so it simply sits on top of
   the <img> and replaces it visually once ready.

   The <img> stays in the DOM and stays visible underneath: it is the LCP
   element, it carries the alt text, and it is the fallback if WebGL2 is
   missing. Because the canvas renders the identical photograph at the identical
   crop, the hand-off is invisible — no flash, no reflow, nothing to reveal.

   No mix-blend-mode. An earlier pass screen-blended dye over the photo and it
   read as spilled paint; blending is exactly what this version removes. */
.hero-shop__fluid {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  opacity: 0;
  transition: opacity 700ms var(--ease-out);
  pointer-events: none;
}
.hero-shop.is-fluid-ready .hero-shop__fluid { opacity: 1; }

@media (prefers-reduced-motion: reduce) {
  .hero-shop__fluid { display: none; }
}

/* A second, softer wash over the whole frame keeps the pale stone from
   out-competing the type on wide screens where the plate runs edge to edge.

   Obsidian, not violet, and it releases the photograph sooner. The old stops
   carried rgba(27,4,66) — saturated violet at 0.72 alpha across the middle of
   the frame — which is where the "purple fog" came from: it was not lighting
   the photograph, it was tinting it. Same structure, same job, hue removed. */
.hero-shop__field::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    /* A short resolve at the very bottom edge. The plate is full-bleed and used
       to end on a hard horizontal cut into the proof strip; against the old
       violet ground that edge was one dark colour meeting another, but against
       obsidian it is a lit photograph meeting near-black and it reads as the
       image having been trimmed. 12% of the height, and only at the end, so
       nothing in the composition above it is touched. */
    linear-gradient(to bottom,
      rgba(var(--hero-canvas-rgb), 0) 88%,
      rgba(var(--hero-canvas-rgb), 0.55) 96%,
      var(--hero-canvas) 100%),
    /* GROUND THE COPY, THEN LET GO SLOWLY.

       The copy column is 34rem and ends at 41% of a 1440 viewport, so the
       opaque region has to reach past the selector row or the right-hand end of
       every row sits on a lighter ground than its left — measured in situ that
       cost pineapple 3.88:1 and jamun 4.41:1 against token values of 5.0 and
       4.8. That part is unchanged: opaque to 27%.

       What changed is everything after it. Three stops (1.0 / 0.72 / 0.08)
       decayed too fast and too evenly, and a linear decay across a short run is
       exactly what the eye reads as an EDGE — the composition looked like a
       black panel butted against a photograph.

       Seven stops now, front-loaded: the alpha falls quickly while it is still
       high (where the change is least visible) and then trails off over a long
       tail to nothing at 92%. The half-way point of the decay has actually
       moved LEFT, from 46% to 43%, so this releases the photograph sooner
       rather than pushing black further across the fruit — the falloff is
       longer and the black is smaller at the same time. */
    linear-gradient(100deg,
      var(--hero-canvas) 27%,
      rgba(var(--hero-canvas-rgb), 0.86) 34%,
      rgba(var(--hero-canvas-rgb), 0.60) 43%,
      rgba(var(--hero-canvas-rgb), 0.36) 53%,
      rgba(var(--hero-canvas-rgb), 0.18) 63%,
      rgba(var(--hero-canvas-rgb), 0.07) 75%,
      rgba(var(--hero-canvas-rgb), 0) 92%);
}

/* WHERE EACH TOKEN LANDS.

     PRIMARY    --hero-ivory       campaign line, the argument's lead, the
                                   payoff line.
     SECONDARY  --hero-secondary   category marker, body of the argument, proof.
     METADATA   --hero-muted       inactive fruit names, both separators,
                                   secondary CTA, micro-commerce.
     HAIRLINE   --hero-hairline    one rule.
     COMMERCE   --hero-commerce    buy button fill, and the price in the
                                   micro-commerce line. Fixed across all three
                                   fruit states.
     PRODUCT    --fruit-*          the active fruit's name and its underline.

   THREE NEUTRALS, NOT TWO. The old pair put the argument's body and the
   payment-methods line in the same grey — a two-step scale cannot express five
   levels, so everything below the headline flattened into one tone. The third
   step is what lets the argument read as copy and the payment methods read as
   fine print.

   The secondary neutral is also WARM now (#b8b0a3 against the old #9b989f).
   The previous value was cool, and on a warm-ivory-and-gold page a cool grey
   reads as slightly dead — it was the last cool cast left in the section.

   TWO TYPEFACES, NOT THREE. PP Editorial New sets the campaign line and nothing
   else in this section — the moment a second serif statement appears the first
   one stops being the voice and becomes a style. Everything else, including the
   argument's lead, is Neue Montreal. There is no mono in the project and none
   is added: nothing in this hero is instrument notation, and a fourth font file
   above the fold would be a real cost for a decorative one.

   SPACING IS DELIBERATELY UNEVEN. A single grid `gap` gave every row the same
   distance from its neighbour, so eight elements read as one list of eight
   things. The margins below group them instead, and one graphite rule splits
   the editorial half from the commercial half. */
.hero-shop__copy {
  position: relative;
  max-width: 34rem;
  display: grid;
  gap: 0;
  justify-items: start;
}

/* LEVEL 01 — CAMPAIGN LINE. The largest and most expressive thing on the page,
   and the only place the display serif appears. Roman for the premise, italic
   for the answer. It does NOT change colour when the fruit changes. */
.hero-shop__title {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(2.6rem, 6.2vw, 4.6rem);
  line-height: 0.98;
  letter-spacing: -0.02em;
  color: var(--hero-ivory);
}
/* Each line is a block so the entrance can wipe them independently. */
.hero-shop__title > span { display: block; }
.hero-shop__title em {
  display: block;
  font-style: italic;
  /* One ivory, not two. The italic used to sit on --moon-soft, a step below the
     roman line — a tonal split inside a single two-line sentence. The voices
     are already distinguished by roman against italic; distinguishing them by
     brightness as well made the answer quieter than the premise. */
  color: var(--hero-ivory);
}

/* CATEGORY MARKER — SECONDARY, not accent.

   This is the level the last pass got wrong. It was amber, which made it the
   third-brightest thing in the hero and put it in direct competition with the
   buy button for the same signal. It is a classification: the customer needs to
   be able to read it, not to be pulled to it. Neutral grey at 7.1:1 on the
   ground is unambiguously legible and unambiguously subordinate.

   `font-size` is set in rem, not em — an em here would scale with the 4.6rem
   heading and put the classification at 0.9rem on desktop and 0.5rem on a
   phone, which is the wrong direction on both. */
.hero-shop__category {
  font-family: var(--font-ui);
  font-size: 0.76rem;
  font-weight: 500;
  line-height: 1;
  letter-spacing: 0.4em;
  text-transform: uppercase;
  color: var(--hero-secondary);
  /* Tight to the headline it labels — they are one group, and the next gap in
     the block is four times this. Optical, not metric: the tracking adds a
     trailing space to the last letter, and the heading below is set with a
     -0.02em negative. */
  margin: 0 0 0.95rem;
}

/* FRUIT SELECTOR. The range and the caption for the current plate, in one
   row. Real fruit names, never a generic category word.

   It has MOVED: it used to sit directly under the campaign line, and it now
   follows the argument. Putting a list of fruits between "The crunch doesn't."
   and "Most dried fruit meets heat." deflated both of them — the two statements
   that carry the hero belong next to each other, and the selector belongs with
   the things it leads into: which fruit, what is in it, what it costs.

   Buttons, because they are: clicking one takes the hero to that fruit. They
   are stripped of every button affordance except the hit area — this has to
   read as a line of type with one word lit, not as a segmented control. */
.hero-shop__fruits {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0 0.55rem;
  /* The largest gap above anything except the button. The switcher used to sit
     1.2rem under the campaign line, close enough to read as its subtitle; it is
     a separate instrument and needs to stand clear of the type it follows. */
  margin: 1.6rem 0 0;
}
/* A real element rather than a ::before on the buttons. Generated content is
   folded into the accessible name in every engine that matters, so the pseudo
   version named the second button "· Jamun". */
.hero-shop__sep {
  font-family: var(--font-ui);
  font-size: 0.8rem;
  color: var(--hero-muted);
  opacity: 0.6;
}
.hero-shop__fruit {
  position: relative;
  appearance: none;
  border: 0;
  background: none;
  padding: 0.15rem 0 0.4rem;
  font-family: var(--font-ui);
  font-size: clamp(0.86rem, 1.5vw, 1rem);
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  cursor: pointer;
  /* Inactive is METADATA, not secondary. At --hero-secondary (9.4:1) the
     inactive names would outshine two of the three active states, which
     inverts the signal the row exists to send. */
  color: var(--hero-muted);
  transition: color 300ms var(--ease-out);
}
.hero-shop__fruit:hover { color: var(--hero-ivory); }

/* THE ACTIVE STATE IS THE FRUIT'S OWN COLOUR.

   All three used to light amber, so the switcher said "one of these is on" but
   never said anything about WHICH. Mango in saffron, jamun in magenta-plum and
   pineapple in pale citrus means the accent is carrying product information
   rather than just marking a selection — and it ties the word to the
   photograph swapping behind it.

   Driven off aria-pressed rather than body[data-sku], deliberately: data-sku is
   written when the transition RESOLVES, and the highlight moves at 46% of it.
   Hanging the colour on the same attribute the highlight uses keeps the two on
   one clock. The underline below reads currentColor, so it follows for free.

   This is the whole of the accent budget, alongside the button fill. */
.hero-shop__fruit[data-hero-fruit="mango"][aria-pressed="true"] { color: var(--fruit-mango); }
.hero-shop__fruit[data-hero-fruit="jamun"][aria-pressed="true"] { color: var(--fruit-jamun); }
.hero-shop__fruit[data-hero-fruit="pineapple"][aria-pressed="true"] { color: var(--fruit-pineapple); }

/* The active name is underscored by a rule that DRAWS itself when the plate
   locks, which is the one moment of mechanism left from the old identity
   readout — it is what makes the highlight read as connected to the
   photograph rather than as a hover state someone left on. */
/* 2px, not 1px.

   The product accents are now deliberately restrained, which means two of the
   three no longer out-shine the inactive names: mango reads 8.2:1 against
   metadata's 5.4:1, but jamun is 4.8 and pineapple 5.0. Brightness has stopped
   carrying the active state — chroma carries it (a mulberry or an olive among
   warm greys is unmistakable), and this rule carries the rest.

   Doubling it is free: the underline is absolutely positioned, so it cannot
   move a single box, which is what keeps the three fruit states pixel-identical
   in layout. */
.hero-shop__fruit::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0.05rem;
  height: 2px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 520ms var(--ease-out);
}
.hero-shop.is-identity-locked .hero-shop__fruit[aria-pressed="true"]::after { transform: scaleX(1); }
/* Ivory, not amber. A focus ring only exists during keyboard navigation so it
   is not part of the resting palette, but ivory also guarantees the same
   contrast against all three fruit accents — an amber ring around an amber
   mango state was the weakest of the three. */
.hero-shop__fruit:focus-visible {
  outline: 2px solid var(--hero-ivory);
  outline-offset: 4px;
  border-radius: 2px;
}

@media (prefers-reduced-motion: reduce) {
  .hero-shop__fruit { transition: none; }
  .hero-shop__fruit::after { transition: none; }
  .hero-shop__fruit[aria-pressed="true"]::after { transform: scaleX(1); }
}

/* LEVEL 02 — THE ARGUMENT. Four beats, and not one of them a rectangle.

   The block this replaces was a convenience pitch: fruit that travels, no
   washing, no peeling, no refrigeration. All true, none of it worth a premium —
   that is the argument for a lunchbox, not for freeze-drying. This one is about
   process and what the process does to the fruit, which is the only reason the
   price makes sense.

   The measure is 34ch, and the last three beats carry hard line breaks. That is
   the whole anti-slab strategy: a paragraph allowed to run the width of the
   column wraps into a grey rectangle no matter how well it is written, and this
   block is four short shapes instead. */
.hero-shop__rtb {
  max-width: 34ch;
  display: grid;
  margin: 1.5rem 0 0;
}

/* The lead — level 2 in the hero, behind only the campaign line. Neue Montreal,
   NOT the serif: the display face is the campaign line's alone, and a second
   serif statement underneath it would read as a competing slogan rather than as
   the argument for the first one. Weight and case carry it instead. */
.hero-shop__rtb-lead {
  margin: 0 0 1.1rem;
  font-family: var(--font-ui);
  font-size: clamp(1.02rem, 1.55vw, 1.18rem);
  font-weight: 500;
  line-height: 1.28;
  letter-spacing: 0.005em;
  color: var(--hero-ivory);
}

.hero-shop__rtb p {
  margin: 0 0 0.75rem;
  font-family: var(--font-ui);
  font-size: clamp(0.93rem, 1.4vw, 1.01rem);
  line-height: 1.55;
  color: var(--hero-secondary);
}
.hero-shop__rtb p:last-child { margin-bottom: 0; }

/* The payoff. One sentence at full ivory at the bottom of an otherwise grey
   block — the argument is the grey, this is what it was for. `em` without
   italics, because the emphasis here is tonal, not typographic; an italic
   sans at this size just looks like a slant. */
.hero-shop__rtb em {
  font-style: normal;
  color: var(--hero-ivory);
}

/* THE HERO'S ONE RULE.

   Graphite, full width of the copy column, and the only piece of structure in
   the section. It divides the editorial half — campaign line and argument —
   from the commercial half. Without it the eight rows read as one continuous
   column of text however the gaps are set; a hairline does in one pixel what
   another 3rem of whitespace would only half do.

   It passes the restraint test on "hierarchy", which is the whole reason it is
   allowed to exist. */
.hero-shop__rule {
  width: 100%;
  height: 0;
  margin: 2.2rem 0 0;
  border: 0;
  border-top: 1px solid var(--hero-hairline);
}

/* PROOF. Two words, down from three claims.

   `list-style: none` on a <ul> silently removes it from the accessibility tree
   in Safari, which is why role="list" is restated in the markup — this row is
   two separate claims and should be announced as two, not as one run-on
   string. */
.hero-shop__proof {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  /* No column gap — the separator carries its own padding, which keeps it
     attached to the claim BEFORE it. A leading dot on the next item hangs into
     the margin the moment the row wraps. */
  gap: 0.15rem 0;
  margin: 1.5rem 0 0;
  padding: 0;
  list-style: none;
  font-family: var(--font-ui);
  font-size: 0.76rem;
  font-weight: 500;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--hero-secondary);
}
.hero-shop__proof li::after {
  content: "·";
  padding: 0 0.55rem;
  color: var(--hero-muted);
  letter-spacing: 0;
}
.hero-shop__proof li:last-child::after { content: none; }

/* LEVEL 05 — THE ACTION. One button and one link.

   The biggest approach in the block, by some way. Everything above it is
   information; this is the only thing on the hero that does anything, and the
   space in front of it is what makes the eye stop here rather than run on into
   the payment methods. */
.hero-shop__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.4rem 1.5rem;
  margin-top: 1.9rem;
}

/* The secondary is deliberately NOT a button. Two pills of similar size and
   shape made "shop individual fruits" compete with ₹599, and asked a first-time
   visitor to choose between two ways of choosing. As a link it is available to
   anyone looking for it and invisible to anyone who is not. */
.hero-shop__secondary {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  /* Touch target, without the box a padded button would draw. */
  min-height: 44px;
  padding: 0 0.1rem;
  font-family: var(--font-ui);
  font-size: 0.8rem;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  text-decoration: none;
  /* SECONDARY. It was ivory, one step below the primary CTA and therefore
     still arguing with it. */
  color: var(--hero-muted);
  transition: color var(--dur-fast) var(--ease-out);
}
.hero-shop__secondary i {
  width: 1.1rem;
  height: 1px;
  background: currentColor;
  transition: width var(--dur-fast) var(--ease-out);
}
/* Hover lifts to ivory, not to amber. Amber here was the fourth accent leak:
   a hover state has no business claiming the same colour as the buy button. */
.hero-shop__secondary:hover { color: var(--hero-ivory); }
.hero-shop__secondary:hover i { width: 1.6rem; }

/* LEVEL 06 — MICRO COMMERCE. The smallest and quietest line in the hero, and
   deliberately tucked close under the button: it is the button's fine print,
   not another row in the stack. */
.hero-shop__terms {
  margin: 0.85rem 0 0;
  font-family: var(--font-ui);
  font-size: 0.7rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--hero-muted);
}
/* NOT commerce gold. The price was picking up the CTA colour on the reasoning
   that gold means "money" — but this whole line is metadata: pack size, payment
   rails, delivery. Making one word in it a purchase colour created a second
   commerce event under the only real one, and split the signal the button is
   supposed to own outright. A tonal step inside the neutral scale says
   "legible, slightly important" without saying "click me". */
.hero-shop__terms b { color: var(--hero-secondary); font-weight: 500; }

/* The point of this hero is that "20g packs from ₹225 · UPI · COD" is visible
   without scrolling. At the roomy desktop spacing the copy column measures
   728px, which clears a 900px viewport and misses a 720px one by 8px — and
   1366x768 is still one of the most common screens in India. Tighten the air,
   not the content: nothing is removed, it just packs down on short screens. */
@media (min-width: 861px) and (max-height: 880px) {
  .hero-shop {
    padding-top: calc(var(--header-height) + 1.75rem);
    padding-bottom: 2.25rem;
  }
  .hero-shop__title { font-size: clamp(2.2rem, 4.4vw, 3.4rem); }
  .hero-shop__category { margin-bottom: 0.75rem; }
  /* The rhythm is scaled, not flattened. Every gap comes down by roughly a
     third and keeps its RATIO to the others, so a 768px screen gets the same
     composition more tightly set rather than the even stack this pass exists to
     get rid of. */
  .hero-shop__rtb { margin-top: 1.05rem; }
  .hero-shop__rtb-lead { margin-bottom: 0.8rem; font-size: 1.06rem; line-height: 1.26; }
  .hero-shop__rtb p { margin-bottom: 0.55rem; font-size: 0.95rem; line-height: 1.48; }
  .hero-shop__rule { margin-top: 1.55rem; }
  .hero-shop__fruits { margin-top: 1.1rem; }
  .hero-shop__proof { margin-top: 1.05rem; }
  .hero-shop__actions { margin-top: 1.35rem; }
  .hero-shop__terms { margin-top: 0.55rem; }
}

/* MOBILE HERO — ONE COMPOSITION, NOT A STACK.

   What was here: the plate was pulled OUT of the background and turned into a
   `position: relative; order: -1; aspect-ratio: 16/10` banner sitting above the
   copy, with 2rem of gap between them. That is a website stack — header, then a
   rectangular picture, then a hard edge, then a purple block with words in it.
   It read as a responsive fallback because that is exactly what it was.

   Now the media is full-bleed behind the whole hero, as it is on desktop, and
   the copy bottom-aligns into it. The scrim is the STRUCTURE: transparent over
   the fruit, ramping to the field colour behind the type, so there is no line
   anywhere that says "image ends here, website begins here".

   The composition is self-adjusting rather than fixed: because the copy is
   bottom-aligned inside 100svh and the scrim stops are proportional, the fruit
   simply occupies whatever height is left above the words. A 700px effective
   viewport and an 844px one both compose — one just gives the fruit less room —
   which is what makes this survive real browser chrome instead of only the
   emulator's clean 844. */
@media (max-width: 860px) {
  .hero-shop {
    /* svh, so this is the height with the address bar SHOWING. Bottom-aligned
       content inside it is therefore above the chrome by construction. */
    min-height: 100svh;
    padding-top: calc(var(--header-height) + 1rem);
    padding-bottom: max(1.6rem, var(--safe-bottom, 0px));
    grid-template-rows: 1fr auto;
    gap: 0;
    align-content: stretch;
    align-items: end;
  }
  /* Back to a bed behind the composition, not a banner above it — but a bed
     that does not run the full height.

     `object-fit: cover` across the whole 390x844 hero meant fitting a 3:2
     photograph into a 0.46 portrait box: the image scaled up 1.24x to reach the
     height and then lost 69% OF ITS WIDTH off the sides. That is what "a
     digital crop of a crop" looks like, and it is also why the chunks read as
     enormous next to desktop.

     At 54% the box is 390x456, aspect 0.86. Cover now scales 0.67x and crops
     about 43% instead of 69% — over a third more of the photographic field is
     visible, the pieces sit at a believable size, and the image is being
     reduced rather than enlarged, which is the sharper direction to be wrong in.

     The canvas gets the identical box: it draws this photograph, so any
     mismatch would show as the plate jumping when the sim takes over. */
  /* ONLY the field gets the height. The canvas is a CHILD of it — grouping the
     two in one selector applied 54% twice and left the canvas covering just the
     top 246px of a 456px stage, with the raw <img> showing below the fold of
     it. That is why the transition appeared to do nothing: most of what was on
     screen was never the canvas. */
  .hero-shop__field {
    position: absolute;
    inset: 0 0 auto 0;
    height: 54%;
    z-index: -1;
    order: 0;
    aspect-ratio: auto;
    margin: 0;
  }
  .hero-shop__fluid { inset: 0; height: 100%; }
  .hero-shop__field img {
    /* No mask. The mask was drawing the hard bottom edge this rebuild exists to
       remove; the scrim below does the blending instead, and it does it into
       the field colour rather than into transparency. */
    -webkit-mask-image: none;
    mask-image: none;
    /* Fruit in the upper-middle, per the brief, with the crop's own negative
       space falling where the type lands. */
    /* Recentred for the shorter box: at 24% the crop hugged the top of a
       full-height frame; in a 54% box the fruit wants to sit near its middle. */
    object-position: 50% 44%;
    opacity: 1;
  }
  /* THE STRUCTURAL TRANSITION. Clear over the product, committed to the field
     colour by the time the headline starts, so the headline begins ON the
     photographic-to-purple crossover rather than below it. */
  /* SURGICAL, not a fog.

     The previous ramp started tinting at 26% and was at 58% opacity by the
     middle of the frame, which put purple haze across the fruit itself — the
     scrim was doing its structural job by degrading the product. It now leaves
     the top 44% of the media completely untouched (zero overlay on the region
     the customer is reading as texture), darkens only through the crossover
     where the headline lands, and commits to the field colour exactly at the
     bottom edge of the media box so there is still no visible seam. */
  /* Obsidian stops, and the untouched region grows from 44% to 47%. A darker
     ground needs less alpha to reach the same legibility, so the "minimum
     darkening necessary" is genuinely less than it was — the photograph keeps
     more of itself and the fall into the field still has no edge in it. */
  .hero-shop__field::after {
    background: linear-gradient(to bottom,
      rgba(var(--hero-canvas-rgb), 0) 0%,
      rgba(var(--hero-canvas-rgb), 0) 47%,
      rgba(var(--hero-canvas-rgb), 0.24) 67%,
      rgba(var(--hero-canvas-rgb), 0.72) 86%,
      var(--hero-canvas) 100%);
  }

  /* RHYTHM. Space recovered from the gaps, not from the identity: the headline
     keeps its size. `width: 100%` rather than `max-width: none` — a grid with
     justify-items:start sizes each child to fit-content, and an unbounded
     column let a long unbroken line size itself past the viewport. */
  .hero-shop__copy {
    max-width: none;
    width: 100%;
    align-self: end;
    /* So ::before below can be pinned behind the copy and nothing else. */
    isolation: isolate;
  }

  /* A SCRIM THAT TRACKS THE COPY, NOT THE MEDIA.

     The media scrim above is pinned to percentages of the image box, which is
     correct for blending the photograph into the field but cannot know where
     the first line of type actually starts — and on a pale plate that is a real
     legibility failure, not a nicety. Measured over the pineapple master, the
     category marker was the worst text on the page at 1.74:1; it is 6.08:1 with
     this in place, and the photograph above the headline is unchanged.

     This one is anchored to the copy column itself, so every line of type has
     ground beneath it no matter how tall the copy grows or how short the
     viewport gets. It ramps from nothing at the top — the fruit above the
     headline stays exactly as clean as it was — to the field colour by the
     time the prose starts.

     It bleeds to the viewport edges via the hero's own gutter so there is no
     rectangle edge in the composition.

     Stops are absolute lengths, not percentages. The copy column's height
     changes with the viewport and with how the prose wraps, and a percentage
     ramp would slide up and down the type with it — the one thing this must
     not do is stop covering the first line. */
  .hero-shop__copy::before {
    content: "";
    position: absolute;
    inset: -3.6rem calc(var(--gutter) * -1) calc(var(--gutter) * -1);
    z-index: -1;
    /* RESHAPED FOR A TALLER COPY BLOCK.

       The argument is ~120px taller than the benefit copy it replaced, so the
       bottom-aligned column starts higher and the category marker now lands
       earlier in this ramp — over brighter fruit than it used to. Measured on
       the pineapple plate it fell to 3.57:1, under AA, and 4.6:1 on mango.

       So the ramp climbs faster at the top and then takes LONGER to close: 0.87
       by 3.6rem, where the marker sits, but not fully committed until 8.5rem.
       More ground under the one vulnerable line, and a longer dissolve
       underneath it — the photograph resolves into the field over 136px instead
       of ending at 120px. Softer and safer at the same time. */
    background: linear-gradient(to bottom,
      rgba(var(--hero-canvas-rgb), 0) 0,
      rgba(var(--hero-canvas-rgb), 0.30) 1.2rem,
      rgba(var(--hero-canvas-rgb), 0.62) 2.4rem,
      rgba(var(--hero-canvas-rgb), 0.87) 3.6rem,
      rgba(var(--hero-canvas-rgb), 0.93) 5.5rem,
      var(--hero-canvas) 8.5rem);
    pointer-events: none;
  }

  .hero-shop__title { line-height: 0.96; }
  .hero-shop__category { margin-bottom: 0.75rem; letter-spacing: 0.34em; }

  /* THE MOBILE HIERARCHY IS THE DESKTOP HIERARCHY, COMPRESSED — not reordered
     and not thinned out. Everything the brief lists is here, in order, above
     the fold on a 390x844 phone.

     Compressed, but NOT flattened. The gaps keep their relative sizes, so a
     phone still reads as category-on-headline / switcher / prose / proof /
     BUY rather than as eight evenly spaced rows. That distinction is the whole
     difference between a composition and a stack, and it is the thing that
     survives a five-second glance.

     The compression is spent where it costs least: the campaign line keeps its
     size (a shrunken thesis is not a thesis), and the prose gives up leading
     and a little size because it is the largest block of height here. */
  /* The copy column is full-bleed on a phone, so the measure has to be held
     here or the argument runs the whole width of the screen. 31ch keeps every
     hard-broken line intact on a 360px viewport. */
  .hero-shop__rtb { max-width: 31ch; margin-top: 1.05rem; }
  .hero-shop__rtb-lead { margin-bottom: 0.85rem; font-size: 1.04rem; line-height: 1.26; }
  .hero-shop__rtb p { margin-bottom: 0.62rem; font-size: 0.91rem; line-height: 1.5; }
  .hero-shop__rule { margin-top: 1.7rem; }
  .hero-shop__fruits { gap: 0 0.5rem; margin-top: 1.2rem; }
  .hero-shop__fruit { font-size: 0.82rem; letter-spacing: 0.11em; }
  /* Two claims and one dot fit on any phone, so unlike the three-item strip
     this replaced, the separator stays. */
  .hero-shop__proof { font-size: 0.71rem; letter-spacing: 0.12em; margin-top: 1.1rem; }

  .hero-shop__actions { width: 100%; gap: 0.15rem; margin-top: 1.6rem; }
  /* Full-width primary, and the secondary as a link beneath it. Side-by-side at
     this width forced "SHOP INDIVIDUAL FRUITS" onto two lines inside its own
     button; stacking keeps the primary the widest, loudest thing here. */
  .hero-shop__actions .c-btn { flex: 1 0 100%; }
  .hero-shop__secondary { flex: 1 0 100%; justify-content: flex-start; min-height: 40px; }
  .hero-shop__terms { margin-top: 0.45rem; font-size: 0.68rem; letter-spacing: 0.06em; }
}

/* SHORT PHONES — GIVE THE FRUIT ITS ROOM BACK.

   The mobile composition bottom-aligns the copy inside 100svh, so the
   photograph gets whatever height the words leave over. On a 390x844 phone that
   is 291px and the hero reads as a product shot with an offer under it. On a
   375x667 screen the same copy left 50px, which is not a photograph, it is a
   strip — the hero stopped selling fruit and became a page of text.

   Everything the brief lists is still present and still in order. What changes
   is the air between it: gaps, leading and the two touch targets that were
   sized well above the 44px minimum. ~55px comes back, which roughly triples
   the visible fruit on the shortest screens. The campaign line gives up the
   least, because a thesis nobody can see is not a thesis.

   `max-height` here is stable, not jittery: mobile engines resolve height media
   queries against the large viewport, so a hiding address bar does not flip
   this on and off mid-scroll. */
@media (max-width: 860px) and (max-height: 720px) {
  .hero-shop__title { font-size: 2.3rem; }
  .hero-shop__category { margin-bottom: 0.55rem; }
  .hero-shop__rtb { margin-top: 0.8rem; }
  .hero-shop__rtb-lead { margin-bottom: 0.6rem; font-size: 0.98rem; line-height: 1.24; }
  .hero-shop__rtb p { margin-bottom: 0.45rem; font-size: 0.87rem; line-height: 1.42; }
  .hero-shop__rule { margin-top: 1.2rem; }
  .hero-shop__fruits { margin-top: 0.85rem; }
  .hero-shop__proof { margin-top: 0.8rem; }
  .hero-shop__actions { margin-top: 1.15rem; }
  .hero-shop__actions .c-btn { padding-block: 0.8rem; }
  .hero-shop__secondary { min-height: 34px; }
  .hero-shop__terms { margin-top: 0.4rem; }
}

/* ---------------------------------------------------------------------------
   PROOF STRIP
   Five claims, no sentences, immediately under the hero. This is the block that
   answers "is this the same as every other pouch" before the shopper has to
   scroll for it. Deliberately not a marquee — it must be readable at a glance
   and legible to a crawler as static text.
   --------------------------------------------------------------------------- */
.proof-strip {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  margin: 0;
  padding: 0;
  list-style: none;
  background: var(--store-canvas);
  border-block: 1px solid var(--store-hairline);
}
.proof-strip li {
  padding: 1.5rem 1rem;
  text-align: center;
  font-family: var(--font-ui);
  font-size: clamp(0.66rem, 1.05vw, 0.8rem);
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--moon);
}
.proof-strip li + li { border-left: 1px solid var(--store-hairline); }
.proof-strip b {
  display: block;
  font-family: var(--font-display);
  font-size: clamp(1.5rem, 3vw, 2.1rem);
  font-weight: 400;
  letter-spacing: -0.01em;
  color: var(--nectar);
  margin-bottom: 0.4rem;
}

/* On a phone this is a LEDGER, not a billboard.

   As a two-column grid it ran to ~870px — the entire second screen — with the
   fifth claim orphaned across a row of its own, and every number set larger
   than the section headline underneath it. The customer's second full screen
   was a table of claims, and the first product sat below it. Five compact rows
   put the same five facts in ~300px and let the product back into the viewport.

   Nothing is removed or truncated: same list, same words, same crawlable text,
   including the naturally-occurring-sugars disclosure. It just stops shouting
   them at display size. */
@media (max-width: 860px) {
  .proof-strip { grid-template-columns: 1fr; }
  .proof-strip li {
    display: grid;
    grid-template-columns: 4.75rem 1fr;
    align-items: baseline;
    gap: 0 0.95rem;
    padding: 0.9rem var(--gutter);
    text-align: left;
    border-top: 1px solid var(--store-hairline);
  }
  .proof-strip li:first-child { border-top: 0; }
  /* The desktop dividers have to be switched off with a selector as specific as
     the one that draws them. This used to be `border-left: 0` on `.proof-strip li`
     (0,1,1), which silently lost to `.proof-strip li + li` (0,1,2): stacked, every
     row but the first kept a hairline down the screen edge, so the first box,
     100% / Fruit. One ingredient, read as the one missing its left side. */
  .proof-strip li + li { border-left: 0; }
  .proof-strip b {
    margin-bottom: 0;
    font-size: 1.32rem;
    text-align: right;
  }
  /* Second column, next row — under the label it qualifies, not under the
     number. */
  .proof-strip li small { grid-column: 2; margin-top: 0.3rem; }
}

/* ---------------------------------------------------------------------------
   SHOP
   The First Harvest Trio first, then the three singles. That order is the whole
   argument: a shopper who has never tasted freeze-dried jamun cannot choose
   between three fruits, so the first decision offered is "all three".
   --------------------------------------------------------------------------- */
/* THE COMMERCE SECTION ARRIVES.

   It had zero reveals while the principle and the collection had nine each --
   every editorial section on this page announced itself and the one that sells
   did not. Same --step mechanism the principle uses, and keyed to the
   section's own named timeline for the same reason: staggering against each
   card's own `entry` phase would put the three cards a couple of pixels apart,
   because a row of cards enters all at once and `entry` for one card is only
   its own height of scroll.

   Deliberately NOT extended to the add button or the bag drawer. The button
   already runs a considered state machine -- label to "<FRUIT> ADDED", icon to
   a tick, sold-out and retry paths, reverting on a timer -- and the drawer
   already has a tuned 420ms --ease-drawer transition. Adding motion over
   either would be replacing working accepted work, not elevating it. */
.shop { view-timeline-name: --shop-view; }

.shop__header h2      { --step: 0; }
.sku-grid__register   { --step: 2; }
.discovery            { --step: 1; }
.sku-card[data-sku="mango"]     { --step: 3; }
.sku-card[data-sku="jamun"]     { --step: 4; }
.sku-card[data-sku="pineapple"] { --step: 5; }

@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .shop [data-reveal] {
      animation-timeline: --shop-view;
      animation-range: cover calc(5% + var(--step, 0) * 3.2%) cover calc(28% + var(--step, 0) * 3.2%);
    }
  }
}

.shop {
  padding: var(--section-space) var(--gutter);
  background: var(--store-canvas);

  /* ------------------------------------------------------------------------
     TRIO COLOUR SYSTEM — scoped here, used ONLY by .shop__header and
     .discovery*. The SKU cards below read none of these and are untouched.

     Same values as the hero's system, deliberately: this is the second module
     to adopt the restrained language, and the two have to agree or the page
     has two competing systems instead of one spreading.
     ------------------------------------------------------------------------ */
  --trio-ivory: #f2e9db;      /* headline, product name, price */
  --trio-secondary: #b8b0a3;  /* body copy, saving */
  --trio-muted: #8a8280;      /* overline, was-price, units */
  --trio-hairline: #26212a;   /* the one rule */
  --trio-commerce: #e7a51a;   /* the CTA fill, and nothing else */
}

/* -- Intro ----------------------------------------------------------------- */
.shop__header {
  display: grid;
  gap: 1rem;
  max-width: 46rem;
  margin-bottom: clamp(2.25rem, 4vw, 3.25rem);
}
.shop__header h2 {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(2rem, 4.6vw, 3.4rem);
  line-height: 1.02;
  letter-spacing: -0.02em;
  color: var(--trio-ivory);
}
/* Italic, not gold. "Nothing else." was set in nectar, which spent the
   commerce colour on a headline flourish two hundred pixels above the only
   button that has any business wearing it. The roman/italic pairing is the
   same device the hero's campaign line uses, and it needs no colour. */
.shop__header h2 em { font-style: italic; color: var(--trio-ivory); }
.shop__header p {
  margin: 0;
  max-width: 42ch;
  font-family: var(--font-ui);
  font-size: 1rem;
  line-height: 1.6;
  color: var(--trio-secondary);
}

/* -- First Harvest Trio ----------------------------------------------------
   ONE COMPOSITION, NOT AN INTRO PLUS A CARD.

   What was here: a rounded rectangle filled with a 120deg gradient from
   --field-orchid into --void-lift, outlined in a light border. A saturated
   red-violet panel sitting under a heading — which is exactly the shape of a
   Shopify bundle block, and it read as one no matter what was written inside
   it.

   All of that chrome is gone. No panel, no border box, no radius. A single
   graphite hairline runs the full width above the offer and ties it to the
   heading, so the sequence reads heading -> range copy -> rule -> product.
   The section is the container; the product does not need its own.
   -------------------------------------------------------------------------- */
.discovery {
  display: grid;
  /* 1.35, not 1.15. The image IS the argument in this module — three pouches,
     visibly three different products — and at the old ratio it read as a
     thumbnail beside a paragraph. */
  grid-template-columns: 1.35fr 1fr;
  align-items: center;
  gap: clamp(1.75rem, 4vw, 3.5rem);
  margin-bottom: clamp(2rem, 4vw, 3.5rem);
  padding-top: clamp(1.75rem, 3.5vw, 2.75rem);
  border-top: 1px solid var(--trio-hairline);
}

/* position:relative was here for FoilPass, which appended its canvas and
   positioned it from the <img>'s rect measured against this box. The pass is
   no longer mounted on this element (see landing.js), but the property is
   harmless and keeps the contract if a future effect wants the same anchor. */
.discovery__media { margin: 0; position: relative; }

/* FEATHERED, NOT FRAMED.

   The master is a still-life on its own aubergine ground, so it arrives as a
   rectangle of picture. Left alone in a section this dark, that rectangle
   announces its own edges and the module goes back to looking like a product
   card with an image in it.

   An elliptical mask dissolves the outer few percent into the section instead.
   The centre — every pixel of all three pouches — is untouched at full opacity;
   only the ground beyond them falls away, and it falls into a colour it is
   already close to. No white staging, no glow, no drop shadow, and nothing
   that could put a coloured edge on a pack. */
.discovery__media img {
  display: block;
  width: 100%;
  height: auto;
  /* FEATHER WHERE THE GROUND ACTUALLY IS.
     A symmetric radial was the wrong tool. Measured on the crop, the packs
     span 5%-95% of the width but only 9%-86% of the height — they very nearly
     fill the frame horizontally. Any radial soft enough to dissolve the left
     and right edges was also dimming the mango and the pineapple.
     So the fade is mostly VERTICAL, where the dead aubergine ground is: 8% at
     the top and 12% at the bottom, both clear of the pouches. The sides get
     3.5%, enough to take the hard corner off without touching product.
     Two layers intersected. If mask-composite is unsupported the initial value
     is "add", which unions them to nearly opaque — i.e. it degrades to a plain
     rectangle rather than to a broken one. */
  -webkit-mask-image: linear-gradient(to bottom, transparent 0, #000 8%, #000 88%, transparent 100%), linear-gradient(to right, transparent 0, #000 3.5%, #000 96.5%, transparent 100%);
  -webkit-mask-composite: source-in;
  mask-image: linear-gradient(to bottom, transparent 0, #000 8%, #000 88%, transparent 100%), linear-gradient(to right, transparent 0, #000 3.5%, #000 96.5%, transparent 100%);
  mask-composite: intersect;
}

.discovery__body { display: grid; gap: 1.05rem; justify-items: start; }

/* OVERLINE, not a badge. It was a filled gold pill — a second commerce-coloured
   object competing with the button below it, and one of the "extra badges" the
   brief rules out. As tracked uppercase it does the same labelling job and
   claims none of the same attention. */
.discovery__badge {
  font-family: var(--font-ui);
  font-size: 0.7rem;
  font-weight: 500;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--trio-muted);
  background: none;
  padding: 0;
  border-radius: 0;
}
.discovery__body h3 {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 400;
  /* Capped at 2.5rem, not 2.8. "ASTROVE First Harvest Trio" is 26 characters
     and at 2.8rem it broke after "Harvest", orphaning "Trio" on its own line.
     There is no good two-line break for this name, so it gets the size that
     keeps it on one. */
  font-size: clamp(1.9rem, 3.1vw, 2.5rem);
  line-height: 1.04;
  letter-spacing: -0.015em;
  color: var(--trio-ivory);
}
.discovery__body > p {
  margin: 0;
  max-width: 38ch;
  font-family: var(--font-ui);
  line-height: 1.6;
  color: var(--trio-secondary);
}

/* PRICE / WAS / SAVING — three parts, read in that order. */
.discovery__meta {
  display: flex;
  align-items: baseline;
  gap: 0.4rem 1rem;
  flex-wrap: wrap;
  margin-top: 0.15rem;
}
.discovery__meta .c-price { color: var(--trio-ivory); }
.discovery__meta .c-price small { color: var(--trio-muted); }
.discovery__meta del {
  font-family: var(--font-ui);
  color: var(--trio-muted);
  text-decoration-thickness: 1px;
}
/* The saving is an argument, not an action, so it is type rather than a chip
   and it is neutral rather than gold. */
.discovery__meta em {
  font-style: normal;
  font-family: var(--font-ui);
  font-size: 0.72rem;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--trio-secondary);
}

/* The module's one commerce-coloured object. */
.discovery .c-btn--primary { background: var(--trio-commerce); }
.discovery .c-btn--primary:hover { background: var(--trio-ivory); }

@media (max-width: 860px) {
  /* MOBILE FIRST: image, then the offer under it, in one column. The image
     leads because it is the argument — three pouches, visibly three different
     products — and the rule above it keeps it tied to the heading rather than
     floating between two blocks. */
  .discovery {
    grid-template-columns: 1fr;
    gap: 1.5rem;
    padding-top: 1.6rem;
  }
  /* GUTTER CONTRACT — restored.

     Removing the card chrome in the First Harvest pass also removed the card
     PADDING, and with it the inset every piece of trio copy used to sit on.
     Measured at 390: the overline, title, body, price and CTA moved from 40px
     to 16px, which put them 23px outboard of the three SKU cards directly
     below them, whose text sits at 39px (grid gutter 16 + 1px border + the
     1.4rem .sku-card__body padding). Two stacked product blocks with different
     left edges is what read as the section being shifted sideways.

     The inset is rebuilt from the SKU card's own numbers rather than guessed,
     so the two land on the same pixel instead of merely near each other.

     It goes on the BODY, not on .discovery. The media stage keeps the section
     gutter — 16px is the established gutter, so a full-width image is flush
     with the contract rather than breaking it, and insetting it too would have
     cost the pouches 38px of width for no alignment gain. The hairline above
     also stays at section width, tying the offer back to the intro headline,
     which sits at that same 16px like every other section-level heading on the
     site (hero, Formula, section registers). */
  .discovery__body {
    justify-items: stretch;
    gap: 0.9rem;
    padding-inline: calc(1.4rem + 1px);
  }
  .discovery__body h3 { font-size: clamp(1.75rem, 7vw, 2.2rem); }
  .discovery__body > p { max-width: none; }
  .discovery .c-btn--primary { width: 100%; }
}

/* -- SKU grid -------------------------------------------------------------- */
.sku-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
  gap: clamp(1rem, 2vw, 1.5rem);
  margin: 0;
  padding: 0;
  list-style: none;
}

/* ONE COLUMN IS THE PHONE ART DIRECTION, NOT AN OUTCOME OF auto-fit.

   16rem = 256px, so auto-fit takes a second track the moment the grid box
   reaches 536px. That is fine on a tablet and wrong on a phone: measured on a
   OnePlus 15 whose layout viewport is 720 CSS px, the grid box came out at
   687.8px and auto-fit produced `335.891px 335.891px` -- two cards side by
   side on a 360px-wide screen. Nothing was broken; the arithmetic was simply
   allowed to make an art-direction decision.

   760px is the canonical compact boundary this codebase already uses for the
   Process engine, so the Shop now agrees with it. Above it the intrinsic
   behaviour above is untouched. */
@media (max-width: 760px) {
  .sku-grid { grid-template-columns: 1fr; }
}

.sku-card {
  display: flex;
  flex-direction: column;
  background: var(--store-surface);
  border: 1px solid var(--store-hairline);
  border-radius: var(--radius-md);
  overflow: hidden;
  transition: border-color var(--dur-base) var(--ease-out),
              transform var(--dur-base) var(--ease-out);
}
.sku-card:hover {
  border-color: var(--store-hairline-strong);
  transform: translateY(-3px);
}
@media (prefers-reduced-motion: reduce) {
  .sku-card, .sku-card:hover { transform: none; transition: border-color var(--dur-base) linear; }
}

/* Borrows .section-register's typography -- small, letterspaced, upper, over a
   hairline -- without borrowing the class, because that one is the numbered
   chapter device used at section tops and this is a group label inside a
   section. Wraps to two lines rather than shrinking the type: at 360 the two
   halves do not fit on one line, and a scaled-down register stops being
   legible before it stops overflowing. */
.sku-grid__register {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.35rem 1rem;
  margin: 0 0 1.15rem;
  padding-bottom: 0.9rem;
  border-bottom: 1px solid var(--store-hairline);
  color: var(--store-metadata, #8a8280);
  font-family: var(--font-ui);
  font-size: 0.62rem;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}
.sku-grid__register i { font-style: normal; margin: 0 0.35em; opacity: 0.5; }

/* The PDP scenes are 1122x1402 (4:5). Locking the ratio here means the three
   cards keep identical faces even though each scene is graded differently. */
.sku-card__media {
  display: block;
  aspect-ratio: 4 / 5;
  overflow: hidden;
}
.sku-card__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.sku-card__body {
  display: grid;
  gap: 0.75rem;
  padding: 1.4rem;
  flex: 1;
  align-content: start;
}
.sku-card__body h3 {
  margin: 0;
  font-family: var(--font-ui);
  font-size: 1.08rem;
  font-weight: 500;
  letter-spacing: 0.01em;
  color: var(--moon);
}
/* inline-block + padding, not a bare inline link: at one line of text the tap
   target measured 23px. The two-line mango title cleared 44px on its own, so
   the three cards were also inconsistent with each other. */
.sku-card__body h3 a {
  display: inline-block;
  padding-block: 0.55rem;
  color: inherit;
  text-decoration: none;
}
.sku-card__body h3 a:hover { color: var(--nectar); }

.sku-card__note {
  margin: 0;
  font-family: var(--font-ui);
  font-size: 0.88rem;
  line-height: 1.55;
  color: var(--moon-soft);
}

.sku-card__spec {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin: 0;
  padding: 0;
  list-style: none;
}
.sku-card__spec li {
  font-family: var(--font-ui);
  font-size: 0.68rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--store-metadata);
  border: 1px solid var(--store-hairline);
  border-radius: var(--radius-pill);
  padding: 0.28rem 0.6rem;
}

.sku-card__buy {
  display: flex;
  align-items: end;
  justify-content: space-between;
  gap: 1rem;
  margin-top: auto;
  padding: 1.4rem;
  border-top: 1px solid var(--store-hairline);
}
.sku-card__buy .c-btn { padding-inline: 1.3rem; }

/* Each card carries its fruit's hue on the rule above the buy row, so the
   three read as a family without recolouring the whole card. */
.sku-card[data-sku="mango"] .sku-card__buy { border-top-color: var(--sku-mango); }
.sku-card[data-sku="jamun"] .sku-card__buy { border-top-color: var(--sku-jamun-bright); }
.sku-card[data-sku="pineapple"] .sku-card__buy { border-top-color: var(--sku-pineapple); }

/* ---------------------------------------------------------------------------
   FAQ — "Surrealist Swiss"

   Two halves, deliberately in tension.

   The SWISS half is the structure: a hard two-column grid, a hairline between
   every entry, mono indices with tabular figures, tight tracking, and a
   left column that behaves like a running head in a journal. Nothing here is
   decorative — the numbers are an index, the rules are separators, the mono
   labels are metadata. That is what makes it read clinical rather than merely
   minimal.

   There is no second layer. A WebGL field and a parallaxing plate were built
   here and cut after review — blurred colour behind a clinical grid reads as
   mud, not depth. What remains carries the section on type alone, which is
   what the reference actually does.

   The type stack is the site's existing grotesk. It is already a Swiss-adjacent
   face; what makes it clinical here is the treatment — scale contrast, tight
   tracking, and figures that line up — not a different font.
   --------------------------------------------------------------------------- */
.faq {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  padding: clamp(5rem, 11vw, 9rem) var(--gutter);
  background: var(--store-canvas);
}

/* -- the swiss grid --------------------------------------------------------- */

.faq__inner {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
  gap: clamp(2.5rem, 6vw, 6rem);
  align-items: start;
  max-width: 82rem;
  margin: 0 auto;
}

.faq__masthead {
  position: sticky;
  top: calc(var(--header-height) + 2rem);
  display: grid;
  gap: 1.15rem;
  justify-items: start;
}

/* Running head. Two fields separated by a rule, the way a journal states its
   section and category above the fold of a page. */
.faq__meta {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin: 0;
  padding-bottom: 0.9rem;
  width: 100%;
  border-bottom: 1px solid var(--store-hairline-strong);
  font-family: var(--font-ui);
  font-size: 0.66rem;
  font-weight: 500;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--store-metadata);
}
.faq__meta span + span::before {
  content: "/";
  margin-right: 0.75rem;
  color: var(--store-hairline-strong);
}

.faq__inner h2 {
  margin: 0;
  font-family: var(--font-ui);
  font-weight: 500;
  font-size: clamp(2rem, 4.2vw, 3.1rem);
  line-height: 1.02;
  /* Negative tracking at display size is the single biggest lever on whether a
     grotesk reads as "premium editorial" or as "system UI at 48px". */
  letter-spacing: -0.035em;
  color: var(--moon);
}

.faq__standfirst {
  margin: 0;
  max-width: 34ch;
  font-family: var(--font-ui);
  font-size: 0.95rem;
  line-height: 1.6;
  color: var(--moon-soft);
}

.faq__count {
  display: flex;
  align-items: baseline;
  gap: 0.55rem;
  margin: 0.5rem 0 0;
  font-family: var(--font-ui);
}
.faq__count b {
  font-size: 2.4rem;
  font-weight: 500;
  line-height: 1;
  letter-spacing: -0.04em;
  font-variant-numeric: tabular-nums;
  color: var(--nectar);
}
.faq__count span {
  font-size: 0.66rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--store-metadata);
}

/* -- the accordion ---------------------------------------------------------- */

.faq__list { display: grid; }

.faq-item {
  border-top: 1px solid var(--store-hairline);
  /* Deep-link landing clearance, same reasoning as the #discovery rule in
     landing.css: the header is sticky, so a fragment jump parked the FAQ
     heading at viewport 6px with 46px of header sitting on top of it.
     Derived from --header-height rather than a pixel guess, so it tracks
     the 5rem/4.4rem breakpoint automatically. */
  scroll-margin-top: calc(var(--header-height) + 2rem);
}
.faq-item:last-child { border-bottom: 1px solid var(--store-hairline); }

.faq-item summary {
  display: grid;
  grid-template-columns: 2.75rem minmax(0, 1fr) 1.5rem;
  align-items: baseline;
  gap: 0.5rem;
  padding: 1.35rem 0;
  cursor: pointer;
  list-style: none;
  transition: color var(--dur-fast) var(--ease-out);
}
.faq-item summary::-webkit-details-marker { display: none; }
.faq-item summary:hover .faq-item__q { color: var(--nectar); }

.faq-item__index {
  font-family: var(--font-ui);
  font-size: 0.72rem;
  font-weight: 500;
  letter-spacing: 0.1em;
  /* Tabular figures so twelve indices form a true column, not a ragged one.
     This is the detail that does most of the "scientific journal" work. */
  font-variant-numeric: tabular-nums;
  color: var(--store-metadata);
}

.faq-item__q {
  /* An <h3> per canonical section 16, so it needs its UA margin and default
     heading size neutralised — otherwise the three-column summary row loses
     its baseline alignment. */
  margin: 0;
  font-family: var(--font-ui);
  font-size: clamp(1.02rem, 1.7vw, 1.28rem);
  font-weight: 500;
  line-height: 1.28;
  letter-spacing: -0.017em;
  color: var(--moon);
  transition: color var(--dur-fast) var(--ease-out),
              text-shadow var(--dur-base) var(--ease-out);
}

/* The bloom. Restrained on purpose: a soft amber halo on the OPEN question
   only, so the light in the section always has exactly one source. Bloom on
   everything is just a blurry page. */
.faq-item[open] .faq-item__index { color: var(--nectar); }
.faq-item[open] .faq-item__q {
  color: var(--moon);
  text-shadow: 0 0 26px rgba(255, 165, 10, 0.34), 0 0 4px rgba(255, 165, 10, 0.18);
}

/* Plus sign built from two rules rather than a glyph, so it can rotate into a
   minus cleanly and stays optically identical at every size. */
.faq-item__mark {
  position: relative;
  justify-self: end;
  align-self: center;
  width: 0.86rem;
  height: 0.86rem;
}
.faq-item__mark::before,
.faq-item__mark::after {
  content: "";
  position: absolute;
  inset: 50% 0 auto 0;
  height: 1px;
  background: var(--store-metadata);
  transition: transform var(--dur-base) var(--ease-out),
              background-color var(--dur-fast) var(--ease-out);
}
.faq-item__mark::after { transform: rotate(90deg); }
.faq-item[open] .faq-item__mark::before,
.faq-item[open] .faq-item__mark::after { background: var(--nectar); }
.faq-item[open] .faq-item__mark::after { transform: rotate(180deg); }

/* Padding belongs to the PANEL, not to <p>. It used to sit on the paragraph,
   which was fine while every answer was prose — the moment answers contained
   ledgers, pickers and buttons, those children hung off the left edge while
   the paragraphs stayed indented. One indent, applied once, and every child
   lines up against the same column as the question above it. */
.faq-item__panel {
  overflow: hidden;
  padding: 0 1.5rem 1.6rem 3.25rem;
}
.faq-item__panel > * { max-width: 68ch; }
.faq-item__panel p {
  margin: 0;
  font-family: var(--font-ui);
  font-size: 0.97rem;
  line-height: 1.72;
  color: var(--moon-soft);
}

@media (max-width: 900px) {
  .faq__inner { grid-template-columns: 1fr; gap: 2.5rem; }
  .faq__masthead { position: static; }
  .faq-item summary { grid-template-columns: 2.25rem minmax(0, 1fr) 1.25rem; }
  .faq-item__panel { padding-left: 2.75rem; padding-right: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .faq-item__q { transition: none; }
  .faq-item__mark::before, .faq-item__mark::after { transition: none; }
}

/* The FSSAI disclosure that has to travel with every no-added-sugar claim
   (canonical section 4). Quiet but never hidden — it is a required statement,
   not a footnote, so it gets the same treatment as a caption rather than
   being tucked into small print. */
.faq-item__disclosure {
  font-family: var(--font-ui);
  font-size: 0.72rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--store-metadata);
}
.faq-item__disclosure { margin: 0.9rem 0 0; }

/* Crawlable internal links to each product (canonical section 20). */
.faq-item__collection {
  margin: 0.8rem 0 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: 0.35rem;
}
.faq-item__collection a {
  display: inline-block;
  padding-block: 0.5rem;
  font-family: var(--font-ui);
  font-size: 0.92rem;
  color: var(--nectar);
  text-decoration: none;
  border-bottom: 1px solid transparent;
  transition: border-color var(--dur-fast) var(--ease-out);
}
.faq-item__collection a:hover { border-bottom-color: var(--nectar); }

.faq-item__panel p + p { margin-top: 0.85rem; }

/* ---------------------------------------------------------------------------
   HEADER — CONDENSED STATE
   The bar used to disappear on downward scroll. It now shrinks instead, so the
   Bag never leaves the screen on a 24-screen page. Height and wordmark shrink
   together; the nav links drop out on the way down because they are the part a
   scrolling customer is least likely to want mid-page.
   --------------------------------------------------------------------------- */
/* Height alone cannot do this. The bar carries a Bag and a Menu control, and
   those must stay at 44px for a thumb — so 46px is the floor while they are
   present, against 57px at rest. Only 11px.

   What actually reads as "much thinner" is losing the CHROME. At rest the
   header is a floating pill: inset from three edges, rounded, shadowed, with
   12px of gap above it. Condensed it goes flush — full width, square, no
   shadow, no offset — which takes the space it occupies from 69px to 46px and
   changes it from an object sitting on the page to a rule drawn across it. */
.site-header.is-condensed {
  /* Flush to the very top of the layout viewport, which under viewport-fit=cover
     is BEHIND the status bar. The rail therefore grows by the inset and pads its
     content down by the same amount: the tinted bar covers the status bar strip
     (so text never collides with the clock) while the controls stay 2.9rem tall
     and fully tappable. On anything without a notch every inset is 0px and this
     collapses to exactly the previous geometry. */
  height: calc(2.9rem + var(--safe-top, 0px));
  padding-top: var(--safe-top, 0px);
  top: 0;
  right: 0;
  left: 0;
  border-width: 0 0 1px 0;
  border-radius: 0;
  border-color: rgba(255, 255, 255, 0.16);
  background: rgba(7, 7, 10, 0.92);
  box-shadow: none;
  padding-inline: var(--gutter-left, var(--gutter)) var(--gutter-right, var(--gutter));
}
.site-header {
  transition: transform 280ms var(--ease-out), background-color 280ms var(--ease-out),
              border-color 280ms var(--ease-out), height 260ms var(--ease-out),
              top 260ms var(--ease-out), border-radius 260ms var(--ease-out),
              padding 260ms var(--ease-out);
}
.site-header.is-condensed .wordmark { width: 5.9rem; }
.site-header.is-condensed .wordmark img { height: 1.45rem; }
.site-header.is-condensed .desktop-nav { opacity: 0; pointer-events: none; }
.site-header .desktop-nav { transition: opacity 200ms var(--ease-out); }
.site-header .wordmark,
.site-header .wordmark img { transition: width 260ms var(--ease-out), height 260ms var(--ease-out); }

@media (max-width: 720px) {
  /* Same inset arithmetic as the wider rule — without repeating it here the
     narrow breakpoint would reset height/padding and put the wordmark back
     under the status bar on exactly the devices that have one. */
  .site-header.is-condensed {
    height: calc(2.9rem + var(--safe-top, 0px));
    padding-top: var(--safe-top, 0px);
    top: 0;
    padding-inline: max(0.75rem, var(--safe-left, 0px)) max(0.75rem, var(--safe-right, 0px));
  }
  .site-header.is-condensed .wordmark { width: 5.2rem; }
  .site-header.is-condensed .wordmark img { height: 1.25rem; }
  /* Controls hold 44px. Thinness is bought from chrome, never from thumbs. */
  .site-header.is-condensed .bag-button,
  .site-header.is-condensed .menu-button { min-height: 2.45rem; }
}

@media (prefers-reduced-motion: reduce) {
  .site-header .desktop-nav,
  .site-header .wordmark,
  .site-header .wordmark img { transition: none; }
}

/* ---------------------------------------------------------------------------
   DESKTOP COMMERCE CONTROL
   The counterpart to the mobile rail below, and it exists for the same reason:
   between the shop grid and the first product block there are nine screens of
   Gateway and Process. Below 861px the rail carries the buy across them. Above
   861px nothing did -- the header held a Bag, and a Bag is only useful once
   something is already in it.

   It goes in the header rather than in a second fixed element because the
   header is already fixed, already survives `is-condensed`, and is already
   where a customer looks to move around the page. One control, no new chrome,
   and nothing new on a phone.

   Metrics are .bag-button's, not .c-btn's. This has to read as a member of the
   header's control group rather than as a page button that wandered up into
   the chrome -- so it takes the header's 0.7rem/0.1em type and 0.22rem radius,
   and only the fill is borrowed from .c-btn--primary.
   --------------------------------------------------------------------------- */
.header-buy { display: none; }

@media (min-width: 861px) {
  .header-buy {
    display: inline-flex;
    align-items: center;
    gap: 0.6rem;
    /* .bag-button's height, rebuilt from its own parts rather than copied as
       a number: its count chip is 2.55rem, its block padding 0.2rem a side,
       and it carries a 1px border. Its own min-height is 44px and loses to
       that content, so matching the declaration would have left this control
       5px short of the one it sits beside. */
    min-height: calc(2.55rem + 0.4rem + 2px);
    padding: 0 1.05rem;
    /* NOT --nectar, which is what .c-btn--primary and .buy-rail__primary take.
       Rendered side by side with the Bag's lime count chip, a solid nectar
       slab put two saturated fills in the chrome 8px apart and the header
       stopped reading as one control group. The rail can carry the solid fill
       because it floats alone; here the same fill is noise.

       So: --store-gold, the one commerce accent, as a tint rather than a slab.
       It is unmistakably the buy without competing with the lime, and it keeps
       the header in the restrained register the rest of the chrome uses. */
    /* rgba first, color-mix second. The rest of the file already leans on
       color-mix, but an unsupported value here would drop a BUY control to no
       border and no ground -- worth two lines of cascade. #e7a51a is
       --store-gold; the literal exists only because color-mix cannot be its
       own fallback. */
    border: 1px solid rgba(231, 165, 26, 0.48);
    border: 1px solid color-mix(in srgb, var(--store-gold) 48%, transparent);
    border-radius: 0.22rem;
    background: rgba(231, 165, 26, 0.15);
    background: color-mix(in srgb, var(--store-gold) 15%, transparent);
    color: var(--store-gold);
    font-family: var(--font-ui);
    font-size: 0.7rem;
    font-weight: 500;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    text-decoration: none;
    white-space: nowrap;
    transition: transform 120ms var(--ease-out), background-color 180ms ease;
  }
  .header-buy b { font-weight: 500; font-variant-numeric: tabular-nums; }
  .header-buy:active { transform: scale(0.97); }
}

/* 861-1099, price only. Two different reasons, one treatment. Below 901 the
   nav has collapsed to the Menu button and wordmark, buy, Bag and Menu share
   one row. Above it the nav is back and centred, and measured at rest the nav
   and this control touch at exactly 0px from 901 through ~1080 -- the label is
   what closes that gap. Dropping it restores 107px and the two clear each
   other by 32px at 1100, where the label returns. The price is the half that
   does the work, so the price is the half that stays. */
@media (min-width: 861px) and (max-width: 1099px) {
  .header-buy span { display: none; }
  .header-buy { padding: 0 0.9rem; }
}

@media (hover: hover) and (pointer: fine) {
  .header-buy:hover {
    border-color: var(--store-gold);
    background: rgba(231, 165, 26, 0.26);
    background: color-mix(in srgb, var(--store-gold) 26%, transparent);
  }
}

@media (prefers-reduced-motion: reduce) {
  .header-buy { transition: background-color 180ms ease; }
  .header-buy:active { transform: none; }
}

/* ---------------------------------------------------------------------------
   MOBILE COMMERCE RAIL
   One rail, not a wall of CTAs. It only exists below 860px, and only after the
   customer has already passed the shop — before that the page has its own
   buttons and a second set would be noise.

   Deliberately NOT a full-width slab of accent colour. It borrows the header's
   own treatment (hairline, blur, near-black) so it reads as part of the same
   chrome rather than as a Shopify app bar bolted onto the bottom.
   --------------------------------------------------------------------------- */
.buy-rail {
  position: fixed;
  z-index: 235;
  left: 0.5rem;
  right: 0.5rem;
  bottom: max(0.5rem, env(safe-area-inset-bottom));
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: stretch;
  gap: 1px;
  padding: 1px;
  border: 1px solid rgba(255, 255, 255, 0.16);
  border-radius: 0.4rem;
  background: rgba(7, 7, 10, 0.9);
  backdrop-filter: blur(18px) saturate(145%);
  box-shadow: 0 0.75rem 2.5rem rgba(0, 0, 0, 0.45);
  /* Starts translated out and is revealed by a class, so a failed script
     leaves it off-screen rather than stranded over the footer. */
  transform: translateY(calc(100% + 1rem));
  opacity: 0;
  transition: transform 380ms var(--ease-drawer), opacity 240ms var(--ease-out);
}
.buy-rail.is-visible { transform: translateY(0); opacity: 1; }

/* `[hidden]` MUST win here. The UA sheet sets [hidden]{display:none} at
   specificity (0,0,1); `.buy-rail__primary{display:flex}` is (0,1,0) and was
   silently beating it, so the trio button JS had already hidden still occupied
   its grid cell and pushed the secondary onto a second row. That phantom cell —
   not a design choice — is what made the rail a 125px two-row panel with a
   duplicate "Try all three ₹599" in it. */
.buy-rail [hidden] { display: none; }

.buy-rail__primary,
.buy-rail__secondary {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  /* One row, thumb-sized: 3.4rem + 1px padding + 1px border lands the rail just
     under 60px before the safe-area inset. */
  min-height: 3.4rem;
  padding: 0 0.9rem;
  white-space: nowrap;
  border-radius: 0.3rem;
  font-family: var(--font-ui);
  font-size: 0.82rem;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  text-decoration: none;
}
.buy-rail__primary { background: var(--nectar); color: var(--ink); }
.buy-rail__primary b { font-weight: 500; }
.buy-rail__secondary { color: var(--moon-soft); }
.buy-rail__secondary:active { color: var(--nectar); }

@media (min-width: 861px) { .buy-rail { display: none; } }

@media (prefers-reduced-motion: reduce) {
  .buy-rail { transition: opacity 200ms linear; transform: none; }
  .buy-rail:not(.is-visible) { opacity: 0; pointer-events: none; }
}

/* ---------------------------------------------------------------------------
   COMMERCE RE-ENTRY
   Two of these on the page, both immediately after a section finishes making
   an argument. Deliberately austere: a rule, a line of display type, two
   controls. If this looked like the shop section the page would read as
   though it had looped back to the beginning.
   --------------------------------------------------------------------------- */
.reentry {
  display: grid;
  justify-items: center;
  gap: 1.4rem;
  padding: clamp(3.5rem, 8vw, 6rem) var(--gutter);
  text-align: center;
  background: var(--store-canvas);
  border-block: 1px solid var(--store-hairline);
}

.reentry__line {
  margin: 0;
  max-width: 22ch;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(1.6rem, 3.6vw, 2.6rem);
  line-height: 1.06;
  letter-spacing: -0.02em;
  text-wrap: balance;
  color: var(--moon);
}

.reentry__actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.75rem;
}

.reentry__terms {
  margin: 0;
  font-family: var(--font-ui);
  font-size: 0.72rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--store-metadata);
}

/* The closing one sits on the page floor rather than the default field, so the
   page darkens toward its end instead of repeating a mid-page tone. */
.reentry--close { background: var(--store-surface); }

@media (max-width: 620px) {
  .reentry__actions { width: 100%; flex-direction: column; }
  .reentry__actions .c-btn { width: 100%; }
}

/* Outbound links from an answer to the page that answers it at length
   (canonical section 20). Set as a quiet footnote rather than a button — the
   answer above already satisfied the question; this is for the reader who
   wants more, not a call to action competing with the commerce. */
.faq-item__more {
  margin: 1rem 0 0;
  font-family: var(--font-ui);
  font-size: 0.82rem;
  letter-spacing: 0.02em;
}
.faq-item__more a {
  display: inline-block;
  padding-block: 0.55rem;
  color: var(--nectar);
  text-decoration: none;
  border-bottom: 1px solid rgba(255, 165, 10, 0.32);
  padding-bottom: 1px;
}
.faq-item__more a:hover { border-bottom-color: var(--nectar); }

.process-engine__further {
  display: flex;
  flex-wrap: wrap;
  gap: 1.5rem;
  justify-content: center;
  margin: 1rem 0 0;
  font-family: var(--font-ui);
  font-size: 0.72rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}
/* The span is the retired self-link: same row, same muted weight, no hover and
   no destination. Typography lives here so inert copy cannot drift brighter
   than the live link beside it. */
.process-engine__further a,
.process-engine__further span {
  display: inline-block;
  padding-block: 0.6rem;
  color: var(--store-metadata);
  text-decoration: none;
  border-bottom: 1px solid transparent;
  transition: color var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out);
}
.process-engine__further a:hover { color: var(--nectar); border-bottom-color: var(--nectar); }


/* ---------------------------------------------------------------------------
   FAQ ANSWER STRUCTURES — closer edition

   The FAQ stopped being a reference and became the last thing a customer reads
   before deciding. Three of these answers are really small tables — a flavour
   picker, an ingredient declaration, a set of occasions — and setting them as
   prose would bury exactly the information the question was asked to surface.

   Set as ledgers, in the same clinical register as the rest of the section:
   hairline rules, two columns, no ornament. The structure IS the answer.
   --------------------------------------------------------------------------- */

/* A line that lands. Used where the copy resolves to a single sentence worth
   more weight than the paragraph before it. */
.faq-item__kicker {
  font-family: var(--font-ui);
  font-size: 1.02rem;
  font-weight: 500;
  line-height: 1.42;
  letter-spacing: -0.012em;
  color: var(--moon);
}

.faq-item__ledger,
.faq-item__picker {
  margin: 1.05rem 0 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: 1px;
  background: var(--store-hairline);
  border-block: 1px solid var(--store-hairline);
}
.faq-item__ledger li,
.faq-item__picker li {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 1rem;
  align-items: baseline;
  padding: 0.66rem 0;
  background: var(--store-surface);
  font-family: var(--font-ui);
  font-size: 0.88rem;
}
.faq-item__ledger span,
.faq-item__picker span { color: var(--store-metadata); }
.faq-item__ledger b,
.faq-item__picker b { color: var(--moon); font-weight: 500; }

/* The flavour picker leads with the CRAVING, not the fruit — a customer who
   knows which fruit they want is not reading this question. So the recommended
   SKU is the emphasised half. */
.faq-item__picker b { color: var(--nectar); }

.faq-item__occasions {
  margin: 0.9rem 0 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
}
.faq-item__occasions li {
  font-family: var(--font-ui);
  font-size: 0.76rem;
  letter-spacing: 0.06em;
  color: var(--moon-soft);
  border: 1px solid var(--store-hairline);
  border-radius: var(--radius-pill);
  padding: 0.32rem 0.7rem;
}

/* Commerce inside an answer, but only in the two entries whose whole job is to
   move toward the First Harvest Trio. Anywhere else this would be a CTA wall. */
.faq-item__cta {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
  margin: 1.25rem 0 0;
}
.faq-item__cta .c-btn { padding: 0.8rem 1.4rem; font-size: 0.82rem; }

/* Inline links inside answer prose (the First Harvest Trio mention in the
   fruit-picker answer). */
.faq-item__panel p a:not(.c-btn) {
  color: var(--nectar);
  text-decoration: none;
  border-bottom: 1px solid rgba(255, 165, 10, 0.32);
}
.faq-item__panel p a:not(.c-btn):hover { border-bottom-color: var(--nectar); }

@media (max-width: 900px) {
  .faq-item__ledger,
  .faq-item__picker,
  .faq-item__occasions,
  .faq-item__cta { margin-left: 0; }
  .faq-item__picker li { grid-template-columns: 1fr; gap: 0.15rem; }
  .faq-item__cta .c-btn { flex: 1 1 100%; }
}

/* ---------------------------------------------------------------------------
   DISCLOSURE HIERARCHY

   "CONTAINS NATURALLY OCCURRING SUGARS" was set as a standalone line under the
   hero commerce block, uppercase and letter-spaced at the same weight as the
   payment terms. It read as a warning label on a premium product — the first
   thing the eye found after the price.

   It is still present, still crawlable, still attached to the claim it
   qualifies. It is simply no longer competing with it: it now sits inside the
   proof-strip cell that makes the no-added-sugar claim, in supporting type.
   The customer reads 0g ADDED SUGAR, then the qualification. Which is the
   correct order — the claim is the campaign, the disclosure is the footnote.
   --------------------------------------------------------------------------- */
.proof-strip li small {
  display: block;
  margin-top: 0.5rem;
  font-size: 0.58rem;
  font-weight: 400;
  letter-spacing: 0.08em;
  text-transform: none;
  line-height: 1.4;
  color: var(--store-metadata);
  opacity: 0.82;
}

.faq-item__disclosure {
  font-size: 0.78rem;
  letter-spacing: 0.02em;
  text-transform: none;
  color: var(--store-metadata);
}

/* ---------------------------------------------------------------------------
   YIELD LEDGER — CURRENTLY UNUSED, DELIBERATELY KEPT

   Three rows, each a per-fruit fresh-fruit input mass, set at display scale.
   The markup was removed from FAQ 02 on 2026-09-08: no current production
   documentation supports an input figure, so there is nothing for the ledger
   to hold and canonical section 9 keeps the claim as PRODUCTION DATA REQUIRED.

   The rules stay because the ledger is the correct presentation for that fact
   the day it is documented, and because deleting them would make republishing
   the claim look like new design work rather than the reinstatement it is.
   .yield-ledger__note is NOT unused -- FAQ 04 still uses it for the retention
   qualifier.
   --------------------------------------------------------------------------- */
.yield-ledger {
  margin: 1.3rem 0 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: 1px;
  background: var(--store-hairline);
  border-block: 1px solid var(--store-hairline-strong);
}
.yield-ledger li {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: baseline;
  gap: 0.85rem;
  padding: 0.95rem 0;
  background: var(--store-surface);
  font-family: var(--font-ui);
}
.yield-ledger b {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(1.8rem, 5vw, 2.6rem);
  line-height: 1;
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
  color: var(--nectar);
}
.yield-ledger span { font-size: 0.86rem; color: var(--moon-soft); }
.yield-ledger i {
  font-style: normal;
  font-size: 0.66rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--store-metadata);
  white-space: nowrap;
}
.yield-ledger__note {
  margin: 0.8rem 0 0;
  font-family: var(--font-ui);
  font-size: 0.74rem;
  line-height: 1.55;
  color: var(--store-metadata);
}

/* ---------------------------------------------------------------------------
   FRUIT PICKER — three blocks, not a table
   --------------------------------------------------------------------------- */
.fruit-picker {
  margin: 1.1rem 0 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: 1px;
  background: var(--store-hairline);
  border-block: 1px solid var(--store-hairline);
}
.fruit-picker li {
  display: grid;
  gap: 0.3rem;
  padding: 0.95rem 0;
  background: var(--store-surface);
  font-family: var(--font-ui);
}
.fruit-picker b {
  font-size: 0.72rem;
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--nectar);
}
.fruit-picker span { font-size: 1rem; color: var(--moon); letter-spacing: -0.008em; }
.fruit-picker i { font-style: normal; font-size: 0.84rem; color: var(--store-metadata); }

/* Attribute chips — LIGHT / CRISP / POROUS / INTENSE */
.faq-item__attrs {
  margin: 1rem 0 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
}
.faq-item__attrs li {
  font-family: var(--font-ui);
  font-size: 0.7rem;
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--moon);
  border: 1px solid var(--store-hairline-strong);
  border-radius: var(--radius-pill);
  padding: 0.38rem 0.85rem;
}
.faq-item__attrs--wide li {
  letter-spacing: 0.04em;
  text-transform: none;
  font-size: 0.78rem;
  font-weight: 400;
  color: var(--moon-soft);
  border-color: var(--store-hairline);
}

/* First Harvest Trio price — the saving is the argument, so it is legible */
.box-price {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin: 1.1rem 0 0;
  font-family: var(--font-ui);
}
.box-price b {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(1.9rem, 5vw, 2.6rem);
  line-height: 1;
  letter-spacing: -0.03em;
  color: var(--moon);
}
.box-price del { font-size: 0.95rem; color: var(--store-metadata); text-decoration-thickness: 1px; }
.box-price em {
  font-style: normal;
  font-size: 0.68rem;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink);
  background: var(--nectar);
  padding: 0.28rem 0.6rem;
  border-radius: var(--radius-pill);
}

@media (max-width: 620px) {
  .yield-ledger li { grid-template-columns: auto minmax(0, 1fr); row-gap: 0.2rem; }
  .yield-ledger i { grid-column: 2; }
}

