/* =========================================================================
   The motion layer for the pricing and progress pages, in the course
   paywall's language: one easing, things rise out of a blur on a stagger,
   headings arrive word by word, numbers roll on odometers, a light crosses
   a surface once as it lands, and the one thing worth choosing carries a
   slow travelling light. js/motion.js decides when; this file is the look.
   ========================================================================= */

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

/* ------------------------------------------------------------- entrances */

@media (prefers-reduced-motion: no-preference) {
  [data-mx]:not([data-mx="stagger"]):not([data-mx="words"]) { opacity: 0; transform: translateY(14px); filter: blur(6px); }
  [data-mx]:not([data-mx="stagger"]):not([data-mx="words"]).is-in { animation: mxRise 0.9s var(--mx-delay, 0s) var(--mx-ease) both; }

  [data-mx="stagger"] > * { opacity: 0; }
  [data-mx="stagger"].is-in > * {
    animation: mxRise 0.85s calc(var(--mx-base, 0s) + var(--i, 0) * var(--mx-step, 70ms)) var(--mx-ease) both;
  }
  /* Plan cards come up out of the page at a slight tilt. */
  [data-mx="stagger"].mx-tilt { perspective: 1400px; }
  [data-mx="stagger"].mx-tilt.is-in > * {
    animation-name: mxTilt;
    animation-duration: 1.1s;
  }
  [data-mx="stagger"].mx-settled > * { animation: none; opacity: 1; }

  .mx-w { display: inline-block; white-space: pre; opacity: 0; }
  .is-in .mx-w, .mx-w.is-in, [data-mx-words].is-in .mx-w { animation: mxWord 0.8s var(--d, 0s) var(--mx-ease) both; }
}
.mx-w { display: inline-block; white-space: pre; }

@keyframes mxRise {
  from { opacity: 0; transform: translateY(14px); filter: blur(6px); }
  to   { opacity: 1; transform: none; filter: none; }
}
@keyframes mxTilt {
  from { opacity: 0; transform: translateY(46px) rotateX(14deg) scale(0.97); filter: blur(8px); }
  to   { opacity: 1; transform: none; filter: none; }
}
@keyframes mxWord {
  from { opacity: 0; transform: translateY(0.4em); filter: blur(8px); }
  to   { opacity: 1; transform: none; filter: none; }
}

/* ------------------------------------------------------------- odometer */

.mx-odo { display: inline-flex; font-variant-numeric: tabular-nums; }
.mx-odo .ch { display: inline-block; height: 1em; line-height: 1; overflow: hidden; }
.mx-odo .col { display: flex; flex-direction: column; transition: transform 1s var(--mx-ease); }
.mx-odo .col span { height: 1em; line-height: 1; }
/* Odometer text sits on one line box exactly 1em tall, so the roll never
   shows the digit above or below. */
.plan-price b.mx-odo, .pg-figure b.mx-odo, .pg-crest-ring b .mx-odo { line-height: 1; }
/* The pages style a price's or a figure's caption as a bare `span`; the
   odometer's columns are spans too, and must keep the number's own size. */
.mx-odo span { font: inherit; color: inherit; letter-spacing: inherit; }

/* --------------------------------------------------------------- the dot */

.mx-ping { display: inline-flex; align-items: center; gap: 0.5rem; }
.mx-ping::before {
  content: "";
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--accent);
  flex: none;
}
@media (prefers-reduced-motion: no-preference) {
  .mx-ping::before { animation: mxPing 2.4s 1.2s ease-out infinite; }
}
@keyframes mxPing {
  0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent) 55%, transparent); }
  70%, 100% { box-shadow: 0 0 0 9px transparent; }
}

/* -------------------------------------------------- one pass of light */

.mx-sheen { position: relative; isolation: isolate; }
.mx-sheen::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: linear-gradient(105deg, transparent 38%, rgba(255, 255, 255, 0.30) 50%, transparent 62%) 130% 0 / 260% 100%;
  pointer-events: none;
  opacity: 0;
  z-index: 3;
}
[data-theme="dark"] .mx-sheen::after { background-image: linear-gradient(105deg, transparent 38%, rgba(255, 255, 255, 0.07) 50%, transparent 62%); }
@media (prefers-reduced-motion: no-preference) {
  .is-in > .mx-sheen::after, .mx-sheen.is-in::after {
    animation: mxSheen 1.5s calc(var(--mx-base, 0s) + var(--i, 0) * var(--mx-step, 70ms) + 0.35s) var(--mx-ease) both;
  }
  .mx-settled > .mx-sheen::after { animation: none; }
}
@keyframes mxSheen {
  0% { opacity: 1; background-position: 130% 0; }
  100% { opacity: 1; background-position: -30% 0; }
}

/* ------------------------------------------------- pointer spotlight */

