/* ==========================================================================
   Everyday Macros — Miranda's Kitchen
   Brand: Lora (display) + Work Sans (text/labels)
   ========================================================================== */

:root {
  --ink:        #262220;  /* near-black text */
  --ink-muted:  #5c5551;  /* secondary headings */
  --ink-label:  #8a8177;  /* small-caps labels */
  --rule:       #d8d2cb;  /* hairlines */
  --green:      #5C7D65;  /* brand green */
  --green-deep: #4a6852;  /* the same green, darkened for hover */
  --paper:      #ffffff;  /* page background */

  --serif: "Lora", Georgia, "Times New Roman", serif;
  --sans:  "Work Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;

  --measure: 62ch;
  --gutter: clamp(1.5rem, 5vw, 4rem);
  --max: 1120px;
}

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

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

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 1.0625rem;
  line-height: 1.7;
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

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

@keyframes rise {
  from { opacity: 0; transform: translateY(20px); }
  to   { opacity: 1; transform: none; }
}

/* ---------- typography ---------------------------------------------------- */

h1, h2, h3 { font-family: var(--serif); font-weight: 500; margin: 0; }

h1 {
  font-size: clamp(3rem, 11vw, 6.5rem);
  line-height: 0.95;
  letter-spacing: -0.015em;
  text-transform: uppercase;
}

h2 {
  font-size: clamp(1.75rem, 4vw, 2.75rem);
  line-height: 1.15;
  letter-spacing: -0.01em;
  text-wrap: balance;
}

h3 { font-size: 1.3125rem; line-height: 1.3; }

p { margin: 0 0 1.15em; max-width: var(--measure); }
p:last-child { margin-bottom: 0; }

a { color: inherit; }

/* letterspaced small-caps label — the cookbook's signature device */
.label {
  font-family: var(--sans);
  font-size: 0.6875rem;
  font-weight: 500;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--ink-label);
  margin: 0;
  /* labels are short — never inherit the paragraph measure, or the box ends up
     narrower than its container and centred text sits left of centre */
  max-width: none;
}

.label--strong { font-weight: 700; }

.lede {
  font-family: var(--serif);
  font-size: clamp(1.125rem, 2.2vw, 1.5rem);
  line-height: 1.55;
  color: var(--ink-muted);
  text-wrap: pretty;
}

.hairline {
  width: 68px; height: 1px;
  background: var(--rule);
  border: 0;
  margin: 2rem auto;
}

/* ---------- layout ------------------------------------------------------- */

.wrap {
  max-width: var(--max);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

section { padding-block: clamp(4rem, 9vw, 8rem); }
.rule-top { border-top: 1px solid var(--rule); }

.center { text-align: center; }
.center p { margin-inline: auto; }

/* ---------- header ------------------------------------------------------- */

.site-head {
  padding-block: 1.75rem;
  border-bottom: 1px solid var(--rule);
}
.site-head .wrap {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}
/* the logo carries the name now, so the header holds an image rather than type */
.wordmark {
  display: block;
  line-height: 0;   /* no descender gap under the image */
}
.wordmark img {
  height: 64px;
  width: auto;
  /* The logo's two lines of type sit 14.5% of its height below the middle of
     the file, because the cutting board reaches higher than the text does.
     Centring the box therefore leaves the name looking low next to the button;
     lifting it by that same fraction lines the two up optically. */
  transform: translateY(-14.5%);
}
.nav-buy {
  font-family: var(--sans);
  font-size: 0.6875rem;
  font-weight: 500;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--ink-muted);
  border-bottom: 1px solid var(--rule);
  padding-bottom: 2px;
  transition: color .25s ease, border-color .25s ease;
}
.nav-buy:hover { color: var(--ink); border-color: var(--ink); }

/* ---------- hero --------------------------------------------------------- */

.hero {
  text-align: center;
  padding-block: clamp(1.5rem, 3.5vw, 2.75rem) clamp(3.5rem, 8vw, 6rem);
}

