/* ==========================================================================
   Motion.css — Dreamlist motion system
   The logo loader on the first page of a visit, native page transitions
   (cross-document View Transitions in Chrome and Safari), hero entrances,
   scroll reveals and small interactions.

   Everything animated here waits for html.has-motion, which the inline
   bootstrap in layout.antlers.html sets only when JavaScript runs and the
   visitor has not asked for reduced motion; without it, pages render as
   they always have. Only transform, opacity and clip-path animate, so the
   work stays on the compositor.

   Rhythm (after Code and Theory): durations sit on a 1/12-second grid
   (167 / 250 / 333 / 500 / 667 / 833 ms) and opacity always runs shorter
   and softer than the movement it travels with. Five curves:
   settle  cubic-bezier(0.12, 0.52, 0.17, 1)   movement into place
   fade    cubic-bezier(0.17, 0.17, 0.67, 1)   opacity
   quick   cubic-bezier(0.33, 0, 0, 1)         hover and press
   glide   cubic-bezier(0.4, 0, 0.2, 1)        indicators, the header
   exit    cubic-bezier(0.4, 0, 1, 1)          leaving
   ========================================================================== */

/* =========================================================
   ENTRANCE CLOCK
   ========================================================= */

/* When each page's hero starts its entrance: straight away on a plain load,
   a beat into an arriving page transition, and as the curtain lifts on the
   first page of a visit. */
html {
  --enter: 0s;
}

.is-arriving {
  --enter: 0.083s;
}

.is-loading {
  --enter: 1.3s;
}

/* =========================================================
   LOADER
   ========================================================= */

/* Shown only on the first page of a visit (html.is-loading), and timed
   entirely in CSS so it starts with the first frame and never waits for a
   script; js/motion.js only adds the skip and removes it afterwards. The
   choreography is the Dreamlist video signature, tightened for the web:
   0.10 s  the D, a notebook page, turns in on its binding edge
   0.30 s  its nine rings punch through, top to bottom
   0.60 s  it slides left into the lockup as "Dreamlist" writes out
   1.25 s  the lockup leaves and the paper lifts away as a curtain
   1.92 s  gone; the page's own entrance has been rising beneath since 1.3 s */

.site-loader {
  display: none;
}

.is-loading .site-loader {
  position: fixed;
  inset: 0;
  z-index: 3000;
  display: grid;
  place-items: center;
  background-color: var(--paper);
  animation: loader-lift 0.667s cubic-bezier(0.12, 0.52, 0.17, 1) 1.25s both;
}

/* Dark Mode */
@media (prefers-color-scheme: dark) {
  .is-loading .site-loader {
    background-color: var(--night);
  }
}

.site-loader__wash {
  position: absolute;
  inset: 0;
  background:
    radial-gradient(60% 60% at 85% 0%, rgba(57, 194, 216, 0.16) 0%, rgba(57, 194, 216, 0) 60%),
    radial-gradient(50% 60% at 0% 100%, rgba(160, 100, 169, 0.16) 0%, rgba(160, 100, 169, 0) 65%);
}

/* The lockup is drawn in em (the official proportions: icon 830, gap 120,
   wordmark 1970 units wide), so one font-size scales it. */
.site-loader__lockup {
  position: relative;
  display: flex;
  align-items: center;
  gap: 0.49em;
  font-size: 16px;
  animation: loader-lockup-leave 0.333s cubic-bezier(0.4, 0, 1, 1) 1.25s both;
}

/* Tablet Portrait Up - Min 600px */
@media (min-width: 600px) {
  .site-loader__lockup {
    font-size: 21px;
  }
}

/* Tablet Landscape Up - Min 900px */
@media (min-width: 900px) {
  .site-loader__lockup {
    font-size: 26px;
  }
}

/* The icon slides; the page inside it turns. */
.site-loader__icon {
  display: block;
  flex: none;
  width: 3.4em;
  animation: loader-icon-slide 0.5s cubic-bezier(0.4, 0, 0.2, 1) 0.6s both;
}

.site-loader__page {
  display: block;
  transform-origin: 0% 50%;
  animation:
    loader-page-turn 0.667s cubic-bezier(0.12, 0.52, 0.17, 1) 0.1s both,
    loader-page-show 0.25s cubic-bezier(0.17, 0.17, 0.67, 1) 0.1s both;
}

