/* ==========================================================================
   Lumière Skincare
   --------------------------------------------------------------------------
   00  Tokens
   01  Reset and base
   02  Header
   03  Buttons, icons, shared bits
   04  Hero
   05  Product lettering (live text over blank containers)
   06  Trust row
   07  Story
   08  Bestsellers
   09  New arrival
   10  Quiz
   11  Footer
   12  Reveals and motion
   13  Responsive
   ========================================================================== */

/* 00  Tokens ============================================================== */

:root {
  --ink:      #1D1B4B;   /* headlines, buttons, every solid dark thing */
  --ink-2:    #75728C;   /* body copy and sub-lines */
  --paper:    #FFFFFF;
  --hero-bg:  #F5F2FA;   /* the pale lilac the hero sits on */
  --line:     #EBE7F2;
  --lav:      #C6B9EA;   /* the new-arrival panel */

  --serif: 'Playfair Display', Georgia, 'Times New Roman', serif;
  --sans:  'Poppins', system-ui, -apple-system, 'Segoe UI', sans-serif;

  /* The shell and, derived from it, the gutter — so a figure can bleed to the
     viewport edge without guessing. Keep the two in step: change one, change
     the other. */
  --shell: min(1200px, 100% - 88px);
  --gut:   max(44px, calc((100vw - 1200px) / 2));

  --r-pill: 999px;
  --r-card: 16px;
  --r-tile: 18px;
  --r-panel: 22px;
}


/* 01  Reset and base ====================================================== */

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 16px;
  font-weight: 400;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  overflow-x: clip;
}

img, svg { display: block; max-width: 100%; }
img { height: auto; }

a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; }

h1, h2, h3, p, ul, figure { margin: 0; }
ul { padding: 0; list-style: none; }

.shell { width: var(--shell); margin-inline: auto; }

.sr-only {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}

.skip-link {
  position: absolute; left: 12px; top: -60px; z-index: 100;
  padding: 10px 18px; border-radius: var(--r-pill);
  background: var(--ink); color: #fff; font-size: 13px;
  transition: top .18s ease;
}
.skip-link:focus-visible { top: 12px; }

:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }

/* Shared type ------------------------------------------------------------ */

.eyebrow {
  font-size: 13px;
  font-weight: 500;
  letter-spacing: .22em;
  text-transform: uppercase;
  color: var(--ink);
}

.h2 {
  font-family: var(--serif);
  font-weight: 500;
  font-size: clamp(36px, 3.6vw, 52px);
  line-height: 1.16;
  letter-spacing: -.005em;
}
.h2--sm { font-size: clamp(30px, 2.9vw, 42px); }


/* 02  Header ============================================================= */

.site-header {
/* Transparent at the top of the page, solid once scrolled. The hero is pulled
   up by the bar's own height, so at rest there IS something behind the links —
   which is the whole reason the scrolled state cannot also be see-through. */
  position: sticky; top: 0; z-index: 40;
  background: transparent;
  /* One declaration, not two. There used to be a second `transition` on the
     next line, and since it replaced rather than extended the first, only
     box-shadow ever eased — the background snapped from clear to filled. */
  transition: background-color .25s ease, box-shadow .25s ease;
}
.site-header.is-stuck,
.site-header.is-open {
  /* Solid, not glass. The bar is clear at the top of the page and opaque once
     it has something to sit over; at .74 the hero's own product photography
     kept showing through the nav links and the blur was the only thing making
     them readable. No backdrop-filter here on purpose — behind an opaque
     background it blurs something nobody can see, and still costs a
     compositing layer. */
  background: var(--paper);
  box-shadow: 0 1px 0 var(--line), 0 6px 20px rgba(29, 27, 75, .05);
}

.nav {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: 24px;
  min-height: var(--nav-h);
}

