@font-face {
  font-family: "Fraunces";
  src: url("fonts/Fraunces.ttf") format("truetype");
  font-weight: 100 900;
  font-display: swap;
}

@font-face {
  font-family: "Instrument Sans";
  src: url("fonts/InstrumentSans.ttf") format("truetype");
  font-weight: 400 700;
  font-display: swap;
}

/* The app's Paper and Graphite palettes. */
:root {
  --bg: #F7F5F0;
  --ink: #1F1D1A;
  --raised: #EFEBE2;
  --text2: #57534C;
  --meta: #75706A;
  --line: #E6E2D9;
  --accent: #BC5A29;
  --accent-ink: #9D4616;
  --on-accent: #FFFFFF;
  --fill: #FBE2D2;
  --mark: #B4592E;
  --card: #FFFFFF;
  --line-strong: #D9D4C9;
  --serif: "Fraunces", Georgia, serif;
  --sans: "Instrument Sans", -apple-system, system-ui, sans-serif;
  --gutter: max(16px, 4vw);
  color-scheme: light dark;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg: #141312;
    --ink: #ECE8E1;
    --raised: #1F1D1B;
    --text2: #A49E94;
    --meta: #8F897F;
    --line: #2A2725;
    --accent: #F0A646;
    --accent-ink: #F0A646;
    --on-accent: #1A1612;
    --fill: #2B2117;
    --mark: #E8A54B;
    --card: #1F1D1B;
    --line-strong: #3A3632;
  }
}

:root[data-theme="dark"] {
  --bg: #141312;
  --ink: #ECE8E1;
  --raised: #1F1D1B;
  --text2: #A49E94;
  --meta: #8F897F;
  --line: #2A2725;
  --accent: #F0A646;
  --accent-ink: #F0A646;
  --on-accent: #1A1612;
  --fill: #2B2117;
  --mark: #E8A54B;
  --card: #1F1D1B;
  --line-strong: #3A3632;
}

* { box-sizing: border-box; }

html { scroll-behavior: smooth; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font: 400 17px/1.5 var(--sans);
  -webkit-font-smoothing: antialiased;
}

/* On body, overflow passes to the viewport and stops clipping; on main it holds, and keeps the sticky stages working. */
main { overflow-x: clip; }

img { display: block; max-width: 100%; height: auto; }

h1, h2, h3 {
  font-family: var(--serif);
  font-weight: 600;
  letter-spacing: -0.02em;
  line-height: 1.05;
  margin: 0;
  text-wrap: balance;
}

p { margin: 0; }

