/* Figtree, self-hosted (SIL Open Font License, fonts/OFL.txt): the site's policy allows no font hosts. */
@font-face { font-family: "Figtree"; font-style: normal; font-weight: 400; font-display: swap; src: url("fonts/figtree-400.woff2") format("woff2"); }
@font-face { font-family: "Figtree"; font-style: normal; font-weight: 500; font-display: swap; src: url("fonts/figtree-500.woff2") format("woff2"); }
@font-face { font-family: "Figtree"; font-style: normal; font-weight: 700; font-display: swap; src: url("fonts/figtree-700.woff2") format("woff2"); }
/* Layout: an out-of-home poster. One black billboard per section, in order: the hero (the mark, the
   menu, and beside them a stack of real scenes rising, product points labelled on the front scene);
   the intro letter; the research; the sign-up. The hero follows the brand book's website concept. */
:root {
  --board: #000; --type: #fff; --mute: #8a8a86; --line: #262624; --soft: #e6e6e2; --body: #bdbdb8; --ring: #2a2a28; --ph: #55554f; --focus: #6a6a66; --err: #ff8f80;
  --face: "Figtree", "Helvetica Neue", Arial, sans-serif;
  --pad: clamp(20px, 3.6vw, 52px); --edge: clamp(12px, 3vw, 40px);
  color-scheme: dark;
}
* { box-sizing: border-box; }
[hidden] { display: none !important; }
html { scroll-behavior: smooth; }
body {
  margin: 0; font: 400 16px/1.5 var(--face); color: var(--type); -webkit-font-smoothing: antialiased;
  background: var(--board); padding: var(--edge); position: relative;
  display: grid; gap: clamp(40px, 6vw, 96px); overflow-x: hidden;
}
a { color: inherit; text-decoration: none; }
:focus-visible { outline: 2px solid var(--type); outline-offset: 3px; }

/* clip, not hidden: a hidden board would be a scroll container, which the scroll animations would
   follow instead of the page (hidden stays as the fallback where clip is unknown) */
.board { position: relative; padding: var(--pad); overflow: hidden; overflow: clip; }
.say { font-size: clamp(26px, 3.4vw, 46px); line-height: 1.12; letter-spacing: -0.02em; margin: 0; font-weight: 400; }
/* Hero, after the brand book's website concept: the maker's line small at the top left; the stacked
   lockup (the supplied file, white on black, never redrawn) with the menu centred under it, in the
   middle of the first screen; the scene stack beside them. */
.masthead { position: absolute; top: var(--pad); left: var(--pad); z-index: 2; font-size: 14px; color: var(--mute); }
.hero { --first: calc(100svh - 2 * var(--edge) - 2 * var(--pad)); display: grid;
  grid-template-columns: minmax(0, 1fr); grid-template-rows: minmax(var(--first), auto); }
