/* boonely.com launch page
   Layout: one column, centered. The wordmark fills the first screen and compresses into the
   header as you scroll; every section after it is set a step smaller than the last. */
@font-face {
  font-family: "Bricolage Grotesque";
  font-style: normal;
  font-weight: 200 800;
  font-display: swap;
  src: url("/fonts/bricolage-grotesque-latin-variable.woff2") format("woff2");
}
@font-face {
  font-family: "Source Sans 3";
  font-style: normal;
  font-weight: 200 900;
  font-display: swap;
  src: url("/fonts/source-sans-3-latin-variable.woff2") format("woff2");
}
/* Metric-matched fallbacks (Arial / Liberation Sans / Roboto) so the swap to the web fonts does
   not shift layout. Ratios computed from the font files' advance widths over the page's own copy
   and their vertical metrics, at the weights the page uses (800 display, 400 text). */
@font-face {
  font-family: "Bricolage Grotesque Fallback";
  src: local("Arial"), local("Liberation Sans"), local("Roboto");
  size-adjust: 100.26%;
  ascent-override: 92.76%;
  descent-override: 26.93%;
  line-gap-override: 0%;
}
@font-face {
  font-family: "Source Sans 3 Fallback";
  src: local("Arial"), local("Liberation Sans"), local("Roboto");
  size-adjust: 93.3%;
  ascent-override: 109.7%;
  descent-override: 42.9%;
  line-gap-override: 0%;
}
:root {
  --forest: #183f30;
  --bark: #103023;
  --cream: #f8f8f0;
  --clem: #ff6b35;
  --lime: #d1ed9e;
  --moss: #65705f;
  --line: #dfe4d7;
  --font-display:
    "Bricolage Grotesque", "Bricolage Grotesque Fallback", Arial, sans-serif;
  --font-sans: "Source Sans 3", "Source Sans 3 Fallback", Arial, sans-serif;
  --gutter: max(
    20px,
    4vw,
    env(safe-area-inset-left, 0px),
    env(safe-area-inset-right, 0px)
  );
  --header-h: 64px;
  --ease: cubic-bezier(0.22, 1, 0.36, 1);
  color-scheme: light;
}
* {
  box-sizing: border-box;
}
html {
  background: var(--cream);
  scroll-padding-top: calc(var(--header-h) + 16px);
  /* scroll-behavior: smooth is set by main.js once the page has loaded */
}
html,
body {
  overflow-x: clip;
}
body {
  margin: 0;
  background: var(--cream);
  color: var(--forest);
  font-family: var(--font-sans);
  font-size: 1.125rem;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
h1,
h2,
p {
  margin: 0;
}
a {
  color: inherit;
}
svg {
  display: block;
}
.stamp-1 {
  fill: var(--clem);
}
.stamp-2 {
  fill: transparent;
}
.ink {
  fill: currentColor;
}
.sr {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}
.skip {
  position: fixed;
  top: max(8px, env(safe-area-inset-top, 0px));
  left: max(8px, env(safe-area-inset-left, 0px));
  z-index: 50;
  padding: 10px 14px;
  background: var(--forest);
  color: var(--cream);
  border-radius: 999px;
  font-weight: 600;
  text-decoration: none;
  transform: translateY(-200%);
}
.skip:focus-visible {
  transform: none;
}
:focus-visible {
  outline: 3px solid var(--forest);
  outline-offset: 4px;
}
.waitlist :focus-visible {
  outline-color: var(--lime);
}

/* Header: the landing slot for the wordmark, and the launch note. */
.top {
  position: fixed;
  inset: 0 0 auto;
  z-index: 20;
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: var(--header-h);
  padding-inline: var(--gutter);
  color: var(--forest);
  transition: color 0.4s var(--ease);
}
.top::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: rgba(248, 248, 240, 0.82);
  -webkit-backdrop-filter: blur(14px);
  backdrop-filter: blur(14px);
  opacity: 0;
  transition:
    opacity 0.3s,
    background 0.4s var(--ease);
}
.top::after {
  content: "";
  position: absolute;
  inset: auto 0 0;
  height: 1px;
  background: var(--line);
  opacity: 0;
  transition: opacity 0.3s;
}
.top.is-compact::before {
  opacity: 1;
}
.top.on-forest::before {
  background: rgba(24, 63, 48, 0.82);
}
.top.is-compact::after {
  opacity: 1;
}
.top.on-forest {
  color: var(--cream);
}
.top.on-forest::after {
  opacity: 0;
}
.top-logo {
  display: flex;
  align-items: center;
  width: 104px;
  min-height: 44px;
  opacity: 0;
  visibility: hidden; /* out of the tab order while invisible */
  transition:
    opacity 0.15s,
    visibility 0s 0.15s;
}
.top-logo svg {
  width: 100%;
  height: auto;
}
.top.is-compact .top-logo {
  opacity: 1;
  visibility: visible;
  transition-duration: 0s; /* appears the instant the hero copy is hidden; fades on the way out */
  transition-delay: 0s;
}
.launch {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 0.95rem;
  letter-spacing: 0.01em;
}
.launch .dot {
  width: 10px;
  height: 10px;
  border-radius: 999px;
  background: var(--clem);
  animation: pulse 2.4s ease-in-out 3;
}
@keyframes pulse {
  0%,
  100% {
    transform: scale(1);
    opacity: 1;
  }
  50% {
    transform: scale(0.6);
    opacity: 0.55;
  }
}