.brand { display: flex; flex-direction: column; align-items: center; line-height: 1; }
.brand__word {
  font-family: var(--serif);
  font-weight: 400;
  font-size: 23px;
  letter-spacing: .2em;
  text-indent: .2em;              /* letter-spacing adds a trailing gap; recentre */
}
.brand__sub {
  margin-top: 5px;
  font-size: 9px;
  font-weight: 500;
  letter-spacing: .34em;
  text-indent: .34em;
  text-transform: uppercase;
  color: var(--ink-2);
}

.nav__links {
  display: flex;
  justify-content: center;
  gap: clamp(18px, 2.4vw, 34px);
  font-size: 15px;
  font-weight: 400;
}
/* "Best Sellers" is the one label with a space in it, so it is the one that
   breaks to two lines and shoves the header taller the moment the row gets
   tight. Nothing in this nav should ever wrap. */
.nav__links a { color: var(--ink); white-space: nowrap; transition: opacity .15s ease; }
.nav__links a:hover { opacity: .6; }

.nav__tools { display: flex; align-items: center; gap: 14px; }

.iconbtn {
  position: relative;
  display: grid; place-items: center;
  width: 34px; height: 34px;
  padding: 0; border: 0; border-radius: var(--r-pill);
  background: none; cursor: pointer;
}
.iconbtn svg {
  width: 19px; height: 19px;
  fill: none; stroke: var(--ink); stroke-width: 1.5;
  stroke-linecap: round; stroke-linejoin: round;
}
.iconbtn__badge {
  position: absolute; top: 1px; right: 0;
  display: grid; place-items: center;
  min-width: 15px; height: 15px; padding: 0 4px;
  border-radius: var(--r-pill);
  background: var(--ink); color: #fff;
  font-size: 9px; font-weight: 500; line-height: 1;
}

.nav__burger { display: none; }

/* Nav height, in one place. The hero is pulled up by exactly this and gives
   it back as padding; two literals drifted apart the moment the mobile bar
   became 64. */
:root { --nav-h: 74px; }

/* 03  Buttons, icons, shared bits ========================================= */

