/*
 * Motion. The sticky note sticks when it arrives and the owl perches; cards
 * rise into place as they come into view, and each demo plays once it is well
 * in view (data-motion, marked seen by motion.js): the Markdown types itself
 * into a note, the files drop into Google Drive, the privacy promises tick.
 * Scroll-driven parts need animation-timeline and are left out without it;
 * everything is visible without any of it, and still with less motion.
 */

:root {
  --spring: cubic-bezier(0.34, 1.56, 0.64, 1);
}

.button:active,
.player:active {
  scale: 0.97;
  transition-duration: 0.1s;
}

@keyframes rise {
  from {
    opacity: 0;
    translate: 0 20px;
  }
}

@keyframes stick {
  from {
    opacity: 0;
    rotate: -9deg;
    scale: 1.12;
    translate: 0 -12px;
  }
}

@keyframes perch {
  from {
    opacity: 0;
    translate: 0 -60%;
  }
}

@keyframes hop {
  from {
    opacity: 0;
    rotate: -20deg;
    translate: 0 36px;
  }
}

@keyframes sweep {
  from {
    background-size: 0% 0.34em;
  }
}

/* Typed out, left to right. */
@keyframes type {
  from {
    clip-path: inset(0 100% 0 0);
  }
}

@keyframes appear {
  from {
    opacity: 0;
    translate: 0 8px;
  }
}

@keyframes drop-in {
  from {
    opacity: 0;
    translate: 28px 0;
  }
}

/* A line drawn along its length (--dash). */
@keyframes draw {
  from {
    stroke-dashoffset: var(--dash);
  }
}

@keyframes check-box {
  from {
    border-color: var(--muted);
    background-color: var(--page);
  }
}

@keyframes blink {
  50% {
    opacity: 0;
  }
}

@keyframes pop {
  40% {
    scale: 1.25;
  }

  70% {
    scale: 0.94;
  }
}

/* Off to the right, and back in from the left. */
@keyframes dash {
  45% {
    opacity: 0;
    translate: 0.6em 0;
  }

  46% {
    opacity: 0;
    translate: -0.6em 0;
  }
}

@keyframes raise {
  to {
    border-bottom-color: transparent;
    box-shadow: 0 10px 24px -18px rgb(38 30 26 / 45%);
  }
}

