/*
 * The look of the web page, and how it moves. Language: CSS.
 *
 * It follows the app: black and white, colour only where it means something
 * (the green of "Paid"), and the app's own shape, a black top with the page
 * rising over it on round corners. The colours and sizes are the app's
 * (apps/mobile/src/constants/theme.ts and glass.ts).
 *
 * Movement. Every rule that makes something move begins with "html.moves" (written
 * ".moves" below). The first lines of each page put that word there, unless the
 * visitor's device asks for less movement: then the page says "still", none of those
 * rules apply, and every thing is simply in its place. So the rules without ".moves"
 * describe the page as it rests, and the ".moves" rules only say how it gets there.
 * What the movement must keep to is in docs/DESIGN.md, "How the web page moves".
 */

@font-face {
  font-family: 'Alexandria';
  src: url('/assets/alexandria-800.ttf') format('truetype');
  font-weight: 800;
  font-display: swap;
}

/* The number in the picture of the app is a real number to the browser, so that it can count. */
@property --paid {
  syntax: '<integer>';
  initial-value: 100;
  inherits: false;
}

:root {
  color-scheme: light dark;
  --text: #000000;
  --text-secondary: #636366;
  --page: #ffffff;
  --element: #f4f4f5;
  --border: #e2e2e4;
  --ghost: #c7c7cc;
  --success: #15803d;
  --top: #000000;
  --top-text: #ffffff;
  --top-secondary: #a9a9ae;
  --top-pill: rgba(255, 255, 255, 0.16);
  --top-success: #4ade80;
  /* The edge of a black card. Only needed where the page around it is black too. */
  --card-edge: transparent;
  --radius-page: 30px;
  --width: 1040px;
  --gutter: 24px;

  /* How things move. Slowing towards the end, like something coming to rest. */
  --ease: cubic-bezier(0.22, 1, 0.36, 1);
  /* The film in the picture of the app: when it begins, and how long until the next person
     pays. With these two it has ended about four and a half seconds after it was let go. */
  --start: 1000ms;
  --step: 600ms;
}

@media (prefers-color-scheme: dark) {
  :root {
    --text: #ffffff;
    --text-secondary: #a1a1a6;
    --page: #000000;
    --element: #1c1c1e;
    --border: #303033;
    --ghost: #48484a;
    --success: #4ade80;
    --card-edge: #303033;
  }
}

/* Going from one page of the site to another, the old page fades into the new one. */
@view-transition {
  navigation: auto;
}

* {
  box-sizing: border-box;
}

html {
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--top);
  color: var(--text);
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Noto Sans Arabic', 'Helvetica Neue', Arial, sans-serif;
  font-size: 17px;
  line-height: 1.6;
}

a {
  color: inherit;
}

a:focus-visible,
summary:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 3px;
  border-radius: 4px;
}

.wrap {
  width: 100%;
  max-width: var(--width);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

/* A word of a headline. Each is a small block of its own, so that it can rise by itself. */
.word {
  display: inline-block;
}

/* ------------------------------------------------------------------ the black top */

.top {
  background: var(--top);
  color: var(--top-text);
  overflow: hidden;
}

/* While the page moves, the black top stays where it is and the white page slides up over
   it, as the sheet does in the app. site.js measures the top (--hero) and says how much of
   it is covered (--cover, from 0 to 1); the top then dims and sinks back a little. A top
   taller than the screen is first scrolled to its end, and stays from there. */
.top.pinned {
  position: sticky;
  top: min(0px, calc(100vh - var(--hero)));
}

.top.pinned > .wrap {
  opacity: calc(1 - var(--cover, 0) * 0.6);
  transform: scale(calc(1 - var(--cover, 0) * 0.05));
  transform-origin: 50% 40%;
  will-change: opacity, transform;
}

/* Once the page has covered all of it, it is put away, so that nothing of it shows past the end of the page. */
.top.covered {
  visibility: hidden;
}

.bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding-block: 20px;
}