.btn {
  display: inline-block;
  padding: 15px 34px;
  border: 0; border-radius: var(--r-pill);
  background: var(--ink); color: #fff;
  font-size: 12.5px; font-weight: 500; line-height: 1;
  letter-spacing: .14em; text-transform: uppercase;
  cursor: pointer;
  transition: transform .18s ease, background-color .18s ease;
}
.btn:hover { background: #2A2765; transform: translateY(-1px); }
.btn--sm { padding: 12px 22px; font-size: 11.5px; }

/* The outlined diamond behind each trust icon. A rotated square with a
   rounded corner radius, so the icon inside stays upright. */
.dia {
  flex: none;
  display: grid; place-items: center;
  width: 38px; height: 38px;
  border: 1px solid var(--ink);
  border-radius: 7px;
  transform: rotate(45deg);
}
.dia svg {
  width: 19px; height: 19px;
  transform: rotate(-45deg);
  fill: none; stroke: var(--ink); stroke-width: 1.4;
  stroke-linecap: round; stroke-linejoin: round;
}

.stars { display: inline-flex; gap: 1.5px; }
.stars svg { width: 10px; height: 10px; fill: var(--ink); }


/* 04  Hero =============================================================== */

/* The photograph is the hero's ground, edge to edge. Anything less means the
   picture's own lavender has to meet a CSS lavender somewhere, and that join is
   a seam no sampled colour quite closes: cover crops from the left, so the edge
   you end up matching is never the edge you measured.

   The colour underneath is only insurance for the moment before the image
   decodes — sampled off the frame's left edge so the swap is invisible. */
.hero {
  position: relative;
  isolation: isolate;
  background-color: #DACEE7;
  /* Up behind the bar, which is 74px, so the plate reaches the top of the page
     and the transparent header has the photograph under it. */
  margin-top: calc(var(--nav-h) * -1);
}

.hero__bg {
  position: absolute;
  inset: 0;
  z-index: -1;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* The left half of the frame is empty ground and the bottles sit right, so
     cropping from the left costs nothing at any width. */
  object-position: right center;
}

.hero__grid {
  display: grid;
  grid-template-columns: 1.14fr 0.86fr;
  align-items: center;
  gap: clamp(24px, 3vw, 48px);
  /* Full height on desktop, so the section ends exactly at the fold instead of
     letting the trust row peek in and get sliced by the bottom of the window.
     That was the old clamp's failure: tied to the plate's own 2.36:1 it capped
     at 800px, and on anything taller than that the next section showed through.

     Going taller is safe here, and it is worth knowing why, because the reverse
     would not be. cover crops whichever axis the box is proportionally short
     on, so a taller box crops the SIDES — and .hero__bg pins the plate to
     `right center`, where the left half is empty ground and the bottles sit
     right. At 1920x945 that takes 14% off the left and touches nothing. It also
     crops LESS off the top and bottom than the old cap did, which is where the
     dropper cap lives.

     The floor stops the copy crushing in a short window; ≤860px replaces this
     with min-height: 0, so the phone layout is unaffected. */
  min-height: max(560px, 100svh);
  padding: calc(var(--nav-h) + clamp(40px, 4.4vw, 64px)) 0 clamp(36px, 3.6vw, 52px);
}

.hero__copy > * + * { margin-top: 22px; }
.hero__copy .eyebrow + .hero__title { margin-top: 18px; }

.hero__title {
  font-family: var(--serif);
  font-weight: 500;
  font-size: clamp(52px, 7.8vw, 112px);
  line-height: 1.02;
  letter-spacing: -.015em;
}
.hero__title span,
.hero__lead span { display: block; }

/* The lead sits on lavender now, not on near-white. The reference's soft grey
   measures 3.2:1 against this ground and fails AA at this size, so it goes
   darker — 5.2:1, and still reads as the quiet line under the headline. */
.hero__lead {
  max-width: 34ch;
  font-size: 19.5px;
  line-height: 1.68;
  color: #4A4665;
}

/* The shot ---------------------------------------------------------------- */

/* Nothing but a positioning context for the price chip — the photograph itself
   is the section's background now. */
.hero__shot { position: relative; align-self: stretch; }

/* The small dense chip over the large sparse thing. Pushed out past the shell's
   right edge and down to the floor: the jar's own lettering runs across the
   middle of that corner, and a chip centred on the jar covers the one thing the
   photograph was reshot to say. */
.pcard {
  /* Lifted off the fold. At bottom:10 it sat on the bottom edge of .hero__shot,
     which was fine while the hero was ~610 tall and is not now that the hero is
     100svh — the card landed exactly where the assistant's launcher is pinned,
     and the launcher covered its add button. This clears a 56px launcher and
     its 24px inset with room to spare, and scales a little with window height
     so it stays near the bottles rather than drifting up a tall window. */
  position: absolute; right: calc(-1 * var(--gut) + 112px);
  bottom: clamp(44px, 5.5vh, 80px);
  width: 190px; padding: 13px 15px 14px;
  border-radius: 13px;
  background: var(--paper);
  box-shadow: 0 2px 4px rgba(29,27,75,.05), 0 12px 30px rgba(29,27,75,.11);
}
.pcard__tag {
  font-size: 8.5px; font-weight: 600;
  letter-spacing: .16em; text-transform: uppercase;
  color: var(--ink-2);
}
.pcard__name { margin-top: 5px; font-size: 16.5px; font-weight: 500; line-height: 1.3; }
.pcard__rate { display: flex; align-items: center; gap: 6px; margin-top: 6px; }
.pcard__score { font-size: 12px; color: var(--ink-2); }
.pcard__foot {
  display: flex; align-items: center; justify-content: space-between;
  margin-top: 10px;
}
.pcard__price { font-size: 17.5px; font-weight: 600; }

.plus {
  display: grid; place-items: center;
  width: 28px; height: 28px; padding: 0;
  border: 0; border-radius: var(--r-pill);
  background: var(--ink); cursor: pointer;
  transition: transform .16s ease;
}
.plus:hover { transform: scale(1.08); }
.plus svg {
  width: 13px; height: 13px;
  fill: none; stroke: #fff; stroke-width: 1.8; stroke-linecap: round;
}


/* 05  Product lettering =================================================== */
/* The containers are generated blank and the lettering set as real text over
   them. multiply blending lets the glass shading run through the type, which
   is what keeps it looking printed rather than pasted on; and a price, a size
   or a product name can change without a reshoot. */

.plabel {
  position: absolute;
  left: var(--x); top: var(--y);
  width: var(--w);
  transform: translate(-50%, -50%);
  display: flex; flex-direction: column; align-items: center;
  text-align: center;
  color: var(--ink);
  mix-blend-mode: multiply;
  pointer-events: none;
  line-height: 1.25;
}
.plabel__brand {
  font-family: var(--serif);
  font-weight: 400;
  font-size: calc(var(--s) * 1.15);
  letter-spacing: .18em; text-indent: .18em;
}
.plabel__sub {
  margin-top: .35em;
  font-size: calc(var(--s) * .62);
  font-weight: 500;
  letter-spacing: .3em; text-indent: .3em;
  text-transform: uppercase;
  opacity: .72;
}
.plabel__name {
  margin-top: 1.5em;
  font-size: var(--s);
  font-weight: 500;
  letter-spacing: .1em;
  text-transform: uppercase;
}
.plabel__size {
  margin-top: 1.2em;
  font-size: calc(var(--s) * .74);
  font-weight: 400;
  letter-spacing: .06em;
  opacity: .78;
}

/* The hero's lettering is in the photograph. These are the four bestseller
   tiles, which are still cut-outs — at 230px on a flat pastel the matte has an
   easy job, and unlike the hero nobody reads the label, so it only has to be
   the right shape and weight.

   Positions are of the TRIMMED image: the matte crops to the subject's
   bounding box, so a percentage here is not a percentage of what came out of
   the generator. */
.plabel--card  { --x: 50%; --y: 56%; --w: 30%; --s: 5px; }
.plabel--squat { --y: 66%; --w: 46%; }


/* 06  Trust row =========================================================== */

.trust { background: var(--paper); }

.trust__grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(20px, 3vw, 44px);
  padding: clamp(28px, 3vw, 40px) 0;
  max-width: 960px;
}