.hero-mark {
  /* Bowl.png carries deliberate asymmetric margin so the bowl — not the sprig —
     lands on the page centre. Never trim it. The canvas is ~83% artwork, so this
     width is sized up so the drawing itself renders at ~275px. */
  width: min(378px, 70vw);
  margin: 0 auto clamp(1.5rem, 3.5vw, 2.25rem);
  opacity: .92;
}

/* the COOKBOOK kicker only — scoped to its own class, because as `.hero .label`
   this was also landing on the tagline row, inflating it to 14px and adding a
   20px bottom margin to every tag */
.hero .kicker {
  margin-bottom: 1.25rem;
  font-size: 0.875rem;
  letter-spacing: 0.3em;
  color: var(--ink-muted);
}

.hero h1 + .hairline { margin-block: clamp(1.5rem, 4vw, 2.25rem); }

.hero-sub {
  font-family: var(--serif);
  font-size: clamp(1.125rem, 2.6vw, 1.625rem);
  line-height: 1.45;
  color: var(--ink);
  margin: 0 auto;
  max-width: 34ch;
  text-wrap: balance;
}

.hero-tags {
  margin-top: clamp(1rem, 2.2vw, 1.5rem);
  display: flex;
  justify-content: center;
  flex-wrap: wrap;
  gap: 0.5rem 1.25rem;
}
.hero-tags .label {
  display: inline-flex;
  align-items: center;
  gap: 1.25rem;
  font-size: 0.8125rem;
}
.hero-tags .label::after { content: "•"; letter-spacing: 0; color: var(--rule); }
.hero-tags .label:last-child::after { content: none; }

.hero-cta { margin-top: clamp(2.5rem, 6vw, 3.5rem); }

/* Staggered page-load reveal. Gated on .anim like the scroll reveals, so the
   hero is never hidden behind an animation that might not run — with JS off,
   these elements are simply visible. */
@media (prefers-reduced-motion: no-preference) {
  .anim .reveal { animation: rise 1s cubic-bezier(.22,.68,.15,1) both; }
  .anim .reveal:nth-child(1) { animation-delay: .08s; }
  .anim .reveal:nth-child(2) { animation-delay: .15s; }
  .anim .reveal:nth-child(3) { animation-delay: .25s; }
  .anim .reveal:nth-child(4) { animation-delay: .35s; }
  .anim .reveal:nth-child(5) { animation-delay: .45s; }
  .anim .reveal:nth-child(6) { animation-delay: .55s; }
  .anim .reveal:nth-child(7) { animation-delay: .65s; }
}

/* ---------- scroll reveals ----------------------------------------------- */
/* Gated on .anim, which a tiny inline script adds to <html>. With JS off nothing
   is ever hidden, so the page is fully readable either way.

   Keyframe animations, not transitions: animation-fill-mode pins the end state,
   so a reveal can't stall partway and leave half-faded text. Removing .in resets
   the element, which is what lets a section replay when you scroll back to it.

   Per-child delay comes from --d, set in JS from each child's real position, so
   the wave follows the layout at any column count. */

@media (prefers-reduced-motion: no-preference) {
  .anim .fx,
  .anim .fx-stagger > * { opacity: 0; }

  .anim .fx.in { animation: rise .8s cubic-bezier(.22,.68,.15,1) both; }

  .anim .fx-stagger.in > * {
    animation: rise .8s cubic-bezier(.22,.68,.15,1) both;
    animation-delay: var(--d, 0s);
  }

  /* the sample pages get a touch of scale, like sheets settling onto a table */
  .anim .pages.fx-stagger.in > * {
    animation-name: settle;
    animation-duration: .9s;
  }

  /* thirty recipe names — keep their travel short so the wave stays quiet */
  .anim .index-grid.fx-stagger.in > * {
    animation-name: riseShort;
    animation-duration: .6s;
  }

  /* the hairline draws itself outward */
  .anim .fx .hairline,
  .anim .fx-stagger .hairline { width: 0; }
  .anim .fx.in .hairline,
  .anim .fx-stagger.in .hairline {
    animation: draw .9s cubic-bezier(.22,.68,.15,1) .2s both;
  }

  @keyframes draw {
    from { width: 0; }
    to   { width: 68px; }
  }

  @keyframes riseShort {
    from { opacity: 0; transform: translateY(10px); }
    to   { opacity: 1; transform: none; }
  }

  @keyframes settle {
    from { opacity: 0; transform: translateY(24px) scale(.985); }
    to   { opacity: 1; transform: none; }
  }
}