@media screen and (prefers-reduced-motion: no-preference) {
  /*
   * The panel fades into the color and theme picked, its stage with it. Only
   * what sets a color of its own moves: the rest inherits it, frame by frame.
   */
  .color-stage,
  .app-panel,
  .app-window *,
  .app-check::after {
    transition:
      background-color 0.35s var(--ease-out),
      border-color 0.35s var(--ease-out),
      box-shadow 0.35s var(--ease-out);
  }

  .app-window,
  .app-header,
  .app-avatar,
  .app-search,
  .app-input,
  .app-tool[data-pressed] {
    transition:
      color 0.35s var(--ease-out),
      background-color 0.35s var(--ease-out),
      border-color 0.35s var(--ease-out);
  }

  .hero .highlight {
    animation: sweep 0.9s var(--ease-out) 0.5s both;
  }

  .lede {
    animation: rise 0.8s var(--ease-out) 0.1s both;
  }

  .hero-scene {
    animation: rise 1.1s var(--ease-out) 0.15s both;
  }

  .hero-scene .perched-owl {
    animation: perch 0.8s var(--ease-out) 0.7s both;
  }

  .hero-sticky {
    animation: stick 0.6s cubic-bezier(0.16, 1, 0.3, 1) 0.9s both;
  }

  .hero-file {
    animation: rise 0.7s var(--ease-out) 1.1s both;
  }

  /* Picked up to read: the sticky note straightens, the owls look over. */
  .hero-sticky,
  .card-owl,
  .closing-owl {
    transition:
      rotate 0.5s var(--spring),
      translate 0.5s var(--spring),
      scale 0.5s var(--spring);
  }

  .hero-sticky:hover {
    rotate: -1deg;
    translate: 0 -6px;
  }

  .card-owl:hover,
  .closing-owl:hover {
    rotate: -8deg;
    scale: 1.06;
  }

  .card {
    transition:
      translate 0.35s var(--ease-out),
      box-shadow 0.35s var(--ease-out);
  }

  .card:hover {
    translate: 0 -4px;
    box-shadow: 0 24px 40px -30px rgb(38 30 26 / 45%);
  }

  .drive {
    transition: rotate 0.5s var(--spring);
  }

  .card:hover .drive {
    rotate: 0deg;
  }

  .icon-arrow {
    transition: translate 0.3s var(--spring);
  }

  .button:hover .icon-arrow {
    translate: 4px 0;
  }

  .arrow-link:is(:hover, :focus-visible)::after {
    animation: dash 0.5s var(--ease-out);
  }

  .swatch input:checked ~ .dot {
    animation: pop 0.4s var(--ease-out);
  }

  /* The answer unfolds rather than appears, where details can be sized to fit. */
  @supports (interpolate-size: allow-keywords) {
    .qa {
      interpolate-size: allow-keywords;
    }

    .qa::details-content {
      height: 0;
      overflow: clip;
      transition:
        height 0.35s var(--ease-out),
        content-visibility 0.35s allow-discrete;
    }

    .qa[open]::details-content {
      height: auto;
    }
  }

  .qa[open] summary::after {
    animation: pop 0.35s var(--ease-out);
  }

  /*
   * The demos, waiting on their first frame until seen. Only once motion.js
   * runs: without it they are simply there.
   */
  .motion
    [data-motion]
    :is(
      .line,
      .got > :not(.demo-label),
      .box,
      .tick,
      .drive-title,
      .drive li,
      .checks li,
      .checks .icon > *
    ) {
    animation-fill-mode: both;
  }

  .motion
    [data-motion]:not([data-seen])
    :is(
      .line,
      .got > :not(.demo-label),
      .box,
      .tick,
      .drive-title,
      .drive li,
      .checks li,
      .checks .icon > *
    ) {
    animation-play-state: paused;
  }

  /* As you type: each line of Markdown, then what it turns into beside it. */
  .typed .line {
    display: inline-block;
  }

  .motion [data-motion] .line {
    animation-name: type;
    animation-duration: 0.45s;
    animation-timing-function: steps(12, end);
  }

  .motion [data-motion] .line:nth-child(2) {
    animation-delay: 0.75s;
  }

  .motion [data-motion] .line:nth-child(3) {
    animation-delay: 1.5s;
  }

  .motion [data-motion] .got > :not(.demo-label) {
    animation-name: appear;
    animation-duration: 0.4s;
    animation-timing-function: var(--ease-out);
    animation-delay: 0.45s;
  }

  .motion [data-motion] .got > .done {
    animation-delay: 1.2s;
  }

  .motion [data-motion] .got > :last-child {
    animation-delay: 1.95s;
  }

  .motion [data-motion] .done .box {
    animation: check-box 0.2s 1.5s both;
  }

  .motion [data-motion] .tick {
    --dash: 20;
    stroke-dasharray: 20;
    animation: draw 0.3s var(--ease-out) 1.6s both;
  }

  /* A caret, once the last line is typed. */
  .motion [data-seen] .typed pre::after {
    content: '';
    display: inline-block;
    width: 0.5em;
    height: 1.1em;
    margin-left: 2px;
    vertical-align: text-bottom;
    opacity: 0;
    background: var(--wordmark-gold);
    animation: blink 1.1s step-end 2s infinite;
  }

  /* Each file dropping into Google Drive. */
  .motion [data-motion] :is(.drive-title, .drive li) {
    animation-name: drop-in;
    animation-duration: 0.5s;
    animation-timing-function: var(--spring);
  }

  .motion [data-motion] .drive li:nth-child(1) {
    animation-delay: 0.15s;
  }

  .motion [data-motion] .drive li:nth-child(2) {
    animation-delay: 0.3s;
  }

  .motion [data-motion] .drive li:nth-child(3) {
    animation-delay: 0.45s;
  }

  /* Each promise ticked: its circle drawn round, then its check. */
  .motion [data-motion] .checks li {
    animation-name: appear;
    animation-duration: 0.4s;
    animation-timing-function: var(--ease-out);
  }

  .motion [data-motion] .checks .icon circle {
    --dash: 57;
    stroke-dasharray: 57;
    animation: draw 0.5s var(--ease-out) 0.15s both;
  }

  .motion [data-motion] .checks .icon path {
    --dash: 13;
    stroke-dasharray: 13;
    animation: draw 0.25s var(--ease-out) 0.55s both;
  }

  .motion [data-motion] .checks li:nth-child(2) {
    animation-delay: 0.25s;
  }

  .motion [data-motion] .checks li:nth-child(2) .icon circle {
    animation-delay: 0.4s;
  }

  .motion [data-motion] .checks li:nth-child(2) .icon path {
    animation-delay: 0.8s;
  }

  .motion [data-motion] .checks li:nth-child(3) {
    animation-delay: 0.5s;
  }

  .motion [data-motion] .checks li:nth-child(3) .icon circle {
    animation-delay: 0.65s;
  }

  .motion [data-motion] .checks li:nth-child(3) .icon path {
    animation-delay: 1.05s;
  }

  /* The four reasons at a glance, each hopping once in turn; never hidden. */
  .motion .glance[data-seen] .icon {
    animation: pop 0.5s var(--ease-out) both;
  }

  .motion .glance[data-seen] li:nth-child(2) .icon {
    animation-delay: 0.1s;
  }

  .motion .glance[data-seen] li:nth-child(3) .icon {
    animation-delay: 0.2s;
  }

  .motion .glance[data-seen] li:nth-child(4) .icon {
    animation-delay: 0.3s;
  }

  @supports (animation-timeline: view()) {
    .card,
    .privacy-card,
    .qa {
      animation: rise linear both;
      animation-timeline: view();
      animation-range: entry 0% entry 60%;
    }

    .closing-owl {
      animation: hop linear both;
      animation-timeline: view();
      animation-range: entry 10% entry 100%;
    }
  }

  /* The header lifts off the page once it has something to float over. */
  @supports (animation-timeline: scroll()) {
    .site-header {
      animation: raise linear both;
      animation-timeline: scroll();
      animation-range: 0 120px;
    }
  }
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  .button,
  .site-nav a,
  .segmented span,
  .player .play,
  .swatch .dot,
  .scheme label,
  .scheme-track,
  .knob {
    transition: none;
  }
}