/* Hero: a tall scroll track with a pinned screen inside it. */
.hero {
  position: relative;
  height: 210vh;
  height: 210svh;
}
.hero-pin {
  position: sticky;
  top: 0;
  height: 100vh;
  height: 100svh;
  display: grid;
  grid-template-columns: minmax(0, 1fr); /* sizes the wordmark */
  place-content: center;
  /* taller content starts at the top instead of under the header */
  align-content: safe center;
  justify-items: center;
  gap: clamp(20px, 3vh, 36px);
  padding-inline: var(--gutter);
  padding-bottom: 72px; /* room for the scroll cue */
  overflow: hidden;
}
.wordmark {
  /* the pin's content box: full width inside the gutters */
  width: min(100%, 215vh);
  width: min(100%, 215svh);
  transform-origin: 0 0;
  color: var(--forest);
  margin-top: var(--header-h);
}
.wordmark svg {
  width: 100%;
  height: auto;
}
.wordmark .stamp-1 {
  transform-box: fill-box;
  transform-origin: center;
  animation: press 0.7s var(--ease) both;
  animation-delay: 0.25s;
}
@keyframes press {
  from {
    transform: scale(1.6);
    opacity: 0;
  }
  to {
    transform: scale(1);
    opacity: 1;
  }
}
.sub {
  max-width: 34ch;
  text-align: center;
  font-size: clamp(1.1rem, 1.1rem + 0.9vw, 1.6rem);
  line-height: 1.4;
  color: var(--forest);
  text-wrap: balance;
}
.cue {
  position: absolute;
  bottom: max(20px, env(safe-area-inset-bottom, 0px));
  left: 50%;
  translate: -50% 0;
  width: 40px;
  height: 40px;
  color: var(--forest);
}
.cue path {
  animation: cue-flash 1.5s var(--ease) infinite;
}
.is-scrolled .cue path {
  animation-play-state: paused; /* the cue is fading out; stop ticking */
}
@keyframes cue-flash {
  0%,
  100% {
    opacity: 1;
    transform: translateY(0);
  }
  50% {
    opacity: 0.3;
    transform: translateY(3px);
  }
}

/* The first heading's first o takes the stamp: a Clementine fill behind the glyph, sized from the
   Bricolage ExtraBold "o" outline (counter 0.19-0.40em wide, 0.10-0.42em above the baseline) with
   margin hidden under the ring. --fill goes 0 to 1 with scroll; without motion or JS it stays full. */
.stamp-o {
  position: relative;
  z-index: 0;
  white-space: nowrap;
  --fill: 1;
}
.stamp-o .fill {
  display: inline-block;
  width: 0;
  height: 0;
  vertical-align: baseline;
  position: relative;
  font-style: normal;
}
.stamp-o .fill::before {
  content: "";
  position: absolute;
  left: 0.155em;
  bottom: 0.065em;
  width: 0.27em;
  height: 0.39em;
  border-radius: 50%;
  background: var(--clem);
  transform: scale(var(--fill));
  z-index: -1;
}