.kicker {
  color: var(--accent-ink);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.lead {
  color: var(--text2);
  font-size: clamp(18px, 2vw, 22px);
  max-width: 34ch;
}

/* Bar */

.bar {
  position: fixed;
  inset: 0 0 auto;
  z-index: 10;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px var(--gutter);
  background: color-mix(in srgb, var(--bg) 82%, transparent);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  border-bottom: 1px solid color-mix(in srgb, var(--line) 70%, transparent);
}

.brand { display: flex; align-items: center; gap: 10px; }
.brand-icon { width: 32px; height: 32px; }
.brand-word { width: 78px; height: auto; }

/* Sound, bottom left. Its three bars dance while the music plays. */

.sound {
  position: fixed;
  left: var(--gutter);
  bottom: 20px;
  z-index: 10;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 9px 14px;
  border: 1px solid color-mix(in srgb, var(--line) 70%, transparent);
  border-radius: 999px;
  background: color-mix(in srgb, var(--bg) 82%, transparent);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  color: var(--meta);
  font: 600 11px/1 var(--sans);
  letter-spacing: 0.24em;
  text-transform: uppercase;
  cursor: pointer;
  transition: color 0.2s ease;
}
.sound:hover, .sound.is-on { color: var(--ink); }
.sound-bars { display: flex; align-items: flex-end; gap: 2px; height: 11px; }
.sound-bars i { width: 2px; height: 100%; border-radius: 1px; background: currentColor; transform: scaleY(0.3); transform-origin: bottom; }
.sound.is-on .sound-bars i { animation: sound-bar 0.9s ease-in-out infinite alternate; }
.sound.is-on .sound-bars i:nth-child(2) { animation-delay: -0.3s; animation-duration: 0.7s; }
.sound.is-on .sound-bars i:nth-child(3) { animation-delay: -0.6s; animation-duration: 1.1s; }
@keyframes sound-bar { to { transform: scaleY(1); } }

/* The bar's Download pill */

.store {
  display: inline-flex;
  flex-direction: column;
  justify-content: center;
  min-height: 52px;
  padding: 8px 22px;
  border-radius: 14px;
  background: var(--ink);
  color: var(--bg);
  font-size: 19px;
  font-weight: 600;
  line-height: 1.1;
  text-decoration: none;
  transition: transform 0.2s ease;
}

.store:hover, .badge:hover { transform: translateY(-1px); }

/* Apple's own badge, black in light mode and white in dark. */
.badge { display: inline-block; line-height: 0; transition: transform 0.2s ease; }
.badge img { display: block; width: auto; height: 52px; }

/* The opening frame's badge, for anyone who would rather not scroll for it. intro.js places it under the tagline. */
.intro-badge { display: none; }
.intro-on .intro-badge { display: block; position: absolute; left: 50%; top: 0; translate: -50% 0; }
.intro-badge img { height: 52px; }

.store-small {
  min-height: 0;
  padding: 7px 14px;
  border-radius: 999px;
  background: var(--accent);
  color: var(--on-accent);
  font-size: 15px;
}

/* Intro. Without the scroll script it is just the hero; with it, the stage holds while the scroll plays the header video's story and lands on the hero. */

.intro { position: relative; }
.intro-stage { position: relative; }
.band, .wash, .hint { display: none; }

.hero {
  display: grid;
  justify-items: center;
  gap: 18px;
  padding: calc(110px + 6vh) var(--gutter) 10vh;
  text-align: center;
}

.hero-icon {
  width: 84px;
  height: 84px;
  margin-bottom: 6px;
  filter: drop-shadow(0 14px 24px rgb(31 29 26 / 0.18));
}

.hero h1 { font-size: clamp(56px, 10vw, 128px); line-height: 0.98; }
.hero .lead { margin-bottom: 10px; }

.hero-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: 14px 24px;
}

.hero-more {
  color: var(--accent-ink);
  font-weight: 600;
  text-decoration: none;
}

.hero-more::after { content: " \2193"; }
.hero-more:hover { text-decoration: underline; text-underline-offset: 4px; }
.hero-note { color: var(--meta); font-size: 14px; }

.intro-on .intro { height: 760vh; }

.intro-on .intro-stage {
  position: sticky;
  top: 0;
  height: 100vh;
  height: 100svh;
  overflow: hidden;
}

.intro-on .hero {
  position: absolute;
  inset: 0;
  align-content: center;
  padding: 64px var(--gutter) 24px;
}

.intro-on .wash {
  display: block;
  position: absolute;
  inset: 0;
  background: var(--fill);
  transform: translateY(100%);
}

.intro-on .hint {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  position: absolute;
  left: 0;
  right: 0;
  bottom: 32px;
  margin: 0;
  color: var(--meta);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.24em;
  text-indent: 0.24em;
  text-transform: uppercase;
}

/* A short line with a drop of the accent running down it, over and over. */
.hint-track {
  position: relative;
  width: 1.5px;
  height: 44px;
  border-radius: 1px;
  background: var(--line-strong);
  overflow: hidden;
}

.hint-track::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  height: 40%;
  border-radius: 1px;
  background: var(--mark);
  animation: hint-run 1.8s cubic-bezier(0.6, 0, 0.3, 1) infinite;
}