/* ---------- buttons ------------------------------------------------------ */

.btn {
  display: inline-block;
  font-family: var(--sans);
  font-size: 0.75rem;
  font-weight: 500;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  text-decoration: none;
  padding: 1.0625rem 2.25rem;
  border: 1px solid var(--green);
  background: var(--green);
  color: var(--paper);
  cursor: pointer;
  white-space: nowrap;   /* a button label never breaks onto a second line */
  /* <a> would inherit the body's 1.7 while <button> defaults to ~1.2, making
     the two render at different heights. Pin it so they always match. */
  line-height: 1.2;
  font-family: var(--sans);
  transition: background .28s ease, color .28s ease, border-color .28s ease;
}
/* darkens rather than inverting: an outlined hover state would drop the green
   out of the page at exactly the moment someone is about to click */
.btn:hover { background: var(--green-deep); border-color: var(--green-deep); color: var(--paper); }

.btn-quiet {
  background: transparent;
  color: var(--ink);
  border-color: var(--rule);
}
.btn-quiet:hover { background: var(--ink); color: var(--paper); border-color: var(--ink); }

.btn-block { display: block; width: 100%; text-align: center; }

.btn:disabled,
.btn[aria-disabled="true"] {
  cursor: default;
  color: var(--ink-label);
  border-color: var(--rule);
  background: transparent;
}
.btn:disabled:hover,
.btn[aria-disabled="true"]:hover {
  background: transparent;
  color: var(--ink-label);
  border-color: var(--rule);
}

/* header-sized button */
.btn-sm {
  font-size: 0.6875rem;
  letter-spacing: 0.18em;
  padding: 0.85rem 1.55rem;
}

/* ---------- three-up value props ---------------------------------------- */

.trio {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: clamp(2rem, 5vw, 3.5rem);
  margin-top: clamp(2.5rem, 6vw, 4rem);
}
.trio > div { border-top: 1px solid var(--rule); padding-top: 1.5rem; }
.trio .num {
  font-family: var(--serif);
  font-size: 0.9375rem;
  color: var(--ink-label);
  display: block;
  margin-bottom: 0.75rem;
}
.trio h3 { margin-bottom: .5rem; }
.trio p { font-size: 0.9375rem; color: var(--ink-muted); max-width: 34ch; }

/* ---------- look inside ------------------------------------------------- */

.pages {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: clamp(1.5rem, 4vw, 2.5rem);
  margin-top: clamp(2.5rem, 6vw, 4rem);
  align-items: start;
}
.sheet {
  margin: 0;
  border: 1px solid var(--rule);
  background: var(--paper);
  box-shadow: 0 1px 2px rgba(38,34,32,.04), 0 12px 32px -18px rgba(38,34,32,.22);
  transition: transform .5s cubic-bezier(.2,.7,.2,1), box-shadow .5s ease;
}
.sheet:hover {
  transform: translateY(-6px);
  box-shadow: 0 1px 2px rgba(38,34,32,.05), 0 22px 46px -20px rgba(38,34,32,.28);
}
/* The sample pages are painted as backgrounds rather than <img> elements: there is
   no image node to drag onto the desktop, and no "Save image as" in the context
   menu. A determined visitor can still pull the file out of the network tab. */