.site-loader__page svg,
.site-loader__word svg {
  display: block;
  width: 100%;
  height: auto;
  overflow: visible;
}

/* The rings are painted in the ground colour over the page, so they read
   as the cut-outs of the official logo while they punch through. */
.site-loader__ring {
  fill: var(--paper);
  transform-box: fill-box;
  transform-origin: 0% 50%;
  animation: loader-ring 0.333s cubic-bezier(0.12, 0.52, 0.17, 1) both;
  animation-delay: calc(0.3s + var(--ring) * 0.04s);
}

/* Dark Mode */
@media (prefers-color-scheme: dark) {
  .site-loader__ring {
    fill: var(--night);
  }
}

.site-loader__word {
  display: block;
  flex: none;
  width: 8.07em;
  color: var(--black);
  animation:
    loader-word-write 0.5s cubic-bezier(0.12, 0.52, 0.17, 1) 0.68s both,
    loader-page-show 0.167s cubic-bezier(0.17, 0.17, 0.67, 1) 0.68s both;
}

/* Dark Mode */
@media (prefers-color-scheme: dark) {
  .site-loader__word {
    color: var(--white); /* on dark grounds the D keeps its gradient and the wordmark turns white */
  }
}

/* Hurried by a key, click, scroll or touch (js/motion.js) */
.is-loading-hurried .site-loader {
  pointer-events: none;
}

/* =========================================================
   PAGE TRANSITIONS
   ========================================================= */

/* Same-site page changes animate natively in Chrome and Safari; other
   browsers simply load the next page. The bootstrap marks the arriving page
   with the kind of move: is-vt-next / is-vt-prev between top-level pages (in
   menu order), is-vt-push into a case study or role, is-vt-pop back out,
   is-vt-lang between English and Japanese. */

/* Motion Safe */
@media (prefers-reduced-motion: no-preference) {
  @view-transition {
    navigation: auto;
  }
}

/* The navigation holds still while pages change beneath it. */
.navigation-top__capsule,
.navigation-top__mbar--capsule {
  view-transition-name: site-header;
}

.navigation-tabbar__list {
  view-transition-name: site-tabbar;
}

/* The active tab and the active menu item glide to their new places. */
.navigation-tabbar__link.is-active {
  view-transition-name: tab-active;
}

.navigation-top__indicator {
  view-transition-name: nav-indicator;
}

/* Cards hand their title and film to the page they open (js/motion.js names
   the card at the moment of the click). */
.project-show__title {
  view-transition-name: project-title;
}

.job-posting__header {
  view-transition-name: job-media;
}

.job-posting__title {
  view-transition-name: job-title;
}

/* DEFAULT — the old page steps back and fades in 167 ms; the new one fades
   in over 333 ms while it settles up from 24 px. */

::view-transition-group(*) {
  animation-duration: 0.667s;
  animation-timing-function: cubic-bezier(0.12, 0.52, 0.17, 1);
}

::view-transition-old(root) {
  animation:
    vt-fade-out 0.167s cubic-bezier(0.4, 0, 1, 1) both,
    vt-lift-out 0.167s cubic-bezier(0.4, 0, 1, 1) both;
}

::view-transition-new(root) {
  animation:
    vt-fade-in 0.333s cubic-bezier(0.17, 0.17, 0.67, 1) 0.083s both,
    vt-rise-in 0.667s cubic-bezier(0.12, 0.52, 0.17, 1) 0.083s both;
}

/* NEXT / PREVIOUS — the same, travelling sideways toward where the page
   sits in the menu. */

.is-vt-next::view-transition-old(root) {
  animation:
    vt-fade-out 0.167s cubic-bezier(0.4, 0, 1, 1) both,
    vt-drift-out-left 0.167s cubic-bezier(0.4, 0, 1, 1) both;
}

.is-vt-next::view-transition-new(root) {
  animation:
    vt-fade-in 0.333s cubic-bezier(0.17, 0.17, 0.67, 1) 0.083s both,
    vt-drift-in-right 0.667s cubic-bezier(0.12, 0.52, 0.17, 1) 0.083s both;
}