.trust__item { display: flex; align-items: center; gap: 18px; }

.trust__text { display: flex; flex-direction: column; gap: 2px; }
.trust__text b {
  font-size: 13.5px; font-weight: 600;
  letter-spacing: .1em; text-transform: uppercase;
}
.trust__text span { font-size: 14.5px; color: var(--ink-2); }


/* 07  Story =============================================================== */

/* The story sits on a light purple band rather than white, and the photograph
   carries the colour into it: story.webp's own backdrop measures #E5DEEE, so
   the section is set a few steps lighter — close enough to belong to the same
   picture, far enough apart that the rounded corners still read as corners. */
/* No vertical padding: the photograph defines the band's height and meets its
   top and bottom edges, which is what the rounded left corners are for. The
   copy is centred against it by the grid. */
.story {
  padding: 0;
  background: #F1ECF9;
}

.story__grid {
  display: grid;
  grid-template-columns: 0.82fr 1.18fr;
  align-items: center;
  gap: clamp(32px, 5vw, 72px);
}

.story__copy > * + * { margin-top: 20px; }
.story__lead { max-width: 36ch; font-size: 17.5px; line-height: 1.75; color: var(--ink-2); }

/* The photograph runs off the right edge of the page and rounds only the
   corner that stays on it. */
.story__figure { margin-right: calc(-1 * var(--gut)); }
.story__figure img {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border-radius: 44px 0 0 44px;
}


/* 08  Bestsellers ========================================================= */

.best { padding: clamp(56px, 6vw, 88px) 0 0; }

.best__head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 20px; margin-bottom: clamp(22px, 2.4vw, 32px);
}
.viewall { font-size: 15px; color: var(--ink-2); }
.viewall:hover { color: var(--ink); }