.logo {
  display: block;
  height: 36px;
  width: auto;
}

.bar a {
  text-decoration: none;
}

.language {
  color: var(--top-text);
  background: var(--top-pill);
  border-radius: 999px;
  padding: 8px 16px;
  font-size: 15px;
  line-height: 1.3;
}

.hero {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 32px;
  padding-block: 24px 0;
}

.hero h1 {
  font-family: 'Alexandria', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  font-weight: 800;
  font-size: clamp(34px, 7vw, 60px);
  line-height: 1.12;
  letter-spacing: -0.01em;
  margin: 0 0 16px;
}

:lang(ar) .hero h1 {
  line-height: 1.4;
  letter-spacing: 0;
}

.hero p {
  color: var(--top-secondary);
  font-size: clamp(18px, 2.4vw, 21px);
  margin: 0 0 24px;
  max-width: 32em;
}

.stores {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
}

.store,
.soon {
  border-radius: 999px;
  padding: 12px 22px;
  font-size: 16px;
  line-height: 1.3;
  text-decoration: none;
}

.store {
  display: inline-block;
  background: var(--top-text);
  color: var(--top);
  font-weight: 600;
}

/* "Coming soon", with a small dot before it. A little smaller than a button, so that it
   stays on one line on a narrow phone. */
.soon {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 11px 20px;
  font-size: 15px;
  background: var(--top-pill);
  color: var(--top-text);
}

.soon::before {
  content: '';
  flex: none;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: currentColor;
}

/* The little picture of the app. Only its upper part shows: the page below rises over the rest. */
.phone {
  justify-self: center;
  width: 280px;
  height: 372px;
  border: 1px solid #3a3a3c;
  border-bottom: 0;
  border-radius: 40px 40px 0 0;
  padding: 10px 10px 0;
  background: #0b0b0c;
  /* A faint light behind it, so that it stands off the black. */
  box-shadow: 0 0 110px 10px rgba(255, 255, 255, 0.08);
}

.screen {
  height: 100%;
  border-radius: 31px 31px 0 0;
  background: var(--top);
  overflow: hidden;
  display: flex;
  flex-direction: column;
  font-size: 13px;
  line-height: 1.4;
}

.screen-top {
  padding: 22px 18px 34px;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.screen-hello {
  color: var(--top-secondary);
}

.screen-pool {
  font-size: 20px;
  font-weight: 700;
  color: var(--top-text);
}

.screen-amount {
  color: var(--top-secondary);
}

/* The number that counts. The browser writes it from --paid, which the film changes. */
.count {
  --paid: 100;
  counter-reset: paid var(--paid);
}

.count::after {
  content: counter(paid);
}

.screen-bar {
  margin-top: 8px;
  height: 6px;
  border-radius: 3px;
  background: var(--top-pill);
  overflow: hidden;
}

/* In Arabic the bar fills from the right: the whole bar is turned round. */
[dir='rtl'] .screen-bar {
  transform: scaleX(-1);
}

.screen-bar i {
  display: block;
  height: 100%;
  border-radius: 3px;
  background: var(--top-text);
}

.screen-sheet {
  flex: 1;
  margin-top: -18px;
  border-radius: 20px 20px 0 0;
  background: #ffffff;
  color: #000000;
  padding: 8px 16px;
}

.screen-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 9px 0;
  border-bottom: 1px solid #e2e2e4;
}

/* "Not yet" and "Paid" lie in the same place, one over the other. At rest only "Paid" shows. */
.status {
  display: inline-grid;
  justify-items: end;
}

.status > span {
  grid-area: 1 / 1;
}

.status-waiting {
  color: #636366;
  opacity: 0;
}

.status-paid {
  color: #15803d;
  font-weight: 600;
}

