/* ---------------------------------------------------------------
   home.css — the landing page at the site root.

   Three sections: the hero (wordmark, dog video, headline, waitlist
   form), one paragraph that darkens word by word as it is read, and
   the footer. Under all of it, once the hero has scrolled away, the
   waitlist form pinned to the foot of the screen.

   Layered on styles.css (tokens, hero, waitlist glass) and landing.css
   (.u-visually-hidden, .access-slot, the pinned bar's mechanics), so
   only what is genuinely new lives here.
   --------------------------------------------------------------- */

/* ---------------------------------------------------------------
   Wordmark

   styles.css draws the fixed wordmark inside a frosted pill and lifts
   the pill with a shadow once it is over the light page. Here it is
   the word alone: no fill, no blur, no shadow, in either state. The
   colour swap it does past the hero is kept, or the cream mark would
   vanish on the cream page.
   --------------------------------------------------------------- */

.site-nav--bare,
.site-nav--bare.is-past-hero {
  background: none;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  box-shadow: none;
  /* Enough around the word for a finger to land on. */
  padding: 10px 14px;
}

/* ---------------------------------------------------------------
   Hero
   --------------------------------------------------------------- */

.hero--v3 {
  /* svh, not vh: on iOS vh is the tallest viewport, so the form would
     start life hidden behind the browser chrome. */
  min-height: 100vh;
  min-height: 100svh;
  /* styles.css sits .hero-content on the floor of the section; here the
     whole block is centred and then weighted down. */
  justify-content: center;
}

/* The dog sits high in the frame, so an even split put the headline
   across its face. The extra padding sits on top, which drops the block
   by half of whatever the two differ by: 95px in a tall window, easing
   off as the window shortens. Both are capped on height as well as
   width — at their full size they pushed the form under the fold in a
   short one. */
.hero-content--v3 {
  padding-top: clamp(150px, 23vw, min(302px, 34vh));
  padding-bottom: clamp(84px, 12vw, min(112px, 13vh));
}

.hero--v3 .hero-title {
  font-size: var(--type-display);
  max-width: 14ch;
}

/* The subtitle is set as two lines, the same two on every screen:
   "Personalised wellbeing for your dog," and "with better ways to care
   for them." Each is its own block, so the break never moves with the
   width; the measure is loosened so it never forces an earlier one. */
.hero--v3 .hero-sub { max-width: none; }
.hero-sub__line { display: block; }

/* Everything the form says sits on the scale too. */
.waitlist-input { font-size: var(--type-body); }
.waitlist-submit,
.waitlist-status { font-size: var(--type-small); }

/* ---------------------------------------------------------------
   Waitlist field tap target

   The field's own box is only as tall as its line, so the top and
   bottom of the pill around it did not focus it — a 20px target, well
   under the 44px a touch device wants, on every tablet. Padding fills
   the pill instead. landing.css already handles this below 481px, where
   the pill wraps and the field takes its own horizontal padding, so
   this starts above that and leaves the wrapped layout alone.
   --------------------------------------------------------------- */

@media (min-width: 481px) {
  .hero-content--v3 .waitlist-input,
  .sticky-cta__slot .waitlist-input { padding: 12px 0; }
}

/* ---------------------------------------------------------------
   Phones

   Below 481px landing.css stacks the pill into a full-width field with
   a full-width button under it, 108px tall. At phone widths the pill
   the desktop gets still fits — a shade less padding either side of
   the button and the whole thing is 50px — so the stack is held back
   for the phones that genuinely cannot: below 371px the placeholder
   would no longer clear the button. The pinned bar takes the same
   rules: two rows at the foot of a phone screen would cover a third
   of it.

   --------------------------------------------------------------- */