.sheet-page {
  aspect-ratio: 816 / 1056;
  background-size: cover;
  background-position: top center;
  background-repeat: no-repeat;
  -webkit-user-select: none;
  user-select: none;
  -webkit-user-drag: none;
  -webkit-touch-callout: none;
}

.sheet figcaption {
  font-family: var(--sans);
  font-size: 0.625rem;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--ink-label);
  text-align: center;
  padding: 0.9rem 1rem 1.05rem;
  border-top: 1px solid var(--rule);
}

/* ---------- recipe index ------------------------------------------------ */

.index-grid {
  columns: 3 200px;
  column-gap: clamp(1.5rem, 4vw, 3rem);
  margin-top: clamp(2rem, 5vw, 3rem);
  padding: 0;
  list-style: none;
}
.index-grid li {
  break-inside: avoid;
  font-family: var(--serif);
  font-size: 1.0625rem;
  padding: .55rem 0;
  border-bottom: 1px solid var(--rule);
  color: var(--ink-muted);
}

/* Tuned so the line breaks after "on the right," on a wide screen. */
.lede--inside { max-width: 44rem; }

/* Only used on mobile, where the recipe list is collapsed. */
.index-more {
  display: none;
  margin: 1.75rem auto 0;
  padding: 0.7rem 1.5rem;
  background: none;
  border: 1px solid var(--rule);
  font-family: var(--sans);
  font-size: 0.6875rem;
  font-weight: 500;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--ink-muted);
  cursor: pointer;
  transition: color .2s ease, border-color .2s ease;
}
.index-more:hover { color: var(--ink); border-color: var(--ink); }

.lede--why {
  margin-top: 1.25rem;
  max-width: 46ch;
  font-size: clamp(1rem, 1.7vw, 1.1875rem);
}

.footnote { font-size: 0.875rem; color: var(--ink-label); margin-top: 2rem; }

/* ---------- meet Miranda -------------------------------------------------- */

.about {
  display: grid;
  grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr);
  gap: clamp(2rem, 6vw, 4.5rem);
  align-items: center;
}

/* Two photos: Miranda large, the family shot tucked in below and to the right
   so the pair reads as one arrangement rather than a row of two. */
.portraits { position: relative; }

.portrait {
  margin: 0;
  border: 1px solid var(--rule);
  background: var(--paper);
  box-shadow: 0 1px 2px rgba(38,34,32,.04), 0 12px 32px -18px rgba(38,34,32,.22);
}
/* the frame owns the crop, so any photo dropped in behaves the same */
.portrait img {
  width: 100%;
  aspect-ratio: 4 / 5;
  object-fit: cover;
  object-position: center;
}

/* the section rule is left-aligned here, unlike the centred ones elsewhere */
.hairline--left { margin-inline: 0; }

.portrait--solo { width: 84%; }

/* pulled up into the solo shot's lower edge; the paper-coloured outline keeps
   the two from touching where they overlap */
.portrait--family {
  width: 54%;
  margin-left: auto;
  margin-top: -15%;
  position: relative;
  outline: 8px solid var(--paper);
}
.portrait--family img { aspect-ratio: 1 / 1; }

.about-copy p { color: var(--ink-muted); max-width: 46ch; }

/* ---------- product shot ------------------------------------------------- */

.product {
  position: relative;
  width: min(240px, 56vw);
  margin: 0 auto clamp(2rem, 4vw, 2.75rem);
  filter: drop-shadow(0 18px 30px rgba(38, 34, 32, .16));
}

.product img { width: 100%; height: auto; display: block; }

.product-badge {
  position: absolute;
  top: 14%;
  left: -14%;
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.45rem 0.7rem;
  background: var(--ink);
  color: var(--paper);
  border-radius: 999px;
  font-family: var(--sans);
  font-size: 0.5rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  white-space: nowrap;
  box-shadow: 0 6px 16px -6px rgba(38, 34, 32, .45);
}

.product-badge svg {
  width: 11px;
  height: 11px;
  flex: none;
}

