/* Table — shared styles for the public site.
   Colours and type are lifted straight from the app (AppTheme.swift and
   Typography.swift), so the site and the product look like the same thing.
   Tweak freely — nothing here is generated. */

:root {
  --bg:        #F6F1EB;  /* AppTheme.background */
  --card:      #FEFDF9;  /* AppTheme.card */
  --ink:       #211E1C;  /* AppTheme.textPrimary */
  --muted:     #8C847D;  /* AppTheme.textSecondary */
  --warm:      #855E47;  /* AppTheme.textWarm */
  --sienna:    #B8573B;  /* AppTheme.accent / sienna */
  --shell:     #F5E1D5;  /* AppTheme.shell */
  --sand:      #DCB495;
  --rule:      #EAE0D5;
  --radius:    16px;

  /* The wide grid. The fan's stage and the feature cards below it both measure
     from this one number, so the phones and the cards sit on the same column
     and stay on it if the number ever changes. Body copy deliberately does NOT
     use it — prose at 900px is unpleasant to read, which is why .wrap stays
     narrow and only .wrap-wide opens up. */
  --grid:      900px;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: Lora, Georgia, "Times New Roman", serif;
  font-size: 17px;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
}

.wrap { max-width: 720px; margin: 0 auto; padding: 0 22px; }

/* +44px is the two 22px gutters, so the CONTENT lands at exactly --grid and
   lines up with .fan-stage, which has no padding of its own. */
.wrap-wide { max-width: calc(var(--grid) + 44px); }

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

.site-header {
  padding: 26px 0;
  border-bottom: 1px solid var(--rule);
}
.site-header .wrap {
  display: flex; align-items: center; gap: 18px; flex-wrap: wrap;
}
.wordmark {
  font-size: 22px; font-weight: 600; letter-spacing: -.01em;
  color: var(--ink); text-decoration: none;
  display: inline-flex; align-items: center; gap: 10px;
}
.wordmark-icon {
  width: 30px; height: 30px; border-radius: 7px; display: block;
}
.site-nav { margin-left: auto; display: flex; gap: 20px; }
.site-nav a {
  font-size: 14.5px; color: var(--warm); text-decoration: none;
}
.site-nav a:hover { color: var(--sienna); text-decoration: underline; }

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

/* Generous above so the headline sits nearer the optical middle of the screen,
   tighter below so the deck can come up to meet it. */
.hero { padding: 122px 0 40px; text-align: center; }
.hero h1 {
  font-size: clamp(38px, 7vw, 60px);
  line-height: 1.08; letter-spacing: -.025em;
  margin: 0 0 18px; text-wrap: balance; font-weight: 600;
}
/* Wide enough that the lede sets as two balanced lines rather than four short
   ones. `balance` then does the tidying, so the break lands somewhere sensible
   instead of leaving a single orphaned word. */
.hero .lede {
  font-size: 20px; color: var(--warm); max-width: 54ch;
  margin: 0 auto 32px; text-wrap: balance;
}

/* Apple's badge is supplied artwork and must not be redrawn or recoloured.
   The only thing we control is the space around it — their guidelines ask for
   clear space of at least 10% of the badge height on every side. */
.appstore-badge {
  display: inline-block; padding: 6px; line-height: 0;
  border-radius: 10px;
}
.appstore-badge img { width: 180px; height: auto; display: block; }
.appstore-badge:focus-visible {
  outline: 2px solid var(--sienna); outline-offset: 2px;
}

/* ------------------------------------------------------------- the fan ---
   Five phones stacked like a hand of cards, opening out as you scroll past.
   JS sets --p from 0 to 1 on .fan-stage; every card derives its own position
   from that single number, so there is one source of truth for the motion and
   nothing to keep in sync.
   --i is the card's distance from the centre (-2 to 2) and drives both the
   sideways travel and the tilt. --y lifts the outer cards so the row reads as
   an arc rather than a straight line. */

/* The section is taller than the screen so the stage can stick while you scroll
   through it. Most of the opening now happens on the APPROACH, before the
   section pins, so this only needs enough extra height to hold the finished fan
   on screen for a beat rather than to drive the whole animation. Making it much
   taller just adds scrolling with nothing happening.
   ⚠️ No overflow on .fan — an overflow value other than visible on an ancestor
   silently kills position: sticky. It goes on .fan-inner instead. */
