/* ==========================================================================
   TOM'S HARVEST — one page
   Layout from the hand-drawn wireframes; visual language from the packaging.
   ========================================================================== */

/* --- reset ---------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
body { -webkit-font-smoothing: antialiased; }
img, svg, video { display: block; max-width: 100%; }
img { height: auto; }
button, input, select { font: inherit; color: inherit; }
button { background: none; border: 0; cursor: pointer; }
ul { list-style: none; padding: 0; }
a { color: inherit; text-decoration: none; }
/* the shelf hides the off-tab cards with the `hidden` attribute; the UA's
   display:none for it loses to any author display, so state it here */
[hidden] { display: none !important; }

/* --- tokens --------------------------------------------------------------- */
:root {
  /* canvas — the ivory the packs are printed on */
  --ivory:        #F7F2E6;
  --ivory-deep:   #EFE7D5;
  --paper:        #FFFDF8;

  /* ink — no black anywhere on the page. Headings and brand furniture take
     the green sampled straight off the logo mark; running text is a warm dark
     grey, which is as close to black as this palette goes. */
  --forest:       #5A7236;
  --forest-soft:  #5A723680;
  --charcoal:     #3E3B34;
  --muted:        #6E6A5E;

  /* fruit accents, sampled from the packs */
  --mango:        #E8942F;
  --mango-tint:   #F8DCAE;
  --strawberry:   #C9385C;
  --strawberry-tint:#F3C6D2;
  --avocado:      #6E9A3A;
  --avocado-tint: #D2E2B4;
  --tropical:     #E4711F;
  --tropical-tint:#F8D3A8;
  --berry:        #7A4A9E;
  --berry-tint:   #DCC8EC;
  --peach:        #E8925E;
  --peach-tint:   #F8D8C2;

  /* the wireframe's marker green, still the hub boxes' default frame.
     The section stain colours now live on the [data-stain] rules below. */
  --blob-hub:     #8DC63F;

  /* one reading measure for the whole page: body copy never runs wider than
     this, so every block of text breaks at a comparable line length. */
  --measure:      62ch;
  --measure-tight:52ch;

  --radius:       22px;
  --radius-lg:    30px;
  --shadow-sm:    0 2px 10px rgba(29, 68, 41, .06);
  --shadow:       0 14px 40px -18px rgba(29, 68, 41, .28);
  --shadow-lg:    0 40px 80px -40px rgba(29, 68, 41, .45);
  --gutter:       clamp(20px, 5vw, 56px);
  --maxw:         1220px;

  --sans: "Poppins", ui-sans-serif, -apple-system, "Segoe UI", Roboto, sans-serif;
  /* Lora, not Fraunces: Fraunces draws its lowercase f with a tail that drops
     below the baseline at every weight and optical size, and it read as a
     broken glyph on the page. Lora keeps the warmth without the quirk. */
  --serif: "Lora", ui-serif, Georgia, "Times New Roman", serif;

  /* The pour silhouette as a mask, so the flat CSS blobs behind the hero and in
     the card corners get the same lobed edge as the inline-SVG stains instead of
     a border-radius oval. Shape from tools/blobs.py; colour stays on the element,
     which is what lets one shape serve every fruit tint. */
  --pour: url("data:image/svg+xml,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%20200%20200'%3E%3Cpath%20d%3D'M195%2C100%20C196%2C108%20196%2C118%20194%2C126%20C191%2C134%20185%2C141%20179%2C147%20C173%2C153%20165%2C158%20158%2C163%20C151%2C168%20145%2C174%20137%2C177%20C129%2C180%20120%2C179%20111%2C178%20C103%2C178%2094%2C174%2086%2C174%20C77%2C174%2069%2C179%2060%2C179%20C52%2C180%2042%2C180%2035%2C176%20C28%2C173%2022%2C165%2019%2C157%20C15%2C150%2015%2C140%2015%2C131%20C15%2C123%2017%2C114%2018%2C106%20C19%2C97%2021%2C88%2023%2C80%20C24%2C71%2023%2C62%2026%2C54%20C29%2C46%2033%2C38%2039%2C32%20C45%2C27%2054%2C24%2062%2C21%20C70%2C18%2078%2C14%2086%2C12%20C95%2C9%20104%2C5%20112%2C7%20C120%2C8%20128%2C14%20134%2C19%20C140%2C25%20143%2C34%20149%2C41%20C154%2C47%20162%2C51%20168%2C57%20C175%2C63%20182%2C69%20186%2C76%20C191%2C83%20194%2C92%20195%2C100%20Z'%2F%3E%3C%2Fsvg%3E");
  --pour-alt: url("data:image/svg+xml,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%20200%20200'%3E%3Cpath%20d%3D'M177%2C100%20C177%2C108%20183%2C117%20183%2C125%20C183%2C134%20180%2C143%20176%2C150%20C172%2C157%20163%2C161%20157%2C167%20C150%2C173%20144%2C179%20137%2C184%20C129%2C188%20121%2C192%20113%2C193%20C105%2C193%2096%2C190%2088%2C187%20C80%2C183%2073%2C178%2066%2C173%20C59%2C167%2053%2C161%2046%2C156%20C39%2C151%2032%2C146%2025%2C140%20C19%2C135%2011%2C129%207%2C122%20C3%2C115%200%2C106%201%2C98%20C2%2C90%208%2C82%2012%2C74%20C17%2C67%2021%2C60%2026%2C53%20C32%2C46%2036%2C37%2042%2C32%20C49%2C28%2059%2C27%2067%2C26%20C76%2C25%2085%2C27%2093%2C25%20C102%2C24%20110%2C19%20118%2C18%20C127%2C16%20136%2C15%20144%2C17%20C152%2C18%20161%2C22%20167%2C27%20C174%2C33%20179%2C41%20181%2C49%20C183%2C57%20181%2C66%20180%2C74%20C180%2C83%20176%2C92%20177%2C100%20Z'%2F%3E%3C%2Fsvg%3E");
  /* The same two silhouettes, but told to stretch. An SVG used as a mask image
     keeps its own aspect ratio (xMidYMid meet) and sits square in the middle of
     whatever box it is given — which is fine for the near-square pours on the
     cards, and useless for a pour that has to run wide and shallow. */
  --pour-flat: url("data:image/svg+xml,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%20200%20200'%20preserveAspectRatio%3D'none'%3E%3Cpath%20d%3D'M195%2C100%20C196%2C108%20196%2C118%20194%2C126%20C191%2C134%20185%2C141%20179%2C147%20C173%2C153%20165%2C158%20158%2C163%20C151%2C168%20145%2C174%20137%2C177%20C129%2C180%20120%2C179%20111%2C178%20C103%2C178%2094%2C174%2086%2C174%20C77%2C174%2069%2C179%2060%2C179%20C52%2C180%2042%2C180%2035%2C176%20C28%2C173%2022%2C165%2019%2C157%20C15%2C150%2015%2C140%2015%2C131%20C15%2C123%2017%2C114%2018%2C106%20C19%2C97%2021%2C88%2023%2C80%20C24%2C71%2023%2C62%2026%2C54%20C29%2C46%2033%2C38%2039%2C32%20C45%2C27%2054%2C24%2062%2C21%20C70%2C18%2078%2C14%2086%2C12%20C95%2C9%20104%2C5%20112%2C7%20C120%2C8%20128%2C14%20134%2C19%20C140%2C25%20143%2C34%20149%2C41%20C154%2C47%20162%2C51%20168%2C57%20C175%2C63%20182%2C69%20186%2C76%20C191%2C83%20194%2C92%20195%2C100%20Z'%2F%3E%3C%2Fsvg%3E");
  --pour-flat-alt: url("data:image/svg+xml,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%20200%20200'%20preserveAspectRatio%3D'none'%3E%3Cpath%20d%3D'M177%2C100%20C177%2C108%20183%2C117%20183%2C125%20C183%2C134%20180%2C143%20176%2C150%20C172%2C157%20163%2C161%20157%2C167%20C150%2C173%20144%2C179%20137%2C184%20C129%2C188%20121%2C192%20113%2C193%20C105%2C193%2096%2C190%2088%2C187%20C80%2C183%2073%2C178%2066%2C173%20C59%2C167%2053%2C161%2046%2C156%20C39%2C151%2032%2C146%2025%2C140%20C19%2C135%2011%2C129%207%2C122%20C3%2C115%200%2C106%201%2C98%20C2%2C90%208%2C82%2012%2C74%20C17%2C67%2021%2C60%2026%2C53%20C32%2C46%2036%2C37%2042%2C32%20C49%2C28%2059%2C27%2067%2C26%20C76%2C25%2085%2C27%2093%2C25%20C102%2C24%20110%2C19%20118%2C18%20C127%2C16%20136%2C15%20144%2C17%20C152%2C18%20161%2C22%20167%2C27%20C174%2C33%20179%2C41%20181%2C49%20C183%2C57%20181%2C66%20180%2C74%20C180%2C83%20176%2C92%20177%2C100%20Z'%2F%3E%3C%2Fsvg%3E");
}