@media (max-width: 480px) {
  .hero-content--v3 .access-slot,
  .sticky-cta__slot { width: min(340px, 100%); }
  .hero-content--v3 .waitlist-form,
  .sticky-cta__slot .waitlist-form {
    flex-wrap: nowrap;
    border-radius: 999px;
    padding: 5px 5px 5px 16px;
    gap: 6px;
  }
  .hero-content--v3 .waitlist-input,
  .sticky-cta__slot .waitlist-input { flex: 1 1 0; padding: 10px 0; }
  .hero-content--v3 .waitlist-submit,
  .sticky-cta__slot .waitlist-submit { flex: none; width: auto; padding: 11px 14px; }
}

@media (max-width: 370px) {
  .hero-content--v3 .waitlist-form,
  .sticky-cta__slot .waitlist-form { flex-wrap: wrap; border-radius: 24px; padding: 8px; gap: 6px; }
  .hero-content--v3 .waitlist-input,
  .sticky-cta__slot .waitlist-input { flex: 1 0 100%; padding: 8px 10px; }
  .hero-content--v3 .waitlist-submit,
  .sticky-cta__slot .waitlist-submit { flex: 1 0 100%; width: 100%; }
}

/* ---------------------------------------------------------------
   The story — one paragraph, read word by word

   home.js wraps each word in a span and lights them in order as the
   paragraph climbs the screen. Unlit words are the ink at a third
   strength, like the line still to be typed; lit ones are the ink.
   With no script there are no spans and the paragraph is plain ink.
   --------------------------------------------------------------- */

.story {
  width: 100%;
  max-width: 1200px;
  margin: 0 auto;
  padding: clamp(96px, 18vw, 224px) clamp(20px, 5vw, 64px);
}

/* Held to 65% of the viewport, inside the section's own gutters. */
.story__copy {
  width: min(100%, 65vw);
  margin: 0 auto;
  font-family: var(--body-font);
  font-size: var(--type-lead-lg);
  font-weight: 500;
  line-height: 1.5;
  letter-spacing: -0.02em;
  color: var(--ink);
}

.story__word {
  color: rgba(50, 48, 49, 0.34);
  transition: color 260ms var(--ease);
}
.story__word.is-lit { color: var(--ink); }

/* ---------------------------------------------------------------
   Product story — one phone, three chapters

   The section is four screens tall. Its stage sticks to the top of
   the viewport for the first three of them, while the three trigger
   blocks that follow it in flow scroll past underneath; home.js sets
   data-showcase-active from whichever trigger is in view. The stage
   then scrolls away with the fourth screen, so the footer arrives the
   way any section does.

   The phone never moves: it is one box, laid out once, and only what
   is inside its clipped screen changes. The three titles share one
   grid cell, as do the three lines of copy, so the columns are sized
   by the tallest and swapping never reflows anything.
   --------------------------------------------------------------- */

.showcase {
  position: relative;
  width: 100%;
}

.showcase__stage {
  position: sticky;
  top: 0;
  height: 100vh;
  height: 100svh;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  align-items: center;
  column-gap: clamp(32px, 5vw, 72px);
  padding: 0 clamp(20px, 8.4vw, 160px);
  overflow: hidden;
}

.showcase__trigger {
  height: 100vh;
  height: 100svh;
}

/* The three texts share one cell, sized by the tallest. Each is in
   one of three places: waiting below (the default), in place
   (.is-active) or gone above (.is-past). home.js moves a text between
   them once the still inside the phone is halfway in, and the change
   itself plays on a clock rather than on the scroll, so it reads the
   same at any scroll speed: the leaving text rises a short way and
   fades out, and a beat later the arriving text rises into place and
   fades in. Scrolling back runs it the other way, down and out, down
   and in. Without a script only the first text shows. */
.showcase__col {
  display: grid;
  align-items: center;
}
.showcase__col > * {
  grid-area: 1 / 1;
  opacity: 0;
  transform: translateY(40px);
  transition: opacity 520ms var(--ease), transform 520ms var(--ease);
  will-change: transform, opacity;
}
.showcase__col > .is-active {
  opacity: 1;
  transform: none;
  transition-delay: 160ms;
}
.showcase__col > .is-past { transform: translateY(-40px); }