@keyframes hint-run {
  from { transform: translateY(-100%); }
  to { transform: translateY(250%); }
}

/* The band is drawn at the video's own size and zoomed to fit, not scaled: Safari leaves stale tiles of a scaled layer behind. intro.js places everything in it. */
.intro-on .band {
  display: block;
  position: absolute;
  pointer-events: none;
}

.band > * { position: absolute; left: 0; top: 0; }

/* The bar waits for the hero. */
/* The bar waits for the hero. Hidden is the default, so the first paint, before intro.js runs, never shows it. */
.intro-on .bar:not(.is-here) { transform: translateY(-100%); opacity: 0; pointer-events: none; }
.intro-ready .bar { transition: transform 0.5s cubic-bezier(0.2, 0.8, 0.2, 1), opacity 0.4s ease; }
.intro-on:not(.intro-ready) .intro-stage { visibility: hidden; }
.bar.is-tucked { transform: translateY(-100%); opacity: 0; pointer-events: none; }

.wordmark { width: 560px; height: 194px; color: var(--ink); }
.wordmark svg { display: block; width: 100%; height: 100%; }

.tagline {
  width: 560px;
  text-align: center;
  font-size: 36px;
  font-weight: 500;
  color: var(--meta);
}

.headline, .say {
  font-family: var(--serif);
  font-weight: 700;
  font-size: 92px;
  letter-spacing: -0.02em;
  line-height: 1;
}

.headline { display: flex; align-items: center; height: 120px; }
.headline .word { display: block; }
.headline .swap { position: relative; display: block; width: 280px; height: 110px; margin-left: 22px; }
.headline .swap .word { position: absolute; left: 0; top: 9px; white-space: nowrap; }

.say { display: flex; flex-direction: column; }
.wave { display: flex; align-items: center; gap: 6px; height: 72px; margin: 26px 0 0 4px; }
.wave span { display: block; width: 6px; height: 72px; border-radius: 3px; background: var(--mark); }

.row {
  width: 490px;
  height: 74px;
  display: flex;
  align-items: center;
  gap: 20px;
  padding: 0 22px;
  border-radius: 22px;
  background: var(--card);
  box-shadow: 0 12px 34px rgb(31 29 26 / 0.09);
  font-size: 30px;
  font-weight: 500;
  color: var(--text2);
  white-space: nowrap;
}

.row .ring {
  display: block;
  flex: none;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  border: 2.5px solid var(--line-strong);
}

.focus { width: 480px; }
.focus .label { display: block; padding-left: 30px; font-size: 22px; font-weight: 600; letter-spacing: 0.14em; color: var(--accent-ink); }
.focus .task { display: block; margin-top: 10px; font-family: var(--serif); font-weight: 700; font-size: 40px; letter-spacing: -0.01em; white-space: nowrap; }
.timer { margin-top: 2px; font-family: var(--serif); font-weight: 300; font-size: 190px; line-height: 1.1; letter-spacing: -0.02em; font-variant-numeric: tabular-nums; }

.done { display: flex; flex-direction: column; align-items: center; }
.done .title { font-family: var(--serif); font-weight: 800; font-size: 84px; letter-spacing: -0.02em; line-height: 1.1; }
.done .sub { margin-top: 12px; font-size: 30px; color: var(--meta); }
.dashes { display: flex; gap: 10px; margin-top: 24px; }
.dash { display: block; width: 44px; height: 8px; border-radius: 4px; background: var(--line-strong); }
.dash.on { background: var(--mark); }

.streams { overflow: visible; }
.streams path { fill: none; stroke: var(--mark); stroke-opacity: 0.35; stroke-width: 2; stroke-dasharray: 1; }
.streams circle { fill: var(--mark); }