/* --- base ----------------------------------------------------------------- */
body {
  font-family: var(--sans);
  font-weight: 400;
  font-size: clamp(15px, .35vw + 14px, 16.5px);
  line-height: 1.68;
  color: var(--charcoal);
  background: var(--ivory);
  overflow-x: hidden;
}

/* The canvas is one flat ivory from the nav to the footer — no washes, no
   gradients, no per-section tinting. Every bit of colour on the page comes from
   a pour, and a pour has a shape; anything painted as a background field would
   read as a panel again. */

.wrap { position: relative; z-index: 1; width: 100%; max-width: var(--maxw); margin-inline: auto; padding-inline: var(--gutter); }

/* The pours are placed past the section's own edges on purpose, so they bleed
   off the page instead of stopping at it. Off the *sides* that means real
   overflow, and on iOS `body { overflow-x: hidden }` does not hold it: the page
   drags sideways and shows empty ground to the right.
   `clip` is the tool rather than `hidden` — it clips the horizontal axis while
   leaving the vertical one visible, so the pours still run across section
   boundaries, which is the whole point of them. `hidden` cannot do that: it
   would force the other axis to scroll and cut the flow between sections. */
section, .foot { overflow-x: clip; }
section { position: relative; }

h1, h2, h3, h4 { line-height: 1.1; font-weight: 700; letter-spacing: -.02em; color: var(--forest); }
h1 { font-size: clamp(2.1rem, 4.4vw, 3.5rem); }
h2 { font-size: clamp(1.7rem, 3.2vw, 2.6rem); }
h3 { font-size: clamp(1.1rem, 1.5vw, 1.35rem); }

.oh {                                   /* the "oh" lockup from the pack front */
  font-family: var(--serif);
  font-style: italic;
  font-weight: 400;
  text-transform: lowercase;
  letter-spacing: 0;
}
.eyebrow {
  font-size: .69rem; font-weight: 700; letter-spacing: .19em;
  text-transform: uppercase; color: var(--forest); opacity: .72;
}
.lede { font-size: clamp(1rem, 1.1vw, 1.1rem); color: var(--muted); max-width: var(--measure); }
.center { text-align: center; }

/* --- the stain: the pack's poured paint, reused as a title backdrop ---------
   Straight off the pouches: a thick pour with a smooth lobed edge, printed in
   three tones of one fruit family stacked with a small offset so a deeper tone
   runs along one side. The wordmark sits straight on the colour, set in the same
   serif as the logo.
   Shapes come from tools/blobs.py — see the note there on why the outline is
   built by pushing a superellipse along its normals rather than radially. */
.blob-title { position: relative; display: inline-block; padding: 2.9rem 3.9rem 2.7rem; }
.blob-title > .stain {
  /* `max-width: none` is the whole point: the reset clamps every svg to 100%,
     which pinned this box at `left: -5%` but only 100% wide, and shunted every
     wordmark 25-30px right of its own pour.
     The explicit height has to stay. Drop it and the svg falls back to its
     viewBox aspect ratio instead of the -8% insets, grows to 158% tall, and
     paints over the lede underneath. */
  position: absolute; inset: -8% -5%; width: 110%; height: 116%;
  max-width: none;
  overflow: visible; z-index: 0; pointer-events: none;
}
.stain path { transform-box: fill-box; transform-origin: 50% 50%; }
.stain .stain-c { fill: var(--stain-deep); opacity: .86; }
.stain .stain-b { fill: var(--stain-mid); }
.stain .stain-f { fill: var(--stain); }

.blob-title > * { position: relative; z-index: 1; }
.blob-title h2, .blob-title h1 {
  font-family: var(--serif);
  font-weight: 600;
  font-size: clamp(1.4rem, 2.8vw, 2.25rem);
  text-transform: uppercase; letter-spacing: .04em; white-space: nowrap;
  color: var(--forest);
}

/* the three layers drift against each other, so the silhouette reads as wet
   paint settling rather than a static shape */
.blob-title .stain-c { animation: stain-drift-a 23s ease-in-out infinite; }
.blob-title .stain-b { animation: stain-drift-b 19s ease-in-out infinite; }
.blob-title .stain-f { animation: stain-drift-c 16s ease-in-out infinite; }
@keyframes stain-drift-a {
  0%, 100% { transform: rotate(0deg)    scale(1, 1); }
  50%      { transform: rotate(1.1deg)  scale(1.035, 1.06); }
}
@keyframes stain-drift-b {
  0%, 100% { transform: rotate(0deg)    scale(1, 1); }
  50%      { transform: rotate(-.9deg)  scale(1.03, .955); }
}
@keyframes stain-drift-c {
  0%, 100% { transform: rotate(0deg)    scale(1, 1); }
  50%      { transform: rotate(.55deg)  scale(1.018, 1.03); }
}