.is-vt-prev::view-transition-old(root) {
  animation:
    vt-fade-out 0.167s cubic-bezier(0.4, 0, 1, 1) both,
    vt-drift-out-right 0.167s cubic-bezier(0.4, 0, 1, 1) both;
}

.is-vt-prev::view-transition-new(root) {
  animation:
    vt-fade-in 0.333s cubic-bezier(0.17, 0.17, 0.67, 1) 0.083s both,
    vt-drift-in-left 0.667s cubic-bezier(0.12, 0.52, 0.17, 1) 0.083s both;
}

/* PUSH AND POP — on phones a case study or role pushes in from the right
   like an app screen and pops back out the same way. Wider screens keep the
   default, because the card's title (and film) carries the move there. */

.is-vt-push::view-transition-old(root) {
  animation: vt-push-under 0.5s cubic-bezier(0.32, 0.72, 0, 1) both;
}

.is-vt-push::view-transition-new(root) {
  animation: vt-push-over 0.5s cubic-bezier(0.32, 0.72, 0, 1) both;
}

.is-vt-pop::view-transition-old(root) {
  z-index: 1;
  animation: vt-pop-away 0.5s cubic-bezier(0.32, 0.72, 0, 1) both;
}

.is-vt-pop::view-transition-new(root) {
  animation: vt-pop-under 0.5s cubic-bezier(0.32, 0.72, 0, 1) both;
}

/* Tablet Landscape Up - Min 900px */
@media (min-width: 900px) {
  .is-vt-push::view-transition-old(root),
  .is-vt-pop::view-transition-old(root) {
    z-index: auto;
    animation:
      vt-fade-out 0.167s cubic-bezier(0.4, 0, 1, 1) both,
      vt-lift-out 0.167s cubic-bezier(0.4, 0, 1, 1) both;
  }
}

/* Tablet Landscape Up - Min 900px */
@media (min-width: 900px) {
  .is-vt-push::view-transition-new(root),
  .is-vt-pop::view-transition-new(root) {
    animation:
      vt-fade-in 0.333s cubic-bezier(0.17, 0.17, 0.67, 1) 0.083s both,
      vt-rise-in 0.667s cubic-bezier(0.12, 0.52, 0.17, 1) 0.083s both;
  }
}

/* LANGUAGE — English and Japanese trade places in a slow dissolve. */

.is-vt-lang::view-transition-old(root) {
  animation: vt-fade-out 0.333s cubic-bezier(0.17, 0.17, 0.67, 1) both;
}

.is-vt-lang::view-transition-new(root) {
  animation: vt-fade-in 0.5s cubic-bezier(0.17, 0.17, 0.67, 1) 0.167s both;
}

/* NAVIGATION — the bars switch to the new page's state at once and stay
   above everything that moves; the active marks glide across. */

::view-transition-group(site-header),
::view-transition-group(site-tabbar) {
  z-index: 10;
  animation-duration: 0.5s;
  animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
}

::view-transition-old(site-header),
::view-transition-old(site-tabbar) {
  animation: none;
  opacity: 0;
}

::view-transition-new(site-header),
::view-transition-new(site-tabbar) {
  animation: none;
}

::view-transition-group(nav-indicator),
::view-transition-group(tab-active) {
  z-index: 11;
  animation-duration: 0.5s;
  animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
}

/* A mark with nowhere to go (the contact page has none) simply fades. */
::view-transition-old(nav-indicator):only-child,
::view-transition-old(tab-active):only-child {
  animation: vt-fade-out 0.167s cubic-bezier(0.4, 0, 1, 1) both;
}

::view-transition-new(nav-indicator):only-child,
::view-transition-new(tab-active):only-child {
  animation: vt-fade-in 0.333s cubic-bezier(0.17, 0.17, 0.67, 1) 0.167s both;
}

/* SHARED TITLES AND FILMS — card to page and back again. The pair trades
   places in 250 ms so the crisp destination is what travels most of the way. */

::view-transition-group(project-title),
::view-transition-group(job-title),
::view-transition-group(job-media) {
  animation-duration: 0.667s;
  animation-timing-function: cubic-bezier(0.12, 0.52, 0.17, 1);
}