/* The small green circle with a tick: the one colour on the page, and it means "paid". */
.done {
  display: inline-grid;
  place-items: center;
  flex: none;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: var(--top-success);
  color: #000000;
}

.done svg {
  display: block;
  width: 12px;
  height: 12px;
}

.screen-pool .done {
  width: 17px;
  height: 17px;
  margin-inline-start: 7px;
  vertical-align: 1px;
}

.screen-pool .done svg {
  width: 10px;
  height: 10px;
}

/* ------------------------------------------------------------------ the page that rises over it */

.page {
  position: relative;
  z-index: 1;
  margin-top: calc(-1 * var(--radius-page));
  border-radius: var(--radius-page) var(--radius-page) 0 0;
  /* Where the page is black too (a device set to dark), a thin edge shows where it begins. */
  border-top: 1px solid var(--card-edge);
  background: var(--page);
  color: var(--text);
  padding-block: 56px 32px;
}

/* The home page begins with the ribbon, which sits closer to the round corners. */
.page.led {
  padding-top: 30px;
}

/* A page of text has only the black row above it. The row is made taller there, so that
   the page still rises over black and the logo keeps its room. */
.top.slim .bar {
  padding-bottom: calc(20px + var(--radius-page));
}

/* A short page of text still reaches the bottom of the screen, so that no black shows
   under it. 76 points is where the page begins under the black row. (The second line is
   for phones, whose screen is shorter while the browser's own bars show.) */
.top.slim + .page {
  min-height: calc(100vh - 76px);
  min-height: calc(100svh - 76px);
}

h2 {
  font-size: clamp(24px, 3.4vw, 30px);
  line-height: 1.25;
  margin: 0 0 24px;
}

/* The ribbon: what people collect for, in large words, from one edge of the screen to the
   other. While the page moves, site.js slides it sideways as the page is scrolled (--slide,
   in points). At rest it simply shows its first words. */
.ribbon {
  overflow: hidden;
  margin-bottom: 44px;
}

.ribbon-track {
  display: flex;
  width: max-content;
  padding-inline-start: var(--gutter);
  transform: translateX(calc(var(--slide, 0) * -1px));
  will-change: transform;
}

[dir='rtl'] .ribbon-track {
  transform: translateX(calc(var(--slide, 0) * 1px));
}

.ribbon span {
  flex: none;
  font-family: 'Alexandria', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  font-weight: 800;
  font-size: clamp(30px, 6.2vw, 58px);
  line-height: 1.35;
  white-space: nowrap;
  padding-inline-end: 0.55em;
  color: var(--text);
}

.ribbon span:nth-child(even) {
  color: var(--ghost);
}

:lang(ar) .ribbon span {
  line-height: 1.75;
}

/* The small scene: the group chat nobody answers, and beside it the app doing the asking. */
.scene {
  margin: 0 0 56px;
}

.scene-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 16px;
}

.chat,
.with {
  display: flex;
  flex-direction: column;
  gap: 8px;
  border-radius: 24px;
  padding: 22px 20px 26px;
}

.chat {
  background: var(--element);
}

.with {
  background: var(--top);
  color: var(--top-text);
  border: 1px solid var(--card-edge);
}

.scene-label {
  margin: 0 0 10px;
  font-size: 13px;
  font-weight: 600;
  color: var(--text-secondary);
}

.with .scene-label {
  color: var(--top-secondary);
}

.bubble {
  margin: 0;
  max-width: 86%;
  padding: 9px 14px;
  border-radius: 19px;
  font-size: 16px;
  line-height: 1.4;
}

/* What the collector wrote is on the far side and dark; an answer is on the near side and light. */
.mine {
  align-self: flex-end;
  background: var(--text);
  color: var(--page);
  border-end-end-radius: 6px;
  transform-origin: 100% 100%;
}

.theirs {
  justify-self: start;
  background: var(--page);
  color: var(--text);
  border-end-start-radius: 6px;
  transform-origin: 0 100%;
}

