/* ============================================================
   saesa — variables & base
   ============================================================ */
:root{
  /* ---- ORIGINAL saesa palette (restored) ---- */
  --terracotta:#c2643a;
  --coral:#ef9c6f;
  --peach:#ffc9a8;
  --blush:#fce2d6;
  --leaf:#b3d97a;
  --olive:#7f8f1e;
  --white:#ffffff;
  --ink:#3a2c22;
  --footer-bg:#201d1b;
  --container-w:1000px;

  /* ---- semantic aliases (point at the original palette) so the redesign's
     structural CSS keeps resolving ---- */
  --paper:var(--blush);          /* page base */
  --paper-raised:#fbf5e9;        /* cream card fill */
  --paper-sink:#fbeee4;          /* faint warm band */
  --brand:var(--terracotta);
  --brand-ink:#a8522e;           /* a touch darker terracotta for small text */
  --ink-70:rgba(58,44,34,.74);
  --ink-45:rgba(58,44,34,.48);
  --hairline:rgba(58,44,34,.16);
  --leaf-soft:#e9f1d6;

  /* ---- type ----
     display = Klee One (Japanese textbook / kyokasho hand — soft, friendly);
     title   = Shippori Mincho (clean literary mincho for recurring sub-titles).
     Both are JP-glyph-only, so Noto Serif TC sits behind them and picks up any
     Hong Kong character forms per-glyph. Klee One tops out at 600, so faux-bold
     is disabled globally (see `font-synthesis` on body) — 700 requests resolve
     to the real 600 face instead of a synthesised heavy weight. */
  --font-display:'Klee One','Noto Serif TC',serif;
  --font-title:'Shippori Mincho','Noto Serif TC',serif;
  --font-body:'Zen Kaku Gothic New','Noto Sans TC',system-ui,sans-serif;
  /* Yomogi is Japanese-glyph-only; Klee One (a soft hand too) then Noto Serif TC
     catch the Hong Kong character forms it can't render, so a mixed line still
     reads as one voice instead of jumping to a geometric gothic mid-sentence */
  --font-hand:'Yomogi','Klee One','Noto Serif TC',cursive;

  --fs-display:clamp(2.1rem, 1.35rem + 3.4vw, 3.55rem);
  --fs-h2:clamp(1.7rem, 1.2rem + 2.1vw, 2.5rem);
  --fs-h3:clamp(1.2rem, 1.05rem + .7vw, 1.5rem);
  --fs-lead:clamp(1.02rem, .97rem + .3vw, 1.16rem);
  --measure:34em;

  /* ---- shape + depth ---- */
  --r-sm:14px; --r-md:22px; --r-lg:34px; --r-pill:999px;
  --shadow-sm:0 3px 10px -3px rgba(74,45,28,.20);
  --shadow-md:0 18px 40px -16px rgba(74,45,28,.30);

  /* ---- motion ---- */
  --ease:cubic-bezier(.22,.68,0,1);
  --dur:.6s;

  /* ---- consistent section rhythm ---- */
  --mascot-space-below:64px;   /* pill → next section (same for every section) */
  --mascot-space-above:72px;   /* content → pill, where set explicitly */
}
@media (max-width:900px){
  :root{ --mascot-space-below:44px; --mascot-space-above:52px; }
}

*,*::before,*::after{box-sizing:border-box;}
html{scroll-behavior:smooth;}
body{
  margin:0;
  font-family:var(--font-body);
  color:var(--ink);
  background:var(--paper);
  overflow-x:hidden;
  -webkit-font-smoothing:antialiased;
  text-rendering:optimizeLegibility;
  /* Klee One only ships 400/600 — never let the browser fake a 700 */
  font-synthesis:none;
}
/* fixed grain overlay — breaks the flat digital fill without touching layout */
body::after{
  content:"";
  position:fixed; inset:0;
  z-index:120;
  pointer-events:none;
  opacity:.04;
  mix-blend-mode:multiply;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)'/%3E%3C/svg%3E");
}
img{max-width:100%;display:block;}
a{color:inherit;text-decoration:none;}
h1,h2,h3{
  font-family:var(--font-display);
  font-weight:700;
  margin:0;
  line-height:1.22;
  letter-spacing:-.012em;
  text-wrap:balance;
}
p{margin:0;line-height:1.85;text-wrap:pretty;}
ul{margin:0;padding:0;list-style:none;}
button{font-family:inherit;cursor:pointer;background:none;border:none;color:inherit;}

/* visible keyboard focus everywhere (was missing site-wide) */
:where(a,button,input,textarea,select,[tabindex]):focus-visible{
  outline:2px solid var(--brand);
  outline-offset:3px;
  border-radius:4px;
}

/* skip link — off-screen until focused */
.skip-link{
  position:fixed; top:12px; left:12px; z-index:300;
  background:var(--brand); color:#fff;
  padding:10px 18px; border-radius:var(--r-pill);
  font-size:.85rem; font-weight:700;
  transform:translateX(-9999px);
}
.skip-link:focus{transform:translateX(0);}

@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{
    animation-duration:.001ms !important;
    transition-duration:.001ms !important;
    scroll-behavior:auto !important;
  }
}

.container{
  width:100%;
  max-width:var(--container-w);
  margin:0 auto;
  padding:0 24px;
  position:relative;
}

.section{
  position:relative;
  min-height:100vh;
  display:flex;
  flex-direction:column;
  padding:100px 0 0;
  /* was overflow:hidden — that clipped any section whose real content ended
     up taller than the viewport (increasingly common: recipes/stockists
     grow with real data, and a shorter browser window needs more room than
     a tall one). Sections now simply grow past 100vh and the extra height
     scrolls into view instead of being cut off. overflow-x stays hidden so
     decorative elements that intentionally bleed past the container's sides
     (hero shape, recipe photo, etc.) don't introduce a horizontal scrollbar. */
  overflow-x:hidden;
}
.section > .container{
  flex:1 0 auto;
  display:flex;
  flex-direction:column;
  justify-content:center;
  padding-top:16px;
  padding-bottom:16px;
}
.snap-section{scroll-margin-top:0;}

/* bottom-of-section mascot bar — width-matched to .container (max-width:var(--container-w),
   same horizontal padding) so a bar sized as a % of this equals the hero shape's own width,
   since the shape is sized the same way relative to .container */
.section-mascot{
  flex-shrink:0;
  display:flex;
  justify-content:center;
  width:100%;
  max-width:var(--container-w);
  margin:0 auto;
  padding:0 24px var(--mascot-space-below);   /* one value, site-wide */
}
.section-mascot .mascot-banner{margin:0;}

.eyebrow{
  display:flex;
  align-items:center;
  gap:10px;
  font-family:var(--font-body);
  font-size:.78rem;
  font-weight:700;
  letter-spacing:.22em;
  text-transform:uppercase;
  color:var(--brand-ink);
  padding-bottom:0;
  margin-bottom:18px;
  width:max-content;
}
.eyebrow::before{
  content:"";
  width:26px;
  height:3px;
  background:var(--brand);
  border-radius:2px;
}
.section-title{
  font-size:var(--fs-h2);
  color:var(--terracotta);          /* site-wide; sections that need white override below */
  margin-bottom:36px;
  max-width:20ch;
}
.section-subtitle{
  font-family:var(--font-title);
  font-size:var(--fs-h3);
  color:var(--ink);
  margin-bottom:16px;
}

/* ============================================================
   Reveal-on-scroll (fade + scale, staggered, replays)
   ============================================================ */
.reveal{
  opacity:0;
  transform:translateY(28px) scale(.94);
  transition:opacity .7s cubic-bezier(.22,.68,0,1), transform .7s cubic-bezier(.22,.68,0,1);
}
.reveal.is-visible{
  opacity:1;
  transform:translateY(0) scale(1);
}

/* ============================================================
   Desktop vertical mini-nav
   ============================================================ */
.side-nav{
  position:fixed;
  left:28px;
  top:50%;
  transform:translateY(-50%);
  z-index:40;
  display:flex;
  flex-direction:column;
  gap:16px;
}
.side-nav a{
  font-size:.8rem;
  color:var(--terracotta);
  opacity:.6;
  white-space:nowrap;
  transition:opacity .25s, color .25s, transform .25s;
}
.side-nav a:hover{opacity:1; transform:translateX(4px);}
.side-nav a.is-active{opacity:1; font-weight:700;}

/* ============================================================
   Mobile hamburger + fullscreen popup
   ============================================================ */
.hamburger-btn{
  position:fixed;
  top:24px;
  left:24px;
  z-index:60;
  width:56px;
  height:40px;
  border-radius:22px;
  background:var(--blush);
  border:1.5px solid var(--terracotta);
  display:none;
  align-items:center;
  justify-content:center;
  flex-direction:column;
  gap:5px;
}
.hamburger-btn span{
  width:22px;
  height:2px;
  background:var(--terracotta);
  display:block;
  transition:transform .3s, opacity .3s;
}
/* the fullscreen menu has its own close button — hide the hamburger while open
   so there aren't two ✕ controls stacked in the corner */
.hamburger-btn.is-open{display:none;}

/* ---- sticky "how to buy" badge, bottom-right, gently bobbing ---- */
.buy-fab{
  position:fixed;
  right:clamp(12px, 3vw, 30px);
  bottom:clamp(12px, 3vw, 30px);
  z-index:50;
  width:clamp(100px, 13vw, 146px);
  line-height:0;
  transition:transform .25s var(--ease);
}
.buy-fab img{
  display:block;
  width:100%;
  height:auto;
  filter:drop-shadow(0 8px 16px rgba(74,45,28,.22));
  animation:buy-fab-float 3.6s ease-in-out infinite;
}
.buy-fab:hover{transform:scale(1.05);}
.buy-fab:active{transform:scale(.96);}
.buy-fab:focus-visible{outline:2px solid var(--terracotta); outline-offset:5px; border-radius:14px;}
@keyframes buy-fab-float{
  0%,100%{transform:translateY(0);}
  50%{transform:translateY(-7px);}
}
@media (prefers-reduced-motion:reduce){
  .buy-fab img{animation:none;}
}

/* ---- sticky logo bar ----------------------------------------------------
   Just the gradient field behind the logo. Its colour is synced by script.js
   to whatever section is under the top edge; the logo that docks in front of
   it is the one .hero-logo element (see above), scroll-driven.            */