.brand { align-self: start; justify-self: center; padding-top: clamp(72px, 17vh, 190px); display: flex; flex-direction: column; align-items: center; }
.lockup { display: block; width: clamp(220px, 27vw, 460px); height: auto; fill: currentColor; }
.menu { display: flex; flex-wrap: wrap; justify-content: center; align-items: center; gap: 16px; margin-top: clamp(32px, 4vw, 56px); }
/* The two sections side by side in one dark pill, both in the muted grey */
.pill { display: inline-flex; padding: 5px; border-radius: 999px; background: #121211; box-shadow: inset 0 0 0 1px var(--line); }
.pill a { padding: 10px 22px; border-radius: 999px; font: 500 15px/1 var(--face); color: var(--mute); transition: color .15s, background .15s; }
.pill a:hover { color: var(--soft); background: rgba(255,255,255,.08); }

/* The rising stack */
.stage { position: relative; min-height: 0; overflow: hidden; }
.stack { position: absolute; inset: 0; pointer-events: none; }
.card {
  position: absolute; left: 50%; top: 50%; height: 86%; aspect-ratio: 2 / 3; border-radius: 10px;
  transition: transform .7s cubic-bezier(.7,0,.2,1), opacity .6s ease; will-change: transform;
}
.card img { width: 100%; height: 100%; object-fit: cover; display: block; max-width: none; border-radius: inherit; }
/* Product points and the product card, as they look in the app */
.dot {
  position: absolute; width: 24px; height: 24px; margin: -12px 0 0 -12px; border-radius: 50%;
  background: rgba(58,58,56,.72); box-shadow: inset 0 0 0 1.5px rgba(255,255,255,.55); backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
  display: grid; place-items: center; opacity: 0; transform: scale(.4); transition: opacity .25s, transform .25s;
}
.dot::after { content: ""; width: 8px; height: 8px; border-radius: 50%; background: #fff; }
.card.front .dot { opacity: 1; transform: scale(1); transition-delay: calc(var(--dots-at) + var(--d)); }
.pick {
  position: absolute; left: clamp(25%, var(--x), 75%); width: max-content; max-width: min(60%, 200px); translate: -50% 0; z-index: 2;
  display: grid; grid-template-columns: 54px minmax(0, 1fr); gap: 10px; align-items: center;
  padding: 5px 14px 5px 5px; border-radius: 13px; color: #111; background: rgba(248,248,246,.82);
  backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px); box-shadow: 0 8px 24px rgba(0,0,0,.25);
  opacity: 0; transform: translateY(6px) scale(.96); transition: opacity .25s, transform .25s;
}
.pick.below { top: calc(var(--y) + 16px); }
.pick.above { bottom: calc(100% - var(--y) + 16px); }
.card.front .pick.show { opacity: 1; transform: none; }
.pick .thumb { width: 54px; height: 54px; border-radius: 9px; object-fit: cover; background: #fff; max-width: none; }
.pick div { min-width: 0; line-height: 1.15; }
.pick b { display: block; font-weight: 400; font-size: 12px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pick .price { display: block; font-weight: 700; font-size: 17px; letter-spacing: -.02em; font-variant-numeric: tabular-nums; margin-top: 2px; }
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 10px; background: var(--type); color: var(--board); border: 0; cursor: pointer;
  font: 500 15px/1 var(--face); padding: 14px 22px; border-radius: 999px; transition: opacity .15s;
}
.btn:hover { opacity: .86; }
.btn:disabled { opacity: .5; cursor: default; }

/* Intro and research boards share one shape: the title on the left, the text beside it. The intro
   is the letter, paragraph after paragraph, in the abstract's face and size; Read more opens the
   long text under it. Helvetica Neue comes from the reader's own system (Apple devices); the font
   file is not shipped. */
.paper h3 { margin: 0 0 clamp(14px, 1.6vw, 22px); font: 500 clamp(24px, 2.4vw, 34px)/1.15 var(--face); letter-spacing: -0.02em; }
/* The founder film, in the text column; Read more opens the long text under it */
.film { border-radius: 14px; overflow: hidden; background: #000; box-shadow: inset 0 0 0 1px var(--line); }
.film video { display: block; width: 100%; aspect-ratio: 16 / 9; }
.film + .abstract { margin-top: clamp(20px, 2.2vw, 30px); }
/* Under the film: Read more, and beside it the way out to the blog */
.actions { display: flex; flex-wrap: wrap; align-items: baseline; gap: 8px 28px; margin-top: clamp(18px, 2vw, 28px); }
.actions .paper-link { margin-top: 0; }
.more { margin-top: 28px; }
.more p { font: 400 clamp(17px, 1.5vw, 19px)/1.6 "Helvetica Neue", Helvetica, Arial, sans-serif; color: var(--body); margin: 0; }
.more p + p { margin-top: 18px; }
.more strong { color: var(--type); font-weight: 500; }
.more em { color: var(--type); font-style: normal; }
.more a { color: var(--type); text-decoration: underline 1px var(--mute); text-underline-offset: 4px; transition: text-decoration-color .2s; }
.more a:hover { text-decoration-color: var(--type); }
.read-more { background: none; border: 0; border-radius: 0; cursor: pointer; color: var(--type); }

/* Research board: the title, and beside it the paper's abstract and the link to it */
.report { border-top: 1px solid var(--line); padding-block: calc(var(--pad) * 1.5) var(--pad); display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.4fr); gap: clamp(32px, 6vw, 96px); align-items: start; }
/* The title stays pinned at the top of the screen while its board scrolls past (web only) */
.report h2 { font-size: clamp(28px, 3.6vw, 52px); line-height: 1.02; letter-spacing: -0.03em; font-weight: 400; margin: 0; text-wrap: balance;
  position: sticky; top: calc(var(--edge) + var(--pad)); align-self: start; }
.abstract { margin: 0; font: 400 clamp(16px, 1.2vw, 18px)/1.55 "Helvetica Neue", Helvetica, Arial, sans-serif; letter-spacing: -0.01em; color: var(--body); }
.abstract em { font-style: normal; color: var(--type); }
/* Underlined like the intro's Read more; the arrow leans forward on hover */
.paper-link { display: inline-flex; align-items: center; gap: 10px; margin-top: clamp(22px, 2.4vw, 34px); padding-bottom: 5px;
  font: 500 clamp(15px, 1.2vw, 17px)/1.2 var(--face); border-bottom: 1px solid var(--mute); transition: border-color .2s; }
.paper-link span { transition: transform .2s ease; }
.paper-link:hover { border-bottom-color: var(--type); }
.paper-link:hover span { transform: translateX(4px); }

/* Early access board: the last screen on its own, so the page ends with nothing above it in view and
   its title, line and form in the middle of the screen; the footer lies along its bottom edge */
/* The title, line and form start near the top of the board; the board keeps a screen's height so the
   page ends with the footer along its bottom edge */
.join { min-height: max(520px, calc(100svh - 2 * var(--edge))); display: grid; justify-items: center; align-content: start; text-align: center; padding-block: calc(var(--pad) * 2) calc(var(--pad) * 3); border-top: 1px solid var(--line); }
.join .say { font-size: clamp(34px, 5.6vw, 84px); line-height: 1; }
.join p.lede { color: var(--mute); margin: 20px auto 36px; max-width: 40ch; font-size: 18px; }
.form { display: flex; gap: 8px; max-width: 460px; margin-inline: auto; padding: 6px; border-radius: 999px; box-shadow: inset 0 0 0 1px var(--ring); }
.form input { flex: 1; min-width: 0; background: transparent; border: 0; outline: 0; color: var(--type); font: 400 16px var(--face); padding: 0 16px; }
.form input::placeholder { color: var(--ph); }
.form:focus-within { box-shadow: inset 0 0 0 1px var(--focus); }
/* Left empty by people; filled by bots that complete every field. */
.trap { position: absolute; left: -10000px; width: 1px; height: 1px; overflow: hidden; }
/* Cloudflare's check appears under the form only when it needs the visitor to act. */
.turnstile { display: flex; justify-content: center; }
.form-status { min-height: 22px; margin: 12px 0 0; font-size: 14px; color: var(--mute); }
.form-status.is-error { color: var(--err); }
.done b { display: block; font-size: clamp(26px, 3vw, 40px); font-weight: 400; letter-spacing: -0.02em; }
.done span { color: var(--mute); }
/* The last line sits where sites put their legal line: about 20px above the page end on a phone, 32px on a desktop */
footer { position: absolute; left: var(--edge); right: var(--edge); bottom: clamp(18px, 2.2vw, 30px);
  display: flex; justify-content: space-between; flex-wrap: wrap; gap: 12px; font-size: 14px; color: var(--mute); padding-inline: var(--pad); }
footer nav { display: flex; gap: 20px; }
.maker-line { display: flex; align-items: center; gap: 14px; }
.logo svg { display: block; width: 120px; height: auto; fill: currentColor; }

/* Web only: the mark and menu on the left, the scene stack on the right as tall as the first screen */
@media (min-width: 761px) {
  .hero { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); column-gap: clamp(24px, 4vw, 72px); }
  .stage { grid-column: 2; grid-row: 1; align-self: start; height: var(--first); }
  .card { height: 94%; }
}
/* Phone: the first screen is the mark in the middle with the menu lower down, so it reads as a full
   page; the stack follows below the fold */
@media (max-width: 760px) {
  /* The mark's block is the whole first screen, and the stack starts well below it, so no edge of a
     scene shows above the fold whatever the browser's bars do */
  .hero { row-gap: clamp(64px, 14vh, 140px); }
  .brand { align-self: stretch; min-height: calc(100lvh - var(--edge) - var(--pad)); padding-top: 0; justify-content: center; }
  .lockup { width: min(78vw, 380px); }
  .brand .menu { margin-top: clamp(64px, 16vh, 160px); }
  .stage { height: 78svh; container-type: size; }
  .card { height: auto; width: min(94cqw, calc(88cqh * 2 / 3)); }
  .report { grid-template-columns: 1fr; }
  .report h2 { position: static; }
}
/* Narrow phones: the menu stacks, the pill above the button, each as wide as the column */
@media (max-width: 560px) {
  .menu { flex-direction: column; align-items: stretch; }
  .pill { justify-content: center; }
}
@media (max-width: 420px) {
  .form { flex-direction: column; border-radius: 20px; }
  .form input { padding: 14px 12px; }
}
@media (prefers-reduced-motion: reduce) { .card, .dot, .pick, .paper-link span { transition: none; animation: none !important; } html { scroll-behavior: auto; } }

/* Scroll animations, tied to the scroll position, so scrolling back up plays them in reverse.
   Browsers without scroll-driven animations, and reduce motion, get the page exactly as above.
   The scene stack's own cycle (scene.js) is untouched: only the stage around it moves. */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    :root { --move: 1; }
    /* Phones move less */
    @media (max-width: 760px) { :root { --move: .6; } }

    /* Hero: still at first. Over the page's first screen of scrolling the mark, menu and masthead fade,
       drifting a little slower than the page. The stage shrinks back and fades as it leaves. */
    .masthead, .brand { animation: field-out linear both; animation-timeline: scroll(); animation-range: 0 80vh; }
    .stage { transform-origin: 50% 40%; animation: stage-out linear both; animation-timeline: view(); animation-range: exit; }

    /* Open: the long text holds still while it is read */
    .report.is-open .paper { animation: none; }

    /* Intro and research, the same way: the title rises, then the text a little after it */
    .report h2 { --rise: 30px; animation: rise linear both; animation-timeline: view(); animation-range: cover 10vh cover 40vh; }
    .paper { --rise: 24px; animation: rise linear both; animation-timeline: view(); animation-range: cover 14vh cover 44vh; }

    /* Early access: the title rises as one line from behind its own edge, then the line under it and the form.
       The page ends with them in the middle of the screen, and each finishes well before that. */
    .say { view-timeline: --say block; overflow: hidden; overflow: clip; padding-bottom: .12em; margin-bottom: -.12em; }
    .say > span { display: inline-block; animation: title-up linear both; animation-timeline: --say; animation-range: cover 5vh cover 36vh; }
    .join p.lede, .join .form { animation: rise linear both; animation-timeline: view(); animation-range: cover 5vh cover 38vh; }
    .join .form { animation-range: cover 5vh cover 32vh; }

    @keyframes field-out { to { opacity: 0; transform: translateY(calc(12vh * var(--move))); } }
    @keyframes stage-out { to { transform: translateY(-5%) scale(.84); opacity: .25; } }
    @keyframes rise { from { opacity: 0; transform: translateY(calc(var(--rise, 20px) * var(--move))); } }
    @keyframes title-up { from { transform: translateY(110%); } }
  }
}