[dir='rtl'] .mine {
  transform-origin: 0 100%;
}

[dir='rtl'] .theirs {
  transform-origin: 100% 100%;
}

.theirs b {
  display: block;
  font-size: 12px;
  font-weight: 600;
  color: var(--text-secondary);
}

/* "Seen by 11", under what the collector wrote. (Not called "seen": that word is the one
   site.js writes on a thing that has been scrolled to.) */
.read-by {
  align-self: flex-end;
  margin: -2px 4px 6px;
  font-size: 12px;
  color: var(--text-secondary);
}

/* The three dots of someone writing, and the answer itself, lie in the same place. At rest only the answer shows. */
.reply {
  display: grid;
  justify-items: start;
  align-items: end;
}

.reply > * {
  grid-area: 1 / 1;
}

.typing {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 15px 14px;
  opacity: 0;
}

.typing i {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--text-secondary);
}

/* The reminder, drawn the way a phone shows a message from an app: white on the black card. */
.remind {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 8px;
  border-radius: 18px;
  padding: 12px 14px;
  background: #ffffff;
  color: #000000;
}

.remind img {
  flex: none;
  display: block;
  border-radius: 9px;
}

.remind p {
  margin: 0;
  font-size: 15px;
  line-height: 1.35;
}

.remind b {
  display: block;
  font-size: 13px;
}

.paid-line {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin: 0;
  padding: 9px 4px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.16);
  font-size: 16px;
}

.everyone {
  margin: 10px 4px 0;
  font-size: 17px;
  font-weight: 700;
}

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

.feature {
  background: var(--element);
  border-radius: 20px;
  padding: 24px;
}

.feature svg {
  display: block;
  width: 28px;
  height: 28px;
  margin-bottom: 16px;
}

.feature h3 {
  font-size: 19px;
  line-height: 1.3;
  margin: 0 0 8px;
}

.feature p {
  margin: 0;
  color: var(--text-secondary);
}

.money {
  border: 1px solid var(--border);
  border-radius: 20px;
  padding: 20px 24px;
  margin: 0 0 56px;
  font-size: 18px;
}

.questions {
  margin: 0 0 56px;
  border-top: 1px solid var(--border);
}

.questions details {
  border-bottom: 1px solid var(--border);
}

.questions summary {
  cursor: pointer;
  list-style: none;
  padding: 18px 0;
  font-size: 18px;
  font-weight: 600;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
}

.questions summary::-webkit-details-marker {
  display: none;
}

/* The sign at the end of a question: a plus, drawn as two bars. Open, the upright bar is gone and a minus is left. */
.questions summary::after {
  content: '';
  flex: none;
  width: 16px;
  height: 16px;
  color: var(--text-secondary);
  background:
    linear-gradient(currentColor, currentColor) center / 100% 2px no-repeat,
    linear-gradient(currentColor, currentColor) center / 2px 100% no-repeat;
}

.questions details[open] summary::after {
  transform: rotate(180deg);
  background-size:
    100% 2px,
    2px 0;
}

.questions details p {
  margin: 0 0 20px;
  color: var(--text-secondary);
  max-width: 44em;
}

.closing {
  background: var(--top);
  color: var(--top-text);
  border: 1px solid var(--card-edge);
  border-radius: 28px;
  padding: 40px 28px;
  text-align: center;
  margin: 0 0 40px;
}

.closing h2 {
  font-family: 'Alexandria', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  font-weight: 800;
  margin: 0 0 20px;
}

:lang(ar) .closing h2 {
  line-height: 1.5;
}

.closing .stores {
  justify-content: center;
}

.foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 12px 24px;
  border-top: 1px solid var(--border);
  padding-top: 24px;
  color: var(--text-secondary);
  font-size: 15px;
}

.foot nav {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 20px;
}

.foot a {
  text-decoration: none;
}