.best__grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: clamp(16px, 1.8vw, 24px);
}

/* Each product is photographed on its own pastel, same as the hero, so the tile
   is the picture rather than a coloured box with a cut-out dropped into it.
   --tile only shows while the image is still decoding; it is the ground colour
   the render was shot on, so the swap is invisible. */
.prod__tile {
  position: relative;
  display: block;
  aspect-ratio: 4 / 5;
  border-radius: var(--r-tile);
  background: var(--tile);
  overflow: hidden;
}
.prod__tile img {
  width: 100%; height: 100%;
  object-fit: cover;
  transition: transform .5s cubic-bezier(.22,.61,.36,1);
}
/* Scale, not translate: the ground is part of the picture now, so lifting it
   would drag a corner of tile colour in behind it. */
.prod__tile:hover img { transform: scale(1.04); }

.prod__name { margin-top: 14px; font-size: 17px; font-weight: 500; }
.prod__sub  { margin-top: 1px; font-size: 14.5px; color: var(--ink-2); }
.prod__foot {
  display: flex; align-items: center; justify-content: space-between;
  margin-top: 9px;
}
.prod__price { font-size: 17px; font-weight: 600; }
.prod__rate  { display: inline-flex; align-items: center; gap: 4px; font-size: 14px; }
.prod__rate svg { width: 10px; height: 10px; fill: var(--ink); }


/* 09  New arrival ========================================================= */

.arrival { padding: clamp(56px, 6vw, 88px) 0 0; }

.arrival__panel {
  position: relative;
  isolation: isolate;
  overflow: hidden;              /* keeps the photograph inside the radius */
  display: grid;
  /* Not 1fr 1fr. The jar, its lid and the lid's shadow reach 62.9% of the
     frame's width (measured off arrival.webp against its own ground colour),
     and an even split starts the copy at about 50% — so the heading began on
     top of the lid. The panel is always wider than the image's 2.36:1 in this
     range, which means cover scales by width and image x maps 1:1 to panel x,
     so that 62.9% is directly usable. 1.95fr puts the copy's left edge roughly
     25-35px clear of it at every width down to the mobile breakpoint. */
  grid-template-columns: minmax(0, 1.95fr) minmax(0, 1fr);
  align-items: center;
  gap: clamp(20px, 3vw, 40px);
  /* 1200/2.357 is 509, so a 330px panel would throw away a third of the frame's
     height — and the parts it takes are the lid's top edge and the jar's base,
     not spare ground. This leaves about 40px cropped each side. */
  min-height: clamp(320px, 30vw, 440px);
  padding: clamp(26px, 3vw, 40px) clamp(28px, 4vw, 60px);
  border-radius: var(--r-panel);
  /* Sampled from the render's empty right edge, so the panel and the picture
     are the same lavender while the image is still decoding. */
  background: #C9B9DF;
}

/* The jar sits in the left third of the frame, so cover crops from the right —
   the side holding nothing but the ground the copy sits on. The panel is wider
   than 21:9, which is the widest the generator offers, so it also loses about
   90px top and bottom; that is empty ground too. */
.arrival__bg {
  position: absolute;
  inset: 0;
  z-index: -1;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: left center;
}

.arrival__copy { grid-column: 2; }