.showcase__title {
  font-family: var(--body-font);
  font-size: var(--type-title);
  font-weight: var(--body-weight);
  line-height: 1.3;
  letter-spacing: -0.02em;
  color: var(--ink);
  max-width: 12ch;
  text-wrap: balance;
}

.showcase__col--copy { justify-self: start; }
.showcase__copy {
  font-family: var(--body-font);
  font-size: var(--type-lead);
  font-weight: var(--body-weight);
  line-height: 1.35;
  letter-spacing: -0.02em;
  color: var(--ink);
  max-width: 20ch;
  text-wrap: pretty;
}

/* The phone: a tall rounded box, half as wide as it is high, with a
   hairline edge. Its height follows the viewport so the whole stage
   fits on one screen. */
.showcase__phone {
  /* 78% of the screen, as drawn, but never within 100px of its top or
     bottom, so the pinned form under it has clear room on a short
     window. */
  --phone-h: clamp(440px, min(78vh, 100vh - 200px), 720px);
  position: relative;
  height: var(--phone-h);
  aspect-ratio: 1 / 2;
  border-radius: calc(var(--phone-h) * 0.063);
  overflow: hidden;
  background: var(--panel);
  /* Keeps the rounded clip honest in Safari while children animate. */
  isolation: isolate;
  transform: translateZ(0);
}
.showcase__phone::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  box-shadow: inset 0 0 0 1px rgba(50, 48, 49, 0.18);
  pointer-events: none;
  z-index: 2;
}

.showcase__screen {
  position: absolute;
  inset: 0;
}

/* The three chapters stack in the screen; the active one shows. The
   still sits under the film and both fill the screen the same way, so
   the film arrives over exactly the frame the still was showing. The
   film stays invisible until it is genuinely running. */
/* The chapters stack in order inside the screen, later ones on top,
   and each one after the first waits below the screen's bottom edge.
   home.js slides it up into place with the scroll itself, through the
   last stretch of the chapter before it, so it covers the old still
   like a card and is fully in exactly as its chapter takes over.
   Nothing fades: the phone clips the move, and the frame stays put.
   With no script only the first chapter shows. */
.showcase__slide {
  position: absolute;
  inset: 0;
  transform: translateY(100%);
  will-change: transform;
  /* Rounded across the top at the phone's own radius, so the still
     reads as a card with the phone's corners as it slides up over the
     one before. */
  border-radius: calc(var(--phone-h) * 0.063) calc(var(--phone-h) * 0.063) 0 0;
  overflow: hidden;
}
.showcase__slide:first-child { transform: none; }

.showcase__still,
.showcase__film {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 50%;
  display: block;
}
.showcase__film {
  opacity: 0;
  pointer-events: none;
  transition: opacity 200ms var(--ease);
}

/* The films are 9:16 and the screen is 1:2, so the sides are cropped.
   The third film's captions sit left of centre and its widest line,
   "More snacks", runs from 10.9% to 95.0% across; the default centred
   crop clipped its right edge. The window is moved so the line has
   the same clearance on both sides. The still takes the same crop, so
   nothing shifts when the film comes in over it. */
[data-showcase-slide="2"] .showcase__still,
[data-showcase-slide="2"] .showcase__film { object-position: 77.5% 50%; }
.showcase__film.is-playing { opacity: 1; }

/* Stacked for a phone: title, phone, copy, all centred, under the
   fixed wordmark and above the pinned form. The phone drops to just
   under half the screen so the three fit on one. */
@media (max-width: 900px) {
  .showcase__stage {
    grid-template-columns: 1fr;
    grid-template-rows: auto auto auto;
    align-content: center;
    justify-items: center;
    row-gap: clamp(24px, 5vh, 48px);
    padding: 72px clamp(20px, 5vw, 64px) 110px;
    text-align: center;
  }
  .showcase__col--copy { justify-self: center; }
  .showcase__title { max-width: 14ch; }
  .showcase__copy { max-width: 26ch; }
  .showcase__phone { --phone-h: clamp(300px, 47vh, 440px); }
}