.foot a:hover {
  text-decoration: underline;
}

/* ------------------------------------------------------------------ the pages of text */

.article {
  max-width: 46em;
}

.article h1 {
  font-size: clamp(28px, 5vw, 38px);
  line-height: 1.2;
  margin: 0 0 8px;
}

.article .updated {
  color: var(--text-secondary);
  margin: 0 0 24px;
}

.article h2 {
  font-size: 21px;
  margin: 32px 0 8px;
}

.article p,
.article li {
  margin: 0 0 12px;
}

.article ul {
  margin: 0 0 12px;
  padding-inline-start: 22px;
}

.notice {
  background: var(--element);
  border-radius: 16px;
  padding: 16px 20px;
  margin: 0 0 24px;
  color: var(--text-secondary);
}

.email {
  font-size: 22px;
  font-weight: 600;
}

/* The page for an address that does not exist: the number large and pale, then the app's
   own words, then the way home as a button. */
.article.lost {
  margin-inline: auto;
  padding-block: 16px 40px;
  text-align: center;
}

.article .lost-number {
  font-family: 'Alexandria', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  font-weight: 800;
  font-size: clamp(76px, 24vw, 136px);
  line-height: 1;
  color: var(--ghost);
  margin: 0 0 16px;
}

.article.lost h1 {
  margin-bottom: 12px;
}

.go {
  display: inline-block;
  margin-top: 12px;
  border-radius: 999px;
  padding: 12px 22px;
  background: var(--text);
  color: var(--page);
  font-weight: 600;
  text-decoration: none;
}

/* ------------------------------------------------------------------ wide screens */

@media (min-width: 720px) {
  .scene-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .chat,
  .with {
    padding: 26px 26px 30px;
  }
}

@media (min-width: 860px) {
  .hero {
    grid-template-columns: minmax(0, 1fr) 300px;
    align-items: end;
    gap: 48px;
    padding-block: 40px 0;
  }

  .hero-text {
    padding-bottom: 96px;
  }

  .phone {
    height: 430px;
  }
}

/* ==================================================================== how the page moves

   Nothing below applies to a page that says "still".

   What it keeps to (docs/DESIGN.md, "How the web page moves"):
   - Whatever starts by itself has ended within five seconds of the page opening, and
     nothing goes round for ever.
   - Only place and see-through-ness change (transform, opacity, the cut-out of a word, the
     dashes of a line): the cheap things for a phone to draw.
   - A press is answered the way the app answers it: the button sinks to 96 hundredths in
     90 thousandths of a second (apps/mobile/src/constants/motion.ts).
*/

/* ---- the top arrives: the row, then the headline word by word, the sentence, the button, the picture */

.moves .bar {
  animation: fade 600ms ease both;
}

.moves .hero .word {
  animation: rise 800ms var(--ease) both;
  animation-delay: calc(100ms + var(--i) * 70ms);
}

.moves .hero-text > p {
  animation: lift 800ms var(--ease) 420ms both;
}

.moves .hero-text > .stores {
  animation: lift 800ms var(--ease) 540ms both;
}

.moves .phone {
  animation: arrive 1000ms var(--ease) 250ms both;
}

/* The dot of "Coming soon" sends out two rings. */
.moves .hero .soon::before {
  animation: ring 1400ms ease-out 1300ms 2;
}

/* A page of text arrives softly, all of it at once. */
.moves .top.slim + .page > .wrap {
  animation: lift 700ms var(--ease) 60ms both;
}

@keyframes fade {
  from {
    opacity: 0;
  }
}

@keyframes lift {
  from {
    opacity: 0;
    transform: translateY(18px);
  }
}

@keyframes arrive {
  from {
    opacity: 0;
    transform: translateY(90px);
  }
}

/* A word comes up from under an edge that cannot be seen. The cut-out ends wider than the
   word, so that no tail or dot of a letter stays cut off. */