.arrival__copy > * + * { margin-top: 16px; }
.arrival__copy .eyebrow + .h2 { margin-top: 12px; }
.arrival__lead { font-size: 17px; line-height: 1.7; color: #4A4570; }
.arrival__lead span { display: block; }


/* 10  Quiz =============================================================== */

.quiz { padding: clamp(56px, 6vw, 88px) 0 clamp(64px, 7vw, 100px); }

.quiz__grid {
  display: grid;
  grid-template-columns: 1fr 0.86fr 1fr;
  align-items: center;
  gap: clamp(26px, 4vw, 56px);
}

.quiz__copy > * + * { margin-top: 18px; }
.quiz__lead { max-width: 32ch; font-size: 17px; line-height: 1.75; color: var(--ink-2); }

.quiz__figure img {
  width: 100%;
  aspect-ratio: 3 / 4;
  object-fit: cover;
  border-radius: 20px;
}

.quiz__list { display: flex; flex-direction: column; gap: 22px; }
.quiz__list li { display: flex; align-items: center; gap: 14px; }

.qico { flex: none; display: grid; place-items: center; width: 26px; height: 26px; }
.qico svg {
  width: 22px; height: 22px;
  fill: none; stroke: var(--ink); stroke-width: 1.4;
  stroke-linecap: round; stroke-linejoin: round;
}

.quiz__text { display: flex; flex-direction: column; gap: 1px; }
.quiz__text b { font-size: 15.5px; font-weight: 600; }
.quiz__text span { font-size: 14.5px; color: var(--ink-2); }


/* 11  Footer ============================================================= */

.site-footer {
  padding: clamp(44px, 4.6vw, 64px) 0 26px;
  background: var(--hero-bg);
}

.foot__grid {
  display: grid;
  grid-template-columns: 1.5fr 1fr 1fr 1.4fr;
  gap: clamp(24px, 3.4vw, 52px);
}

.foot__brand .brand__word,
.foot__brand .brand__sub { display: block; text-align: left; text-indent: 0; }
.foot__brand .brand__word { font-size: 19px; letter-spacing: .2em; }
.foot__brand .brand__sub { margin-top: 5px; letter-spacing: .34em; }
.foot__blurb { margin-top: 16px; max-width: 30ch; font-size: 14.5px; line-height: 1.7; color: var(--ink-2); }

.foot__title {
  font-size: 12.5px; font-weight: 600;
  letter-spacing: .12em; text-transform: uppercase;
}
.foot__col ul { margin-top: 14px; display: flex; flex-direction: column; gap: 9px; }
.foot__col a { font-size: 14px; color: var(--ink-2); }
.foot__col a:hover { color: var(--ink); }

.news { display: flex; gap: 8px; margin-top: 14px; }
.news input {
  flex: 1 1 auto; min-width: 0;
  padding: 12px 16px;
  border: 1px solid var(--line); border-radius: var(--r-pill);
  background: var(--paper); color: var(--ink);
  font-family: inherit; font-size: 12.5px;
}
.news input::placeholder { color: #A6A2B8; }
.foot__note { margin-top: 12px; font-size: 11px; color: var(--ink-2); }

.foot__bottom {
  display: flex; flex-wrap: wrap; justify-content: space-between; gap: 8px;
  margin-top: clamp(32px, 3.4vw, 48px);
  padding-top: 20px;
  border-top: 1px solid var(--line);
  font-size: 11px; color: var(--ink-2);
}


/* 12  Reveals and motion ================================================= */

.js .reveal { opacity: 0; transform: translateY(16px); }
.js .reveal.is-in {
  opacity: 1; transform: none;
  transition: opacity .6s ease, transform .6s cubic-bezier(.22,.61,.36,1);
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    transition-duration: .001ms !important;
  }
  .js .reveal { opacity: 1; transform: none; }
}


/* 13  Responsive ========================================================= */

@media (max-width: 1080px) {
  .hero__grid { grid-template-columns: 0.92fr 1.08fr; }
  .pcard { width: 168px; }
  .quiz__grid { grid-template-columns: 1fr 1fr; }
  /* The three benefit rows drop under the copy and share its column, so the
     photograph keeps a sensible shape instead of being squeezed to a slot. */
  .quiz__figure { grid-row: 1 / 3; grid-column: 2; }
  .quiz__list { flex-direction: column; }
}

@media (max-width: 860px) {
  :root { --shell: min(1200px, 100% - 48px); --gut: 24px; }

  :root { --nav-h: 64px; }
  .nav { grid-template-columns: auto 1fr auto; min-height: 64px; }
  /* The strip sits directly under the status bar on a phone and the header
     floats on the hero below it, so it needs room beneath the words. */
  .nav__burger {
    display: grid; align-content: center; gap: 4px;
    order: -1;
    width: 34px; height: 34px; padding: 0 7px;
    border: 0; background: none; cursor: pointer;
  }
  .nav__burger span { height: 1.5px; background: var(--ink); border-radius: 2px; }
  .brand { align-items: flex-start; }

  .nav__links {
    position: absolute; left: 0; right: 0; top: 100%;
    flex-direction: column; align-items: flex-start;
    gap: 0;
    padding: 8px 24px 18px;
    background: var(--paper);
    border-bottom: 1px solid var(--line);
    box-shadow: 0 14px 24px rgba(29,27,75,.07);
    opacity: 0; transform: translateY(-8px);
    transition: opacity .2s ease, transform .2s ease;
  }
  .nav__links.is-open { opacity: 1; transform: none; }
  .nav__links a { width: 100%; padding: 11px 0; font-size: 15px; }

  /* The copy cannot sit on top of the bottles once the hero is one column, so
     the photograph stops being a backdrop and becomes a band beneath it —
     cropped hard to the right of the frame rather than shrunk, because fitting
     the whole 1.78:1 frame to a phone's width renders the bottles about 90px
     tall and spends the other half of the band on empty ground. */
  /* The band's own top edge, measured, so the copy's ground and the plate
     meet without a seam. Desktop keeps #DACEE7 because there the plate
     covers the whole section and no join is visible. */
  .hero { display: flex; flex-direction: column; background-color: #DCCEE7; }
  .hero__grid { grid-template-columns: 1fr; gap: 24px; min-height: 0; padding-bottom: clamp(24px, 4vw, 36px); }
  .hero__copy { text-align: center; }
  .hero__lead { margin-inline: auto; }
  .hero__title span,
  .hero__lead span { display: inline; }
  /* display:contents drops the wrapper's box without dropping the chip inside
     it, so the chip's containing block becomes .hero and it can go bottom-right
     over the band. Hiding the wrapper outright would take the price with it. */
  .hero__shot { display: contents; }
  /* The chip leaves the picture for the whole mobile range, not just phones.
     Once the band was cropped harder to centre the bottles they also grew, and
     a chip floating bottom-right landed squarely on the jar's lettering. It
     goes into a strip of padding under the band instead — the one place in this
     layout that hides nothing. Still absolute: it lives inside .hero__grid and
     .hero__bg comes after that grid, so static would put it above the picture. */
  .hero { padding-bottom: 78px; }
  /* z-index, because the band's mask makes the picture a stacking context
     and it comes later in the DOM: without this the chip painted under it. */
  .pcard { left: var(--gut); right: var(--gut); bottom: 14px; width: auto; z-index: 2; }

  /* A ratio, not a height. cover only crops the axis the box is short on, so a
     band wider than the frame's 1.78:1 crops top-and-bottom and keeps the empty
     left half — half a phone's hero spent on nothing. Anything narrower than
     1.78 crops from the left instead, which is the half worth losing. */
  /* 9/7, solved the same way as the arrival band. The bottles' energy-weighted
     centre is at 72.7% of the frame and the band is right-aligned, so the
     visible window is [1-W, 1] and the subject lands at (0.727-(1-W))/W. Set
     that to 0.5 and W = 2(1-0.727) = 0.546, i.e. a band ratio of 0.546 x 2.357
     = 1.287. 9/7 is 1.286. At 3/2 the window was 63.6% and the bottles sat at
     57% of the band and smaller; cropping harder both centres and enlarges. */
  /* 1/1 is hero-mobile.webp's own ratio, so nothing is cropped: the plate
     was composed for this band, both products whole and the smears at its
     top edge, which the 9/7 crop of the desktop frame could never give. */
  .hero__bg {
    position: static;
    z-index: auto;
    height: auto;
    aspect-ratio: 1 / 1;
    /* The plate's ground is not perfectly flat, so its top edge read as a
       faint line against the section's colour. Fading the top tenth of the
       picture into that colour makes the join a dissolve instead. */
    -webkit-mask-image: linear-gradient(to bottom, transparent 0, #000 11%);
    mask-image: linear-gradient(to bottom, transparent 0, #000 11%);
  }

  .trust__grid { grid-template-columns: 1fr; gap: 18px; }

  /* The section drops its vertical padding so the photograph can meet the
     band's edges — but that only works while the photograph is beside the copy
     and centring it. Stacked, there is nothing to centre against and the
     heading sits flush against the trust row above, so the top padding comes
     back here. The bottom stays at zero: the picture is last and should still
     run into the band's edge. */
  .story { padding-top: clamp(44px, 9vw, 72px); }
  .story__grid { grid-template-columns: 1fr; gap: 28px; }
  .story__figure { margin-right: calc(-1 * var(--gut)); margin-left: calc(-1 * var(--gut)); }
  /* 4/3 is story.webp's own ratio (1400x1045), so nothing is cropped. At
     16/10 the box showed 83% of the frame height and took the crop off the
     women's chests. */
  .story__figure img { border-radius: 0; aspect-ratio: 4 / 3; }

  .best__grid { grid-template-columns: repeat(2, 1fr); }

  /* Flex, so order can put the picture above the copy — it is last in the DOM
     because on desktop it is a backdrop, not a column. */
  /* The panel keeps no horizontal padding of its own — the copy carries it.
     Pulling the picture out to the edges with negative margins could not work:
     it is width:auto and max-width:100%, so it can never exceed the content
     box, and the margins only shifted it. Worse, being loading="lazy" it has no
     intrinsic width until it decodes, so width:auto measured zero and the
     panel had nothing to size against at all. width:100% on a full-bleed
     element fixes both. */
  .arrival__panel {
    display: flex;
    flex-direction: column;
    text-align: center;
    min-height: 0;
    padding: 0 0 clamp(26px, 4vw, 34px);
  }
  .arrival__copy {
    grid-column: auto;
    padding: 4px clamp(20px, 5vw, 32px) 0;
  }
  /* overflow:hidden on the panel clips the top corners to its own radius, so
     the picture inherits the rounding rather than needing its own. */
  .arrival__bg {
    position: static;
    z-index: auto;
    order: -1;
    width: 100%;
    height: auto;
    /* 7/5, solved rather than nudged. object-position cannot help here — the
       jar already sits against the source's left edge, so there is nothing
       further left to reveal. The band's RATIO is the only lever: cover crops
       from the right, and a taller band crops more, which walks the subject
       towards the middle. The subject's energy-weighted centre is at 29.7% of
       the frame, a 7/5 band shows 59.4% of the frame's width, and 29.7/59.4
       lands it at 50%. (16/9 showed 75.4% and left it at 39%.) */
    aspect-ratio: 7 / 5;
    margin: 0 0 clamp(18px, 3vw, 26px);
  }
  .arrival__lead span { display: inline; }

  .quiz__grid { grid-template-columns: 1fr; }
  .quiz__figure { grid-row: auto; grid-column: auto; max-width: 420px; }
  /* 3/4 is quiz.webp's own ratio (900x1205). The 4/3 box here was showing
     just 56% of the frame height — cover crops the axis the source is longer
     on, and this source is portrait — which is what cut the top of her head
     off. Matching the source crops nothing. */
  .quiz__figure img { aspect-ratio: 3 / 4; }

  .foot__grid { grid-template-columns: 1fr 1fr; }
  .foot__col--news { grid-column: 1 / -1; }
}

@media (max-width: 520px) {
  :root { --shell: min(1200px, 100% - 36px); --gut: 18px; }
  .hero__title { font-size: clamp(40px, 13vw, 56px); }

  /* The tile keeps its 4:5 — it is the photograph's own shape now, and forcing
     a landscape box would make cover eat the top and bottom off the bottle. */
  .best__grid { grid-template-columns: 1fr 1fr; gap: 12px; }
  .foot__grid { grid-template-columns: 1fr; }
  .news { flex-direction: column; }
  .news .btn { width: 100%; }
}