/* ---------- pricing ----------------------------------------------------- */

.tiers {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: clamp(1.25rem, 3vw, 2rem);
  margin-top: clamp(2.5rem, 6vw, 4rem);
  align-items: stretch;
}

.tier {
  border: 1px solid var(--rule);
  padding: clamp(1.75rem, 4vw, 2.5rem);
  display: flex;
  flex-direction: column;
  text-align: center;
  position: relative;
  background: var(--paper);
}
.tier--feature { border-color: var(--ink); }

/* not on sale yet: recede, and make the state unmistakable */
.tier--soon { border-style: dashed; }
.tier--soon h3,
.tier--soon .price { color: var(--ink-muted); }
.tier--soon .flag { color: var(--ink-label); }
.tier--soon li { color: var(--ink-label); }
/* The coming-soon cards carry an empty price block so every row — feature list
   and button alike — lines up with the Digital card and reads across. */

.tier--feature .flag,
.tier--soon .flag {
  position: absolute;
  top: 0; left: 50%;
  transform: translate(-50%, -50%);
  background: var(--paper);
  padding-inline: .85rem;
  font-family: var(--sans);
  font-size: 0.625rem;
  font-weight: 500;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--ink);
  white-space: nowrap;
}

.tier h3 { font-size: 1.5rem; margin-bottom: .35rem; }
.tier .tier-kind { margin-bottom: 1.5rem; }

.price {
  font-family: var(--serif);
  font-size: clamp(2.5rem, 6vw, 3.25rem);
  line-height: 1;
  letter-spacing: -0.02em;
  display: block;
}
.price-note {
  font-size: 0.8125rem;
  color: var(--ink-label);
  margin-top: .6rem;
}

.tier ul {
  list-style: none;
  padding: 0;
  margin: 1.75rem 0 2rem;
  border-top: 1px solid var(--rule);
  text-align: left;
}
.tier li {
  font-size: 0.9375rem;
  color: var(--ink-muted);
  padding: .7rem 0;
  border-bottom: 1px solid var(--rule);
}
.tier .btn { margin-top: auto; }

.pay-note { font-size: 0.8125rem; color: var(--ink-label); margin-top: 2.5rem; text-align: center; }

/* ---------- faq --------------------------------------------------------- */

.faq { max-width: 720px; margin-inline: auto; margin-top: clamp(2rem, 5vw, 3rem); }
.faq details { border-bottom: 1px solid var(--rule); }
.faq details:first-of-type { border-top: 1px solid var(--rule); }
.faq summary {
  cursor: pointer;
  list-style: none;
  padding: 1.35rem 2.5rem 1.35rem 0;
  font-family: var(--serif);
  font-size: 1.125rem;
  position: relative;
}
.faq summary::-webkit-details-marker { display: none; }
/* Transition colour only. Putting font-weight in a transition leaves it pinned
   at the start value in some engines, and animating weight would reflow the line
   anyway — the weight change should snap. */
.faq summary { transition: color .18s ease; }
.faq summary:hover,
.faq summary:focus-visible,
.faq details[open] > summary { font-weight: 600; color: var(--ink); }
.faq summary::after {
  content: "+";
  position: absolute;
  right: .35rem; top: 50%;
  transform: translateY(-50%);
  font-family: var(--sans);
  font-size: 1.1rem;
  color: var(--ink-label);
  transition: transform .3s ease;
}
.faq details[open] summary::after { content: "–"; }
.faq .answer { padding: 0 2.5rem 1.6rem 0; }
.faq .answer p { font-size: 0.9375rem; color: var(--ink-muted); }

/* ---------- footer ------------------------------------------------------ */

.site-foot {
  border-top: 1px solid var(--rule);
  padding-block: 3rem;
  text-align: center;
}
.site-foot .label + .label { margin-top: .9rem; }