.site-topbar{
  position:fixed;
  top:0; left:0; right:0;
  z-index:44;                 /* under the docking logo (45) and the mobile menu (55) */
  height:78px;
  pointer-events:none;
  /* fallback tint; script.js overrides with the live section colour */
  background:linear-gradient(to bottom,
    rgba(251,245,233,.82) 0%,
    rgba(251,245,233,.42) 46%,
    rgba(251,245,233,0)  100%);
  -webkit-backdrop-filter:blur(3px);
          backdrop-filter:blur(3px);
  -webkit-mask-image:linear-gradient(to bottom, #000 55%, transparent 100%);
          mask-image:linear-gradient(to bottom, #000 55%, transparent 100%);
  opacity:0;                  /* script.js ramps opacity with scroll progress */
  transition:background .35s ease;
}
@media (min-width:901px){
  .site-topbar{height:88px;}
}

.mobile-menu{
  position:fixed;
  inset:0;
  background:var(--terracotta);
  z-index:55;
  display:flex;
  align-items:center;
  justify-content:center;
  opacity:0;
  visibility:hidden;
  transform:scale(1.05);
  transition:opacity .35s ease, transform .35s ease, visibility .35s;
}
.mobile-menu.is-open{opacity:1; visibility:visible; transform:scale(1);}
.mobile-menu-close{
  position:absolute;
  top:24px;
  right:24px;
  font-size:2.2rem;
  color:#fff;
  line-height:1;
}
.mobile-menu-nav{
  display:flex;
  flex-direction:column;
  gap:24px;
  align-items:center;
}
/* plain white menu text on the coral overlay — no pill */
.pill-btn{
  font-family:var(--font-title);
  font-size:1.5rem;
  color:#fff;
  padding:6px 10px;
  transition:opacity .2s var(--ease);
}
.pill-btn:hover,
.pill-btn:focus-visible{opacity:.68;}

/* ============================================================
   Mascot inline banners (hero / feeding / testimonials)
   ============================================================ */
.mascot-banner{
  position:relative;
  display:flex;
  align-items:center;
  gap:16px;
  
  flex-shrink:0;          /* without this, the flex parent (.section-mascot) shrinks it back down to fit */
  background:var(--peach); /* was --blush, which is also the page background in several sections (hero, testimonials) — same color as its surroundings made the pill invisible against the page, leaving only the shadow rim visible */
  border-radius:999px;
  padding:14px 32px 14px 200px; /* left padding reserves room for the absolutely-positioned character so the text never sits under it */
  margin:40px auto 0;
  /* solid-shape-offset-behind treatment — the same technique as the hero shape
     (a duplicate shape sitting behind, offset down-right, showing as a rim),
     just done as a hard (0-blur, 0-spread) box-shadow instead of a second element,
     and in terracotta instead of leaf-green */
  box-shadow:6px 6px 0 0 var(--terracotta);
}
.mascot-banner__img{
  position:absolute;
  z-index:2;
  left:25px;
  bottom:0px;
  width:172px;
  height:auto;
}
.mascot-banner p{font-family:var(--font-hand); font-size:1.2rem;}

/* ============================================================
   HERO
   ============================================================ */
.hero-section{padding-top:3px; padding-bottom:0;}
.hero-section > .container{padding-top:6px; padding-bottom:6px;}
.hero-container{display:flex; align-items:center; justify-content:center;}

/* ---- scroll cue: floats over the very bottom of the hero, hinting there's
   more below. Absolutely positioned (not part of the normal flex flow) so
   it doesn't push/shrink the hero collage above it. The arrow gets a very
   light, slow up/down drift — deliberately smaller and slower than
   .buy-fab's bouncier float — just enough to catch the eye without being
   distracting on a section people look at for a while. */
/* centered with left:0/right:0/margin:auto, NOT transform:translateX(-50%)
   — this element also carries the site-wide .reveal utility class, which
   sets its OWN transform (translateY + scale, for the fade/scale-in on
   scroll). Both rules have equal specificity, so whichever is declared
   later in the stylesheet wins outright — .reveal happens to be declared
   after this block, silently dropping any translateX centering here and
   leaving the box's left edge pinned at 50% instead of truly centered
   (visible as a rightward shift by half the box's own width). Margin-based
   centering doesn't touch `transform` at all, so it can't collide with
   .reveal's. */
.hero-scroll-cue{
  position:absolute;
  left:0;
  right:0;
  width:max-content;
  margin:0 auto;
  bottom:26px;
  z-index:5;
  display:flex;
  flex-direction:column;
  align-items:center;
  gap:10px;
  color:var(--brand-ink);
  text-decoration:none;
  opacity:.85;
  transition:opacity .2s ease, transform .2s ease;
}
.hero-scroll-cue:hover{opacity:1; transform:translateY(-2px);}
.hero-scroll-cue__text{
  font-family:var(--font-body);
  font-size:.74rem;
  font-weight:700;
  letter-spacing:.14em;
  text-transform:uppercase;
  text-shadow:0 1px 10px rgba(255,255,255,.5);
}
/* same circular-badge language as the product gallery's prev/next arrows —
   a light ring so the chevron reads as a clear, tappable control rather
   than a bare floating icon */
.hero-scroll-cue__arrow-badge{
  width:36px;
  height:36px;
  border-radius:50%;
  border:1.5px solid var(--brand-ink);
  background:rgba(255,255,255,.5);
  display:flex;
  align-items:center;
  justify-content:center;
  animation:hero-scroll-cue-drift 3.2s ease-in-out infinite;
}
.hero-scroll-cue__arrow{width:16px; height:16px;}
@keyframes hero-scroll-cue-drift{
  0%,100%{transform:translateY(0);}
  50%{transform:translateY(5px);}
}
@media (prefers-reduced-motion:reduce){
  .hero-scroll-cue__arrow-badge{animation:none;}
}
.hero-shape{
  position:relative;
  width:112%;
  max-width:none;
  aspect-ratio:1655/1180; /* matches the exported collage canvas exactly */
  --spread:1;
  /* the oval sits low within this box (centered at top:57%, not 50%) so the
     logo can straddle its rim — that leaves a lot of dead space above the
     oval that flex-centering the box doesn't account for, badly unbalancing
     top vs bottom whitespace. Nudge the whole box up to compensate. */
  transform:translateY(-34px);
}

/* two stacked ovals: solid leaf-green sits behind, offset down-right;
   cream oval on top with no stroke of its own — the green only shows
   as a rim where the offset exposes it (bottom/bottom-right), matching
   the mockup. Sized/positioned to the collage's actual content bounds. */
.hero-shape__bg-green,
.hero-shape__bg-cream{
  position:absolute;
  width:82%;
  height:86%;
  left:47.3%;
  top:57%;
  border-radius:41%;
}
.hero-shape__bg-green{
  z-index:1;
  background:var(--leaf);
  transform:translate(-50%,-50%);
}
.hero-shape__bg-cream{
  z-index:2;
  background:#fbf5e9;
  transform:translate(calc(-50% - 10px), calc(-50% - 13px));
}

/* the two flattened collage exports (start / finish), same canvas size, crossfaded.
   Only the FINISH frame is clipped to the oval (so it bleeds past the rim and gets
   cut off cleanly, like the mockup) — the START frame stays unclipped so items can
   fly in freely across the whole viewport before they land. */
.hero-collage{position:absolute; inset:0; z-index:3;}
.hero-collage__img{
  position:absolute;
  object-fit:contain;
  transition:opacity 1.35s ease, filter 1.35s ease, transform 1.35s cubic-bezier(.16,.85,.22,1);
}
.hero-collage__img--start{
  inset:0; width:100%; height:100%;
  z-index:2; opacity:0; filter:blur(14px); transform:scale(.96);
}

/* wrapper sized/positioned exactly like the cream oval, same border-radius, with
   overflow hidden — this is what actually crops the finish frame. The image inside
   is oversized/offset by the inverse of the wrapper's own size ratio so that, once
   cropped, it lines up pixel-for-pixel with where it'd sit if it filled the whole
   shape directly (see the ow/oh/ocx/ocy math: wrapper is 82%x86% of the shape,
   centered at 47.3%/57%, so the image inside is scaled by 100/82 and 100/86 and
   shifted to compensate). */
.hero-oval-clip{
  position:absolute;
  width:82%;
  height:86%;
  left:47.3%;
  top:57%;
  transform:translate(calc(-50% - 10px), calc(-50% - 13px));
  border-radius:41%;
  overflow:hidden;
  z-index:1;
}
.hero-collage__img--finish{
  left:50%;
  top:50%;
  max-width:none; /* override the global img{max-width:100%} reset — this image needs to overflow its wrapper on purpose */
  width:204%;
  height:194.51%; /* keeps the same aspect ratio as the 204% width */
  z-index:1; opacity:1; filter:blur(0); transform:translate(-50%,-50%) scale(1);
}

/* pre-fly: the start frame is fully visible and blown up big (so items read as entering
   from around/off the browser edges, not just a tight shuffle) — stays blurred the whole
   way through (never sharpens), matching the "still in motion" feel. Finish frame starts
   hidden/blurred — ships baked into the HTML so first paint has no prior state to
   transition from */
.hero-shape.pre-fly .hero-collage__img--start{ opacity:1; filter:blur(10px); transform:scale(2.15); }
.hero-shape.pre-fly .hero-collage__img--finish{ opacity:0; filter:blur(16px); transform:translate(-50%,-50%) scale(1.06); }

/* logo straddles the top rim of the shape: half above, half inside */
/* The single saesa logo. It's fixed to the viewport and script.js drives its
   transform from scroll: at the top it sits on the hero oval's rim at full
   size; as you scroll it tracks the page up and shrinks, locking into the
   docked top-bar size/position. One element — no duplicate. */
.hero-logo{
  position:fixed;
  z-index:45;
  top:0;
  left:50%;
  width:min(28.6vw, 260px);   /* hero (full) size */
  line-height:0;
  transform-origin:center top;
  transform:translate(-50%, 0) scale(1);   /* JS overrides on load + scroll */
  will-change:transform;
  opacity:0;                                /* JS shows it once measured/placed */
  transition:opacity .25s ease;
}
.hero-logo img{
  display:block;
  width:100%;
  height:auto;
  filter:drop-shadow(0 3px 12px rgba(74,45,28,.16));
  transition:filter .3s ease;
}
/* flip the wordmark to white over a dark section (red band, etc.) */
.hero-logo.on-dark img{
  filter:brightness(0) invert(1) drop-shadow(0 2px 10px rgba(0,0,0,.3));
}
.hero-logo:focus-visible{outline:2px solid var(--terracotta); outline-offset:6px; border-radius:10px;}

/* vertical "美味の秘密" graphic — centered in the middle of the oval shape itself
   (same center point as the cream oval), both axes */
.hero-tagline-img{
  position:absolute;
  z-index:5;
  left:50%;
  top:57%;
  height:56%;
  width:auto;
  transform:translate(calc(-50% - 10px), calc(-50% - 13px)) scale(1);
  opacity:1;
  transition:opacity 1.35s ease .25s, transform 1.35s cubic-bezier(.16,.85,.22,1) .25s;
}
/* hidden/small while the start frame is flying in — fades + zooms in shortly after
   the finish frame appears (small delay so it reads as arriving after the food) */
.hero-shape.pre-fly .hero-tagline-img{
  opacity:0;
  transform:translate(calc(-50% - 10px), calc(-50% - 13px)) scale(.7);
}

/* ============================================================
   FEATURES (after hero) — left column: eyebrow/title + the 4-sachet photo,
   same two-column grid convention as .product-slide. Right column: 4 rows,
   each a square photo overlapping the left edge of a cream pill card (simple
   overlap, not the hero/aboutus-shape offset-shadow-rim technique).
   ============================================================ */
/* content-sized rather than forced to fill the viewport — see the base
   .section rule's min-height:100vh above; this section only needs to be as
   tall as its own copy + sachet photo, not a full screen. */
/* no .section-mascot bar in this section to own the below-content gap (see
   other sections), so now that min-height:auto no longer pads it out to a
   full screen, give it back its own bottom breathing room explicitly */
.features-section{background:var(--peach); min-height:auto; padding-bottom:100px;}
.section > .container.features-slide{
  display:grid;
  grid-template-columns:minmax(320px,460px) 1fr;
      align-content: space-between;
  gap:56px;
}
.features-slide__info{
  display:flex;
  flex-direction:column;
  align-items:flex-start;
  gap:36px;
}
.features-slide__photo{
  position:relative;
  z-index:1;
  width:100%;
  max-width:440px;
  filter:drop-shadow(0 20px 30px rgba(58,44,34,.18));
}
/* the sachets photo sits in a visual wrapper so 2 speech-bubble callouts
   (each framing a small looping GIF) can be pinned around it — one poking
   past the top-left corner, one past the bottom-right, each with a little
   solid-colour "tail" pointing back toward the sachets. Pure CSS, no image
   asset needed for the bubble shape itself. */
.features-slide__visual{
  position:relative;
  width:100%;
  max-width:440px;
}
.feature-bubble{
  position:absolute;
  width:220px;
  aspect-ratio:7/4; /* matches the 700x400 gifs so they're never stretched/cropped oddly */
  z-index:3;
}
.feature-bubble__inner{
  width:100%;
  height:100%;
  border-radius:24px;
  border:5px solid var(--white);
  overflow:hidden;
  background:#fff;
  position:relative;
  z-index:1;
}
.feature-bubble__inner img{
  width:100%;
  height:100%;
  object-fit:cover;
  display:block;
}
/* curved "swoosh" tail (per Ken's reference) instead of a plain triangle —
   an SVG path so the curve can taper smoothly to a point, filled in coral to
   match the bubble border. Each bubble's tail is a corner-to-point shape;
   the --br path is the exact 180°-rotated mirror of the --tl path so both
   point back toward the sachets photo between them. */
.feature-bubble__tail{
  position:absolute;
  width:52px;
  height:52px;
  z-index:0;
}
.feature-bubble__tail path{
  fill:var(--white);
}
.feature-bubble--tl{
      top: -7%;
    left: -23%;
}
.feature-bubble__tail--tl{
  bottom:-14px;
  right:-14px;
}
.feature-bubble--br{
      bottom: -26%;
    right: -2%;
}
.feature-bubble__tail--br{
  top:-14px;
  left:-14px;
}
.features-list{
  display:flex;
  flex-direction:column;
  gap:28px;
}
/* the photo sits mostly OUTSIDE the card, to its left, poking up slightly
   above the card's top edge — only its right sliver actually overlaps the
   card. Needs position:relative + absolute rather than the old flex layout,
   since a flex sibling can only overlap by however much negative margin you
   give it (no room for "mostly outside, corner tucked in" the way the
   photo/card overlap on top-left). */
.feature-row{
  position:relative;
  margin-top:20px; /* clears the photo's upward poke (18px) so it doesn't crowd the row above */
}
.feature-row__photo{
      position: absolute;
    left: 15px;
    top: -18px;
    width: 150px;
    height: 150px;
    border-radius: 28px;
    object-fit: cover;
    z-index: 2;
}
.feature-row__card{
      min-height: 150px;
    background: #fbf5e9;
    border-radius: 32px;
    padding: 20px 32px 20px 181px;
    display: flex;
    flex-direction: column;
    justify-content: center;
}
.feature-row__title{
  font-family:var(--font-title);
  font-size:1.15rem;
  color:var(--terracotta);
  margin-bottom:2px;
}
.feature-row__subtitle{
  font-size:.95rem;
  font-weight:700;
  color:var(--ink);
  margin-bottom:6px;
}
.feature-row__desc{
  font-size:.9rem;
  line-height:1.6;
  color:var(--ink);
  opacity:.85;
}

/* ============================================================
   ABOUTUS (關於我們) — the shape/timeline fades in on scroll (reveal-on-scroll,
   same IntersectionObserver pattern as every other .reveal element).
   ============================================================ */
.aboutus-section{
  background:var(--blush);
  padding:0;
  min-height:100vh;
}
.aboutus-stage{
  position:relative;
  flex:1 1 auto;
  min-height:0;
  overflow:hidden;
  display:flex;
  flex-direction:column;
  align-items:center;
  justify-content:center;
  gap:20px;
  padding:0 24px;
}

/* the shape — same treatment as the hero shape (a green backing oval offset behind a
   cream oval, giving the same solid-color rim "shadow"). Only starts fading in once
   the full-screen photo above has completely faded away (the user's release scroll). */
.aboutus-shape{
  position:relative;
  z-index:1;
  width:100%;
  max-width:900px;
  aspect-ratio:1655/1180;
  margin:0 auto;
  opacity:0;
  transition:opacity .8s ease;
  transition-delay:.7s;
}
.aboutus-stage.revealed .aboutus-shape{
  opacity:1;
}
.aboutus-shape__bg-green, .aboutus-shape__bg-cream{
  position:absolute; inset:0; border-radius:41%;
}
.aboutus-shape__bg-green{ z-index:1; background:var(--leaf); }
.aboutus-shape__bg-cream{ z-index:2; background:#fbf5e9; transform:translate(-10px,-13px); }
.aboutus-shape__clip{
  position:absolute; inset:0;
  transform:translate(-10px,-13px);
  border-radius:41%;
  overflow:hidden;
  z-index:3;
}
.aboutus-shape__steps-layer{
  position:absolute; inset:0;
  /* left/right inset needs to clear the oval's curve, which pinches in a lot
     more at top/bottom (steps 1 & 3, near the narrow ends) than at the
     vertical center (step 2) — 6% was only safe for the middle row and let
     step 1/3's text run into the curved edge and get clipped by
     .aboutus-shape__clip's overflow:hidden. */
  padding:13% 14%;
  opacity:0;
  transition:opacity .8s ease;
  transition-delay:1.4s;
}
.aboutus-stage.revealed .aboutus-shape__steps-layer{
  opacity:1;
}

/* shape title: a brand-new heading that appears above the shape (not inside it) once
   it's fully formed — simultaneous with the shape crossfading to reveal the timeline.
   Sits in normal flow, stacked above .aboutus-shape by .aboutus-stage's own flex-column
   + gap, so it never overlaps the shape. Its box is always reserved (only opacity
   animates) so nothing shifts when it fades in. */
.aboutus-shape-title{
  flex-shrink:0;
  text-align:center;
  color:var(--white);
  font-size:clamp(1.6rem,3vw,2.2rem);
  opacity:0;
  transition:opacity .8s ease;
  transition-delay:1.4s;
}
.aboutus-stage.revealed .aboutus-shape-title{
  opacity:1;
}

/* timeline: a central spine with 3 dots, dashed connectors alternating left/right to
   each step's content, ending in an arrow that hands off to the bowl below. Everything
   plays automatically in sequence once the shape has appeared — no scrolling needed. */
.aboutus-timeline{position:relative; width:100%; height:100%;}
.aboutus-timeline__spine{
  position:absolute;
  left:50%; top:4%; bottom:12%;
  width:3px;
  background:var(--leaf);
  transform:translateX(-50%) scaleY(0);
  transform-origin:top;
  transition:transform 1.4s linear;
}
.aboutus-stage.revealed .aboutus-timeline__spine{ transform:translateX(-50%) scaleY(1); transition-delay:1.6s; }
.aboutus-timeline__arrow{
  position:absolute;
  left:50%; bottom:9%;
  width:0; height:0;
  border-left:7px solid transparent;
  border-right:7px solid transparent;
  border-top:12px solid var(--leaf);
  transform:translate(-50%, 6px);
  opacity:0;
  transition:opacity .4s ease, transform .4s ease;
}
.aboutus-stage.revealed .aboutus-timeline__arrow{ opacity:1; transform:translate(-50%,0); transition-delay:3.1s; }

/* the step "row" spans the full timeline width (not just the center point) so that
   the connector/content percentage widths below resolve against something real —
   only the dot sits exactly on the spine; connector + content are offset from center. */
.aboutus-tl-step{position:absolute; left:0; right:0;}
.aboutus-tl-step--1{top:14%;}
.aboutus-tl-step--2{top:45%;}
.aboutus-tl-step--3{top:76%;}
/* step 4 only exists for the mobile layout (see media query below) — hidden by
   default so it never appears in the 3-step desktop timeline */
.aboutus-tl-step--4{display:none;}
.aboutus-tl-dot{
  position:absolute; left:50%; top:0; z-index:2;
  width:16px; height:16px; border-radius:50%; background:var(--leaf);
  transform:translate(-50%,-50%) scale(0);
  box-shadow:0 0 0 7px rgba(179,217,122,.35);
  transition:transform .4s ease;
}
.aboutus-tl-connector{
  position:absolute; top:0; height:0;
  border-top:2px dashed var(--leaf);
  transform:translateY(-50%) scaleX(0);
  transition:transform .4s ease;
}
.aboutus-tl-connector--left{right:calc(50% + 9px); width:15%; transform-origin:right;}
.aboutus-tl-connector--right{left:calc(50% + 9px); width:15%; transform-origin:left;}
.aboutus-tl-content{
  position:absolute; top:0; width:40%;
  opacity:0;
  transition:opacity .4s ease, transform .4s ease;
}
.aboutus-tl-content--left{right:calc(50% + 9px + 15% + 6px); text-align:right;}
.aboutus-tl-content--right{left:calc(50% + 9px + 15% + 6px); text-align:left;}

/* the connector/dot points at the SUBTITLE line specifically, not the row below —
   the label alone is shifted up by half its own line-height so its vertical
   center lands on the dot's y; the desc+image row simply flows underneath it. */
.aboutus-tl-content .aboutus-step__label{
  display:block;
  transform:translateY(-50%);
}
.aboutus-tl-row{
  display:flex;
  align-items:center;
  gap:14px;
  margin-top:2px;
}
.aboutus-tl-content--left .aboutus-tl-row{justify-content:flex-end;}
.aboutus-tl-content--right .aboutus-tl-row{justify-content:flex-start;}

.aboutus-stage.revealed .aboutus-tl-step--1 .aboutus-tl-dot{transform:translate(-50%,-50%) scale(1); transition-delay:1.7s;}
.aboutus-stage.revealed .aboutus-tl-step--1 .aboutus-tl-connector{transform:translateY(-50%) scaleX(1); transition-delay:1.8s;}
.aboutus-stage.revealed .aboutus-tl-step--1 .aboutus-tl-content{opacity:1; transition-delay:1.9s;}
.aboutus-stage.revealed .aboutus-tl-step--2 .aboutus-tl-dot{transform:translate(-50%,-50%) scale(1); transition-delay:2.3s;}
.aboutus-stage.revealed .aboutus-tl-step--2 .aboutus-tl-connector{transform:translateY(-50%) scaleX(1); transition-delay:2.4s;}
.aboutus-stage.revealed .aboutus-tl-step--2 .aboutus-tl-content{opacity:1; transition-delay:2.5s;}
.aboutus-stage.revealed .aboutus-tl-step--3 .aboutus-tl-dot{transform:translate(-50%,-50%) scale(1); transition-delay:2.9s;}
.aboutus-stage.revealed .aboutus-tl-step--3 .aboutus-tl-connector{transform:translateY(-50%) scaleX(1); transition-delay:3s;}
.aboutus-stage.revealed .aboutus-tl-step--3 .aboutus-tl-content{opacity:1; transition-delay:3.1s;}
.aboutus-stage.revealed .aboutus-tl-step--4 .aboutus-tl-dot{transform:translate(-50%,-50%) scale(1); transition-delay:3.5s;}
.aboutus-stage.revealed .aboutus-tl-step--4 .aboutus-tl-connector{transform:translateY(-50%) scaleX(1); transition-delay:3.6s;}
.aboutus-stage.revealed .aboutus-tl-step--4 .aboutus-tl-content{opacity:1; transition-delay:3.7s;}

.aboutus-step__label{color:var(--olive); margin-bottom:0; display:block;}
.aboutus-step__desc{font-size:1rem; color:var(--ink); flex:1 1 auto;}
.aboutus-step__map{width:64px; flex-shrink:0; opacity:.85;}
/* every step photo is a plain circle — consistent frame across all three steps */
.aboutus-step__photo{width:72px; height:72px; object-fit:cover; border-radius:50%; flex-shrink:0; border:3px solid #fff; box-shadow:0 4px 10px rgba(0,0,0,.1);}
/* step 4's product shot: no card treatment at all (no border/shadow/crop) —
   plain image, same bare styling as the step-1 map icon */
.aboutus-step__photo--square{
  width:64px; height:auto;
  border-radius:0; border:none; box-shadow:none;
  object-fit:contain;
}

/* the bowl sits outside the clip, straddling the shape's bottom rim — same idea as
   the hero logo/tagline overlapping the hero shape's edge. */
.aboutus-step__bowl{
  position:absolute;
  z-index:4;
  bottom:-40px;
  left:50%;
  transform:translateX(-50%);
  width:150px;
  opacity:0;
  transition:opacity .4s ease, transform .4s ease;
}
.aboutus-stage.revealed .aboutus-step__bowl{ opacity:1; transform:translate(-50%,0); transition-delay:3.1s; }

/* ============================================================
   PRODUCT
   ============================================================
   Full revamp: 4 independent full-height sections (one per flavour), each
   its own solid product-colour background — the user scrolls through them
   one after another like any other section on the site, instead of the old
   click/swipe carousel. Every .product-section is built by JS from PRODUCTS
   (see script.js) but shares this one stylesheet block. */
/* .section reserves padding-top:100px (site-wide) for the fixed header, then
   centres its .container in whatever's left — which biases that centring
   downward, since the reserved space only exists at the top. Other sections
   are tuned around that bias, but here it reads as uneven top/bottom
   framing around the pack photo + copy, so product-section mirrors the same
   100px at the bottom too. That makes the centred band symmetric regardless
   of a flavour's copy length, instead of relying on content height matching
   a specific viewport (see .container.product-slide below, which no longer
   needs to be squeezed to fit exactly one screen). */
/* content-sized rather than forced to fill the viewport — see the base
   .section rule's min-height:100vh above. The gallery/copy row still gets
   its own min-height (below) so the photo has decent presence even when a
   flavour's copy is short, but the section as a whole no longer pads out
   to fill any leftover screen height. */
.product-section{color:#fff; padding-top:0; min-height:auto;}
/* the eyebrow/title styling elsewhere on the site (.eyebrow / .section-title)
   assumes a light page background — override to white here since every
   product section is a solid, usually fairly dark, product colour */
.product-section .eyebrow{color:#fff; border-color:rgba(255,255,255,.65);}
.product-section .section-title{color:#fff;}

/* ---- layout: full-bleed photo gallery (left) + copy (right) ----
   Per Ken's mockup: the gallery runs edge-to-edge to the section's own
   top/bottom AND to the browser's left edge (not capped by the site's usual
   .container), while the copy sits in a normal readable column on the right.
   .product-slide replaces .section > .container here (this section doesn't
   use .container at all) and stretches to fill the same space .container
   would have (flex:1 0 auto, matching the base .section > .container rule),
   just at full viewport width instead of var(--container-w). */
.product-slide{
  flex:1 0 auto;
  display:flex;
  align-items:stretch;
  width:100%;
  /* keeps the gallery photo a decent size even on a flavour whose copy is
     short (now that .product-section is content-sized, not full-viewport) */
  min-height:560px;
}
/* alternating layout — apple & sweet potato flip to gallery-right/copy-left
   (desktop only; set per-flavour via p.reverse in script.js). Mobile always
   stacks gallery-on-top regardless, since the later mobile media query's
   plain .product-slide{flex-direction:column} rule (same specificity, later
   in source) wins over this row-reverse there. */
/* apple & sweet potato flip the GALLERY to the other side (see script.js
   p.reverse) — text stays centered either way (below), so no separate
   text-alignment handling is needed per flavour any more. */
.product-slide--reverse{flex-direction:row-reverse;}
.product-slide__visual{
  position:relative;
  flex:0 0 46%;
  overflow:hidden;
}
.product-slide__info{
  flex:1;
  display:flex;
  align-items:center;
  justify-content:center;
  padding:64px clamp(32px,5vw,90px);
}
.product-slide__inner{
  width:100%;
  max-width:460px;
  text-align:center;
}
/* .product-slide__desc / .product-slide__name (via .product-section
   .section-title below) each carry their own narrower max-width for
   readability — text-align:center on the parent only centers the text
   INSIDE those boxes, not the boxes themselves, so without margin:auto
   they would still sit flush against the left edge. */
.product-slide__desc{margin-left:auto; margin-right:auto;}
.product-slide__eyebrow-block{display:flex; flex-direction:column; align-items:center; margin-bottom:20px;}
.product-slide__title{font-weight:700; font-size:1.3rem; line-height:1.4; margin-bottom:4px;}
.product-slide__name{font-family:var(--font-title); font-size:clamp(1.5rem,2.4vw,2rem); margin-bottom:16px; margin-left:auto; margin-right:auto;}
.product-slide__hook{font-size:.92rem; line-height:1.6; font-weight:600; opacity:.95; margin-bottom:12px;}
.product-slide__desc{font-size:1rem; line-height:1.7; opacity:.92; margin-bottom:18px;}
.chip-pill{
  display:inline-block;
  padding:6px 20px;
  border-radius:999px;
  border:1.5px solid rgba(255,255,255,.7);
  font-size:.8rem;
  letter-spacing:.03em;
  margin:6px 0 10px;
}
.product-slide__ingredients{font-size:1rem; line-height:1.6; opacity:.92; margin-bottom:6px;}
.product-slide__stats-fallback{font-size:1rem; line-height:1.6; opacity:.92;}

/* ---- visual: full-bleed photo gallery with prev/next arrows + dots ---- */
.product-slide__gallery{position:absolute; inset:0;}
.product-slide__gallery-track{position:absolute; inset:0;}
.product-slide__gallery-img{
  position:absolute; inset:0;
  width:100%; height:100%;
  object-fit:cover;
  opacity:0;
  /* Ken Burns: starts at rest, slowly zooms in once active — same pattern
     as the feeding section's book slideshow (.book-slide/.is-active).
     .product-slide__visual clips this via overflow:hidden so it never
     grows past the gallery's own box. */
  transform:scale(1);
  transition:opacity .5s ease, transform .5s ease;
}
.product-slide__gallery-img.is-active{
  opacity:1;
  transform:scale(1.1);
  transition:opacity .5s ease, transform 6s ease-out;
}
@media (prefers-reduced-motion:reduce){
  .product-slide__gallery-img, .product-slide__gallery-img.is-active{transform:none; transition:opacity .4s ease;}
}
.product-slide__arrow{
  position:absolute;
  top:50%;
  transform:translateY(-50%);
  width:44px; height:44px;
  border-radius:50%;
  border:1.5px solid rgba(255,255,255,.8);
  background:rgba(0,0,0,.18);
  color:#fff;
  display:flex; align-items:center; justify-content:center;
  cursor:pointer;
  z-index:2;
  transition:background .2s ease, transform .2s ease;
}
.product-slide__arrow svg{width:20px; height:20px;}
.product-slide__arrow:hover{background:rgba(0,0,0,.32);}
.product-slide__arrow--prev{left:20px;}
.product-slide__arrow--next{right:20px;}
.product-slide__dots{
  position:absolute;
  left:50%;
  bottom:22px;
  transform:translateX(-50%);
  display:flex;
  gap:8px;
  z-index:2;
}
.product-slide__dot{
  width:8px; height:8px;
  border-radius:50%;
  border:1.5px solid rgba(255,255,255,.85);
  background:transparent;
  padding:0;
  cursor:pointer;
  transition:background .2s ease;
}
.product-slide__dot.is-active{background:#fff;}

/* ---- 保證分析 radar/spider chart ----
   3 static rounded-corner hexagons behind (outer = outline only, mid = light
   wash, inner = a touch richer/less washed-out — a decorative "gem" backdrop,
   not data), plus the actual data shape: the 6 stat dots connected to EACH
   OTHER (not centre-to-dot spokes — that read as a starburst, not a radar
   chart), on the white-on-solid-colour treatment (no light disc behind the
   whole widget — the section itself is already the product's colour). Sits
   inline in the text column, under the 保證分析 pill. */
.product-slide__radar{width:220px; max-width:80%; margin:12px auto 0;}
.product-slide__radar-svg{width:100%; height:auto; overflow:visible; display:block;}
.radar-ring{stroke-linejoin:round;}
.radar-ring--outer{fill:none; stroke:rgba(255,255,255,.5); stroke-width:.8;}
.radar-ring--mid{fill:rgba(255,255,255,.14); stroke:rgba(255,255,255,.3); stroke-width:.5;}
.radar-ring--inner{fill:rgba(255,255,255,.22); stroke:none;}
.radar-spoke{stroke:rgba(255,255,255,.4); stroke-width:.5;}
/* the connecting line: starts fully "undrawn" (dashoffset = its own full
   perimeter, set inline per-chart in JS since it depends on that flavour's
   actual data shape) and draws itself in stroke-first, fill-second */
.radar-data-stroke{
  fill:none;
  stroke:#fff;
  stroke-width:1;
  stroke-linejoin:round;
  stroke-linecap:round;
  transition:stroke-dashoffset .8s cubic-bezier(.22,.9,.3,1);
}
/* fill uses the flavour's own colour, mixed a bit darker/richer than the
   section background so the shape reads instead of vanishing into it */
.radar-data-fill{
  fill:color-mix(in srgb, var(--stat-color, #7d5abe) 82%, black 18%);
  opacity:0;
  transition:opacity .5s ease;
  transition-delay:1.75s;
}
.radar-dot{
  fill:#fff;
  transform-box:fill-box;
  transform-origin:center;
  transform:scale(0);
  transition:transform .35s cubic-bezier(.34,1.56,.64,1);
}
.radar-label{fill:#fff; font-size:5.4px; font-weight:600; opacity:.95;}
/* entrance: the whole chart is itself a .reveal (fade+scale on scroll, see
   script.js). Layered on top of that, this is the 3-stage sequence:
     1. dots pop in, staggered (per-dot transition-delay set in JS)
     2. the line connecting them draws itself around the shape (dashoffset
        driven directly from a dedicated IntersectionObserver in JS, not
        this class — an inline dashoffset always wins over a class rule)
     3. the area it encloses fades in, tinted with the flavour's own colour
   all gated on .is-visible (or the equivalent JS observer, for the line) so
   it replays each time the chart scrolls into/out of view. */
.product-slide__radar.is-visible .radar-data-fill{opacity:.75;}
.product-slide__radar.is-visible .radar-dot{transform:scale(1);}

/* ============================================================
   FEEDING
   Assets are pre-illustrated PNGs (baked-in text, per Ken's Section 4
   exports) — no text markup needed here, just positioning. Both the main
   circle and the dosage card use the same "aboutus-shape" two-layer offset
   technique as 關於我們 (see .aboutus-shape__bg-green/-cream above): a solid
   colour sits at the natural position as the shadow, a second layer of the
   real fill sits on top nudged up-left, so the shadow only peeks out as a
   hard-edged rim at the bottom-right. Content sits in its own layer with
   the same nudge so it stays aligned with the visible (front) shape. */
/* ============================================================
   FEEDING — "open book" panel overlapping a photo slideshow that
   sits as a band across the TOP of the section (heading over it,
   book straddling its lower edge)
   ============================================================ */
.feeding-section{background:var(--blush); overflow:hidden; padding:0; min-height:auto;}

.hero-book{
  position:relative;
  width:100%;
  flex:0 0 auto;               /* content height — no empty stretch below the book */
  min-height:0;
  display:flex;
  flex-direction:column;
  align-items:center;
  padding:0 24px 56px;         /* bottom clears the bottom fan so it stays visible */
}

/* ---- Layer 1: background slideshow — a top band, not full height ---- */
.hero-book__bg{
  position:absolute;
  top:0; left:0;
  width:100%;
  height:clamp(400px, 50vh, 520px);
  z-index:0;
  overflow:hidden;              /* clips the Ken Burns zoom to the band */
}
.book-slides{position:absolute; inset:0;}
.book-slide{
  position:absolute; inset:0;
  width:100%; height:100%;
  object-fit:cover;
  opacity:0;
  transform:scale(1.02);
  transition:opacity 1.6s ease, transform 1.6s ease;
}
/* Ken Burns: the active slide slowly zooms in, then fades out */
.book-slide.is-active{
  opacity:1;
  transform:scale(1.14);
  transition:opacity 1.6s ease, transform 7s ease-out;
}
@media (prefers-reduced-motion:reduce){
  .book-slide, .book-slide.is-active{transform:none; transition:opacity .4s ease;}
}
/* warm scrim so the white heading reads and the photo blends with the blush */
.hero-book__bg::after{
  content:"";
  position:absolute; inset:0;
  background:
    linear-gradient(180deg, rgba(58,44,34,.5) 0%, rgba(58,44,34,.28) 34%, rgba(58,44,34,.32) 100%),
    linear-gradient(90deg, rgba(194,100,58,.16), rgba(58,44,34,.12));
}

/* ---- heading: over the top of the photo band ---- */
.feeding-heading{
  position:relative;
  z-index:2;
  width:100%;
  max-width:1010px;
  margin:0 auto;
  padding:clamp(84px, 12vh, 132px) 6px 0;
}
.feeding-heading .eyebrow{color:#fff;}
.feeding-heading .eyebrow::before{background:#fff;}
.feeding-heading .section-title{color:#fff; margin-bottom:0; text-shadow:0 1px 14px rgba(40,28,20,.35);}

/* ---- Layer 2: the book — ONE continuous panel, read as an open spread;
   overlaps the photo band above and extends down onto the blush below ---- */
.hero-book__panel{
  --gutter:clamp(36px, 4.5vw, 68px);    /* the centre fold — wide + constant */
  --panel:#fbf5e9;
  position:relative;
  z-index:2;
  width:100%;
  max-width:860px;                      /* smaller — the content is light */
  margin-top:clamp(52px, 8vh, 92px);    /* clear gap below the heading */
  padding:40px 46px 38px;               /* straight sides; fans sit outside */
  background:var(--panel);              /* the single solid surface, both pages */
  border-radius:0;                      /* fans cap top/bottom, sides straight */
}
/* fanned page-edges — top (::before) and bottom (::after): a solid bar the
   width of the panel, its shape cut by an SVG "fan of pages" mask, pushed
   just outside the flat body so the fans extend the book past it */
.hero-book__panel::before,
.hero-book__panel::after{
  content:"";
  position:absolute;
  left:0;
  z-index:1;
  width:100%;
  aspect-ratio:1600 / 83.81;            /* wide, shallow curve */
  background-color:var(--panel);
  -webkit-mask:no-repeat center / 100% 100%;
          mask:no-repeat center / 100% 100%;
  pointer-events:none;
}
.hero-book__panel::before{
  top:0;
  transform:translateY(calc(-100% + 1px));   /* 1px overlap kills the seam */
  -webkit-mask-image:url(assets/fan-top.svg?v=2);
          mask-image:url(assets/fan-top.svg?v=2);
}
.hero-book__panel::after{
  bottom:0;
  transform:translateY(calc(100% - 1px));    /* 1px overlap kills the seam */
  -webkit-mask-image:url(assets/fan-bottom.svg?v=3);
          mask-image:url(assets/fan-bottom.svg?v=3);
}

/* ---- page-edge lines: 3 thin verticals at BOTH outer edges (this is what
   completes the "opened flat" read) — warm, soft, kept within the page ---- */
.book-lines{
  position:absolute;
  top:46px;
  bottom:46px;
  width:12px;
  display:flex;
  justify-content:space-between;
  pointer-events:none;
  z-index:2;
}
.book-lines--left{left:9px;}
.book-lines--right{right:9px;}
.book-lines i{display:block; width:1px; background:rgba(150,96,58,.24);}

/* ---- inner layout: the two facing pages come from the 2-column method
   grid; the column gap IS the centre spine (panel-centred, whitespace only —
   no crease shadow) ---- */
.book-inner{
  position:relative;
  z-index:2;
  display:flex;
  flex-direction:column;
}
/* each way: the illustration is the hero, the numbered title sits over its
   top edge (small overlap for interest), the caption sits below */
.book-methods{
  display:grid;
  grid-template-columns:1fr 1fr;        /* left page = ways 1 & 3, right = 2 & 4 */
  column-gap:var(--gutter);
  row-gap:26px;
  margin:0 0 22px;
}
.book-methods li{
  display:flex;
  flex-direction:column;
  align-items:center;
  text-align:center;
}
.book-methods h3{
  order:1;
  position:relative;
  z-index:2;
  margin:0 0 -16px;                     /* pulls the image up under it → overlap */
  /* the illustrations' bowl sits left-of-centre (sachet fills the top-right),
     so a box-centred title reads as right-shifted — nudge it back left a touch */
  transform:translateX(-8px);
  font-family:var(--font-display);
  font-weight:700;
  font-size:1.14rem;
  color:var(--terracotta);
}
.book-methods img{
  order:2;
  position:relative;
  z-index:1;
  width:100%;
  max-width:min(132px, 58%);
  height:auto;
  object-fit:contain;
}
.book-methods p{
  order:3;
  margin:6px 0 0;
  font-size:.92rem;
  line-height:1.7;
  color:var(--ink-70);
}
/* synced with the recipe tab buttons: coral fill, same rounded-rect corner
   (not a full pill), and the site's hard offset shadow */
.book-cta{
  align-self:center;
  display:inline-flex;
  align-items:center;
  gap:8px;
  padding:12px 24px;
  border-radius:var(--r-md);
  background:var(--coral);
  color:#fff;
  font-weight:700;
  font-size:.92rem;
  box-shadow:4px 4px 0 0 var(--terracotta);
  transition:background .2s var(--ease), transform .2s var(--ease), box-shadow .2s var(--ease);
}
.book-cta:hover{background:var(--terracotta); transform:translateY(-1px); box-shadow:5px 5px 0 0 rgba(58,44,34,.28);}
.book-cta:active{transform:scale(.97); box-shadow:2px 2px 0 0 var(--terracotta);}
.book-cta span{transition:transform .2s var(--ease);}
.book-cta:hover span{transform:translateX(3px);}

/* ---- dosage mascot: sits just below the book — the character pokes up over
   the bottom fan, but the pill and the fan stay fully visible. Bottom gap
   uses the shared token so the rhythm matches every other section. ---- */
.feeding-section .section-mascot{
  position:relative;
  z-index:3;
  margin-top:6px;
  padding-top:0;
  padding-bottom:var(--mascot-space-below);
}
/* the character image is removed from this section's pill (see index.html)
   — the base .mascot-banner rule's padding-left:200px only exists to
   reserve room for that absolutely-positioned character, so without it
   the text would sit stranded behind a huge empty gap; drop it back to a
   plain, evenly-padded pill. */
.feeding-section .mascot-banner{padding-left:32px;}

/* ---- phones only: HALF a book — one scallop, one column, and the book bleeds
   to the right screen edge (no gap on the right). Tablets keep the full desktop
   two-page spread (2 scallops, 2×2 grid) — it fits comfortably above ~600px. ---- */
@media (max-width:600px){
  .hero-book{min-height:0; padding:0 0 40px 16px;}   /* left margin only */
  .hero-book__bg{height:clamp(320px, 42vh, 420px);}
  .feeding-heading{padding:clamp(78px, 13vh, 118px) 16px 0;}

  .hero-book__panel{
    align-self:flex-start;        /* left edge keeps the page margin ... */
    max-width:none;
    width:calc(100% + 12px);      /* ... while the right edge bleeds off-screen */
    margin-top:clamp(24px, 4vh, 44px);
    padding:34px 22px 30px;
  }
  /* show only the left half of the 2-scallop mask → one scallop, full width */
  .hero-book__panel::before,
  .hero-book__panel::after{
    -webkit-mask-size:200% 100%;
            mask-size:200% 100%;
    -webkit-mask-position:left center;
            mask-position:left center;
  }
  .book-lines--right{display:none;}
  .book-lines--left{left:9px;}
  .book-methods{grid-template-columns:1fr; row-gap:30px;}
  .book-methods img{max-width:min(132px, 52%);}
  .book-cta{align-self:center; justify-content:center;}
  .feeding-section .section-mascot{margin-top:4px;}
}

/* ============================================================
   TESTIMONIALS
   ============================================================ */
.testimonials-section{background:var(--peach); position:relative;}
.testimonials-product{
  position:absolute;
  top:-46px;
  right:24px;
  width:clamp(140px,16vw,180px);
  height:auto;
  z-index:2;
}
.testimonial-grid{
  display:grid;
  grid-template-columns:repeat(3,1fr);
  gap:26px;
}
.testimonial-card{
  position:relative;
  background:#fff;
  border-radius:28px;
  padding:26px 24px 60px;
  font-size:1rem;
  min-height:150px;
}
.testimonial-card__author{display:block; margin-top:12px; font-size:1rem; opacity:.7;}
.testimonial-card__avatar-wrap{
  position:absolute;
  bottom:-24px;
  left:50%;
  transform:translateX(-50%);
  width:64px;
  height:64px;
}
/* solid-shape-offset-behind treatment (same technique as the hero shape /
   feeding circle) — a solid peach circle sits behind, nudged down-left, so
   it peeks out as a hard-edged shadow rather than an all-round ring */
.testimonial-card__avatar-bg{
  position:absolute;
  inset:0;
  border-radius:50%;
  background:var(--peach);
  transform:translate(6px,3px);
  z-index:1;
}
.testimonial-card__avatar{
  position:absolute;
  inset:0;
  width:64px; height:64px;
  border-radius:50%;
  object-fit:cover;
  z-index:2;
}
.testimonial-card__veggie{
  position:absolute;
  top:50%;
  width:46px;
  height:auto;
  transform:translateY(-50%);
  z-index:0;
}
.testimonial-card__veggie--left{right:100%; margin-right:2px;}
.testimonial-card__veggie--right{left:100%; margin-left:2px;}

.lifestyle-grid{
  width:80%;
  margin:38px auto 0;
  display:grid;
  grid-template-columns:repeat(3,1fr);
  column-gap:28px;
  row-gap:28px;
  align-items:start; /* keep every tile at its own aspect-ratio height instead of
    stretching to match the offset middle column's taller row — stretching is
    what was leaving a strip of the section bg showing inside the top/bottom
    tiles' own cells */
  padding-bottom:22px; /* reserves room for the middle column's translateY
    below, which (being a transform, not layout) doesn't add to the grid's
    own measured height on its own */
}
.lifestyle-grid__item{
  --y-offset:0px;
  aspect-ratio:1.89/1;
  border-radius:20px;
  overflow:hidden;
  background:var(--peach);
  cursor:pointer;
  transform:translateY(var(--y-offset));
  transition:transform .25s ease;
}
.lifestyle-grid__item:hover{transform:translateY(var(--y-offset)) scale(1.02);}
/* the stagger is a transform (visual-only) instead of margin-top, so it
   doesn't inflate the row track height for the other two tiles in that row */
.lifestyle-grid__item:nth-child(3n+2){--y-offset:22px;}
.lifestyle-grid__item img{width:100%; height:100%; object-fit:cover; display:block;}

/* ============================================================
   RECIPES
   ============================================================ */
/* content-sized rather than forced to fill the viewport — see the base
   .section rule's min-height:100vh above; this section only needs to be as
   tall as the thumbnail row + recipe shape. No .section-mascot bar here
   (removed) to own the below-content gap, so give it back explicitly, same
   token the mascot bar itself used. */
.recipes-section{background:var(--blush); min-height:auto; padding-bottom:100px;}
.recipes-section .section-title{margin-bottom:14px;}
/* now that the stage (thumbnails + big shape) fills most of the section's
   height, the default center-justify (same as every other section) splits
   whatever's left evenly above the heading and below the stage, instead of
   the old flex-start pack-to-top treatment the small recipe-grid needed. */
/* ---------- recipe stage: thumbnail row + big oval "recipe card" + peeking
   dish photo. One recipe shown at a time; desktop advances through the 5
   recipes via wheel (scroll-jack, like the aboutus section) OR by clicking a
   thumbnail directly — both wired up in script.js. On mobile the wheel-jack
   is disabled (same rule as gravity-scroll: mobile sections already run
   long, so it's click-only there), everything else stays functional. */
.recipe-stage{
  position:relative;
  display:flex;
  flex-direction:column;
  align-items:center;
  gap:25px;
}
.recipe-thumbs{
  display:flex;
  align-items:flex-start;
  gap:22px;
}
.recipe-thumb-item{
      position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    width: 145px;
    padding: 10px 8px 12px;
    border-radius: 24px;
    cursor: pointer;
    transition: background .25s ease;
}
/* the divider line between two thumbnails only shows when NEITHER neighbour
   is the active (filled-card) one — matches the mockup, where the active
   card's own rounded corners replace the line beside it. */
.recipe-thumb-item:not(.is-active) + .recipe-thumb-item:not(.is-active)::before{
  content:'';
  position:absolute;
  left:-11px; top:18%; bottom:30px;
  width:1px;
  background:rgba(58,44,34,.18);
}
.recipe-thumb{
  position:relative;
  width: 110px;
    height: 110px;
  padding:4px;
  border:none;
  border-radius:18px;
  background:transparent;
  cursor:pointer;
}
/* cartoon dish illustrations (transparent PNGs) — contained, not cropped, so
   the whole bowl floats on the card. A soft drop-shadow lifts it off the tint. */
.recipe-thumb img{
  width:100%; height:100%;
  object-fit:contain;
  display:block;
  filter:drop-shadow(0 4px 8px rgba(74,45,28,.18));
  transition:transform .25s var(--ease);
}
.recipe-thumb-item.is-active .recipe-thumb img{transform:scale(1.04);}
.recipe-thumb-name{
  font-size:1rem;
  line-height:1.25;
  text-align:center;
  color:var(--terracotta);
}
.recipe-thumb-item.is-active{
  background:var(--coral);
}
.recipe-thumb-item.is-active .recipe-thumb-name{
  color:#fff;
  font-weight:700;
}
/* hover feedback on the still-inactive tabs — a soft coral tint, never on
   the already-filled active card (its own background already reads as
   "selected"). Guarded with (hover: hover) so a tap on touch screens can't
   get stuck showing the hover tint after the finger lifts. */
@media (hover:hover){
  .recipe-thumb-item:not(.is-active):hover{
    background:rgba(239,156,111,.2);
  }
  .recipe-thumb-item:not(.is-active):hover .recipe-thumb-name{
    color:var(--coral);
  }
}

/* same solid-duplicate-shape-offset-behind treatment as .feeding-circle: a
   plain white shape sits behind, the solid terracotta shape sits in front
   offset up-left — the white only shows as a thin rim where the offset
   exposes it (bottom-right), matching the new mockup. No separate cream
   layer this time — the whole card reads as one solid terracotta circle. */
.recipe-shape{
  position:relative;
  width:min(51%,420px);
  aspect-ratio:11/10;
  margin:0 auto;
}
.recipe-shape__bg-green,
.recipe-shape__bg-cream{
  position:absolute; inset:0;
  border-radius:41%;
}
.recipe-shape__bg-green{ z-index:1; background:#fff; }
.recipe-shape__bg-cream{ z-index:2; background:var(--coral); transform:translate(-10px,-13px); }

/* text lives INSIDE the oval. The oval pinches in hard at top/bottom (see the
   aboutus-section clipping bug this same padding pattern fixed), so generous
   left/right padding is used here too — and rather than clip overflow (which
   is what caused that bug), long recipe copy simply scrolls inside its own
   box instead of getting cut off. */
.recipe-shape__content{
  position:absolute;
  /* the aboutus-section fix only needed extra L/R padding because its rows
     sit near the vertical center; this box holds full-width paragraphs top
     to bottom, which also clip on the curve near top/bottom. Rather than
     padding a full inset:0 box (the padded content's wide lines still nick
     the curve near the top/bottom edges), the content box itself is inset
     well clear of the oval's curve on all four sides — safely inside the
     tan fill everywhere a line of text can reach. Anything still too long
     scrolls inside this smaller box instead of spilling past the shape. */
  top:13%; bottom:13%; left:18%; right:18%;
  z-index:3;
  transform:translate(-10px,-13px);
  display:flex;
  flex-direction:column;
  gap:1px;
  overflow-y:auto;
  text-align:left;
}
.recipe-content__name{
  font-family:var(--font-title);
  color:#fff;
  font-size:1.25rem;
  margin:3px 0 4px;
}
.recipe-content__row{font-size:.85rem; line-height:1.2; color:#fff;}
.recipe-content__row .chip-pill{
  margin-right:6px; margin-bottom:1px; padding:2px 10px; font-size:.82rem;
  background:rgba(255,255,255,.16);
  border-color:rgba(255,255,255,.75);
  color:#fff;
}

.recipe-photo{
  position:absolute;
  right:2%;
  bottom:-4%;
  width:32%;
  max-width:180px;
  border-radius:22px;
  z-index:4;
}

/* ============================================================
   FAQ
   ============================================================ */
/* content-sized rather than forced to fill the viewport — see the base
   .section rule's min-height:100vh above; this section only needs to be as
   tall as the FAQ list itself. No .section-mascot bar here (removed) to own
   the below-content gap, so give it back explicitly, same token the mascot
   bar itself used. */
.faq-section{background:var(--peach); min-height:auto; padding-bottom:100px;}
.faq-section .section-title{margin-bottom:14px;}
.faq-section > .container{justify-content:flex-start;}
/* the default mascot pill is --peach, same as this section's background, so it
   would vanish into the page — give it a contrasting fill + leaf shadow here */
.faq-section .mascot-banner{background:var(--blush); box-shadow:6px 6px 0 0 var(--leaf);}
.faq-card{
  background:#fbf5e9;
  border-radius:130px;
  padding:14px 70px;
}
.faq-item{border-bottom:1px solid rgba(58,44,34,.15);}
.faq-item:last-child{border-bottom:none;}
.faq-item__q{
  width:100%;
  display:flex;
  align-items:center;
  justify-content:space-between;
  padding:18px 0;
  font-size:1rem;
  text-align:left;
}
.faq-item__icon{transition:transform .3s ease; opacity:.6;}
.faq-item.is-open .faq-item__icon{transform:rotate(180deg);}
.faq-item__a{
  max-height:0;
  overflow:hidden;
  transition:max-height .35s ease, padding .35s ease;
  font-size:1rem;
  line-height:1.8;
  opacity:.85;
}
.faq-item.is-open .faq-item__a{max-height:200px; padding-bottom:18px;}

/* ============================================================
   STOCKISTS
   ============================================================ */
/* section background is set in the palette block lower down (--blush) */

/* ---- search field ---- */
.stockists-search{margin:8px 0 0;}
.stockists-search input{
  width:100%;
  max-width:520px;
  padding:14px 20px;
  border:1px solid var(--hairline);
  border-radius:var(--r-pill);
  background:var(--paper-raised);
  font:inherit;
  color:var(--ink);
  transition:border-color .2s var(--ease), box-shadow .2s var(--ease);
}
.stockists-search input::placeholder{color:var(--ink-40, rgba(58,44,34,.45));}
.stockists-search input:focus{
  outline:none;
  border-color:var(--terracotta);
  box-shadow:0 0 0 3px rgba(194,100,58,.18);
}

/* ---- region filter pills ---- */
.stockists-filters{
  display:flex;
  flex-wrap:wrap;
  gap:10px;
  margin:18px 0 40px;
}
.region-pill{
  padding:9px 18px;
  border-radius:var(--r-pill);
  border:1px solid transparent;
  background:var(--paper-raised);
  color:var(--ink);
  font-size:.9rem;
  font-weight:500;
  cursor:pointer;
  transition:background .2s var(--ease), border-color .2s var(--ease), color .2s var(--ease), box-shadow .2s var(--ease);
}
@media (hover:hover){
  .region-pill:not(.is-active):hover{background:#fff; border-color:var(--terracotta);}
}
.region-pill.is-active{
  background:var(--terracotta);
  color:#fff;
  font-weight:700;
  box-shadow:4px 4px 0 0 rgba(58,44,34,.18);
}

/* ---- region blocks ---- */
.region-block{margin-bottom:40px;}
.region-block:last-of-type{margin-bottom:0;}
.region-block__title{
  display:flex;
  align-items:center;
  gap:9px;
  margin:0 0 18px;
  padding-bottom:12px;
  border-bottom:1px solid rgba(58,44,34,.15);
  font-family:var(--font-display);
  font-weight:700;
  font-size:1.15rem;
  color:var(--terracotta);
}
.region-block__title::before{
  content:"";
  width:9px; height:9px;
  border-radius:50%;
  background:var(--leaf);
  flex-shrink:0;
}
.stockist-list{
  list-style:none;
  margin:0;
  padding:0;
  display:grid;
  grid-template-columns:repeat(auto-fill, minmax(min(100%, 300px), 1fr));
  gap:18px;
}
.stockist-empty,
.stockists-noresult{
  margin:0;
  background:var(--paper-raised);
  border-radius:var(--r-md);
  padding:16px 20px;
  font-size:.9rem;
  line-height:1.7;
  color:var(--ink-70);
}
.stockists-noresult{margin-top:8px;}

/* ---- individual stockist card ---- */
.stockist-card{
  background:var(--paper-raised);
  border-radius:var(--r-lg);
  /* solid offset shadow — same hard-edged treatment as the recipe panel and
     testimonial cards */
  box-shadow:6px 6px 0 0 var(--coral);
  padding:22px 22px 20px;
  text-align:left;
  display:flex;
  flex-direction:column;
}
.stockist-card__name{
  font-family:var(--font-display);
  font-weight:700;
  font-size:1.05rem;
  color:var(--ink);
  margin:0 0 6px;
}
.stockist-card__meta{
  font-size:.82rem;
  font-weight:600;
  letter-spacing:.02em;
  color:var(--terracotta);
  margin-bottom:8px;
}
.stockist-card__addr{
  font-size:.9rem;
  line-height:1.65;
  color:var(--ink-70);
}
.stockist-card__addr a{
  color:var(--terracotta);
  text-decoration:underline;
  font-weight:600;
}
.stockist-card__actions{
  display:flex;
  flex-wrap:wrap;
  gap:8px;
  margin-top:auto;
  padding-top:16px;
}
.stockist-card__call,
.stockist-card__map{
  display:inline-flex;
  align-items:center;
  gap:6px;
  padding:8px 15px;
  border-radius:var(--r-pill);
  font-size:.85rem;
  font-weight:700;
  transition:background .2s var(--ease), border-color .2s var(--ease), transform .2s var(--ease);
}
.stockist-card__call{background:var(--terracotta); color:#fff;}
.stockist-card__call:hover{background:#a8522e; transform:translateY(-1px);}
.stockist-card__map{border:1.5px solid rgba(58,44,34,.25); color:var(--ink);}
.stockist-card__map:hover{border-color:var(--terracotta); color:var(--terracotta); transform:translateY(-1px);}
.stockist-card__call:active,
.stockist-card__map:active{transform:scale(.97);}

/* ============================================================
   FOOTER
   ============================================================ */
.site-footer{background:var(--footer-bg); color:#f1e9df; padding:70px 0 30px;}
.footer-layout{
  display:grid;
  grid-template-columns:1.6fr 1fr 1fr 1fr 1fr;
  gap:24px;
  padding-bottom:40px;
}
.footer-logo{width:120px; margin-bottom:14px; filter:invert(1) brightness(1.6);}
.footer-brand p{font-size:.8rem; opacity:.6; line-height:1.7;}
.footer-col h3{font-family:var(--font-body); font-weight:700; color:var(--terracotta); font-size:.85rem; margin-bottom:14px;}
.footer-col a{display:block; font-size:.8rem; opacity:.7; margin-bottom:10px; transition:opacity .2s, color .2s;}
.footer-col a:hover{opacity:1; color:var(--olive);}
.footer-bottom{border-top:1px solid rgba(255,255,255,.12); padding-top:24px;}
.footer-bottom p{font-size:.72rem; opacity:.5; margin-bottom:6px;}

/* ============================================================
   RESPONSIVE
   ============================================================ */
@media (min-width:901px){
  .hamburger-btn, .mobile-menu{display:none !important;}
}

@media (max-width:900px){
  .side-nav{display:none;}
  .hamburger-btn{display:flex;}
  /* bottom pad stays 0 — the below-mascot gap is owned solely by
     .section-mascot's var(--mascot-space-below), same as desktop, so every
     section ends on the same rhythm on mobile too */
  .section{padding:80px 0 0;}
  .container{padding:0 20px;}

  .hero-section{padding-top:90px;}
  /* feeding leads with a full-bleed photo band — no top padding, so it sits
     flush under the previous section like it does on desktop */
  .feeding-section{padding-top:0;}
  /* product bands are also full-bleed (gallery photo runs edge-to-edge) —
     no reserved header gap, same as feeding above */
  .product-section{padding-top:0;}
  /* keep the collage inside the viewport — 150% cropped the edge vegetables */
  .hero-shape{width:min(118%,420px); transform:none;}
  /* mobile: centre the whole oval group AND the 美味の秘密 graphic dead-centre.
     The desktop rim offset is diagonal (−10px x, −13px y); on mobile drop the
     horizontal part so nothing sits left of centre — the green rim still peeks
     out the bottom from the remaining −12px vertical offset. */
  .hero-shape__bg-green,
  .hero-shape__bg-cream,
  .hero-oval-clip{ left:50%; }
  .hero-shape__bg-cream,
  .hero-oval-clip{ transform:translate(-50%, calc(-50% - 12px)); }
  .hero-tagline-img{ transform:translate(-50%, calc(-50% - 12px)) scale(1); }
  .hero-shape.pre-fly .hero-tagline-img{ transform:translate(-50%, calc(-50% - 12px)) scale(.7); }
  .hero-logo{width:min(34vw,150px);}
  .mascot-banner{padding:10px 18px 10px 108px; box-shadow:4px 4px 0 0 var(--terracotta);}
  .mascot-banner__img{width:95px; left:14px; bottom:0;}
  .mascot-banner p{font-size:1rem;}

  /* features: single column — info block (eyebrow/title/sachets photo) on
     top, the 4 feature rows below, same stacking convention as product-slide. */
  .section > .container.features-slide{grid-template-columns:1fr; gap:32px;}
  .features-slide__info{align-items:center; text-align:center; gap:24px;}
  .features-slide__photo{max-width:320px;}
  .features-slide__visual{max-width:320px; margin:0 auto;}
  .feature-bubble{width:150px;}
  .feature-bubble__inner{border-radius:18px; border-width:4px;}
  .feature-bubble--tl{top:-7%; left:-8%;}
  .feature-bubble--br{bottom:-22%; right:-2%;}
  .feature-bubble__tail{width:38px; height:38px;}
  .feature-bubble__tail--tl{bottom:-10px; right:-10px;}
  .feature-bubble__tail--br{top:-10px; left:-10px;}
  /* mirrors the desktop card Ken hand-tuned: photo tucked near the card's
     own top-left corner (poking slightly above it), not sticking out past
     the card's left edge — so no margin-left on the card any more, just a
     padding-left generous enough to clear the photo. */
  .feature-row{margin-top:14px;}
  .feature-row__photo{width:104px; height:104px; left:10px; top:-12px; border-radius:20px;}
  .feature-row__card{padding:14px 18px 14px 128px; min-height:104px;}
  .feature-row__title{font-size:1.05rem;}
  .feature-row__desc{font-size:.85rem;}

  /* on mobile the shape fallback below is a fixed 660px tall regardless of viewport
     height, so — unlike desktop — this section can't be capped to exactly one
     screen; let it flow to its natural (taller) height and scroll normally. */
  .aboutus-section{height:auto; overflow:visible;}
  .aboutus-stage{height:800px; flex:none; min-height:0; overflow:visible; padding-bottom:0;}

  /* the wide hero-style oval doesn't work for stacked step content at this width —
     fall back to a gentler rounded shape (same green-behind/cream-front offset
     shadow technique) with an explicit height, since the shape's height normally
     comes from aspect-ratio alone and its layers are all absolutely positioned. */
  .aboutus-shape{aspect-ratio:auto; min-height:740px;}
  .aboutus-shape__bg-green, .aboutus-shape__bg-cream, .aboutus-shape__clip{border-radius:48px;}
  .aboutus-shape__steps-layer{padding:38px 28px 28px;}

  /* mobile gets a 4th step (see .aboutus-tl-step--4 below) — re-space all four
     dots evenly down the spine instead of the desktop 3-step 14/45/76 split */
  .aboutus-tl-step--1{top:6%;}
  .aboutus-tl-step--2{top:31%;}
  .aboutus-tl-step--3{top:56%;}
  .aboutus-tl-step--4{display:block; top:81%;}
  /* arrow now hands off after step 4, not step 3 */
  .aboutus-stage.revealed .aboutus-timeline__arrow{transition-delay:3.7s;}
  /* the floating bowl below the shape is redundant on mobile now that the same
     shot appears inline as step 4's photo */
  .aboutus-step__bowl{display:none;}

  /* single-column timeline on mobile: spine hugs the left edge, all content sits to
     its right (no alternating sides — there isn't room), same progressive reveal. */
  .aboutus-timeline__spine, .aboutus-timeline__arrow{left:8%;}
  .aboutus-tl-dot{left:8%;}
  .aboutus-tl-connector--left, .aboutus-tl-connector--right{
    left:calc(8% + 9px); right:auto; width:8%; transform-origin:left;
  }
  .aboutus-tl-content--left, .aboutus-tl-content--right{
    left:calc(8% + 9px + 8% + 6px); right:auto; width:70%; text-align:left;
  }
  /* single column: both variants sit to the right of the spine, so the row
     always hugs the left edge here regardless of desktop's --left/--right split */
  .aboutus-tl-content--left .aboutus-tl-row, .aboutus-tl-content--right .aboutus-tl-row{
    justify-content:flex-start;
  }
  /* steps 1 & 3 flip to image-left/text-right on mobile (opposite of desktop);
     step 2 (and the step-4 image) already read image-left/text-right by DOM
     order, so they need no override here */
  .aboutus-tl-content--left .aboutus-tl-row img{order:-1;}

  /* mobile: stack the gallery on top (full-width, fixed-height photo band)
     and the copy below it, instead of the desktop 46%/54% side-by-side split. */
  .product-slide{
    flex-direction:column;
    align-items:stretch;
  }
  .product-slide__visual{
    flex:none;
    width:100%;
    height:52vh;
    min-height:320px;
  }
  .product-slide__info{
    padding:36px 24px 50px;
  }
  .product-slide__inner{
    max-width:none;
    text-align:center;
  }
  .product-slide__eyebrow-block{display:flex; flex-direction:column; align-items:center;}
  .product-slide__radar{margin:12px auto 0;}
  /* .product-section .section-title carries its own max-width:14ch (see
     desktop rule) — a block box narrower than its parent still sits flush
     against the LEFT edge without margin:auto, even though the parent is
     text-align:center (that only centers the text INSIDE the box, not the
     box itself — same issue .product-slide__desc had). Centre the box too. */
  /* the desktop single-line treatment (.product-section .product-slide__name
     {white-space:nowrap}) isn't scoped to a min-width query, so without this
     it would also force one line here — on a narrow phone that risks
     overflowing/clipping the flavour name instead of just wrapping to a
     second line like the rest of the copy already does. Match/beat that
     rule's specificity (also two classes) so this wins inside the query. */
  .product-section .product-slide__name{white-space:normal; max-width:14ch;}
  .product-slide__name{margin:0 auto 16px;}

  /* feeding is now the "open book" hero — its own responsive rules live in
     the FEEDING block above (@media max-width:600px, phones only) */

  .testimonials-product{width:110px; top:-30px; right:16px;}
  .testimonial-grid{grid-template-columns:1fr; gap:40px;}
  .lifestyle-grid{width:100%; grid-template-columns:repeat(2,1fr); column-gap:20px; row-gap:20px; padding-bottom:14px;}
  .lifestyle-grid__item:nth-child(3n+2){--y-offset:0px;} /* cancels the desktop 3-col stagger for item 5 (mobile col 1) */
  .lifestyle-grid__item:nth-child(2n){--y-offset:14px;} /* mobile is 2 cols — the offset column is every even item */

  .recipe-thumbs{gap:12px;}
  .recipe-thumb-item{width:60px; gap:5px; padding:7px 5px 8px; border-radius:16px;}
  .recipe-thumb-item:not(.is-active) + .recipe-thumb-item:not(.is-active)::before{left:-7px; bottom:20px;}
  .recipe-thumb{width:54px; height:54px; border-radius:13px;}
  /* body copy on mobile stays at the same size as everywhere else on the
     site (aboutus-step__desc, product-slide__desc, faq-item__a, etc. all
     carry no separate mobile font-size — 1rem throughout). The circle just
     grows taller to hold it instead of shrinking the text to fit. */
  .recipe-thumb-name{font-size:.78rem; line-height:1.3;}
  /* border-radius:41% is computed against each axis independently, so a
     much taller box (like the old 1062/1560 ratio here) reads far curvier
     at the top/bottom than the same 41% does on desktop's near-square box.
     Keep the same proportions as desktop's shape and let long recipe text
     scroll inside .recipe-shape__content instead of stretching the oval
     tall to fit it. */
  .recipe-shape{width:100%; max-width:380px; aspect-ratio:11/12;}
  .recipe-shape__content{top:13%; bottom:13%; left:17%; right:17%; gap:4px;}
  .recipe-content__name{font-size:1rem; margin:2px 0 4px;}
  .recipe-content__row{font-size:0.8rem; line-height:1.4;}
  .recipe-content__row .chip-pill{font-size:.8rem; padding:3px 11px; margin-right:5px; margin-bottom:2px;}
  .recipe-photo{width:34%; max-width:110px; right:0; bottom:-5%;}

  .faq-card{padding:36px 24px; border-radius:50px;}

  /* .stockist-list already collapses to one column via its auto-fill minmax */

  .footer-layout{grid-template-columns:1fr 1fr; text-align:left;}
  .footer-brand{grid-column:1/-1;}
}

@media (max-width:520px){
  .hero-logo{width:130px;}
}

/* ============================================================
   LIGHTBOX (product thumbnail pop-ups)
   ============================================================ */
.lightbox{
  position:fixed; inset:0;
  display:flex; align-items:center; justify-content:center;
  background:rgba(20,14,10,.86);
  opacity:0; visibility:hidden;
  transition:opacity .3s ease, visibility 0s linear .3s;
  z-index:200;
  padding:40px;
}
.lightbox.is-open{
  opacity:1; visibility:visible;
  transition:opacity .3s ease, visibility 0s linear 0s;
}
.lightbox__img{
  max-width:min(90vw,720px);
  max-height:85vh;
  border-radius:24px;
  box-shadow:0 30px 60px rgba(0,0,0,.4);
  transform:scale(.92);
  transition:transform .3s cubic-bezier(.22,.9,.3,1);
}
.lightbox.is-open .lightbox__img{transform:scale(1);}
.lightbox__close{
  position:absolute; top:24px; right:28px;
  width:44px; height:44px; border-radius:50%;
  border:none; background:rgba(255,255,255,.15); color:#fff;
  font-size:1.6rem; line-height:1; cursor:pointer;
  display:flex; align-items:center; justify-content:center;
  transition:background .2s ease;
}
.lightbox__close:hover{background:rgba(255,255,255,.3);}


/* ════════════════════════════════════════════════════════════
   REDESIGN — "elevate the current vibe"
   Structural + typographic pass layered over the section CSS above.
   The ORIGINAL saesa colour palette is kept (blush / coral / peach /
   leaf / terracotta — see :root); this block only changes layout,
   type (Noto Serif TC display), motion and a few components:
   features rows, testimonial wall, open FAQ list, stockist tiles,
   footer, and the 關於我們 / 食譜 sections (out of their clipped blobs).
   ════════════════════════════════════════════════════════════ */

/* ---- section backgrounds: original saesa palette (blush / coral / peach) ---- */
.features-section{background:var(--peach);}
.feeding-section{background:var(--blush);}
.recipes-section{background:var(--blush);}
.testimonials-section{background:var(--peach);}
/* stockists has no bottom mascot, so give the section its own closing gap
   before the footer (other sections get theirs from the .section-mascot pad) */
.stockists-section{background:var(--blush); padding-bottom:104px;}
.faq-section{background:var(--peach);}

/* the four product bands keep their original per-flavour colours (set inline in JS) */
.product-slide__desc{opacity:.96;max-width:50ch;}
.product-slide__hook{opacity:1;font-weight:500;}
.product-slide__title{opacity:.9;letter-spacing:.02em;}
.product-slide__name{
  font-family:var(--font-display);
  font-weight:700;
  letter-spacing:0;
  line-height:1.35;
  text-wrap:balance;
}
.product-section .section-title{max-width:14ch;}
/* the flavour name ("original．經典原味", "番薯．sweet potato", etc.) reads
   oddly split across two lines — keep it on one line on desktop, where the
   copy column has plenty of room. Needs to match/beat the max-width:14ch
   rule above's specificity (also two classes) to actually win. */
.product-section .product-slide__name{max-width:none; white-space:nowrap;}
.product-section .eyebrow{color:#fff;}
.product-section .eyebrow::before{background:rgba(255,255,255,.72);}


/* ---- side-nav: no chrome — labels sit directly on the page and flip to
   light over the darker sections (product bands). script.js toggles .on-dark
   by sampling the section colour behind the nav. ---- */
.side-nav{
  left:24px;
  gap:14px;
}
.side-nav a{
  color:var(--brand-ink);
  letter-spacing:.02em;
  font-weight:500;
  font-size:.76rem;
  text-shadow:0 1px 3px rgba(251,245,233,.55);   /* faint halo over busy photo edges */
}
.side-nav a.is-active{color:var(--brand);font-weight:700;}
.side-nav.on-dark a{
  color:#fff;
  opacity:.74;
  text-shadow:0 1px 4px rgba(0,0,0,.38);
}
.side-nav.on-dark a:hover,
.side-nav.on-dark a.is-active{color:#fff;opacity:1;}

.hamburger-btn{background:rgba(246,236,224,.9);backdrop-filter:blur(6px);border-color:var(--brand);}
.hamburger-btn span{background:var(--brand);}
.mobile-menu{background:var(--brand);}
.pill-btn{color:#fff;}
.pill-btn:active{opacity:.5;}

/* ---- mascot banners ---- */
.mascot-banner p{line-height:1.55;}

/* ════ FEATURES — pill-cards → editorial numbered rows ════ */
.features-list{display:flex;flex-direction:column;gap:0;counter-reset:feat;margin-top:8px;}
@media (max-width:900px){
  /* clear the GIF speech-bubble that overhangs the bottom of the sachets visual */
  .features-list{margin-top:48px;}
}
.feature-row{
  position:static;
  counter-increment:feat;
  margin:0;
  display:grid;
  grid-template-columns:auto 92px 1fr;
  align-items:center;
  gap:22px;
  padding:24px 4px;
  border-top:1px solid var(--hairline);
}
.feature-row:last-child{border-bottom:1px solid var(--hairline);}
.feature-row::before{
  content:counter(feat,decimal-leading-zero);
  font-family:var(--font-display);
  font-weight:700;
  font-size:1.4rem;
  line-height:1;
  color:var(--brand);
  opacity:.5;
  align-self:start;
}
.feature-row__photo{
  position:static;
  left:auto;top:auto;
  width:92px;height:92px;
  border-radius:var(--r-md);
  object-fit:cover;
  box-shadow:var(--shadow-sm);
}
.feature-row__card{
  min-height:0;
  background:none;
  border-radius:0;
  padding:0;
  display:block;
}
.feature-row__title{
  font-family:var(--font-display);
  font-weight:700;
  font-size:1.1rem;
  color:var(--ink);
  margin-bottom:6px;
  line-height:1.45;
}
.feature-row__desc{
  font-size:.92rem;
  line-height:1.75;
  color:var(--ink-70);
  opacity:1;
  max-width:46ch;
}
@media (max-width:560px){
  .feature-row{grid-template-columns:64px 1fr;gap:8px 16px;padding:20px 2px;}
  .feature-row::before{grid-column:1;grid-row:1;font-size:1rem;align-self:center;}
  .feature-row__photo{grid-column:1;grid-row:2;width:64px;height:64px;}
  .feature-row__card{grid-column:2;grid-row:1 / span 2;align-self:center;}
}

/* ════ TESTIMONIALS — 3 equal cards → one pull-quote + a stacked pair ════ */
/* .testimonials-section .section-title inherits the site-wide --terracotta */
.testimonial-grid{
  grid-template-columns:1.35fr 1fr;
  align-items:start;
  gap:24px 28px;
  max-width:820px;
  /* was flush against the container's left edge (block default, no
     centering) while .lifestyle-grid below it is centered via its own
     width:80%; margin:0 auto — same treatment here so both grids line up
     on the same central axis instead of one looking shifted left. */
  margin:0 auto;
}
.testimonial-card{
  border:1px solid var(--hairline);
  border-radius:var(--r-lg);
  box-shadow:var(--shadow-md);
  padding:30px 28px 56px;
  font-size:1rem;
  line-height:1.9;
}
.testimonial-card__author{opacity:.6;font-size:.9rem;}
.testimonial-card:nth-child(1){
  grid-row:span 2;
  align-self:stretch;
  display:flex;flex-direction:column;justify-content:center;
  padding:40px 38px 62px;
  font-family:var(--font-display);
  font-weight:600;
  font-size:clamp(1.2rem,1rem + .8vw,1.6rem);
  line-height:1.75;
}
@media (max-width:760px){
  .testimonial-grid{grid-template-columns:1fr;gap:44px;}
  .testimonial-card:nth-child(1){grid-row:auto;}
}

/* ════ FAQ — accordion → open two-column reference list ════ */
.faq-card{
  background:none;
  border-radius:0;
  padding:0;
  display:grid;
  grid-template-columns:repeat(2,1fr);
  gap:0 56px;
}
.faq-item{border-bottom:1px solid var(--hairline);padding:22px 0;}
.faq-item__q{
  display:block;
  width:auto;
  font-family:var(--font-title);   /* Shippori Mincho — crisp mincho, distinct from the Klee One section title */
  font-weight:600;
  font-size:1.02rem;
  color:var(--ink);
  margin:0 0 8px;
  padding:0;
}
.faq-item__a{
  max-height:none;
  overflow:visible;
  padding:0;
  font-size:.92rem;
  line-height:1.8;
  color:var(--ink-70);
  opacity:1;
}
@media (max-width:760px){
  .faq-card{grid-template-columns:1fr;gap:0;}
}

/* ════ RECIPES — cramped internal-scroll oval → open two-column panel ════
   The recipe details used to be squeezed into a rounded blob with
   overflow-y:auto (so longer recipes scrolled inside a tiny box). Now the
   dish photo and the details sit side by side in a full-width cream panel
   that simply grows to fit its content. (#recipePhoto is moved inside
   .recipe-shape by script.js so it can be a grid column here.) */
.recipe-stage{gap:34px;}
.recipe-shape{
  position:relative;
  width:100%;
  max-width:860px;
  aspect-ratio:auto;
  margin:0 auto;
  display:grid;
  grid-template-columns:minmax(0,320px) 1fr;
  align-items:stretch;
  background:var(--paper-raised);
  border-radius:var(--r-lg);
  overflow:hidden;
  /* solid offset shadow — same hard-edged treatment as the mascot pills and
     testimonial cards elsewhere on the site, not a soft blur */
  box-shadow:12px 12px 0 0 var(--coral);
}
.recipe-shape__bg-green,
.recipe-shape__bg-cream{display:none;}
.recipe-photo{
  position:static;
  grid-column:1;
  width:100%;
  height:100%;
  min-height:320px;
  max-width:none;
  object-fit:cover;
  border-radius:0;
}
.recipe-shape__content{
  position:static;
  inset:auto;
  grid-column:2;
  transform:none;
  overflow:visible;
  padding:30px 34px;
  gap:11px;
  text-align:left;
}
.recipe-content__name{
  color:var(--ink);
  font-size:var(--fs-h3);
  line-height:1.35;
  margin:0 0 4px;
}
.recipe-content__row{
  color:var(--ink);
  font-size:.93rem;
  line-height:1.7;
}
.recipe-content__row .chip-pill{
  display:inline-block;
  margin:0 8px 5px 0;
  padding:3px 12px;
  font-size:.76rem;
  background:var(--coral);
  border:none;
  color:#fff;
}
.recipe-thumb-item.is-active{background:var(--coral);}
@media (hover:hover){
  .recipe-thumb-item:not(.is-active):hover{background:rgba(239,156,111,.2);}
  .recipe-thumb-item:not(.is-active):hover .recipe-thumb-name{color:var(--coral);}
}
@media (max-width:760px){
  .recipe-shape{grid-template-columns:1fr;max-width:420px;}
  .recipe-photo{grid-column:1;height:200px;min-height:0;}
  .recipe-shape__content{grid-column:1;padding:24px 22px;}
}
/* tablet: the phone rule (max-width:900px) shrinks the tab buttons to ~60px,
   which is far too cramped once there's this much width. Give them back a
   comfortable size and let the row wrap if a narrow tablet can't fit all five. */
@media (min-width:601px) and (max-width:900px){
  .recipe-thumbs{gap:16px 14px; flex-wrap:wrap; justify-content:center;}
  .recipe-thumb-item{width:96px; gap:7px; padding:9px 7px 11px; border-radius:20px;}
  .recipe-thumb{width:84px; height:84px; border-radius:16px;}
  .recipe-thumb-name{font-size:.9rem; line-height:1.3;}
  /* the between-tabs divider line assumes a single non-wrapping row — drop it
     here so it doesn't cut across a wrapped layout */
  .recipe-thumb-item:not(.is-active) + .recipe-thumb-item:not(.is-active)::before{display:none;}
}

/* ════ ABOUT / 關於我們 — timeline clipped inside a blob → open step cards ════
   The three process steps used to be absolutely positioned inside a cream
   ellipse whose curved edge clipped the text (hence the 13%/14% padding
   hacks and the tiny reading column). They are now plain cards in a row on
   the coral band, each with its photo, label and full-width copy. The
   scroll-triggered stagger is kept; the SVG spine / dots / connectors that
   only made sense inside the blob are dropped. */
.aboutus-section{background:var(--blush);padding:96px 0 0;min-height:auto;}
.aboutus-stage{
  height:auto;
  min-height:0;
  overflow:visible;
  gap:34px;
  padding:0 24px;
  max-width:1060px;
  /* gap to the mascot below — shared token (the character still pokes up
     past its pill into this space) */
  margin:0 auto var(--mascot-space-above);
}
.aboutus-shape-title{
  color:var(--terracotta);    /* matches the site-wide .section-title colour */
  font-family:var(--font-display);
  font-size:var(--fs-h2);
  letter-spacing:.01em;
  margin-bottom:4px;
  opacity:1;               /* was gated behind a 1.4s auto-play delay */
}
.aboutus-shape{
  position:static;
  width:100%;
  max-width:none;
  aspect-ratio:auto;
  margin:0;
  opacity:1;               /* only the individual cards animate now */
}
.aboutus-shape__bg-green,
.aboutus-shape__bg-cream,
.aboutus-step__bowl{display:none;}
.aboutus-shape__clip{
  position:static;
  inset:auto;
  overflow:visible;
  border-radius:0;
  transform:none;
}
.aboutus-shape__steps-layer{
  position:static;
  inset:auto;
  padding:0;
  opacity:1;               /* was gated behind a 1.4s auto-play delay */
}
.aboutus-timeline{
  position:static;
  width:100%;
  height:auto;
  display:grid;
  grid-template-columns:repeat(3,1fr);
  gap:22px;
}
.aboutus-timeline__spine,
.aboutus-timeline__arrow,
.aboutus-tl-dot,
.aboutus-tl-connector{display:none;}
.aboutus-tl-step{
  position:static;
  top:auto;
  opacity:0;
  transform:translateY(18px);
  transition:opacity .55s var(--ease), transform .55s var(--ease);
  background:var(--paper-raised);
  border-radius:var(--r-lg);
  padding:26px 24px 28px;
}
.aboutus-stage.revealed .aboutus-tl-step{opacity:1;transform:none;}
.aboutus-stage.revealed .aboutus-tl-step--2{transition-delay:.12s;}
.aboutus-stage.revealed .aboutus-tl-step--3{transition-delay:.24s;}
.aboutus-stage.revealed .aboutus-tl-step--4{transition-delay:.36s;}
.aboutus-tl-content,
.aboutus-tl-content--left,
.aboutus-tl-content--right{
  position:static;
  width:auto;
  left:auto;right:auto;
  text-align:center;
  opacity:1;
  /* fixed media row keeps the label + copy on the same baseline across all
     three cards, whether the media is the map or a circular photo */
  display:grid;
  grid-template-rows:132px auto auto;
  justify-items:center;
  align-content:start;
  gap:14px;
}
/* flatten the desc/photo wrapper so the photo can always sit on top,
   whatever DOM order that step happens to use */
.aboutus-tl-row{display:contents;}
.aboutus-tl-row img{order:-1;grid-row:1;align-self:center;}
.aboutus-step__label{
  order:0;
  color:var(--terracotta);
  font-family:var(--font-display);
  font-size:1.12rem;
  transform:none;
  margin:0;
}
.aboutus-step__desc{
  order:1;
  font-size:.95rem;
  line-height:1.75;
  color:var(--ink);
}
.aboutus-step__photo{
  width:124px;height:124px;
  border-radius:50%;
  border:4px solid #fff;
  box-shadow:var(--shadow-sm);
}
.aboutus-step__photo--square{width:auto;height:124px;border:none;box-shadow:none;border-radius:var(--r-md);}
.aboutus-step__map{width:auto;height:118px;margin:0;opacity:.9;object-fit:contain;}
/* kill the long per-step content delays from the old auto-play sequence */
.aboutus-stage.revealed .aboutus-tl-step--1 .aboutus-tl-content,
.aboutus-stage.revealed .aboutus-tl-step--2 .aboutus-tl-content,
.aboutus-stage.revealed .aboutus-tl-step--3 .aboutus-tl-content,
.aboutus-stage.revealed .aboutus-tl-step--4 .aboutus-tl-content{opacity:1;transition-delay:0s;}
@media (max-width:820px){
  /* one card per row — keep the same photo-on-top / centred layout as desktop */
  .aboutus-timeline{grid-template-columns:1fr;gap:16px;}
  .aboutus-tl-step--4{display:block;}
  .aboutus-tl-step{padding:26px 22px;}
  .aboutus-tl-content,
  .aboutus-tl-content--left,
  .aboutus-tl-content--right{max-width:34ch;margin:0 auto;}
}

/* ════ STOCKISTS — the full styling for this section lives in the STOCKISTS
   block above (search field, region pills, region blocks, cards). ════ */
/* .stockists-section .section-title inherits the site-wide --terracotta */

/* ════ FOOTER — link farm → brand + one nav group + contact ════ */
.site-footer{padding:72px 0 32px;}
.footer-layout{grid-template-columns:1.5fr 1fr 1fr;gap:40px;}
.footer-col h3{
  font-family:var(--font-display);
  color:var(--terracotta);
  font-size:.78rem;
  letter-spacing:.18em;
  text-transform:uppercase;
}
.footer-col a{transition:color .2s var(--ease),opacity .2s var(--ease);}
.footer-col a:hover{opacity:1;color:#fff;}
@media (max-width:700px){
  .footer-layout{grid-template-columns:1fr 1fr;}
  .footer-brand{grid-column:1 / -1;}
}

/* ---- shared interactive polish ---- */
.chip-pill{transition:background .2s var(--ease),border-color .2s var(--ease);}
.reveal{transform:translateY(18px) scale(.985);}

/* ---- mobile fixes ---- */
@media (max-width:900px){
  /* the mascot pill text used to run off the right edge on narrow screens —
     let it wrap and keep the pill inside the viewport */
  .section-mascot{padding-left:14px;padding-right:14px;}
  .mascot-banner{max-width:100%;flex-wrap:wrap;}
  .mascot-banner p{flex:1 1 auto;min-width:0;font-size:.9rem;line-height:1.5;}
  .stockists-section{padding-bottom:64px;}
  .features-section{padding-bottom:64px;}
  .recipes-section, .faq-section{padding-bottom:64px;}
}
@media (max-width:560px){
  .section-title{font-size:clamp(1.55rem,1.2rem + 3vw,2rem);}
  .testimonial-card:nth-child(1){font-size:1.15rem;padding:30px 24px 56px;}
  .stockist-card{padding:20px 18px 18px;}
}