::view-transition-old(project-title),
::view-transition-old(job-title) {
  animation: vt-fade-out 0.25s cubic-bezier(0.17, 0.17, 0.67, 1) both;
}

::view-transition-new(project-title),
::view-transition-new(job-title) {
  animation: vt-fade-in 0.25s cubic-bezier(0.17, 0.17, 0.67, 1) both;
}

::view-transition-group(job-media) {
  overflow: hidden;
}

::view-transition-old(job-media),
::view-transition-new(job-media) {
  height: 100%;
  object-fit: cover;
  animation-duration: 0.25s;
  animation-timing-function: cubic-bezier(0.17, 0.17, 0.67, 1);
}

/* A title or film without a partner on the other page just dissolves. */
::view-transition-old(project-title):only-child,
::view-transition-old(job-title):only-child,
::view-transition-old(job-media):only-child {
  animation: vt-fade-out 0.167s cubic-bezier(0.4, 0, 1, 1) both;
}

::view-transition-new(project-title):only-child,
::view-transition-new(job-title):only-child,
::view-transition-new(job-media):only-child {
  animation: vt-fade-in 0.333s cubic-bezier(0.17, 0.17, 0.67, 1) 0.083s both;
}

/* SLOW NETWORK — if the next page takes longer than 900 ms, a thin brand
   rule runs along the top so the click never goes unanswered. */
.is-navigating body::after {
  content: "";
  position: fixed;
  top: 0;
  left: 0;
  z-index: 4000;
  width: 100%;
  height: 2px;
  background: var(--brand-gradient);
  transform-origin: 0% 50%;
  animation: navigating 1.667s cubic-bezier(0.4, 0, 0.2, 1) infinite;
  pointer-events: none;
}

/* =========================================================
   NAVIGATION
   ========================================================= */

.navigation-top__links a {
  position: relative;
}

/* A short gradient rule (the one the eyebrows carry) marks the page you are
   on; it glides between items when the page changes. */
.navigation-top__indicator {
  position: absolute;
  right: 0;
  bottom: -0.45rem;
  left: 0;
  height: 2px;
  border-radius: 2px;
  background: var(--brand-gradient);
  pointer-events: none;
}

/* The header steps out of the way on the way down the page and comes back
   on the way up (navigation-top.js sets .is-hidden). */
.has-motion .navigation-top {
  transition: transform 0.333s cubic-bezier(0.33, 0, 0, 1) 0.1s;
}

.navigation-top.is-hidden {
  transform: translateY(-120%);
}

/* =========================================================
   HERO ENTRANCES
   ========================================================= */

/* Each page's first screen builds itself in: headline lines rise 0.45 em one
   after another, then the copy and actions follow 16 px behind. */

.has-motion .landing-hero__title-line,
.has-motion .how-we-work__heading-line,
.has-motion .project-show__title,
.has-motion .job-posting__title,
.has-motion .contact-brief__step.is-active .contact-brief__question {
  animation:
    rise 0.833s cubic-bezier(0.12, 0.52, 0.17, 1) calc(var(--enter) + var(--delay, 0s)) both,
    fade 0.5s cubic-bezier(0.17, 0.17, 0.67, 1) calc(var(--enter) + var(--delay, 0s)) both;
}

.has-motion .landing-hero__lede,
.has-motion .landing-hero__actions,
.has-motion .how-we-work__lede,
.has-motion .how-we-work__ctas,
.has-motion .project-show__tag,
.has-motion .project-show__summary,
.has-motion .project-show__actions,
.has-motion .project-show__facts-grid > div,
.has-motion .job-posting__kicker,
.has-motion .contact-brief__step.is-active .contact-brief__field,
.has-motion .contact-brief__step.is-active .contact-brief__field-pair,
.has-motion .contact-brief__step.is-active .contact-brief__cards {
  animation:
    rise-small 0.833s cubic-bezier(0.12, 0.52, 0.17, 1) calc(var(--enter) + var(--delay, 0s)) both,
    fade 0.5s cubic-bezier(0.17, 0.17, 0.67, 1) calc(var(--enter) + var(--delay, 0s)) both;
}

.has-motion .project-show__eyebrow,
.has-motion .contact-brief__step.is-active .contact-brief__eyebrow {
  animation: wipe-in 0.667s cubic-bezier(0.12, 0.52, 0.17, 1) calc(var(--enter) + var(--delay, 0s)) both;
}