/* The negative margin is the dial for how close the deck sits to the badge.
   It exists because .fan-inner is a full screen tall and centres the stage
   inside it, which leaves a lot of empty space above the phones before the
   section pins. Pulling the section up eats that space without disturbing the
   centring once it IS pinned, which is where it belongs.
   More negative = phones higher. */
.fan { position: relative; height: 135vh; margin-top: -150px; }

.fan-inner {
  position: sticky; top: 0;
  height: 100vh;
  display: grid; place-items: center;
  overflow: hidden;
}

.fan-stage {
  --p: 0;             /* scroll progress 0 to 1, set by JS */
  --spread: 165px;    /* sideways travel per step out from centre */
  --tilt: 7deg;       /* rotation per step out from centre */
  position: relative;
  height: 520px;      /* must clear the tallest card: 240 x 4816/2335 = 495 */
  width: 100%;
  max-width: var(--grid);
  margin: 0 auto;
}

/* The captures are Bezel exports: the device frame, its corners and its glass
   edge are all IN the PNG, on transparency. So this element draws nothing of
   its own — no background, no border, no radius. Anything drawn here would
   appear as a rectangle sticking out from behind the phone.

   aspect-ratio is the real trimmed frame (2335 x 4816), not a nominal 9:19.5,
   so the box is exactly the picture and there is no dead space to letterbox.
   Regenerate the images and this number changes with them.

   The lift comes from drop-shadow rather than box-shadow because the artwork
   is a phone silhouette, not a rectangle — box-shadow would trace the corners
   of the element and cast a hard oblong behind the rounded frame. */
.shot {
  position: absolute;
  top: 0; left: 50%;
  width: 240px; margin-left: -120px;
  aspect-ratio: 2335 / 4816;
  filter: drop-shadow(0 14px 26px rgba(70, 45, 30, .20));
  /* The 7px and 1deg are the resting offsets: at --p:0 the cards still sit as a
     visible deck rather than one card hiding four others, so there is something
     to open. Everything beyond that is driven by --p. */
  transform:
    translateX(calc(var(--i) * (7px + var(--spread) * var(--p))))
    translateY(calc(var(--y, 0px) * var(--p)))
    rotate(calc(var(--i) * (1deg + var(--tilt) * var(--p))))
    scale(calc(0.94 + 0.06 * var(--p)));
  transform-origin: 50% 92%;
  will-change: transform;
}

/* Centre card on top, each step outwards sits behind the one before it.
   Set per card in the HTML with --z, so the stacking is stated where the
   position is rather than inferred from a selector matching the style string. */
.shot { z-index: var(--z, 1); }

/* contain, not cover: the box already matches the picture, and contain means a
   rounding error shows as an invisible hairline of transparency rather than
   shaving a slice off the top and bottom of the device frame. */
.shot img {
  width: 100%; height: 100%; object-fit: contain;
  display: block;
}

@media (max-width: 900px) {
  .fan { height: 130vh; margin-top: -110px; }
  .fan-stage { --spread: 124px; --tilt: 6deg; height: 450px; }
  .shot { width: 206px; margin-left: -103px; }
}
@media (max-width: 620px) {
  .hero { padding: 68px 0 28px; }
  .fan { height: 125vh; margin-top: -70px; }
  .fan-stage { --spread: 64px; --tilt: 5deg; height: 365px; }
  /* No border-radius here any more — see .shot. The frame is in the artwork. */
  .shot { width: 156px; margin-left: -78px; }
}

/* Someone who has asked for less motion gets the finished arrangement
   immediately, and the section collapses to its natural height so there is no
   runway of empty scrolling to wade through for an effect they will not see. */
@media (prefers-reduced-motion: reduce) {
  /* margin-top goes back to 0 as well as the height: the negative pull only
     makes sense against a full-screen sticky area, and left in place here it
     would drag the static deck up over the download badge. */
  .fan { height: auto; margin-top: 0; }
  .fan-inner { position: static; height: auto; padding: 30px 0 54px; }
  .fan-stage { --p: 1 !important; }
  .shot { will-change: auto; }
}

/* --------------------------------------------------------------- content */

section { padding: 44px 0; }
h2 {
  font-size: 27px; font-weight: 600; letter-spacing: -.015em;
  margin: 0 0 14px; text-wrap: balance;
}
h3 { font-size: 19px; font-weight: 600; margin: 30px 0 8px; }
p  { margin: 0 0 16px; }
a  { color: var(--sienna); }