@media (prefers-reduced-motion: reduce) {
  .showcase__film,
  .showcase__col > * { transition: none; }
}

/* ---------------------------------------------------------------
   Footer

   The tagline and the logo on one side, the links on the other. On a
   phone it is one centred column: tagline, logo, links, with the
   pinned form beneath. The bottom padding leaves room for that form
   at every width, so it never covers the last link.
   --------------------------------------------------------------- */

.foot {
  width: 100%;
  max-width: 1200px;
  margin: 0 auto;
  padding: clamp(72px, 12vw, 120px) clamp(20px, 5vw, 64px) calc(clamp(72px, 12vw, 120px) + 96px);
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: clamp(48px, 10vw, 80px);
}

.foot__brand {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 24px;
}

.foot__tagline {
  font-family: var(--body-font);
  font-size: var(--type-lead);
  font-weight: var(--body-weight);
  line-height: 1.5;
  letter-spacing: -0.02em;
  color: var(--ink);
  max-width: 16ch;
  text-wrap: balance;
}

.foot__logo {
  width: clamp(110px, 14vw, 132px);
  height: auto;
}

.foot__links {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
}
.foot__links a {
  font-family: var(--body-font);
  font-size: var(--type-body);
  line-height: 1.35;
  color: rgba(50, 48, 49, 0.72);
  transition: color 120ms var(--ease);
}
.foot__links a:hover { color: var(--ink); }

@media (min-width: 901px) {
  /* Both columns sit on the same baseline: the logo and the line end
     level with the last link. */
  .foot {
    flex-direction: row;
    justify-content: space-between;
    align-items: flex-end;
    text-align: left;
    padding-top: clamp(96px, 10vw, 128px);
  }
  .foot__brand { align-items: flex-start; gap: 28px; }
  .foot__tagline { max-width: none; }
  .foot__links { align-items: flex-end; text-align: right; gap: 4px; }
}

/* ---------------------------------------------------------------
   The pinned form

   landing.css draws .sticky-cta as a phone-only bar that fades in once
   the hero has scrolled away (initStickyCta() in landing.js). Here it
   is on at every width, and it holds the waitlist form itself rather
   than a button back up to the hero's: the field and the button leave
   the hero and stay at the foot of the screen for the rest of the
   page. The glass takes a heavier fill and shadow than the hero's, so
   it sits on the cream page rather than dissolving into it.
   --------------------------------------------------------------- */

.sticky-cta--form {
  display: block;
  padding: 24px 16px calc(16px + env(safe-area-inset-bottom));
  /* landing.css fades the bar up from the page with a cream gradient,
     which would sit between the pill and whatever scrolls under it and
     leave its blur nothing to frost. The pill is the only thing here. */
  background: none;
}

.sticky-cta__slot {
  margin: 0 auto;
  width: min(440px, 100%);
}

/* The same frosted glass as the hero's pill, over whatever scrolls
   under it: a faint tint of the ink instead of a white fill, a blur
   behind it, a thin rim of the ink so the edge reads on the cream
   page, and the white button the hero's has. */
.sticky-cta--form .waitlist-form {
  background: rgba(50, 48, 49, 0.06);
  backdrop-filter: blur(18px) saturate(140%);
  -webkit-backdrop-filter: blur(18px) saturate(140%);
  box-shadow: 0 14px 40px rgba(50, 48, 49, 0.14);
}

/* Neither pill carries a rim: the glass edge is the fill and the
   shadow alone. */
.hero-content--v3 .waitlist-form,
.sticky-cta--form .waitlist-form { border: 0; }
.sticky-cta--form .waitlist-submit {
  background: #FFFFFF;
  color: var(--ink);
  box-shadow: 0 1px 2px rgba(50, 48, 49, 0.10);
}