/* Beats: each heading one step smaller than the one before it. */
.beat {
  overflow-x: clip;
  display: grid;
  justify-items: center;
  gap: clamp(16px, 2.4vw, 28px);
  padding-block: clamp(22vh, 26vh, 30vh);
  padding-inline: var(--gutter);
  text-align: center;
}
.beat h2 {
  font-family: var(--font-display);
  font-weight: 800;
  line-height: 0.98;
  letter-spacing: -0.03em;
  text-wrap: balance;
  max-width: min(
    9em,
    100%
  ); /* em, not ch, so the fallback face breaks lines like the real one */
  transform-origin: center;
}
.beat p {
  max-width: 44ch;
  font-size: clamp(1.05rem, 1rem + 0.5vw, 1.35rem);
  line-height: 1.5;
  color: var(--moss);
  text-wrap: pretty;
}
.beat-1 h2 {
  font-size: clamp(3rem, 11.5vw, 13rem);
}
.beat-2 h2 {
  font-size: clamp(2.4rem, 7.6vw, 8.6rem);
  font-weight: 700;
}
.beat-3 h2 {
  font-size: clamp(2rem, 5vw, 5.6rem);
  font-weight: 600;
  letter-spacing: -0.02em;
}
.beat-4 h2 {
  font-size: clamp(1.7rem, 3.4vw, 3.8rem);
  font-weight: 600;
  letter-spacing: -0.02em;
}
.beat-4 .eyebrow {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 0.85rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--moss);
}

/* Waitlist: the one Forest surface on the page. */
.waitlist {
  background: var(--forest);
  color: var(--cream);
  padding-block: clamp(80px, 14vh, 160px);
  padding-inline: var(--gutter);
}
.waitlist-inner {
  max-width: 720px;
  margin: 0 auto;
  display: grid;
  gap: 28px;
  justify-items: start;
}
.waitlist .mark {
  width: clamp(88px, 12vw, 132px);
  color: var(--cream);
}
.waitlist .mark svg {
  width: 100%;
  height: auto;
}
.waitlist .mark .stamp-2 {
  transform-box: fill-box;
  transform-origin: center;
  transition:
    fill 0.3s,
    transform 0.6s var(--ease);
  transform: scale(0.4);
}
.waitlist.is-joined .mark .stamp-2 {
  fill: var(--lime);
  transform: scale(1);
}
.waitlist .eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 0.85rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  opacity: 0.85;
}
.waitlist .eyebrow .dot {
  width: 8px;
  height: 8px;
  border-radius: 999px;
  background: var(--clem);
}
.waitlist h2 {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: clamp(2rem, 1.4rem + 3vw, 3.6rem);
  line-height: 1;
  letter-spacing: -0.03em;
  text-wrap: balance;
  max-width: 16ch;
}
.waitlist .lede {
  max-width: 46ch;
  font-size: clamp(1.05rem, 1rem + 0.4vw, 1.3rem);
  opacity: 0.9;
}
.wl-form {
  width: 100%;
  display: grid;
  gap: 14px;
}
.wl-row {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  width: 100%;
}
.wl-row input[type="email"] {
  flex: 1 1 260px;
  min-width: 0;
  height: 60px;
  padding: 0 20px;
  border: 2px solid rgba(248, 248, 240, 0.35);
  border-radius: 999px;
  background: rgba(248, 248, 240, 0.06);
  color: var(--cream);
  font: inherit;
  font-size: 1.1rem;
}
.wl-row input[type="email"]::placeholder {
  color: rgba(248, 248, 240, 0.65);
}
.wl-row input[type="email"]:focus-visible {
  outline: 3px solid var(--lime);
  outline-offset: 3px;
  border-color: var(--cream);
}
.wl-row button {
  flex: 0 0 auto;
  height: 60px;
  padding: 0 28px;
  border: 0;
  border-radius: 999px;
  background: var(--clem);
  color: var(--bark);
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.05rem;
  cursor: pointer;
  transition:
    transform 0.15s var(--ease),
    background 0.15s;
}
.wl-row button:hover {
  background: #ff7d4e;
}
.wl-row button:active {
  transform: translateY(1px);
}
.wl-row button:disabled {
  opacity: 0.6;
  cursor: default;
}
.hp {
  position: absolute;
  left: -10000px;
  top: auto;
  width: 1px;
  height: 1px;
  overflow: hidden;
}
.consent {
  font-size: 0.9rem;
  line-height: 1.5;
  opacity: 0.75;
  max-width: 52ch;
}
.consent a {
  text-decoration: underline;
  text-underline-offset: 3px;
}
.status {
  min-height: 1.5em;
  font-size: 1rem;
  font-weight: 600;
}
.status.is-error {
  color: #ffd4c2;
}
.status.is-ok {
  color: var(--lime);
}
.waitlist.is-joined .wl-row,
.waitlist.is-joined .consent {
  visibility: hidden; /* keep their boxes so the band does not jump when the reply lands */
}
.waitlist.is-joined .status {
  order: -1; /* the success line takes the input row's place */
}

