/* Styles for the post-launch landing page (launch.html).
 *
 * A second file rather than additions to styles.css: the waitlist page has to
 * keep working until the day this replaces it, and one stylesheet serving two
 * pages with different jobs is how both end up compromised. Tokens come from
 * styles.css, loaded first — this adds only what the new page needs.
 *
 * The page has one visual idea and repeats it: the grip, the thing the app is
 * about, is on screen and moving. A landing page for an app whose whole pitch
 * is "watch it shrink" that shows only static screenshots is arguing for
 * something it refuses to demonstrate.
 *
 * The device frame is Apple's own bezel artwork from their Design Resources,
 * not a drawing of one — their guidelines reserve product imagery for their
 * supplied files, and a hand-built frame dates the day the next model ships. */

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

.wrap {
  width: min(1120px, 100% - 40px);
  margin-inline: auto;
}

.section {
  position: relative;
  padding-block: clamp(88px, 13vw, 168px);
}

.section--dark {
  background: var(--deep-teal);
  color: #fff;
  overflow: hidden;
}

.section--tint {
  background:
    radial-gradient(120% 80% at 50% 0%, #fff 0%, transparent 60%),
    linear-gradient(180deg, var(--off-white) 0%, var(--mint-soft) 100%);
}

.section__head {
  text-align: center;
  max-width: 22ch;
  margin: 0 auto clamp(56px, 8vw, 96px);
}

.section__head--wide { max-width: 32ch; }

.section__head h2 {
  font-size: clamp(34px, 6vw, 62px);
  line-height: 1.04;
  letter-spacing: -0.038em;
  font-weight: 650;
  color: var(--deep-teal);
  margin: 0 0 18px;
  text-wrap: balance;
}

.section--dark .section__head h2 { color: #fff; }

.section__head p {
  font-size: clamp(17px, 2.2vw, 21px);
  line-height: 1.5;
  letter-spacing: -0.01em;
  color: var(--text-muted);
  margin: 0 auto;
  max-width: 36ch;
  text-wrap: pretty;
}

.section--dark .section__head p { color: var(--mint); }

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

.lhero {
  position: relative;
  padding-block: clamp(56px, 9vw, 120px) clamp(56px, 9vw, 112px);
  overflow: hidden;
}

/* A wash of brand colour behind the whole hero, so the fold is not flat white
 * before the first screenshot loads. */
.lhero::before {
  content: "";
  position: absolute;
  inset: -20% -10% auto;
  height: 140%;
  background:
    radial-gradient(46% 40% at 78% 22%, var(--mint-soft) 0%, transparent 62%),
    radial-gradient(38% 34% at 12% 68%, #e9f6ef 0%, transparent 60%);
  z-index: -1;
}

.lhero__grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: clamp(44px, 7vw, 72px);
  align-items: center;
}

@media (min-width: 940px) {
  .lhero__grid { grid-template-columns: 1.04fr 0.96fr; }
}

.lhero h1 {
  font-size: clamp(46px, 8.6vw, 92px);
  line-height: 0.96;
  letter-spacing: -0.046em;
  font-weight: 700;
  color: var(--deep-teal);
  margin: 0 0 22px;
  text-wrap: balance;
}

/* The gradient line.
 *
 * background-clip: text paints the text through the background box, and that
 * box stops at the line box — so with line-height under 1 the descender of a
 * "y" or "p" falls outside it and is cut off. Measured at 92px/0.96: the box
 * is 88.3px for a 92px em, leaving the descender about 2px short.
 *
 * Fixed by giving the box room rather than by opening up the line-height,
 * which would pull the two lines of the headline apart. The padding grows the
 * background, the negative margin takes the space back out of the layout, so
 * nothing below it moves. */
.lhero h1 span {
  display: block;
  padding-bottom: 0.12em;
  margin-bottom: -0.12em;
  background: linear-gradient(100deg, var(--petrol) 0%, #1f9c86 100%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.lhero__sub {
  font-size: clamp(17px, 2.3vw, 21px);
  line-height: 1.5;
  letter-spacing: -0.011em;
  color: var(--text-muted);
  max-width: 40ch;
  margin: 0 0 36px;
  text-wrap: pretty;
}

/* ---- store badges ----------------------------------------------------- */

/* Both stores publish rules for these, and they happen to agree on the two
 * that matter:
 *   - minimum clear space around the badge = one quarter of its height
 *   - Apple's minimum height on screen is 40px
 *   - neither may be recoloured, redrawn or stretched
 *
 * At 54px high that means 13.5px of clear space, so the 14px gap satisfies it
 * horizontally, and the 36px above plus 18px below do vertically. Below 420px
 * the badges drop to 46px, still over Apple's floor, and 14px still clears the
 * 11.5px required there.
 *
 * The two files have different aspect ratios (Apple 2.99, Google 3.37), so
 * Google's comes out about 13% wider at the same height. Matching HEIGHT is
 * the correct alignment — matching width would mean scaling one of them out of
 * proportion, which both sets of guidelines forbid.
 *
 * Google's PNG carries its own thin grey border as part of the artwork, so it
 * must not be given a border-radius or a background of its own: that would
 * clip or double the frame Google drew. */
.badges {
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  align-items: center;
}

.badges a {
  display: inline-flex;
  /* No radius or background on the link itself — see the note above. The
   * artwork already has its own shape. */
  transition: transform 0.28s var(--ease), opacity 0.28s var(--ease);
}

.badges a:hover { transform: translateY(-2px); opacity: 0.86; }

/* Offset well clear of the badge, so the focus ring never sits inside the
 * required clear space and reads as part of the artwork. */
.badges a:focus-visible { outline: 2px solid var(--petrol); outline-offset: 6px; }

.badges img { display: block; height: 54px; width: auto; }

@media (max-width: 420px) {
  .badges img { height: 46px; }
}

.badges__note {
  margin: 18px 0 0;
  font-size: 14.5px;
  letter-spacing: -0.006em;
  color: var(--text-muted);
}

/* ---- the grip, as a live thing --------------------------------------- */

/* The centrepiece. A ring that drains from 100% to 0 as the visitor scrolls
 * past it, with the number counting down in step — the app's core mechanic,
 * shown rather than described.
 *
 * Driven by one custom property (--p, 0 to 100) that the script sets. Both the
 * ring and the number read from it, so they can never disagree. */
.grip {
  --p: 100;
  position: relative;
  width: min(340px, 74vw);
  aspect-ratio: 1;
  margin-inline: auto;
  display: grid;
  place-items: center;
}

.grip__ring {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: conic-gradient(
    var(--petrol) calc(var(--p) * 1%),
    rgba(255, 255, 255, 0.10) 0
  );
  mask: radial-gradient(farthest-side, transparent calc(100% - 14px), #000 calc(100% - 13px));
  -webkit-mask: radial-gradient(farthest-side, transparent calc(100% - 14px), #000 calc(100% - 13px));
  transition: background 0.1s linear;
}

/* The orb itself. Shrinks with the number, the way it does in the app. */
.grip__orb {
  width: calc(34% + var(--p) * 0.30%);
  aspect-ratio: 1;
  border-radius: 50%;
  background: radial-gradient(circle at 34% 30%, #1e7d78 0%, #104a4c 52%, #0a2f30 100%);
  box-shadow: 0 18px 50px -12px rgba(0, 0, 0, 0.45);
  display: grid;
  place-items: center;
  transition: width 0.25s var(--ease);
}

.grip__num {
  font-size: clamp(38px, 7vw, 62px);
  font-weight: 660;
  letter-spacing: -0.04em;
  line-height: 1;
  color: #fff;
  font-variant-numeric: tabular-nums;
}

.grip__num sup {
  font-size: 0.42em;
  font-weight: 500;
  vertical-align: super;
  margin-left: 2px;
  opacity: 0.72;
}

.grip__label {
  margin-top: 8px;
  font-size: 11.5px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--mint);
  opacity: 0.75;
}

.grip__caption {
  text-align: center;
  margin: 34px auto 0;
  max-width: 30ch;
  font-size: clamp(16px, 2vw, 19px);
  line-height: 1.55;
  color: var(--mint);
}

/* ---- phone ------------------------------------------------------------ */

/* Named .device, not .phone, on purpose: styles.css already defines .phone for
 * the waitlist page — 260x540 with a dark background and its own radius — and
 * it loads first. Overriding only some of those properties left the old drawn
 * box sitting behind this one, visible around the edges of the real bezel.
 * A separate name is the fix that does not touch the page still in production.
 *
 * The frame is Apple's own bezel image, from their Design Resources
 * (Bezel, iPhone 17, black, portrait). Their guidelines require their supplied
 * artwork rather than a drawing of one, which is also why the previous CSS
 * version of this went — a hand-built frame is both a licensing question and
 * dated the day the next model ships.
 *
 * The PNG is transparent everywhere except the device edge itself, so the
 * screenshot sits BEHIND it and shows through. The screen window was measured
 * off the alpha channel of the original 1350x2760 file:
 *   x 72..1277, y 69..2690  ->  5.33% / 2.50% / 89.33% / 95.00%
 * Those percentages are what keep the screenshot registered to the frame at
 * every size, since both scale together. */
.device {
  position: relative;
  width: min(300px, 74vw);
  margin-inline: auto;
  aspect-ratio: 1350 / 2760;
}

/* The screenshot, behind the bezel. Its corners are rounded to match the
 * device so nothing square peeks out at the edge of the glass. */
.device__screen {
  position: absolute;
  left: 5.33%;
  top: 2.50%;
  width: 89.33%;
  height: 95.00%;
  overflow: hidden;
  border-radius: 11.5% / 5.6%;
  background: var(--off-white);
}

.device__screen img { display: block; width: 100%; height: 100%; object-fit: cover; }

/* The bezel on top. pointer-events off so it never eats a tap meant for
 * something beneath it. */
.device__frame {
  position: relative;
  display: block;
  width: 100%;
  height: auto;
  z-index: 2;
  pointer-events: none;
  filter: drop-shadow(0 24px 46px rgba(14, 46, 46, 0.28));
}

.lhero__device,
.frow__media {
  position: relative;
  display: grid;
  place-items: center;
}

.lhero__device::before,
.frow__media::before {
  content: "";
  position: absolute;
  width: 112%;
  aspect-ratio: 1;
  background: radial-gradient(circle, var(--mint-soft) 0%, transparent 66%);
  opacity: 0.85;
  z-index: -1;
}

/* ---- feature rows ----------------------------------------------------- */

.frow {
  display: grid;
  grid-template-columns: 1fr;
  gap: clamp(40px, 6vw, 80px);
  align-items: center;
}

.frow + .frow { margin-top: clamp(96px, 14vw, 168px); }

@media (min-width: 880px) {
  .frow { grid-template-columns: 1fr 1fr; }
  .frow--flip .frow__media { order: -1; }
}

.frow__copy h3 {
  font-size: clamp(28px, 4.6vw, 46px);
  line-height: 1.08;
  letter-spacing: -0.035em;
  font-weight: 650;
  color: var(--deep-teal);
  margin: 14px 0 16px;
  text-wrap: balance;
}

.frow__copy p {
  font-size: clamp(16.5px, 2vw, 19px);
  line-height: 1.55;
  letter-spacing: -0.008em;
  color: var(--text-muted);
  margin: 0;
  max-width: 38ch;
  text-wrap: pretty;
}

/* ---- counting numbers ------------------------------------------------- */

.stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: clamp(20px, 4vw, 48px);
  text-align: center;
}

.stat__num {
  font-size: clamp(44px, 8vw, 76px);
  font-weight: 680;
  letter-spacing: -0.045em;
  line-height: 1;
  color: #fff;
  font-variant-numeric: tabular-nums;
}

.stat__label {
  margin-top: 12px;
  font-size: 15.5px;
  line-height: 1.5;
  color: var(--mint);
  opacity: 0.86;
}

.stats__note {
  margin: clamp(36px, 5vw, 56px) auto 0;
  max-width: 44ch;
  text-align: center;
  font-size: 14px;
  line-height: 1.6;
  color: rgba(255, 255, 255, 0.55);
}

/* ---- cards ------------------------------------------------------------ */

.cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 16px;
}

.card {
  background: #fff;
  border-radius: 26px;
  padding: 32px 28px;
  box-shadow:
    0 1px 2px rgba(14, 46, 46, 0.04),
    0 8px 24px -12px rgba(14, 46, 46, 0.10);
  transition: transform 0.3s var(--ease), box-shadow 0.3s var(--ease);
}

.card:hover {
  transform: translateY(-3px);
  box-shadow:
    0 1px 2px rgba(14, 46, 46, 0.05),
    0 16px 40px -16px rgba(14, 46, 46, 0.16);
}

.card h4 {
  font-size: 18.5px;
  line-height: 1.25;
  letter-spacing: -0.02em;
  font-weight: 620;
  color: var(--deep-teal);
  margin: 18px 0 9px;
  text-wrap: balance;
}

.card p {
  font-size: 15.5px;
  line-height: 1.6;
  letter-spacing: -0.005em;
  color: var(--text-muted);
  margin: 0;
  text-wrap: pretty;
}

.card__icon {
  width: 42px;
  height: 42px;
  display: grid;
  place-items: center;
  border-radius: 13px;
  background: linear-gradient(150deg, var(--mint-soft), #eaf8f1);
  color: var(--petrol);
}

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

/* This page uses <details>/<summary>, which open and close on their own. The
 * waitlist page used <button> plus a JavaScript-toggled .is-open class, and
 * styles.css still carries those rules — including `max-height: 0` on .faq__a,
 * which is released only by .is-open. Without a fix the answers stayed shut
 * however far the browser opened the <details>, so the whole section read as
 * six headings and nothing else.
 *
 * Overridden here rather than changed in styles.css, so the waitlist page keeps
 * working until it is retired. */
.faq__item[open] > .faq__a,
.faq__item > .faq__a {
  max-height: none;
  overflow: visible;
}

/* The default disclosure triangle goes; a plus that turns into a minus takes
 * its place, matching what the other page does with .faq__icon. */
.faq__q {
  list-style: none;
  position: relative;
  padding-right: 56px;
}

.faq__q::-webkit-details-marker { display: none; }

.faq__q::after {
  content: "";
  position: absolute;
  right: 24px;
  top: 50%;
  width: 14px;
  height: 2px;
  background: var(--petrol);
  border-radius: 2px;
  transform: translateY(-50%);
}

/* The vertical stroke of the plus, which rotates away when the item opens. */
.faq__q::before {
  content: "";
  position: absolute;
  right: 30px;
  top: 50%;
  width: 2px;
  height: 14px;
  background: var(--petrol);
  border-radius: 2px;
  transform: translateY(-50%);
  transition: transform 0.3s var(--ease), opacity 0.3s var(--ease);
}

.faq__item[open] > .faq__q::before {
  transform: translateY(-50%) rotate(90deg);
  opacity: 0;
}

@media (prefers-reduced-motion: reduce) {
  .faq__q::before { transition: none; }
}

/* ---- closing ---------------------------------------------------------- */

.close {
  position: relative;
  overflow: hidden;
  background:
    radial-gradient(90% 120% at 50% 0%, #1a6b6a 0%, transparent 60%),
    var(--deep-teal);
  color: #fff;
  border-radius: clamp(28px, 4.5vw, 44px);
  padding: clamp(64px, 10vw, 112px) clamp(28px, 5vw, 64px);
  text-align: center;
}

.close h2 {
  font-size: clamp(34px, 6vw, 60px);
  line-height: 1.04;
  letter-spacing: -0.04em;
  font-weight: 680;
  margin: 0 0 16px;
  color: #fff;
  text-wrap: balance;
}

.close p {
  font-size: clamp(16.5px, 2.1vw, 20px);
  line-height: 1.5;
  letter-spacing: -0.01em;
  color: var(--mint);
  margin: 0 auto 38px;
  max-width: 34ch;
  text-wrap: pretty;
}

.close .badges { justify-content: center; }
.close .badges__note { color: rgba(255, 255, 255, 0.68); }

/* ---- motion ----------------------------------------------------------- */

/* Content lifts in as it enters the viewport. Small translate, short fade:
 * anything larger turns reading into watching. The class is added by script,
 * so without JavaScript everything is simply visible. */
.reveal {
  opacity: 0;
  transform: translateY(20px);
  transition: opacity 0.7s var(--ease), transform 0.7s var(--ease);
}

.reveal.is-in { opacity: 1; transform: none; }

/* Staggered children, for grids where twelve things appearing at once reads as
 * a flash rather than an entrance. */
.stagger > * {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity 0.6s var(--ease), transform 0.6s var(--ease);
}

.stagger.is-in > * { opacity: 1; transform: none; }
.stagger.is-in > *:nth-child(2) { transition-delay: 0.07s; }
.stagger.is-in > *:nth-child(3) { transition-delay: 0.14s; }
.stagger.is-in > *:nth-child(4) { transition-delay: 0.21s; }
.stagger.is-in > *:nth-child(5) { transition-delay: 0.28s; }
.stagger.is-in > *:nth-child(6) { transition-delay: 0.35s; }

@media (prefers-reduced-motion: reduce) {
  .reveal,
  .stagger > * {
    opacity: 1;
    transform: none;
    transition: none;
  }
  .grip__orb,
  .grip__ring { transition: none; }
  .card:hover,
  .badges a:hover { transform: none; }
}