/* Per-section palettes — each pour stays inside one fruit family: pale mass,
   mid tone, deep tone. */
[data-stain="shelf"]   { --stain: #E4F0CC; --stain-mid: #C8E39A; --stain-deep: #8DC63F; }
[data-stain="lab"]     { --stain: #FBE6C2; --stain-mid: #F6C87E; --stain-deep: #E8942F; }
[data-stain="story"]   { --stain: #F8DCE3; --stain-mid: #EE9CB2; --stain-deep: #C9385C; }
[data-stain="hub"]     { --stain: #E7D8F2; --stain-mid: #BE9BD8; --stain-deep: #7A4A9E; }
[data-stain="harvest"] { --stain: #FBDDC6; --stain-mid: #F5AE7A; --stain-deep: #E4711F; }
[data-stain="cta"]     { --stain: #FBE7A8; --stain-mid: #F6D372; --stain-deep: #F2C230; }

/* The wordmarks used to carry a thick white outline lifted off the pack fronts.
   It is gone: the titles are now set in the same serif as the logo wordmark, in
   the logo's green, straight on the pour. */

/* decorative splashes scattered across the page, built by js/main.js -------- */
/* no clipping here: a splash cut flat at a section boundary shows a straight
   seam in the middle of the ivory. They bleed across sections the way they bleed
   across a pack, and `body { overflow-x: hidden }` keeps the page from scrolling
   sideways. Two tones per splash, same construction as the title stains. */
.field { position: absolute; inset: 0; z-index: 0; pointer-events: none; }
.field-in { position: absolute; inset: 0; }
.splat { position: absolute; }
.splat svg { width: 100%; height: 100%; display: block; overflow: visible; }
.splat .s-b { fill: var(--splat-deep, currentColor); opacity: .55; }
.splat .s-f { fill: currentColor; }

@keyframes splat-float {
  0%, 100% { transform: translate3d(0, 0, 0) rotate(0deg)   scale(1); }
  33%      { transform: translate3d(2%, -3%, 0) rotate(4deg)  scale(1.05); }
  66%      { transform: translate3d(-2%, 2%, 0) rotate(-3deg) scale(.97); }
}

/* --- nav ------------------------------------------------------------------ */
.nav {
  position: sticky; top: 0; z-index: 60;
  background: color-mix(in srgb, var(--ivory) 88%, transparent);
  backdrop-filter: blur(14px);
  transition: box-shadow .3s;
}
/* a soft fade off the bar, not a rule — the page must never show a hard line */
.nav.stuck { box-shadow: 0 10px 26px -22px rgba(29, 68, 41, .5); }
.nav-in { display: flex; align-items: center; gap: 1.6rem; height: 74px; }
.brand { display: flex; align-items: center; gap: .6rem; margin-right: auto; }
.brand img { width: 48px; height: 48px; object-fit: contain; }
.brand span {
  font-weight: 600; font-size: .98rem; letter-spacing: .15em;
  text-transform: uppercase; color: var(--forest);
}
.nav-links { display: flex; gap: 1.8rem; align-items: center; }
.nav-links .pill { display: none; }   /* only surfaces inside the mobile drawer */
.nav-links a {
  font-size: .74rem; font-weight: 600; letter-spacing: .13em; text-transform: uppercase;
  color: var(--forest); opacity: .78; position: relative; padding-block: .4rem;
}
.nav-links a::after {
  content: ""; position: absolute; left: 0; bottom: 0; height: 2px; width: 0;
  background: var(--mango); border-radius: 2px; transition: width .28s ease;
}
.nav-links a:hover { opacity: 1; }
.nav-links a:hover::after, .nav-links a.active::after { width: 100%; }

.pill {
  display: inline-flex; align-items: center; gap: .5rem;
  border: 2px solid var(--forest); border-radius: 999px;
  padding: .62rem 1.3rem; font-size: .72rem; font-weight: 700;
  letter-spacing: .12em; text-transform: uppercase; color: var(--forest);
  transition: background .25s, color .25s, transform .25s;
}
.pill:hover { background: var(--forest); color: var(--ivory); transform: translateY(-1px); }
.pill.solid { background: var(--forest); color: var(--ivory); }
.pill.solid:hover { background: #16341f; }

.burger { display: none; width: 42px; height: 42px; place-items: center; }
.burger span, .burger span::before, .burger span::after {
  content: ""; display: block; width: 21px; height: 2px; border-radius: 2px;
  background: var(--forest); transition: transform .3s, opacity .2s;
}
.burger span::before { transform: translateY(-6.5px); }
.burger span::after  { transform: translateY(4.5px); }
.nav.open .burger span { background: transparent; }
.nav.open .burger span::before { transform: rotate(45deg); }
.nav.open .burger span::after  { transform: rotate(-45deg) translateY(0); }

/* --- hero ----------------------------------------------------------------- */
/* no `overflow: hidden` — it would crop the splash field flat at the hero's
   bottom edge, which is exactly the seam we are trying not to have. Sideways
   scroll is already held by `body { overflow-x: hidden }`. */
.hero { padding: clamp(2.5rem, 6vw, 5rem) 0 clamp(1rem, 3vw, 2rem); }
.hero-grid {
  display: grid; grid-template-columns: minmax(0, 1.02fr) minmax(0, 1fr);
  gap: clamp(1.5rem, 4vw, 3.5rem); align-items: center;
}
/* headline and subline both serif, the way the logo wordmark is set */
.hero h1 {
  font-family: var(--serif);
  font-weight: 600;
  font-size: clamp(2rem, 4.1vw, 3.25rem);
  line-height: 1.14; letter-spacing: -.01em;
  color: var(--forest);
  max-width: 17ch; margin-bottom: 1.2rem;
}
.hero-sub {
  font-family: var(--serif);
  font-size: clamp(1rem, 1.15vw, 1.14rem);
  line-height: 1.62; color: var(--charcoal); max-width: 52ch;
}
/* Capped, not column-wide: with the ground shadow gone the shot is a much
   taller crop than the old one, and at full column width the three pouches
   stood taller than the headline beside them. This keeps the art no larger
   than the block of type it sits next to. */
.hero-art { position: relative; max-width: 74%; margin-inline: auto; }
/* No drop-shadow: the pack shot itself carries none any more, and the flat
   pours are the only depth the page uses. */
.hero-art img { width: 100%; }
/* The pour the pouches stand in — two flat tones stacked with a small offset,
   the same construction as the section stains and as the paint printed on the
   packs themselves.
   It has to be deeper than it looks like it should be. The pouches are lit so
   their bottoms wash out almost to the page's own ivory, and against a pale
   tint they dissolved: the shot read as a photograph that had faded away at
   the bottom. Peach rather than the CTA's lemon, so the two blobs in this
   corner of the page do not read as the same shape twice. */
.hero-art::before {                     /* the light tone, the wider of the two */
  content: ""; position: absolute; z-index: -1;
  left: -21%; bottom: -8%; width: 142%; aspect-ratio: 3.6;
  background: #F8D8C2;
  -webkit-mask: var(--pour-flat) center / 100% 100% no-repeat;
          mask: var(--pour-flat) center / 100% 100% no-repeat;
}
.hero-art::after {                      /* the deep tone, offset down and in */
  content: ""; position: absolute; z-index: -1;
  left: -6%; bottom: -12%; width: 118%; aspect-ratio: 3.9;
  background: #F0B58C; opacity: .8;
  -webkit-mask: var(--pour-flat-alt) center / 100% 100% no-repeat;
          mask: var(--pour-flat-alt) center / 100% 100% no-repeat;
}

/* the yellow marker CTA from the wireframe — now a filled stain that drifts */
.blob-cta {
  position: relative; display: inline-grid; place-items: center;
  /* the padding grows with the type, so the stain keeps the same margin of
     colour all around the copy and the text stays optically centred */
  padding: clamp(1.7rem, 2.6vw, 2.1rem) clamp(2.6rem, 4vw, 3.3rem); text-align: center;
  font-family: var(--serif);
  font-size: .98rem; font-weight: 500; color: var(--forest); line-height: 1.5;
  transition: transform .45s cubic-bezier(.2, .7, .3, 1), filter .45s;
  filter: drop-shadow(0 10px 22px rgba(29, 68, 41, .13));
}
/* tighter than the title stains: the pour hugs the copy instead of ballooning
   around it, which is what keeps the sticker small on the page */
.blob-cta > .stain { position: absolute; inset: -6% -4%; width: 108%; height: 112%; overflow: visible; }
.blob-cta .stain-c { animation: stain-drift-a 17s ease-in-out infinite; }
.blob-cta .stain-b { animation: stain-drift-b 14s ease-in-out infinite; }
.blob-cta .stain-f { animation: stain-drift-c 11s ease-in-out infinite; }
.blob-cta span {
  position: relative; z-index: 1; max-width: 25ch;
  text-wrap: balance;                   /* keeps both lines seated on the pour */
}
/* The arrow is drawn, not typed: one ink stroke with a hand-made head, in the
   same forest green as the copy. The old glyph was strawberry red — the only
   red on the page — set in the UI font, and it read as a control pasted onto a
   painted sticker rather than as part of it.
   The negative bottom margin is what centres the copy: the arrow hangs into the
   pour's lower padding instead of pushing the two lines above the middle. */
.blob-cta .cta-arrow {
  position: relative; z-index: 1; display: block;
  width: clamp(42px, 5vw, 56px); height: auto;
  margin: .5rem 0 -1.25rem; overflow: visible;
  fill: none; stroke: var(--forest); stroke-width: 2.4;
  stroke-linecap: round; stroke-linejoin: round;
  opacity: .8;
  transition: transform .45s cubic-bezier(.2, .7, .3, 1), opacity .3s;
}
.blob-cta:hover .cta-arrow, .blob-cta:focus-visible .cta-arrow {
  transform: translateX(8px); opacity: 1;
}
/* nothing hovers on a phone, so there the arrow keeps a slow nudge of its own */
@media (hover: none) {
  .blob-cta .cta-arrow { animation: cta-nudge 4.6s ease-in-out infinite; }
}
@keyframes cta-nudge {
  0%, 100% { transform: translateX(0); }
  50%      { transform: translateX(5px); }
}
.cta-float .blob-cta:hover, .cta-float .blob-cta:focus-visible {
  transform: translateY(-5px) scale(1.05);
  filter: drop-shadow(0 18px 30px rgba(29, 68, 41, .2));
}
.blob-cta:focus-visible { outline: 3px solid var(--forest); outline-offset: 8px; }

/* the whole sticker breathes, so it keeps moving even at rest.
   One transform per element — entrance on .rise, bob here, hover on the anchor —
   otherwise they overwrite each other. */
.cta-float { display: inline-block; animation: cta-bob 7s ease-in-out infinite; }
@keyframes cta-bob {
  0%, 100% { transform: translateY(0) rotate(var(--tilt, 0deg)); }
  50%      { transform: translateY(-9px) rotate(calc(var(--tilt, 0deg) * .4)); }
}

/* clears the pack shot above: the bob lifts the sticker 9px at the top of its
   cycle, so the resting gap has to be bigger than the travel */
.hero-cta { margin-top: clamp(3.8rem, 6.6vw, 5.8rem); }

/* pushed out to the page edge rather than centred */
.cta-row { display: flex; justify-content: center; }
.cta-row.to-right { justify-content: flex-end; }
.cta-row.to-left  { justify-content: flex-start; }
.cta-row.to-right > * { margin-right: clamp(-2.6rem, -3vw, -1rem); }
.cta-row.to-left  > * { margin-left:  clamp(-2.6rem, -3vw, -1rem); }

/* …and they slide in from that same edge on reveal */
.rise.from-right { transform: translate(46px, 16px); }
.rise.from-left  { transform: translate(-46px, 16px); }
.rise.from-right.in, .rise.from-left.in { transform: none; }

/* --- section frame -------------------------------------------------------- */
/* One continuous canvas: no rules, no banded backgrounds, nothing that draws a
   line across the page. Sections are told apart by rhythm and by the pack
   splashes bleeding across them, never by an edge. */
.sect { padding: clamp(3.2rem, 7vw, 6rem) 0; }
.sect-head { display: grid; justify-items: center; text-align: center; gap: .9rem; margin-bottom: 2.8rem; }
.sect-head p { max-width: var(--measure); margin-inline: auto; }

/* --- retail shelf --------------------------------------------------------- */
.toggle {
  display: inline-flex; padding: 5px; gap: 4px; border-radius: 999px;
  background: #1d44290d; border: 1px solid #1d442916;
}
.toggle button {
  border-radius: 999px; padding: .6rem 1.6rem; font-size: .72rem; font-weight: 700;
  letter-spacing: .11em; text-transform: uppercase; color: var(--forest);
  opacity: .62; transition: all .28s;
}
.toggle button[aria-selected="true"] {
  background: var(--forest); color: var(--ivory); opacity: 1; box-shadow: var(--shadow-sm);
}

/* Flex rather than grid: once the "Coming soon" placeholders came out, an
   auto-fit grid stretched the two blends into oversized cards. Here a card keeps
   the same footprint whichever tab is open, and short rows sit centred. */
.shelf { display: flex; flex-wrap: wrap; justify-content: center; gap: clamp(1rem, 2vw, 1.6rem); }
.shelf > .card { flex: 1 1 228px; max-width: 300px; }
.card {
  position: relative; overflow: hidden; text-align: left;
  background: var(--paper); border: 1px solid #1d442914; border-radius: var(--radius-lg);
  padding: 1.5rem 1.5rem 1.35rem; cursor: pointer;
  transition: transform .35s cubic-bezier(.2,.7,.3,1), box-shadow .35s, border-color .35s;
}
.card::before {                          /* the pack's pour, tinted per fruit */
  content: ""; position: absolute; top: -34%; right: -26%;
  width: 78%; aspect-ratio: 1;
  background: var(--tint); opacity: .58; transition: transform .5s ease;
  -webkit-mask: var(--pour-alt) center / 100% 100% no-repeat;
          mask: var(--pour-alt) center / 100% 100% no-repeat;
}
.card:hover { transform: translateY(-7px); box-shadow: var(--shadow); border-color: color-mix(in srgb, var(--accent) 35%, transparent); }
.card:hover::before { transform: scale(1.16) rotate(8deg); }
.card:focus-visible { outline: 3px solid var(--accent); outline-offset: 3px; }
.card-media { position: relative; margin-bottom: 1rem; }
.card-media img {
  height: clamp(180px, 17vw, 232px); width: 100%;
  object-fit: contain; object-position: center bottom;
  filter: drop-shadow(0 18px 22px rgba(29,68,41,.18)); transition: transform .45s ease;
}
.card:hover .card-media img { transform: translateY(-6px) scale(1.04); }
.card-kicker { position: relative; font-size: .6rem; font-weight: 800; letter-spacing: .085em; text-transform: uppercase; color: var(--accent); white-space: nowrap; }
.card h3 { position: relative; margin: .3rem 0 .4rem; color: var(--charcoal); }
.card h3 .oh { color: var(--accent); margin-right: .18rem; }
.card p { position: relative; font-size: .84rem; color: var(--muted); min-height: 3.2em; max-width: var(--measure); }
.card-foot {
  position: relative; display: flex; align-items: center; justify-content: space-between;
  gap: .6rem; margin-top: 1rem; padding-top: .9rem; border-top: 1px solid #1d44290f;
}
.card-foot { flex-wrap: wrap; }
.card-foot .link { font-size: .74rem; font-weight: 700; color: var(--forest); white-space: nowrap; }
.card-foot .link::after { content: " →"; transition: margin .25s; display: inline-block; }
.card:hover .card-foot .link::after { margin-left: .25rem; }
/* the format is set in the fruit's own colour — no chip behind it */
.tag {
  font-size: .62rem; font-weight: 800; letter-spacing: .1em; text-transform: uppercase;
  color: color-mix(in srgb, var(--accent) 84%, var(--charcoal));
  white-space: nowrap;
}
/* what is in the bag, above the nutrition line, on the blends only */
.card-mix { font-size: .82rem; color: var(--muted); margin-bottom: .25rem; }

/* The teaser card, now the one thing on the shelf that catches the light: a
   gold pour behind the words, a foil glint sweeping across, and the two words
   themselves lit by a highlight travelling through the letterforms. Still no
   pack shot — any pack in here reads as a product that already exists. */
.card.soon {
  border-color: #f2c23052; background: #f2c2300f;
  cursor: default; display: grid; place-items: center; min-height: 260px;
}
.card.soon:hover { transform: none; box-shadow: none; border-color: #f2c23085; }
/* the fruit pour, recoloured gold and breathing slowly */
.card.soon::before {
  content: ""; top: -32%; right: -26%; width: 80%;
  background: #F2C230; opacity: .18;
  animation: soon-glow 6.5s ease-in-out infinite;
}
.card.soon:hover::before { transform: none; }
/* the foil glint: a narrow band of light crossing the whole card, letters
   included, the way light runs over a printed foil block */
.card.soon::after {
  content: ""; position: absolute; z-index: 2; inset: -60% -30%;
  background: linear-gradient(72deg,
      transparent 40%, #FFFFFFA6 47%, #FFF6D9CC 50%, #FFFFFFA6 53%, transparent 60%);
  transform: translateX(-115%);
  animation: soon-sweep 5.5s cubic-bezier(.5, 0, .3, 1) infinite;
  pointer-events: none;
}
@keyframes soon-glow {
  0%, 100% { opacity: .13; transform: scale(1)    rotate(0deg); }
  50%      { opacity: .3;  transform: scale(1.09) rotate(6deg); }
}
@keyframes soon-sweep {
  0%, 62%  { transform: translateX(-115%); }
  92%, 100%{ transform: translateX(115%); }
}
.soon-in { position: relative; z-index: 1; display: grid; justify-items: center; gap: .4rem; text-align: center; }
/* two sparks, off the corners of the lockup, taking turns */
.soon-in::before, .soon-in::after {
  content: "✦"; position: absolute; color: #E8942F; line-height: 1;
  opacity: 0; animation: soon-twinkle 3.8s ease-in-out infinite;
}
.soon-in::before { top: -1.45rem; left: -.5rem;    font-size: .72rem; }
.soon-in::after  { bottom: -1.3rem; right: -.35rem; font-size: .56rem; animation-delay: 1.7s; }
@keyframes soon-twinkle {
  0%, 100% { opacity: 0;   transform: scale(.55) rotate(0deg); }
  38%      { opacity: .95; transform: scale(1)   rotate(85deg); }
  72%      { opacity: 0;   transform: scale(.7)  rotate(155deg); }
}
.card.soon .soon-eyebrow {
  min-height: 0; font-size: .58rem; font-weight: 800; letter-spacing: .2em;
  text-transform: uppercase; color: var(--mango); opacity: .85;
}
.card.soon h3 {
  margin: 0; font-family: var(--serif); font-weight: 600;
  font-size: clamp(1.2rem, 1.7vw, 1.42rem); letter-spacing: .02em;
  /* the highlight is a gradient clipped to the glyphs; the sweep above passes
     over them, this one passes through them */
  background-image: linear-gradient(96deg,
      var(--forest) 0%, var(--forest) 32%, #9C7A22 41%, #C79418 47%,
      #E2A81C 50%, #C79418 53%, #9C7A22 59%, var(--forest) 72%, var(--forest) 100%);
  background-size: 300% 100%;
  -webkit-background-clip: text; background-clip: text;
  color: transparent; -webkit-text-fill-color: transparent;
  animation: soon-shine 5.5s ease-in-out infinite;
}
@keyframes soon-shine {
  0%, 12%   { background-position: 130% 0; }
  62%, 100% { background-position: -30% 0; }
}
/* if the glyph clip is unavailable the letters must not vanish */
@supports not ((-webkit-background-clip: text) or (background-clip: text)) {
  .card.soon h3 {
    background-image: none; color: var(--forest); -webkit-text-fill-color: currentColor;
  }
}
.card.soon .soon-note {
  min-height: 0; font-size: .68rem; font-style: italic; color: var(--muted);
}

/* --- product drawer ------------------------------------------------------- */
.scrim {
  position: fixed; inset: 0; z-index: 90; background: #1d2a1fbb;
  opacity: 0; visibility: hidden; transition: opacity .35s, visibility .35s;
  backdrop-filter: blur(3px);
}
.scrim.on { opacity: 1; visibility: visible; }
.drawer {
  position: fixed; top: 0; right: 0; bottom: 0; z-index: 95; width: min(560px, 100%);
  background: var(--ivory); box-shadow: var(--shadow-lg); overflow-y: auto;
  transform: translateX(102%); transition: transform .45s cubic-bezier(.3,.8,.3,1);
  padding: clamp(1.6rem, 4vw, 2.6rem);
}
.drawer.on { transform: none; }
.drawer-x {
  /* z-index matters: the pack shot below carries a drop-shadow filter, which
     opens its own stacking context and used to paint over this button once the
     drawer was scrolled — the click then landed on the image, not on the X. */
  position: sticky; top: 0; z-index: 20; margin-left: auto;
  display: grid; place-items: center;
  width: 44px; height: 44px; border-radius: 50%; background: var(--paper);
  border: 1px solid #1d442918; font-size: 1.15rem; color: var(--forest);
  box-shadow: var(--shadow-sm); transition: background .2s, transform .2s;
}
.drawer-x:hover { background: var(--ivory-deep); transform: scale(1.06); }
.drawer-x:focus-visible { outline: 3px solid var(--forest); outline-offset: 3px; }
/* nothing inside the panels may sit above the close button */
.drawer-hero, .facts, .recipe, .retailers, #locator-result { position: relative; z-index: 0; }
.drawer-hero { margin: -.5rem 0 1.2rem; }
.drawer-hero img { height: 230px; width: 100%; object-fit: contain; filter: drop-shadow(0 22px 26px rgba(29,68,41,.2)); }
.drawer h3 { font-size: 1.7rem; margin-bottom: .3rem; }
.drawer p { max-width: var(--measure); }
.drawer .accentbar { width: 54px; height: 4px; border-radius: 4px; background: var(--accent); margin: .9rem 0 1.2rem; }
/* four readings on most products, five on avocado and the tropical mix */
.facts { display: grid; grid-template-columns: repeat(auto-fit, minmax(78px, 1fr)); gap: .5rem; margin: 1.4rem 0; }
.drawer-mix { color: var(--charcoal); font-weight: 600; margin-bottom: .35rem; }
.drawer-rich { color: var(--muted); }
.fact { background: var(--paper); border: 1px solid #1d442914; border-radius: 16px; padding: .7rem .4rem; text-align: center; }
/* Same type as the Smoothie Lab's nutrient board — serif figure, uppercase
   label, unit on its own line underneath. Only the size differs, because these
   cells are half the width of the board's. */
.fact b {
  display: block; font-family: var(--serif); font-size: clamp(1.2rem, 1.9vw, 1.5rem);
  font-weight: 600; color: var(--forest); line-height: 1.05;
  font-variant-numeric: tabular-nums;
}
.fact span {
  display: block; margin-top: .4rem; font-size: .58rem; font-weight: 700;
  letter-spacing: .08em; text-transform: uppercase; color: var(--muted); line-height: 1.3;
}
.fact i {
  display: block; font-style: normal; font-size: .92em; font-weight: 600;
  letter-spacing: .04em; opacity: .62; text-transform: lowercase;
}
.recipe { background: var(--paper); border: 1px solid #1d442914; border-radius: 18px; padding: 1rem 1.1rem; margin-bottom: .7rem; }
.recipe b { display: block; color: var(--forest); font-size: .95rem; }
.recipe span { font-size: .82rem; color: var(--muted); }
.recipe em { display: block; font-style: normal; font-size: .64rem; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; color: var(--accent); margin-bottom: .25rem; }

/* --- smoothie lab --------------------------------------------------------- */
/* no background of its own: the canvas is one ivory the whole way down, and the
   lab is set apart by the pours running through it like every other section. */
.lab-grid { display: grid; grid-template-columns: minmax(0, .85fr) minmax(0, 1.15fr); gap: clamp(1.6rem, 4vw, 3.4rem); align-items: center; }
.lab-copy h2 { margin: .6rem 0 1rem; }
.lab-copy .lede { max-width: var(--measure-tight); }
.panel { background: var(--paper); border: 1px solid #1d44291f; border-radius: var(--radius-lg); padding: clamp(1.3rem, 3vw, 2rem); box-shadow: var(--shadow); }
.step { margin-bottom: 1.1rem; }
.step label { display: block; font-size: .64rem; font-weight: 800; letter-spacing: .15em; text-transform: uppercase; color: var(--muted); margin-bottom: .45rem; }
.select {
  position: relative; border: 2px solid var(--avocado); border-radius: 999px; background: var(--paper);
  transition: border-color .25s, box-shadow .25s;
}
.select:focus-within { box-shadow: 0 0 0 4px #6e9a3a26; }
.select select {
  appearance: none; width: 100%; border: 0; background: none; cursor: pointer;
  padding: .82rem 2.8rem .82rem 1.25rem; font-size: .9rem; font-weight: 600; color: var(--forest);
  border-radius: 999px;
}
.select select:focus { outline: none; }
.select::after {
  content: ""; position: absolute; right: 1.2rem; top: 50%; width: 8px; height: 8px;
  border-right: 2px solid var(--forest); border-bottom: 2px solid var(--forest);
  transform: translateY(-70%) rotate(45deg); pointer-events: none;
}
/* Nothing in the board changes length with the selection — the figures are
   fixed-width and the basis line is static — so it never resizes. */
.board { margin-top: 1.5rem; border: 2px solid var(--avocado); border-radius: 22px; padding: 1.35rem 1.4rem 1.25rem; background: #6e9a3a0a; }
.board-h { font-size: .64rem; font-weight: 800; letter-spacing: .15em; text-transform: uppercase; color: var(--forest); margin-bottom: .8rem; }
.board-grid { display: grid; grid-template-columns: repeat(5, 1fr); gap: .7rem .5rem; }
/* The figure carries the reading; the unit belongs to the label, one step
   smaller and lighter, so five columns still scan as five numbers. */
.metric { min-width: 0; text-align: center; }
.metric b {
  display: block; font-family: var(--serif); font-size: clamp(1.35rem, 2.5vw, 1.85rem);
  font-weight: 600; color: var(--forest); line-height: 1.05;
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.metric span {
  display: block; margin-top: .4rem; font-size: .58rem; font-weight: 700;
  letter-spacing: .08em; text-transform: uppercase; color: var(--muted); line-height: 1.3;
}
/* the unit always sits on its own line, so all five labels are two lines deep
   and the row of figures reads level */
.metric i {
  display: block; font-style: normal; font-size: .92em; font-weight: 600;
  letter-spacing: .04em; opacity: .62; text-transform: lowercase;
}
.board-basis {
  margin-top: 1.1rem; font-size: .64rem; font-style: italic;
  color: var(--muted); line-height: 1.5;
}

/* --- story ---------------------------------------------------------------- */
.story-body { max-width: var(--measure); margin-inline: auto; text-align: center; }
.story-body p { margin-bottom: 1.15rem; color: var(--charcoal); }
.story-body p.big { font-family: var(--serif); font-weight: 700; font-size: clamp(1.15rem, 1.9vw, 1.5rem); line-height: 1.45; color: var(--forest); }
.story-sign { font-family: var(--serif); font-style: italic; font-weight: 600; font-size: 1.15rem; color: var(--forest); margin-top: 1.6rem; }

/* --- community hub -------------------------------------------------------- */
.hub-head { margin-bottom: 2.2rem; text-align: center; }
.hub-head .lede { max-width: var(--measure-tight); margin-inline: auto; }
.hub-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 1.3rem; }
.hub-box {
  position: relative; border: 2px solid var(--hue, var(--blob-hub)); border-radius: var(--radius);
  background: var(--paper); overflow: hidden; display: flex; flex-direction: column;
  transition: transform .4s cubic-bezier(.2,.7,.3,1), box-shadow .4s;
}
.hub-box:hover { transform: translateY(-6px); box-shadow: var(--shadow); }
.hub-box::before {                       /* a pack pour tucked into the corner */
  content: ""; position: absolute; top: -30%; right: -22%; width: 64%; aspect-ratio: 1;
  background: var(--hue); opacity: .15; transition: transform .6s ease;
  -webkit-mask: var(--pour-alt) center / 100% 100% no-repeat;
          mask: var(--pour-alt) center / 100% 100% no-repeat;
}
.hub-box:hover::before { transform: scale(1.2) rotate(10deg); }
.viewport { overflow: hidden; flex: 1; }
.track { display: flex; transition: transform .42s cubic-bezier(.5,.02,.2,1); height: 100%; }
.slide { position: relative; min-width: 100%; padding: 1.5rem 1.4rem; display: flex; flex-direction: column; gap: .5rem; }
.slide .eyebrow { color: var(--forest); }
.slide h4 { font-size: 1.02rem; color: var(--charcoal); }
.slide p { font-size: .85rem; color: var(--muted); max-width: var(--measure); }
.slide a.more { margin-top: auto; font-size: .74rem; font-weight: 700; color: var(--forest); }

/* the incoming slide's lines settle in one after another, so each turn of the
   carousel reads as a deliberate beat rather than a jump cut. The whole cascade
   has to finish well inside the 2.9 s a slide is held, hence the tight delays. */
.slide > * { transition: opacity .26s ease .06s, transform .3s cubic-bezier(.2,.7,.3,1) .06s; }
.slide[data-on="false"] > * { opacity: 0; transform: translateY(12px); }
.slide[data-on="true"]  > *:nth-child(2) { transition-delay: .11s; }
.slide[data-on="true"]  > *:nth-child(3) { transition-delay: .16s; }
.slide[data-on="true"]  > *:nth-child(4) { transition-delay: .21s; }

.hub-foot { position: relative; display: flex; align-items: center; justify-content: space-between; gap: .8rem; padding: .85rem 1.2rem; border-top: 2px solid var(--hue, var(--blob-hub)); }
.hub-foot b { font-size: .78rem; font-weight: 800; letter-spacing: .11em; text-transform: uppercase; color: var(--forest); }
.pips { display: flex; gap: 5px; }
.pips button { width: 7px; height: 7px; border-radius: 50%; background: #1d442930; transition: background .3s, width .3s; }
.pips button[aria-current="true"] { background: var(--hue, var(--forest)); width: 18px; border-radius: 4px; }

/* the countdown to the next slide, so the box is visibly running */
.hub-prog { position: absolute; left: 0; right: 0; top: -2px; height: 2px; overflow: hidden; }
.hub-prog i { display: block; height: 100%; background: var(--hue); transform: scaleX(0); transform-origin: left; }
.hub-box.playing .hub-prog i { animation: hub-prog var(--dur, 2900ms) linear infinite; }
@keyframes hub-prog { from { transform: scaleX(0); } to { transform: scaleX(1); } }

/* --- faq ------------------------------------------------------------------ */
.faq { max-width: 760px; margin: 3.2rem auto 0; }
.faq h3 { text-align: center; margin-bottom: 1.4rem; }
.qa { border-bottom: 1px solid #1d44291f; }
.qa button {
  width: 100%; display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  text-align: left; padding: 1.1rem 0; font-weight: 600; color: var(--forest); font-size: 1rem;
}
.qa button::after {
  content: "+"; font-size: 1.3rem; font-weight: 400; color: var(--mango);
  transition: transform .3s; flex: none;
}
.qa[open] button::after { transform: rotate(45deg); }
.qa .a { max-height: 0; overflow: hidden; transition: max-height .4s ease, opacity .3s; opacity: 0; }
.qa[open] .a { max-height: 420px; opacity: 1; }
.qa .a p { padding-bottom: 1.15rem; font-size: .92rem; color: var(--muted); max-width: var(--measure); }

/* --- contact -------------------------------------------------------------- */
.harvest { text-align: center; }
.subscribe {
  display: flex; align-items: center; gap: .4rem; margin: 1.6rem auto 0;
  max-width: 520px; background: var(--paper); border: 2px solid var(--charcoal);
  border-radius: 999px; padding: 5px 5px 5px 1.4rem;
}
.subscribe input { flex: 1; min-width: 0; border: 0; background: none; padding: .7rem 0; font-size: .92rem; }
.subscribe input:focus { outline: none; }
.subscribe input::placeholder { color: #9a968a; letter-spacing: .02em; }
.subscribe button {
  border-radius: 999px; padding: .72rem 1.5rem; font-size: .72rem; font-weight: 800;
  letter-spacing: .12em; text-transform: uppercase; color: var(--ivory);
  background: var(--avocado); transition: background .25s, transform .25s;
}
.subscribe button:hover { background: #5c8430; transform: translateY(-1px); }

.contact {
  display: flex; flex-direction: column; gap: .9rem; margin: 1.6rem auto 0;
  max-width: 520px; text-align: left; background: var(--paper);
  border: 2px solid var(--charcoal); border-radius: var(--radius); padding: 1.4rem;
}
.contact-row { display: grid; grid-template-columns: 1fr 1fr; gap: .9rem; }
.contact-field { display: flex; flex-direction: column; gap: .35rem; min-width: 0; }
.contact-field label {
  font-size: .68rem; font-weight: 800; letter-spacing: .12em;
  text-transform: uppercase; color: var(--forest);
}
.contact input, .contact textarea {
  width: 100%; font: inherit; font-size: .92rem; color: inherit;
  background: var(--ivory); border: 1px solid #1d442926; border-radius: 12px;
  padding: .68rem .85rem; transition: border-color .2s, box-shadow .2s;
}
.contact textarea { resize: vertical; min-height: 120px; line-height: 1.55; }
.contact input::placeholder, .contact textarea::placeholder { color: #9a968a; letter-spacing: .02em; }
.contact input:focus, .contact textarea:focus {
  outline: none; border-color: var(--avocado); box-shadow: 0 0 0 3px #6d9c3a26;
}
.contact button {
  align-self: flex-start; border-radius: 999px; padding: .78rem 1.7rem;
  font-size: .72rem; font-weight: 800; letter-spacing: .12em; text-transform: uppercase;
  color: var(--ivory); background: var(--avocado); transition: background .25s, transform .25s;
}
.contact button:hover { background: #5c8430; transform: translateY(-1px); }
.contact button[disabled] { opacity: .6; cursor: default; transform: none; }
/* consent line — deliberately plain, never pre-ticked */
.consent {
  display: flex; align-items: flex-start; gap: .6rem; text-align: left;
  max-width: 520px; margin: 1.1rem auto 0; font-size: .78rem; line-height: 1.5;
  color: var(--muted); cursor: pointer;
}
.consent input { flex: none; width: 17px; height: 17px; margin-top: .18rem; accent-color: var(--avocado); cursor: pointer; }
.consent a { color: var(--forest); font-weight: 600; text-decoration: underline; text-underline-offset: 2px; }

.form-note { margin-top: .9rem; font-size: .78rem; color: var(--muted); min-height: 1.4em; }
.form-note.ok { color: var(--avocado); font-weight: 600; }
.form-note.err { color: var(--strawberry); font-weight: 600; }

/* --- locator modal -------------------------------------------------------- */
.modal {
  position: fixed; z-index: 95; left: 50%; top: 50%; transform: translate(-50%, -46%) scale(.97);
  width: min(560px, calc(100% - 2rem)); background: var(--ivory); border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg); padding: clamp(1.5rem, 4vw, 2.4rem);
  opacity: 0; visibility: hidden; transition: opacity .3s, transform .3s, visibility .3s;
}
.modal.on { opacity: 1; visibility: visible; transform: translate(-50%, -50%) scale(1); }
.modal .drawer-x { position: absolute; top: 1rem; right: 1rem; z-index: 20; }
.retailers { display: grid; grid-template-columns: repeat(2, 1fr); gap: .8rem; margin-top: 1.4rem; }
.retailer { background: var(--paper); border: 1px solid #1d442914; border-radius: 14px; padding: .8rem 1rem; font-size: .84rem; font-weight: 600; color: var(--forest); }
.retailer span { display: block; font-size: .7rem; font-weight: 400; color: var(--muted); }
#locator-result { margin-top: 1.1rem; border-radius: 16px; padding: .9rem 1.1rem; background: #6e9a3a14; border: 1px solid #6e9a3a3d; font-size: .86rem; color: var(--forest); display: none; }
#locator-result.on { display: block; }

/* --- footer --------------------------------------------------------------- */
.foot { padding: clamp(2.4rem, 5vw, 3.4rem) 0 2rem; background: var(--ivory-deep); }
.foot-top {
  display: grid; gap: clamp(1.6rem, 4vw, 2.6rem);
  grid-template-columns: minmax(240px, 1.5fr) repeat(2, minmax(150px, 1fr));
}
.foot .brand span { font-size: .9rem; }
.foot-brand p { margin-top: .8rem; font-size: .8rem; color: var(--muted); max-width: 34ch; }
.foot-col { display: flex; flex-direction: column; gap: .5rem; }
.foot-col h4 { font-size: .64rem; font-weight: 800; letter-spacing: .16em; text-transform: uppercase; color: var(--forest); opacity: .72; margin-bottom: .25rem; }
.foot-col a { font-size: .8rem; color: var(--muted); width: fit-content; }
.foot-col a:hover { color: var(--forest); }
.foot-legal-info p { font-size: .75rem; line-height: 1.75; color: var(--muted); }
.foot-legal-info p + p { margin-top: .7rem; }
.foot-legal-info b { color: var(--forest); font-weight: 700; }
.foot-legal-info a { text-decoration: underline; text-underline-offset: 2px; }
.foot-bottom {
  display: flex; align-items: flex-start; justify-content: space-between; gap: 1rem 2rem; flex-wrap: wrap;
  margin-top: clamp(1.8rem, 4vw, 2.6rem); padding-top: 1.2rem; border-top: 1px solid #1d442918;
}
.foot small { font-size: .72rem; color: var(--muted); max-width: var(--measure); }

/* --- motion --------------------------------------------------------------- */
.rise { opacity: 0; transform: translateY(22px); transition: opacity .7s ease, transform .7s cubic-bezier(.2,.7,.3,1); }
.rise.in { opacity: 1; transform: none; }

/* --- responsive ----------------------------------------------------------- */
@media (max-width: 980px) {
  .foot-top { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .hero-grid, .lab-grid { grid-template-columns: 1fr; }
  /* stacked, the art gets the full column, but a tall crop across a 900px
     tablet would be a wall of packaging — so it stays capped here too */
  .hero-art { order: -1; max-width: 480px; }
  /* the headline now sits directly under the shot: the pour stays behind the
     pouches instead of running a hard edge across the first two lines */
  .hero-art::before { bottom: -5%; }
  .hero-art::after  { bottom: -8%; }
  .nav-links {
    position: fixed; inset: 74px 0 auto; flex-direction: column; gap: 0;
    background: var(--ivory); border-bottom: 1px solid #1d442918; padding: .5rem var(--gutter) 1.4rem;
    transform: translateY(-140%); transition: transform .4s cubic-bezier(.3,.8,.3,1);
  }
  .nav.open .nav-links { transform: none; }
  .nav-links a { padding: .85rem 0; font-size: .82rem; border-bottom: 1px solid #1d442910; }
  .burger { display: grid; }
  .nav .pill { display: none; }
  .nav-links .pill { display: inline-flex; margin-top: 1rem; justify-content: center; }
}
@media (max-width: 560px) {
  .foot-top { grid-template-columns: 1fr; }
  .blob-title { padding: 2.2rem 1.6rem; }
  .blob-title h2 { white-space: normal; font-size: 1.35rem; }
  .blob-cta { padding: 1.5rem 2.1rem; font-size: .96rem; }
  .blob-cta span { max-width: 22ch; }
  .blob-cta .cta-arrow { margin-bottom: -1.05rem; }
  .facts { grid-template-columns: repeat(2, 1fr); }
  .board-grid { grid-template-columns: repeat(3, 1fr); }
  .retailers { grid-template-columns: 1fr; }
  .subscribe { flex-direction: column; border-radius: var(--radius); padding: 1rem; align-items: stretch; }
  .subscribe input { text-align: center; }
  .subscribe button { width: 100%; }
  .contact-row { grid-template-columns: 1fr; }
  .contact button { align-self: stretch; width: 100%; }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .01ms !important; animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
  }
  .rise, .rise.from-left, .rise.from-right { opacity: 1; transform: none; }
  .cta-float { transform: rotate(var(--tilt, 0deg)); }
  .slide > * { opacity: 1; transform: none; }
}