.has-motion .lh-ticker {
  animation: fade 0.833s cubic-bezier(0.17, 0.17, 0.67, 1) calc(var(--enter) + 0.5s) both;
}

.has-motion .job-posting__media {
  animation: media-settle 1.667s cubic-bezier(0.12, 0.52, 0.17, 1) var(--enter) both;
}

/* Arrived from its card: the title (and film) are already in place. */
.is-morph-project .project-show__title,
.is-morph-job .job-posting__title,
.is-morph-job .job-posting__media {
  animation: none;
}

/* Later questions of the brief rise as soon as they become current. */
.contact-brief__step:not([data-step="1"]) {
  --enter: 0s;
}

/* The order of things, 80 ms apart. */
.landing-hero__title-line + .landing-hero__title-line,
.how-we-work__heading-line:nth-child(2),
.project-show__title,
.contact-brief__question {
  --delay: 0.08s;
}

.how-we-work__heading-line:nth-child(3),
.job-posting__title {
  --delay: 0.16s;
}

.landing-hero__lede,
.how-we-work__lede,
.project-show__tag,
.contact-brief__field,
.contact-brief__field-pair,
.contact-brief__cards {
  --delay: 0.26s;
}

.landing-hero__actions,
.how-we-work__ctas,
.project-show__summary {
  --delay: 0.34s;
}

.project-show__actions {
  --delay: 0.42s;
}

.project-show__facts-grid > div {
  --delay: 0.5s;
}

.project-show__facts-grid > div:nth-child(2) {
  --delay: 0.58s;
}

.project-show__facts-grid > div:nth-child(3) {
  --delay: 0.66s;
}

.project-show__facts-grid > div:nth-child(4) {
  --delay: 0.74s;
}

.project-show__facts-grid > div:nth-child(5) {
  --delay: 0.82s;
}

/* =========================================================
   SCROLL REVEALS
   ========================================================= */

/* js/motion.js marks content below the first screen with data-reveal and
   adds .is-revealed as it comes into view (10% up from the bottom edge);
   once its animation is done both come off again. Headings rise word by
   word 25 ms apart, copy and list items 16 px behind, 80 ms apart. */

.has-motion [data-reveal="words"],
.has-motion [data-reveal="block"],
.has-motion [data-reveal="fade"],
.has-motion [data-reveal="media"],
.has-motion [data-reveal="eyebrow"],
.has-motion [data-reveal="stagger"] > *,
.has-motion [data-reveal="cards"] > *,
.has-motion [data-reveal="letters"] .nb-w__letter {
  opacity: 0;
}

.has-motion [data-reveal="words"].is-revealed {
  opacity: 1;
}

.reveal-word {
  display: inline-block;
}

.has-motion [data-reveal="words"].is-revealed .reveal-word {
  animation:
    rise 0.833s cubic-bezier(0.12, 0.52, 0.17, 1) var(--word-delay) both,
    fade 0.5s cubic-bezier(0.17, 0.17, 0.67, 1) var(--word-delay) both;
}

.has-motion [data-reveal="block"].is-revealed,
.has-motion [data-reveal="media"].is-revealed {
  animation:
    rise-large 0.833s cubic-bezier(0.12, 0.52, 0.17, 1) both,
    fade 0.5s cubic-bezier(0.17, 0.17, 0.67, 1) both;
}

.has-motion [data-reveal="fade"].is-revealed {
  animation:
    rise-small 0.833s cubic-bezier(0.12, 0.52, 0.17, 1) both,
    fade 0.5s cubic-bezier(0.17, 0.17, 0.67, 1) both;
}

.has-motion [data-reveal="eyebrow"].is-revealed {
  animation: wipe-in 0.667s cubic-bezier(0.12, 0.52, 0.17, 1) both;
}

.has-motion [data-reveal="stagger"].is-revealed > * {
  animation:
    rise-small 0.833s cubic-bezier(0.12, 0.52, 0.17, 1) calc(var(--reveal-index) * 0.08s) both,
    fade 0.5s cubic-bezier(0.17, 0.17, 0.67, 1) calc(var(--reveal-index) * 0.08s) both;
}