.foot-logo {
  width: 100px;
  height: auto;
  margin: 0 auto 1.5rem;
}
/* one colour for everything in the footer, and no rule under the address */
.site-foot a {
  color: inherit;
  text-decoration: none;
  border-bottom: 0;
  transition: opacity .2s ease;
}
.site-foot a:hover { opacity: .62; }

/* ---------- thank-you page --------------------------------------------- */

.receipt {
  max-width: 620px;
  margin-inline: auto;
  text-align: center;
}
.receipt .steps {
  list-style: none;
  padding: 0;
  margin: clamp(2rem, 5vw, 3rem) 0 0;
  text-align: left;
  border-top: 1px solid var(--rule);
}
.receipt .steps li {
  padding: 2.25rem 0;
  border-bottom: 1px solid var(--rule);
}
.receipt .steps .label { display: block; margin-bottom: .8rem; }
.receipt .steps p { font-size: 0.9375rem; color: var(--ink-muted); margin: 0; }

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


/* ==========================================================================
   Mobile
   ========================================================================== */

@media (max-width: 720px) {

  /* --- type scale: bigger headlines on a small screen, not smaller ---
     h1 is capped by viewport width so EVERYDAY still fits on one line on a
     320px phone, where 3.5rem would overflow. */
  h1 { font-size: min(3.75rem, 16vw); }
  h2 { font-size: min(2.125rem, 9vw); }

  /* --- the header logo gives way before the button does --- */
  .wordmark img { height: 46px; }
  .btn-sm { font-size: 0.625rem; padding: 0.72rem 1.1rem; }


  /* --- the tagline row: keep the first two on one line --- */
  /* the labels inherit the body's 1.7 line-height, which is what opened up the
     gap between the two rows — pin it so the lines sit close together */
  .hero-tags {
    gap: 0.15rem 0.7rem;
    margin-top: clamp(1.75rem, 5vw, 2.5rem);
  }
  .hero-tags .label {
    letter-spacing: 0.14em;
    gap: 0.7rem;
    line-height: 1.35;
  }
  /* the row breaks 2 + 1 here, so the second item's bullet would dangle at the
     end of the first line with nothing after it */
  .hero-tags .label:nth-child(2)::after { content: none; }

  /* --- no rule between the section heading and the first value prop --- */
  .trio > div:first-child {
    border-top: 0;
    padding-top: 0;
  }

  /* --- sample pages and price cards scroll sideways instead of stacking ---
     Full-bleed: the negative margin cancels the wrap's gutter so cards can
     travel to the screen edge, and the matching padding keeps the first one
     aligned with the text above it. Cards are sized so the next one peeks in,
     which is what tells you the row scrolls. */
  .pages,
  .tiers {
    grid-template-columns: none;
    grid-auto-flow: column;
    grid-auto-columns: 76%;
    gap: 1rem;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scroll-snap-type: x mandatory;
    scroll-padding-left: var(--gutter);
    margin-inline: calc(var(--gutter) * -1);
    padding-inline: var(--gutter);
    scrollbar-width: none;
  }

  /* overflow-x: auto makes overflow-y compute to auto, so anything drawn
     outside a card gets clipped. These paddings are the room that the sheet
     shadows (below) and the Available now / Coming soon flags (above) need. */
  .pages  { padding-block: 0.25rem 2.25rem; }
  .tiers  { padding-block: 1rem 1.25rem; }

  .pages::-webkit-scrollbar,
  .tiers::-webkit-scrollbar { display: none; }

  .pages > *,
  .tiers > * { scroll-snap-align: start; }

  /* Keep the closing sentence whole on its own line, at any phone width.
     Chasing a max-width that breaks correctly from 320 to 430 is not
     achievable; making the sentence a block is. */
  .lede-tail { display: block; }

  /* --- recipe list collapses to 12 with the last three fading out --- */
  .index-more { display: block; }

  .index-grid.is-collapsed > li:nth-child(n+13) { display: none; }

  /* The fade has to be a mask on the list, not opacity on the items. The
     reveal keyframes end at opacity: 1 with fill-mode both, and an animation
     outranks a normal declaration in the cascade — so per-item opacity was
     being overwritten the moment the section animated in. A mask sits outside
     that fight, and gives a smooth fade instead of three steps. */
  .index-grid.is-collapsed {
    -webkit-mask-image: linear-gradient(to bottom, #000 64%, rgba(0, 0, 0, 0) 100%);
            mask-image: linear-gradient(to bottom, #000 64%, rgba(0, 0, 0, 0) 100%);
  }
  .index-grid.is-collapsed > li:nth-child(12) { border-bottom-color: transparent; }

  /* --- Miranda stacks: photo first, then the story --- */
  .about { grid-template-columns: 1fr; gap: 2rem; }
  .portraits { width: min(360px, 100%); }
  .about-copy p { max-width: none; }

  /* narrower cards need the button padding to give way before the label does */
  .tier { padding-inline: 1.25rem; }
  .tier .btn { padding-inline: 1.25rem; }
}

/* Very narrow phones (320px and similar). At the sizes above, HIGH PROTEIN and
   FAMILY FRIENDLY need ~318px and only have 272, so the tagline is tightened
   just here rather than shrinking it on every phone. */
@media (max-width: 360px) {
  /* The button won't shrink, so on a 320px screen the logo gives way further
     rather than letting the button hang off the edge. */
  .wordmark img { height: 38px; }
  .btn-sm {
    font-size: 0.5625rem;
    letter-spacing: 0.14em;
    padding: 0.65rem 0.9rem;
  }

  .hero-tags { gap: 0.3rem 0.4rem; }
  .hero-tags .label {
    font-size: 0.625rem;
    letter-spacing: 0.08em;
    gap: 0.4rem;
  }
}


/* ==========================================================================
   Waitlist dialog
   ========================================================================== */

.modal[hidden] { display: none; }

.modal {
  position: fixed;
  inset: 0;
  z-index: 50;
}

/* The scrolling lives here rather than on .modal, so the backdrop is not a
   child of a scroller. iOS gives a touch-scrolling element its own containing
   block, which pins a fixed backdrop to the scrolled area instead of the
   screen and leaves the page showing below it. */
.modal-scroll {
  position: absolute;
  inset: 0;
  overflow-y: auto;
  display: flex;
  padding: var(--gutter);
}

.modal-backdrop {
  /* covers .modal, which spans the whole viewport and is never resized, so the
     keyboard cannot shrink it */
  position: absolute;
  inset: 0;
  background: rgba(38, 34, 32, .72);
  animation: fadeIn .25s ease both;
}

/* focused on open so the dialog is announced; it is not a control, so it
   should not draw a focus ring */
.modal-card:focus { outline: none; }

.modal-card {
  position: relative;
  width: min(30rem, 100%);
  background: var(--paper);
  border: 1px solid var(--ink);
  padding: clamp(2rem, 5vw, 2.75rem);
  text-align: center;
  box-shadow: 0 24px 60px -24px rgba(38, 34, 32, .4);
  animation: modalIn .38s cubic-bezier(.22,.68,.15,1) both;
  /* auto margins rather than the flex centring properties: a centred flex item
     that outgrows its scroll container has its top clipped and unreachable */
  margin: auto;
}

@media (prefers-reduced-motion: reduce) {
  .modal-backdrop, .modal-card { animation: none; }
}

@keyframes fadeIn { from { opacity: 0 } to { opacity: 1 } }
@keyframes modalIn {
  from { opacity: 0; transform: translateY(14px) scale(.985); }
  to   { opacity: 1; transform: none; }
}

.modal-x {
  position: absolute;
  top: .5rem; right: .75rem;
  background: none;
  border: 0;
  font-size: 1.6rem;
  line-height: 1;
  color: var(--ink-label);
  cursor: pointer;
  padding: .25rem .4rem;
  transition: color .2s ease;
}
.modal-x:hover { color: var(--ink); }

.modal-card h3 {
  font-size: 1.75rem;
  margin: .6rem 0 .85rem;
}

.modal-copy {
  font-size: .9375rem;
  color: var(--ink-muted);
  margin: 0 auto 1.75rem;
  max-width: 34ch;
}

.modal-label {
  display: block;
  font-family: var(--sans);
  font-size: 0.6875rem;
  font-weight: 500;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--ink-label);
  text-align: left;
  margin-bottom: .5rem;
}

.modal-input {
  width: 100%;
  font-family: var(--serif);
  font-size: 1.0625rem;
  color: var(--ink);
  background: transparent;
  border: 0;
  border-bottom: 1px solid var(--rule);
  padding: .6rem 0;
  margin-bottom: 1.5rem;
  transition: border-color .2s ease;
}
.modal-input::placeholder { color: var(--rule); }
.modal-input:focus {
  outline: none;
  border-bottom-color: var(--green);
}

/* honeypot — off-screen rather than display:none, which some bots skip */
.modal-hp {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.modal-error {
  font-size: .8125rem;
  color: var(--ink);
  text-align: left;
  margin: -1rem 0 1rem;
}


/* ---------- sample recipe lightbox --------------------------------------- */

.lightbox[hidden] { display: none; }

.lightbox {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: grid;
  /* a definite row, so the page's max-height has something to resolve against
     and a tall recipe is scaled down rather than run off the bottom */
  grid-template-rows: minmax(0, 1fr);
  place-items: center;
  --lb-top: clamp(3.25rem, 7vw, 4rem);
  --lb-pad: clamp(1rem, 4vw, 2.5rem);
  padding: var(--lb-top) var(--lb-pad) var(--lb-pad);
}

.lightbox-backdrop {
  position: fixed;
  inset: 0;
  height: 100vh;
  height: 100lvh;
  background: rgba(38, 34, 32, .82);
  animation: fadeIn .25s ease both;
}

.lightbox-figure {
  position: relative;
  margin: 0;
  min-height: 0;
  max-height: 100%;
  animation: modalIn .32s cubic-bezier(.22,.68,.15,1) both;
}

.lightbox-figure img {
  display: block;
  /* measured against the viewport, not the figure: the figure has no height of
     its own, and a percentage there would leave the picture free to run off the
     bottom of a short window */
  max-height: calc(100vh - var(--lb-top) - var(--lb-pad));
  max-height: calc(100dvh - var(--lb-top) - var(--lb-pad));
  max-width: 100%;
  width: auto;
  height: auto;
  box-shadow: 0 30px 70px -30px rgba(0, 0, 0, .7);
}

/* the close control sits above the page rather than on it, so it never covers
   a corner of the recipe */
.lightbox-x {
  position: absolute;
  top: clamp(.75rem, 2.5vw, 1.25rem);
  right: clamp(.75rem, 2.5vw, 1.25rem);
  z-index: 1;
  width: 2.75rem;
  height: 2.75rem;
  display: grid;
  place-items: center;
  border: 0;
  background: transparent;
  color: var(--paper);
  font-size: 2rem;
  line-height: 1;
  cursor: pointer;
  opacity: .85;
  transition: opacity .2s ease;
}
.lightbox-x:hover { opacity: 1; }

@media (prefers-reduced-motion: reduce) {
  .lightbox-backdrop, .lightbox-figure { animation: none; }
}

/* only set once the script has wired the sheet up */
.sheet--zoomable { cursor: zoom-in; }

body.modal-open { overflow: hidden; }

/* a button that sits inside a sentence and reads as a link */
.linklike {
  background: none;
  border: 0;
  padding: 0;
  font: inherit;
  color: var(--ink);
  cursor: pointer;
  border-bottom: 1px solid var(--rule);
  transition: border-color .2s ease;
}
.linklike:hover { border-bottom-color: var(--ink); }