hr {
  border: 0; border-top: 1px solid var(--rule); margin: 34px 0;
}

ul, ol { margin: 0 0 16px; padding-left: 24px; }
li { margin-bottom: 8px; }

/* The three-up feature row on the home page. */
.features {
  display: grid; gap: 18px;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  padding: 10px 0 30px;
}
.feature {
  background: var(--card); border: 1px solid var(--rule);
  border-radius: var(--radius); padding: 22px 24px 24px;
}
.feature h3 {
  margin: 0 0 10px;
  font-size: 21px; line-height: 1.25; letter-spacing: -.015em;
}
.feature p  { margin: 0; font-size: 15.5px; color: var(--warm); }

/* Illustration slot.
   FIXED HEIGHT rather than a fixed aspect ratio, because the three pieces of
   artwork are not the same shape: Recipes and Apron are landscape (3:2) and
   Pantry is portrait (2:3). Sizing by height means all three render the same
   height and vary in width, so the row still reads as a set and the headings
   below stay on a common baseline. An aspect-ratio box would instead have
   letterboxed the portrait one into a thin strip.
   No background fill: the PNGs carry transparency, so a tinted box would show
   as a hard rectangle behind a soft illustration. They sit on the card. */
/* The bottom margin is the gap between a drawing and its heading. It is
   deliberately much larger than the heading-to-body gap below it, so each card
   reads as picture / then a block of text, rather than three evenly spaced
   things with no grouping. */
.feature-art {
  height: 165px;
  margin: -2px 0 32px;
  display: grid; place-items: center;
}
/* --art-scale is an OPTICAL correction, not a layout one. The slot is a fixed
   165px for every card so the three headings stay on the same line; this only
   changes how much of that slot a given drawing fills.

   It exists because matching heights does not make drawings match in weight.
   The envelope is a single solid pale mass that fills its whole bounding box,
   while the recipe box and the shelf carryempty space inside their outlines, so at
   an identical height the envelope reads as much the biggest of the three.
   Scale it down until the three look equal, not until they measure equal. */
.feature-art img {
  height: calc(100% * var(--art-scale, 1));
  width: auto; max-width: 100%;
  object-fit: contain;
  display: block;
}

/* Sign-off under the features. Deliberately quiet — it is an attribution note,
   not a pitch, so the body text sits near footer size rather than body size. */
.colophon { padding: 26px 0 40px; text-align: center; }
.colophon h2 { font-size: 19px; margin: 0 0 6px; }
.colophon p {
  font-size: 14px; color: var(--muted); margin: 0 auto; max-width: 46ch;
}

/* Used on the legal pages for the "last updated" line. */
.stamp {
  display: inline-block; background: var(--shell); color: var(--sienna);
  font-size: 13.5px; padding: 4px 12px; border-radius: 999px;
  margin-bottom: 8px;
}

/* Contact block on the support page. */
.contact {
  background: var(--card); border: 1px solid var(--rule);
  border-left: 3px solid var(--sienna);
  border-radius: 0 var(--radius) var(--radius) 0;
  padding: 22px 26px; margin: 0 0 24px;
}
.contact p:last-child { margin-bottom: 0; }

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

.site-footer {
  border-top: 1px solid var(--rule); margin-top: 60px;
  padding: 30px 0 60px; font-size: 14.5px; color: var(--muted);
}
.site-footer .wrap { display: flex; gap: 20px; flex-wrap: wrap; }
.site-footer a { color: var(--warm); text-decoration: none; }
.site-footer a:hover { text-decoration: underline; }
.site-footer .spacer { margin-left: auto; }

/* Long legal pages read better a little narrower and a little tighter. */
.legal { padding: 46px 0 20px; }
.legal h1 { font-size: 36px; letter-spacing: -.02em; margin: 0 0 6px; font-weight: 600; }
.legal h2 { font-size: 22px; margin: 36px 0 10px; }
.legal ul { padding-left: 22px; }
.legal li { margin-bottom: 6px; }

@media (max-width: 560px) {
  body { font-size: 16.5px; }
  .hero { padding: 54px 0 44px; }
  .site-nav { width: 100%; margin-left: 0; }
}