/* Footer */
.foot {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 12px 24px;
  padding: 28px var(--gutter) max(28px, env(safe-area-inset-bottom, 0px));
  font-size: 0.9rem;
  color: var(--moss);
}
.foot a {
  display: inline-block;
  padding: 12px 0;
  margin: -12px 0;
  text-decoration: none;
}
.foot a:hover {
  text-decoration: underline;
  text-underline-offset: 3px;
}

/* Secondary pages */
.page {
  max-width: 640px;
  margin: 0 auto;
  padding: calc(var(--header-h) + 48px) var(--gutter) 80px;
  display: grid;
  gap: 18px;
}
.page h1 {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: clamp(2.2rem, 2rem + 2vw, 3.6rem);
  letter-spacing: -0.03em;
  line-height: 1;
}
.page h2 {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 1.3rem;
  margin-top: 12px;
}
.page p,
.page li {
  color: var(--forest);
}
.page .back {
  font-weight: 600;
}
/* The unsubscribe form on the cream page. */
.unsub {
  margin-top: 6px;
}
/* The Worker sets unsub-link on <body> when the page is opened from a removal link. */
.unsub-nolink .only-link,
.unsub-link .only-nolink {
  display: none;
}
.unsub button {
  height: 56px;
  padding: 0 26px;
  border: 0;
  border-radius: 999px;
  background: var(--forest);
  color: var(--cream);
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.05rem;
  cursor: pointer;
}
.unsub button:hover {
  background: var(--bark);
}

/* Scroll-driven animations: the browser moves the wordmark, the beats and the stamp in step
   with the scroll instead of a script doing it on each frame, so where the browser runs these
   animations off the main thread nothing lands a frame behind the finger. main.js only
   measures the header slot into --tx/--ty/--k and the hero track into --track, flips the
   compact header, and sets is-scrolled on <html> while the page is scrolled at all: at the
   very top the wordmark has no animation attached and is painted in place rather than through
   a compositor layer, which keeps it sharp. Browsers without scroll timelines keep the
   script-driven path in main.js; reduced motion gets neither. */