/* Role cards open like a shutter while their film settles. */
.has-motion [data-reveal="cards"].is-revealed > * {
  animation: card-open 0.833s cubic-bezier(0.12, 0.52, 0.17, 1) calc(var(--reveal-index) * 0.08s) both;
}

.has-motion [data-reveal="cards"].is-revealed video {
  animation: media-settle 1.667s cubic-bezier(0.12, 0.52, 0.17, 1) calc(var(--reveal-index) * 0.08s) both;
}

/* FOOTER WORDMARK — the letters of "Dreamlist" rise out of the baseline. */

.nb-w__letter {
  display: inline-block;
}

.has-motion [data-reveal="letters"].is-revealed .nb-w__letter {
  animation: letter-rise 1s cubic-bezier(0.12, 0.52, 0.17, 1) calc(var(--reveal-index) * 0.04s) both;
}

/* Counters keep their width while they count. */
.lp-snapshot__num {
  font-variant-numeric: tabular-nums;
}

/* =========================================================
   INTERACTIONS
   ========================================================= */

/* Press: everything you can click answers at once. */
.has-motion .lh-btn:active,
.has-motion .how-we-work__cta:active,
.has-motion .landing-cta__btn:active,
.has-motion .button:active,
.has-motion .navigation-top__capsule-cta:active,
.has-motion .navigation-top__mcta:active {
  transform: scale(0.96);
  transition: transform 0.1s cubic-bezier(0.33, 0, 0, 1);
}

.has-motion .projects-index__card:active,
.has-motion .careers-index__card:active,
.has-motion .project-show__related-card:active {
  transform: scale(0.985);
  transition: transform 0.1s cubic-bezier(0.33, 0, 0, 1);
}

/* Arrow buttons: the arrow nudges toward where it points. */
.lh-btn svg,
.how-we-work__cta svg,
.landing-cta__btn svg {
  transition: transform 0.333s cubic-bezier(0.4, 0, 0.2, 1);
}

.lh-btn:hover svg,
.how-we-work__cta:hover svg,
.landing-cta__btn:hover svg {
  transform: translate(3px, -3px);
}

/* Lists: the row you point at stays bright, the rest step back. */
.projects-index__card,
.project-show__related-card {
  transition: opacity 0.167s cubic-bezier(0.17, 0.17, 0.67, 1), transform 0.4s cubic-bezier(0.2, 0.8, 0.2, 1);
}

/* Hover Capable */
@media (hover: hover) {
  .projects-index__grid:has(.projects-index__card:hover) .projects-index__card:not(:hover),
  .project-show__related-grid:has(.project-show__related-card:hover) .project-show__related-card:not(:hover),
  .nb-w__col ul:has(a:hover) a:not(:hover) {
    opacity: 0.4;
  }
}

/* Project cards: a gradient rule draws along the card's divider and the
   title steps forward. */
.projects-index__row {
  position: relative;
}

.projects-index__row::after {
  content: "";
  position: absolute;
  top: -1px;
  left: 0;
  width: 100%;
  height: 1px;
  background: var(--brand-gradient);
  transform: scaleX(0);
  transform-origin: 100% 50%;
  transition: transform 0.667s cubic-bezier(0.4, 0, 0.2, 1);
}

.projects-index__card:hover .projects-index__row::after,
.projects-index__card:focus-visible .projects-index__row::after {
  transform: scaleX(1);
  transform-origin: 0% 50%;
}

.projects-index__title {
  transition: transform 0.833s cubic-bezier(0.12, 0.52, 0.17, 1);
}

.projects-index__card:hover .projects-index__title {
  transform: translateX(0.35rem);
}

/* Role cards: the film leans in slowly. */
.careers-index__video {
  transition: transform 1.25s cubic-bezier(0.12, 0.52, 0.17, 1);
}

.careers-index__card:hover .careers-index__video {
  transform: scale(1.04);
}

/* Footer links: an underline draws in from the left and leaves to the right. */
.nb-w__col a {
  background-image: linear-gradient(currentColor, currentColor);
  background-position: 100% 100%;
  background-repeat: no-repeat;
  background-size: 0% 1px;
  transition: background-size 0.5s cubic-bezier(0.4, 0, 0.2, 1), color 0.2s ease, opacity 0.167s cubic-bezier(0.17, 0.17, 0.67, 1);
}