@keyframes rise {
  from {
    opacity: 0;
    transform: translateY(70%);
    clip-path: inset(0 -10% 100% -10%);
  }
  30% {
    opacity: 1;
  }
  to {
    opacity: 1;
    transform: none;
    clip-path: inset(-40% -10% -40% -10%);
  }
}

@keyframes ring {
  from {
    box-shadow: 0 0 0 0 rgba(255, 255, 255, 0.55);
  }
  to {
    box-shadow: 0 0 0 11px rgba(255, 255, 255, 0);
  }
}

/* ---- the film in the picture of the app

   It begins at --start and each person takes --step. Person number --n pays at
   --start + n steps. The bar and the number are one movement five steps long, cut into
   five equal parts: in the first half of each part they change, in the second they rest.
   site.js plays the film again by taking "rest" on and off the picture. */

.moves .phone:not(.rest) .status-waiting {
  animation: leave 260ms ease both;
  animation-delay: calc(var(--start) + var(--n) * var(--step));
}

.moves .phone:not(.rest) .status-paid {
  animation: pop 420ms ease-out both;
  animation-delay: calc(var(--start) + var(--n) * var(--step) + 60ms);
}

.moves .phone:not(.rest) .screen-bar i {
  animation: fill calc(5 * var(--step)) var(--ease) var(--start) both;
}

.moves .phone:not(.rest) .count {
  animation: count calc(5 * var(--step)) var(--ease) var(--start) both;
}

.moves .phone:not(.rest) .screen-pool .done {
  animation: pop 520ms ease-out both;
  animation-delay: calc(var(--start) + 5 * var(--step));
}

/* site.js writes "hold" on the picture as the page opens, and takes it off once most of
   the picture is really being shown. Until then the film waits at its first moment. */
.moves .phone.hold .screen * {
  animation-play-state: paused !important;
}

@keyframes leave {
  from {
    opacity: 1;
  }
  to {
    opacity: 0;
  }
}

/* Something small arrives a little too big and settles: the app's own "pop" starts at 0.8 too. */
@keyframes pop {
  from {
    opacity: 0;
    transform: scale(0.8);
  }
  60% {
    opacity: 1;
    transform: scale(1.12);
  }
}

@keyframes fill {
  0% {
    transform: translateX(-100%);
  }
  10%,
  20% {
    transform: translateX(-80%);
  }
  30%,
  40% {
    transform: translateX(-60%);
  }
  50%,
  60% {
    transform: translateX(-40%);
  }
  70%,
  80% {
    transform: translateX(-20%);
  }
  90%,
  100% {
    transform: translateX(0);
  }
}

@keyframes count {
  0% {
    --paid: 0;
  }
  10%,
  20% {
    --paid: 20;
  }
  30%,
  40% {
    --paid: 40;
  }
  50%,
  60% {
    --paid: 60;
  }
  70%,
  80% {
    --paid: 80;
  }
  90%,
  100% {
    --paid: 100;
  }
}

/* ---- what is further down waits, and arrives when it is scrolled to

   site.js writes "wait" on each such thing that is still below the screen when the page
   opens, and "seen" once it has been scrolled to. --i makes neighbours arrive one after
   another. */

.moves .wait {
  opacity: 0;
  transform: translateY(26px);
}

.moves .wait.seen {
  opacity: 1;
  transform: none;
  transition:
    opacity 700ms var(--ease),
    transform 800ms var(--ease);
  transition-delay: calc(var(--i, 0) * 90ms);
}

/* The pieces of the small scene arrive one by one, each at its own moment (--d). */
.moves .wait.seen .step {
  animation: step 520ms var(--ease) both;
  animation-delay: var(--d);
}

.moves .wait.seen .bubble.step {
  animation-name: bubble;
}

.moves .wait.seen .remind.step {
  animation-name: drop;
  animation-duration: 650ms;
}