.mx-spot { position: relative; }
.mx-spot > .mx-spot-light {
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  background: radial-gradient(320px circle at var(--mx-x, 50%) var(--mx-y, -20%), color-mix(in srgb, var(--accent) 16%, transparent), transparent 70%);
  opacity: 0;
  transition: opacity 0.4s var(--mx-ease);
  z-index: 0;
}
.mx-spot:hover > .mx-spot-light { opacity: 1; }
.mx-spot > :not(.mx-spot-light) { position: relative; z-index: 1; }
.mx-spot > .plan-flag { position: absolute; z-index: 2; }

/* --------------------------------------------- the travelling light ring */

@property --mx-angle { syntax: "<angle>"; inherits: false; initial-value: 0deg; }
.mx-ring { position: relative; }
.mx-ring::before {
  content: "";
  position: absolute;
  inset: -1px;
  padding: 1.5px;
  border-radius: inherit;
  background: conic-gradient(from var(--mx-angle), transparent 0 62%, color-mix(in srgb, var(--accent) 90%, #fff) 78%, transparent 92%);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask-composite: exclude;
  pointer-events: none;
  z-index: 2;
}
@media (prefers-reduced-motion: no-preference) {
  .mx-ring::before { animation: mxOrbit 6s linear infinite; }
}
@keyframes mxOrbit { to { --mx-angle: 360deg; } }

/* --------------------------------------------- a button the light crosses */

.mx-cta { overflow: hidden; }
.mx-cta::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(105deg, transparent 35%, rgba(255, 255, 255, 0.28) 50%, transparent 65%) 150% 0 / 250% 100%;
  pointer-events: none;
}
[data-theme="dark"] .mx-cta::after { background-image: linear-gradient(105deg, transparent 35%, rgba(0, 0, 0, 0.14) 50%, transparent 65%); }
@media (prefers-reduced-motion: no-preference) {
  .mx-cta::after { animation: mxCtaSheen 4.5s 2.2s ease-in-out infinite; }
}
@keyframes mxCtaSheen {
  0%, 62% { background-position: 150% 0; }
  100% { background-position: -50% 0; }
}

/* ----------------------------------------------- an apple segmented control */

.mx-seg { position: relative; isolation: isolate; }
.mx-seg-thumb {
  position: absolute;
  top: 3px; bottom: 3px; left: 0;
  border-radius: 9px;
  background: var(--paper-raised, #fff);
  box-shadow: 0 0 0 0.5px rgba(0, 0, 0, 0.04), 0 3px 8px rgba(0, 0, 0, 0.12), 0 3px 1px rgba(0, 0, 0, 0.04);
  z-index: 0;
  pointer-events: none;
}
[data-theme="dark"] .mx-seg-thumb { background: #5b5b63; box-shadow: 0 3px 8px rgba(0, 0, 0, 0.35); }
.mx-seg-ready .mx-seg-thumb { transition: transform 0.5s var(--mx-spring), width 0.5s var(--mx-spring); }
.mx-seg > button { position: relative; z-index: 1; }

/* ------------------------------------------------------- pricing page */

.pricing-head { position: relative; }
.mx-ambient { position: absolute; inset: -30% 0 -40%; pointer-events: none; z-index: -1; overflow: hidden; }
.mx-ambient i {
  position: absolute;
  width: 34vmax; height: 34vmax;
  border-radius: 50%;
  background: radial-gradient(closest-side, var(--glow-a), transparent);
  filter: blur(10px);
}
.mx-ambient i:nth-child(1) { left: -6%; top: -10%; }
.mx-ambient i:nth-child(2) { right: -10%; top: 10%; width: 26vmax; height: 26vmax; background: radial-gradient(closest-side, var(--glow-b), transparent); }
@media (prefers-reduced-motion: no-preference) {
  .mx-ambient i:nth-child(1) { animation: mxDrift 19s ease-in-out infinite alternate; }
  .mx-ambient i:nth-child(2) { animation: mxDrift 23s ease-in-out -6s infinite alternate-reverse; }
}
@keyframes mxDrift { from { transform: translate3d(0, 0, 0) scale(1); } to { transform: translate3d(5vmax, 3vmax, 0) scale(1.1); } }

/* Ticks pop in down each card once its price has rolled. */
@media (prefers-reduced-motion: no-preference) {
  .mx-tilt.is-in:not(.mx-settled) .plan-features li::before {
    animation: mxTick 0.5s calc(var(--mx-base, 0s) + var(--i, 0) * 70ms + 0.75s + var(--li, 0) * 70ms) var(--mx-spring) both;
  }
  .mx-tilt.is-in:not(.mx-settled) .plan-flag { animation: mxFlag 0.6s calc(var(--i, 0) * 70ms + 0.7s) var(--mx-spring) both; }
  /* The plan the paywall sent you for: its entrance, then its ring of light. */
  .mx-tilt.is-in > .plan-card.is-suggested {
    animation: mxTilt 1.1s calc(var(--i, 0) * 70ms) var(--mx-ease) both, planSuggest 1.6s calc(var(--i, 0) * 70ms + 0.9s) var(--mx-ease) both;
  }
  .mx-tilt.mx-settled > .plan-card.is-suggested { animation: planSuggest 1.6s 0.2s var(--mx-ease) both; }
}
@keyframes mxTick {
  from { opacity: 0; transform: rotate(-45deg) scale(0); }
  to   { opacity: 1; transform: rotate(-45deg) scale(1); }
}
@keyframes mxFlag {
  from { opacity: 0; transform: translate(-50%, -20%) scale(0.7); }
  to   { opacity: 1; transform: translate(-50%, -50%) scale(1); }
}
/* A changed saving line swaps through a blur rather than snapping. */
@media (prefers-reduced-motion: no-preference) {
  .mx-swap { animation: mxRise 0.6s var(--mx-ease) both; }
}

/* ------------------------------------------------------ progress page */

.pg-crest-ring { isolation: isolate; }
/* The ring draws in slowly, with a glowing tip riding its end. */
.pg-crest-ring .ring-fg { transition: stroke-dashoffset 1.8s 0.35s var(--mx-ease); filter: drop-shadow(0 0 4px color-mix(in srgb, var(--accent) 55%, transparent)); }
.pg-crest-tip {
  position: absolute;
  inset: 0;
  transform: rotate(calc(var(--pct, 0) * 360deg));
  transition: transform 1.8s 0.35s var(--mx-ease);
  pointer-events: none;
}
.pg-crest-tip::before {
  content: "";
  position: absolute;
  top: calc(6.94% - 4px);
  left: calc(50% - 4px);
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 25%, transparent), 0 0 16px 4px color-mix(in srgb, var(--accent) 55%, transparent);
}
.pg-crest-tip[data-empty]::before { opacity: 0; }
.pg-crest-ring::after {
  content: "";
  position: absolute;
  inset: 8%;
  border-radius: 50%;
  background: radial-gradient(closest-side, color-mix(in srgb, var(--accent) 16%, transparent), transparent);
  z-index: -1;
}
@media (prefers-reduced-motion: no-preference) {
  .pg-crest-ring::after { animation: mxBreathe 4s 2s ease-in-out infinite; }
}
@keyframes mxBreathe { 0%, 100% { opacity: 0.5; transform: scale(0.92); } 50% { opacity: 1; transform: scale(1.04); } }

/* The level bar fills with a shimmer running through it and a lit leading edge. */
.pg-level-bar { position: relative; overflow: visible; }
.pg-level-bar i { position: relative; transition: width 1.8s 0.35s var(--mx-ease); overflow: hidden; }
.pg-level-bar i::before {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.55), transparent) -100% 0 / 40% 100% no-repeat;
}
.pg-level-bar b.pg-level-edge {
  position: absolute;
  top: 50%;
  left: var(--edge, 0%);
  width: 12px; height: 12px;
  margin: -6px 0 0 -6px;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 22%, transparent), 0 0 14px 3px color-mix(in srgb, var(--accent) 50%, transparent);
  transition: left 1.8s 0.35s var(--mx-ease);
  pointer-events: none;
}
.pg-level-bar b.pg-level-edge[data-empty] { opacity: 0; }
@media (prefers-reduced-motion: no-preference) {
  .pg-level-bar i::before { animation: mxShimmer 2.6s 2.2s ease-in-out infinite; }
}
@keyframes mxShimmer { 0% { background-position: -100% 0; } 60%, 100% { background-position: 250% 0; } }

/* A chart gets one scan of light across it as it lands. */
.pg-chart.mx-scan { position: relative; }
.pg-chart.mx-scan::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(100deg, transparent 30%, color-mix(in srgb, var(--accent) 16%, transparent) 50%, transparent 70%) 160% 0 / 250% 100%;
  pointer-events: none;
  opacity: 0;
}
@media (prefers-reduced-motion: no-preference) {
  .is-in > .pg-chart.mx-scan::after { animation: mxScan 1.5s calc(var(--i, 0) * 120ms + 0.5s) var(--mx-ease) both; }
}
@keyframes mxScan { 0% { opacity: 1; background-position: 160% 0; } 100% { opacity: 1; background-position: -60% 0; } }

/* Your rung on the ladder keeps a slow pulse. */
@media (prefers-reduced-motion: no-preference) {
  .pg-rung.is-here .pg-rung-level { animation: mxRung 2.6s 1.5s ease-out infinite; }
}
@keyframes mxRung {
  0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent) 50%, transparent); }
  70%, 100% { box-shadow: 0 0 0 10px transparent; }
}