@media (prefers-reduced-motion: no-preference) {
  @supports (animation-timeline: scroll()) {
    .is-scrolled .wordmark {
      animation: hero-compress cubic-bezier(0.65, 0, 0.35, 1) both;
      animation-timeline: scroll(root);
      animation-range: 0 var(--track, 110svh); /* the pinned part of the hero */
    }
    @keyframes hero-compress {
      from {
        transform: translate(0, 0) scale(1);
      }
      to {
        transform: translate(var(--tx, 0px), var(--ty, 0px)) scale(var(--k, 1));
      }
    }
    .sub {
      animation: sub-away linear both;
      animation-timeline: scroll(root);
      animation-range: 0 calc(var(--track, 110svh) * 0.3);
    }
    @keyframes sub-away {
      from {
        opacity: 1;
        transform: none;
      }
      to {
        opacity: 0;
        transform: translateY(-28px);
      }
    }
    .cue {
      animation: fade-away linear both;
      animation-timeline: scroll(root);
      animation-range: 0 calc(var(--track, 110svh) * 0.15);
    }
    @keyframes fade-away {
      from {
        opacity: 1;
      }
      to {
        opacity: 0;
      }
    }
    /* Each heading drives its section: 0% when its top reaches the bottom of the screen, 100%
       when its bottom leaves the top. The inset is spelled out because its default follows
       scroll-padding-top (the header), which would end the timeline, and drop the scale, while
       the heading is still showing under the header. */
    .beat h2 {
      view-timeline: --beat block;
      view-timeline-inset: 0;
      animation:
        beat-scale linear none,
        beat-fade cubic-bezier(0.33, 1, 0.68, 1) none;
      animation-timeline: --beat, --beat;
      animation-range:
        cover 0% cover 100%,
        cover 0% cover 28%;
    }
    @keyframes beat-scale {
      from {
        transform: scale(1.1);
      }
      to {
        transform: scale(0.86);
      }
    }
    @keyframes beat-fade {
      from {
        opacity: 0;
      }
      to {
        opacity: 1;
      }
    }
    /* Copy fades in as it arrives and is left alone before and after, so nothing on the page
       is hidden before it has been scrolled to. */
    .beat p {
      animation: beat-fade cubic-bezier(0.33, 1, 0.68, 1) none;
      animation-timeline: view(block 0);
      animation-range: cover 0% cover 35%;
    }
    .stamp-o .fill::before {
      animation: stamp-land cubic-bezier(0.33, 1, 0.68, 1) backwards;
      animation-timeline: view(block 0);
      animation-range: cover 30% cover 55%;
    }
    @keyframes stamp-land {
      from {
        transform: scale(0);
      }
      to {
        transform: scale(1);
      }
    }
    @supports (timeline-scope: --beat) {
      .beat {
        timeline-scope: --beat;
      }
      /* Body copy trails its heading; the beat-4 label above the heading keeps its own timeline
         so it leads instead. */
      .beat h2 ~ p {
        animation-timeline: --beat;
        animation-range: cover 0% cover 38%;
      }
      .stamp-o .fill::before {
        animation-timeline: --beat;
        animation-range: cover 26% cover 50%;
      }
    }
  }
}

/* Reduced motion: the page reads top to bottom with no pinning or transforms. */
@media (prefers-reduced-motion: reduce) {
  .hero {
    height: auto;
  }
  .hero-pin {
    position: static;
    height: auto;
    min-height: 100svh;
  }
  .wordmark,
  .sub,
  .beat h2,
  .beat p,
  .cue {
    transform: none !important;
    opacity: 1 !important;
    animation: none;
  }
  .wordmark .stamp-1,
  .stamp-o .fill::before,
  .cue path,
  .launch .dot {
    animation: none;
  }
  .waitlist .mark .stamp-2 {
    transition: fill 0.3s;
    transform: none;
  }
}
@media (max-height: 480px) {
  .cue {
    display: none;
  }
  .hero-pin {
    padding-bottom: 0; /* no cue, no room reserved for it */
  }
}
/* Without JavaScript the hero is a normal section and the header logo stays hidden. */
.no-js .top {
  position: absolute; /* scrolls away with the hero; no frosted bar without JS */
}
.no-js .hero {
  height: auto;
}
.no-js .hero-pin {
  position: static;
  height: auto;
  min-height: 100svh;
}

/* Print: a plain top-to-bottom document with no fixed chrome or scroll choreography. */
@media print {
  .top,
  .skip,
  .cue,
  .wl-form {
    display: none;
  }
  .hero {
    height: auto;
  }
  .hero-pin {
    position: static;
    height: auto;
    padding-bottom: 0;
    overflow: visible;
  }
  .wordmark {
    margin-top: 0;
  }
  .wordmark,
  .sub,
  .beat h2,
  .beat p,
  .stamp-o .fill::before {
    animation: none;
    transform: none !important;
    opacity: 1 !important;
  }
  .beat {
    padding-block: 48px;
  }
  .waitlist {
    background: none;
    color: var(--forest);
    padding-block: 48px;
  }
  .waitlist .mark {
    color: var(--forest);
  }
}