.services { width: 0; height: 0; }
/* A service is its chip, placed by its centre; the name sits on the side away from the badge. */
.service { position: absolute; width: 64px; height: 64px; }
.service .chip {
  display: grid;
  place-items: center;
  flex: none;
  width: 64px;
  height: 64px;
  border-radius: 18px;
  background: var(--card);
  color: var(--ink);
  box-shadow: 0 10px 26px rgb(31 29 26 / 0.08), inset 0 0 0 2px transparent;
  transition: box-shadow 0.3s ease;
}
.service.is-lit .chip { box-shadow: 0 10px 26px rgb(31 29 26 / 0.08), inset 0 0 0 2.5px var(--mark); }
.service .chip img, .service .chip svg { width: 34px; height: 34px; object-fit: contain; }
.service .name { position: absolute; font-size: 24px; font-weight: 600; color: var(--text2); white-space: nowrap; }
.service[data-side="left"] .name { right: calc(100% + 14px); top: 50%; transform: translateY(-50%); }
.service[data-side="right"] .name { left: calc(100% + 14px); top: 50%; transform: translateY(-50%); }
.service[data-side="up"] .name { bottom: calc(100% + 10px); left: 50%; transform: translateX(-50%); }
.service[data-side="down"] .name { top: calc(100% + 10px); left: 50%; transform: translateX(-50%); }
.tall .service .name { font-size: 20px; }

.dot { width: 100px; height: 100px; border-radius: 50%; background: var(--mark); }
.dot svg { display: block; width: 100%; height: 100%; }

/* Made for the Duo, then its three modes. The section is tall so its scroll drives the phone; the stage stays put. */

.modes { height: 540vh; position: relative; }

/* After the intro the section starts over its last screen, zoomed into the phone showing the same hero, and pulls back.
   The link to it lands where the phone has settled. */
.intro-on:not(.no-3d) .modes { height: 620vh; margin-top: -100vh; scroll-margin-top: -100vh; }
.intro-on:not(.no-3d) .modes .stage { background: var(--bg); }
.intro-on:not(.no-3d) .modes:not(.is-pinned) .stage { visibility: hidden; }

.stage {
  position: sticky;
  top: 0;
  height: 100vh;
  height: 100svh;
  display: grid;
  grid-template-columns: minmax(300px, 36%) 1fr;
  align-items: center;
  padding: 64px var(--gutter) 0;
}

/* The canvas spans the stage so the phone can fill it; .view only marks where the phone rests. */
.view { height: 100%; min-height: 0; grid-column: 2; grid-row: 1; }
/* The phone passes in front of the steps while it is still large. */
#duo {
  position: absolute;
  inset: 0;
  z-index: 1;
  width: 100%;
  height: 100%;
  pointer-events: none;
  /* The shadow follows whatever outline the phone is drawn with, so it holds in every pose. */
  filter: drop-shadow(0 14px 18px rgb(40 30 20 / 0.14)) drop-shadow(0 44px 64px rgb(40 30 20 / 0.16));
}

/* The inner display while zooming, placed by main.js over the canvas's own. */
.screen {
  position: absolute;
  left: 0;
  top: 0;
  z-index: 1;
  transform-origin: 0 0;
  overflow: hidden;
  visibility: hidden;
  background: var(--bg);
  pointer-events: none;
}

.screen .hero { position: absolute; inset: auto; left: 50%; top: 50%; }

.steps {
  grid-column: 1;
  grid-row: 1;
  position: relative;
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
}

.step {
  grid-area: 1 / 1;
  display: grid;
  gap: 14px;
  align-content: center;
  opacity: 0;
  transform: translateY(16px);
  transition: opacity 0.45s ease, transform 0.45s ease;
  pointer-events: none;
}

.step.is-active { opacity: 1; transform: none; pointer-events: auto; }
.step h2 { font-size: clamp(34px, 4.2vw, 56px); }
.step p:not(.kicker) { color: var(--text2); font-size: 18px; max-width: 36ch; }
.still { display: none; }