/* The three dots of someone writing show for a second, then the answer takes their place. */
.moves .wait.seen .typing {
  animation: typing 1100ms ease both;
  animation-delay: var(--d);
}

.moves .wait.seen .typing i {
  animation: dot 480ms ease-in-out 2;
  animation-delay: calc(var(--d) + 120ms);
}

.moves .wait.seen .typing i:nth-child(2) {
  animation-delay: calc(var(--d) + 240ms);
}

.moves .wait.seen .typing i:nth-child(3) {
  animation-delay: calc(var(--d) + 360ms);
}

.moves .wait.seen .paid-line .done {
  animation: pop 460ms ease-out both;
  animation-delay: calc(var(--d) + 200ms);
}

@keyframes step {
  from {
    opacity: 0;
    transform: translateY(10px);
  }
}

@keyframes bubble {
  from {
    opacity: 0;
    transform: translateY(8px) scale(0.86);
  }
}

@keyframes drop {
  from {
    opacity: 0;
    transform: translateY(-22px) scale(0.96);
  }
}

@keyframes typing {
  0% {
    opacity: 0;
  }
  18%,
  82% {
    opacity: 1;
  }
  100% {
    opacity: 0;
  }
}

@keyframes dot {
  50% {
    transform: translateY(-4px);
  }
}

/* The three small drawings draw themselves, line after line. When a line is done its
   dashes are taken away again, so the drawing rests exactly as it was. */
.moves .feature.wait.seen svg > * {
  animation: draw 900ms var(--ease) backwards;
  animation-delay: calc(250ms + var(--i) * 90ms);
}

.moves .feature.wait.seen svg > :nth-child(2) {
  animation-delay: calc(360ms + var(--i) * 90ms);
}

.moves .feature.wait.seen svg > :nth-child(3) {
  animation-delay: calc(470ms + var(--i) * 90ms);
}

.moves .feature.wait.seen svg > :nth-child(n + 4) {
  animation-delay: calc(580ms + var(--i) * 90ms);
}

@keyframes draw {
  0% {
    stroke-dasharray: 1;
    stroke-dashoffset: 1;
    opacity: 0;
  }
  12% {
    opacity: 1;
  }
  100% {
    stroke-dasharray: 1;
    stroke-dashoffset: 0;
    opacity: 1;
  }
}

/* The last card says the headline once more, word by word, and its dot sends out its rings. */
.moves .closing.wait.seen .word {
  animation: rise 800ms var(--ease) both;
  animation-delay: calc(250ms + var(--i) * 70ms);
}

.moves .closing.wait.seen .soon::before {
  animation: ring-again 1400ms ease-out 900ms 2;
}

@keyframes ring-again {
  from {
    box-shadow: 0 0 0 0 rgba(255, 255, 255, 0.55);
  }
  to {
    box-shadow: 0 0 0 11px rgba(255, 255, 255, 0);
  }
}

/* ---- answers to a touch */

/* A button sinks under the finger and comes back, as in the app. */
.moves .language,
.moves .store,
.moves .go {
  transition: transform 90ms ease-out;
}

.moves .language:active,
.moves .store:active,
.moves .go:active {
  transform: scale(0.96);
}

/* The plus of a question turns into its minus, and the answer comes in softly. */
.moves .questions summary::after {
  transition:
    transform 300ms var(--ease),
    background-size 300ms var(--ease);
}

.moves .questions details[open] p {
  animation: lift 360ms var(--ease) both;
}

/* Where the browser can do it, the answer also opens and closes by growing and shrinking. */
@supports (interpolate-size: allow-keywords) {
  .moves .questions details {
    interpolate-size: allow-keywords;
  }

  .moves .questions details::details-content {
    block-size: 0;
    overflow: clip;
    transition:
      block-size 360ms var(--ease),
      content-visibility 360ms allow-discrete;
  }

  .moves .questions details[open]::details-content {
    block-size: auto;
  }
}