.nb-w__col a:hover,
.nb-w__col a:focus-visible {
  background-position: 0% 100%;
  background-size: 100% 1px;
}

/* =========================================================
   KEYFRAMES
   ========================================================= */

@keyframes rise {
  from {
    transform: translateY(0.45em);
  }
}

@keyframes rise-small {
  from {
    transform: translateY(16px);
  }
}

@keyframes rise-large {
  from {
    transform: translateY(32px);
  }
}

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

/* A label writes itself out left to right, rule first. */
@keyframes wipe-in {
  from {
    opacity: 1;
    clip-path: inset(-0.4em 100% -0.4em 0);
  }
  to {
    opacity: 1;
    clip-path: inset(-0.4em -0.4em -0.4em 0);
  }
}

/* A letter rises out of a mask that stays at the baseline: the mask's bottom
   edge moves up exactly as far as the letter does. */
@keyframes letter-rise {
  from {
    opacity: 1;
    transform: translateY(calc(100% + 0.15em));
    clip-path: inset(-0.15em -0.2em 100% -0.2em);
  }
  to {
    opacity: 1;
    transform: translateY(0);
    clip-path: inset(-0.15em -0.2em -0.15em -0.2em);
  }
}

@keyframes media-settle {
  from {
    transform: scale(1.08);
  }
}

@keyframes card-open {
  from {
    opacity: 1;
    clip-path: inset(100% 0 0 0 round 18px);
    transform: translateY(32px);
  }
  to {
    opacity: 1;
    clip-path: inset(0 0 0 0 round 18px);
    transform: translateY(0);
  }
}

@keyframes navigating {
  from {
    transform: translateX(-100%) scaleX(0.3);
  }
  to {
    transform: translateX(100%) scaleX(0.3);
  }
}

/* LOADER */

@keyframes loader-page-turn {
  from {
    transform: perspective(900px) translateY(0.6em) rotateY(-86deg);
    filter: brightness(0.55);
  }
  to {
    transform: perspective(900px) translateY(0) rotateY(0deg);
    filter: brightness(1);
  }
}

@keyframes loader-page-show {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

/* The icon starts alone in the middle of the screen: half the lockup's
   width minus half its own, to the right of its place in the lockup. */
@keyframes loader-icon-slide {
  from {
    transform: translateX(4.28em);
  }
}

@keyframes loader-ring {
  from {
    transform: scaleX(0);
  }
}

@keyframes loader-word-write {
  from {
    clip-path: inset(-20% 100% -20% 0);
    transform: translateX(0.9em);
  }
  to {
    clip-path: inset(-20% -5% -20% 0);
    transform: translateX(0);
  }
}

@keyframes loader-lockup-leave {
  to {
    opacity: 0;
    transform: translateY(-0.6em);
  }
}

@keyframes loader-lift {
  from {
    clip-path: inset(0 0 0 0);
  }
  to {
    clip-path: inset(0 0 100% 0);
    visibility: hidden;
  }
}

/* PAGE TRANSITIONS */

@keyframes vt-fade-out {
  to {
    opacity: 0;
  }
}

@keyframes vt-fade-in {
  from {
    opacity: 0;
  }
}

@keyframes vt-lift-out {
  to {
    transform: translateY(-8px);
  }
}

@keyframes vt-rise-in {
  from {
    transform: translateY(24px);
  }
}

@keyframes vt-drift-out-left {
  to {
    transform: translateX(-8px);
  }
}

@keyframes vt-drift-out-right {
  to {
    transform: translateX(8px);
  }
}

@keyframes vt-drift-in-right {
  from {
    transform: translateX(24px);
  }
}

@keyframes vt-drift-in-left {
  from {
    transform: translateX(-24px);
  }
}

@keyframes vt-push-under {
  to {
    opacity: 0.6;
    transform: translateX(-28%);
  }
}

@keyframes vt-push-over {
  from {
    transform: translateX(100%);
  }
}

@keyframes vt-pop-away {
  to {
    transform: translateX(100%);
  }
}

@keyframes vt-pop-under {
  from {
    opacity: 0.6;
    transform: translateX(-28%);
  }
}