@media (max-width: 820px) {
  .stage {
    grid-template-columns: 1fr;
    grid-template-rows: 1fr auto;
    padding: 56px var(--gutter) 28px;
  }
  .view { grid-column: 1; grid-row: 1; }
  .steps { grid-row: 2; min-height: 200px; align-content: start; }
  .step { align-content: start; }
  .step h2 { font-size: 32px; }
  .step p:not(.kicker) { font-size: 16px; }
}

/* Without WebGL the steps become a plain list with their captures. */

.no-3d .modes { height: auto; }
.no-3d .stage { position: static; height: auto; display: block; padding-top: 0; }
.no-3d .view, .no-3d #duo { display: none; }
.no-3d .steps { gap: 64px; }
.no-3d .step { grid-area: auto; opacity: 1; transform: none; }
.no-3d .still {
  display: block;
  margin-top: 12px;
  max-height: 520px;
  width: auto;
  border-radius: 24px;
  box-shadow: 0 20px 50px rgb(0 0 0 / 0.12);
}

/* How it works */

.how { padding: 18vh var(--gutter) 10vh; max-width: 1200px; margin: 0 auto; }
.how > h2 { font-size: clamp(36px, 5vw, 64px); margin-bottom: 40px; }

/* Three numbered steps on one rule, the number in the accent above each. */
.steps-how {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 40px;
  counter-reset: how;
}

.steps-how li {
  counter-increment: how;
  display: grid;
  gap: 10px;
  align-content: start;
  padding-top: 22px;
  background: linear-gradient(var(--line-strong), var(--line-strong)) top left / 100% 1.5px no-repeat;
}

.steps-how li::before {
  content: counter(how, decimal-leading-zero);
  font-family: var(--serif);
  font-size: 15px;
  font-weight: 600;
  letter-spacing: 0.08em;
  color: var(--mark);
}

.steps-how h3 { font-size: clamp(30px, 3.4vw, 40px); }
.steps-how p { color: var(--text2); max-width: 32ch; }

.how-also { margin-top: 40px; color: var(--meta); }

@media (max-width: 760px) {
  .steps-how { grid-template-columns: 1fr; gap: 28px; }
}

/* Scroll reveals, set up by reveal.js. */
.reveal-on [data-reveal] {
  opacity: 0;
  transform: translate(var(--rx, 0), var(--ry, 32px)) scale(var(--rs, 1));
  transition: opacity 0.8s ease var(--d, 0s), transform 1s cubic-bezier(0.2, 0.8, 0.2, 1) var(--d, 0s);
}
.reveal-on [data-reveal="spring"] { transition-timing-function: ease, cubic-bezier(0.34, 1.56, 0.64, 1); }
.reveal-on [data-reveal].is-in { opacity: 1; transform: none; }
.badge picture { display: block; }

/* Each step's rule draws across as it arrives. */
.reveal-on .steps-how li[data-reveal] { background-size: 0% 1.5px; transition-property: opacity, transform, background-size; transition-duration: 0.8s, 1s, 1.2s; }
.reveal-on .steps-how li[data-reveal].is-in { background-size: 100% 1.5px; }

/* Other devices */

.devices {
  max-width: 1200px;
  margin: 0 auto;
  padding: 10vh var(--gutter);
  display: grid;
  grid-template-columns: minmax(0, 0.7fr) minmax(0, 1fr) minmax(0, 1.6fr);
  gap: 40px;
  align-items: center;
}

.devices figure { margin: 0; }
.devices-copy { display: grid; gap: 14px; }
.devices-copy h2 { font-size: clamp(32px, 4vw, 48px); }
.devices-copy p { color: var(--text2); }

.phone img, .pad img {
  border: 6px solid #1c1b19;
  box-shadow: 0 30px 60px rgb(0 0 0 / 0.14);
}

.phone img { border-radius: 34px; }
.pad img { border-radius: 22px; }

@media (max-width: 820px) {
  .devices { grid-template-columns: 1fr 1.6fr; }
  .devices-copy { grid-column: 1 / -1; grid-row: 1; }
}

/* Private by design. Quieter than Pro: the copy on the left, four short points on a rule each. */

.private {
  max-width: 1200px;
  margin: 0 auto;
  padding: 10vh var(--gutter);
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.3fr);
  gap: 32px 64px;
  align-items: start;
}

.private-copy { display: grid; gap: 18px; justify-items: start; }
.private h2 { font-size: clamp(36px, 5vw, 64px); }

.private-more {
  color: var(--accent-ink);
  font-weight: 600;
  text-decoration: none;
}
.private-more::after { content: " \2192"; }
.private-more:hover { text-decoration: underline; text-underline-offset: 4px; }

.private-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 28px 40px;
}

.private-list li {
  padding-top: 18px;
  border-top: 1.5px solid var(--line-strong);
  color: var(--text2);
}

.private-list strong {
  display: block;
  margin-bottom: 6px;
  font-family: var(--serif);
  font-size: 22px;
  font-weight: 600;
  color: var(--ink);
}

@media (max-width: 820px) {
  .private { grid-template-columns: 1fr; }
}

@media (max-width: 560px) {
  .private-list { grid-template-columns: 1fr; gap: 22px; }
}

/* Pro */

.pro {
  max-width: 1200px;
  margin: 8vh auto 0;
  padding: 10vh var(--gutter);
  display: grid;
  gap: 18px;
}

.pro h2 { font-size: clamp(36px, 5vw, 64px); }

.pro-list {
  list-style: none;
  margin: 24px 0 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 16px;
}

.pro-list li {
  display: grid;
  align-content: start;
  gap: 8px;
  padding: 26px 24px 28px;
  border-radius: 22px;
  background: var(--raised);
}

.pro-icon { display: block; width: 28px; height: 28px; margin-bottom: 10px; color: var(--mark); }
.pro-icon svg { display: block; width: 100%; height: 100%; }
.pro-list strong { font-family: var(--serif); font-size: 22px; font-weight: 600; }
.pro-mark { margin-left: 2px; color: var(--mark); font-size: 0.6em; vertical-align: super; line-height: 0; }
.pro-note { color: var(--meta); font-size: 14px; }
.pro-note a { color: inherit; text-underline-offset: 3px; }
.pro-note a:hover { color: var(--ink); }
.pro-text { color: var(--text2); }

/* The last card is an open end, not a feature: no fill, a dashed edge. */
.pro-list .pro-more {
  align-content: center;
  justify-items: center;
  background: none;
  border: 1.5px dashed var(--line-strong);
}
.pro-more .pro-icon { margin-bottom: 0; color: var(--meta); }
.pro-more strong { color: var(--meta); font-weight: 500; }

/* Get it */

.get {
  display: grid;
  justify-items: center;
  gap: 22px;
  padding: 14vh var(--gutter);
  text-align: center;
}

.get > img { border-radius: 22px; }
.get h2 { font-size: clamp(40px, 6vw, 72px); }
.soon { margin: 0; color: var(--text2); font-size: 19px; }

/* Before launch there is nowhere to send people. */
:root.no-store [data-store] { display: none; }
:root:not(.no-store) .soon { display: none; }

.foot {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 8px 24px;
  padding: 28px var(--gutter) 40px;
  border-top: 1px solid var(--line);
  color: var(--meta);
  font-size: 13px;
}

.foot-links { display: flex; gap: 20px; }
.foot-text { display: flex; flex-direction: column; gap: 6px; }
.foot-legal { max-width: 62ch; font-size: 11px; line-height: 1.5; opacity: 0.7; }
.foot a { color: inherit; text-decoration: none; }
.foot a:hover, .foot a[aria-current] { color: var(--ink); }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .step, .store, .badge { transition: none; }
  .sound.is-on .sound-bars i { animation: none; transform: scaleY(0.7); }
}
