/* Shared motion for /, /platform and /notch (driven by /motion.js).
   Transform + opacity only. Reduced motion = final state, instantly. */
:root {
  /* Spring curves from the Visualiser wiki (spring-physics): snappy settles 400ms, gentle 730ms */
  --spring-snappy: linear(0, 0.049, 0.16, 0.295, 0.429, 0.552, 0.658, 0.745, 0.814, 0.867, 0.908, 0.938, 0.959, 0.974, 0.985, 0.992, 0.996, 0.999, 1, 1.001, 1.001, 1.002, 1.001, 1.001, 1);
  --spring-gentle: linear(0, 0.057, 0.18, 0.32, 0.455, 0.572, 0.671, 0.75, 0.812, 0.86, 0.896, 0.924, 0.944, 0.959, 0.971, 0.979, 0.985, 0.989, 0.992, 0.994, 0.996, 0.997, 0.998, 0.999, 1);
}

/* ---------- Split-text hero ----------
   Hidden only until motion.js splits it (a few ms); words keep their own width, so no layout shift. */
.js [data-split]:not(.split-on):not(.split-done) { opacity: 0; animation: split-safety 0s 1.2s forwards; }
@keyframes split-safety { to { opacity: 1; } }
.split-on .sw { display: inline-block; animation: sw-in 420ms var(--ease) var(--d, 0ms) both; }
@keyframes sw-in { from { opacity: 0; transform: translateY(.32em); } to { opacity: 1; transform: none; } }
.split-on .grad { background: none; }
.split-on .sw-grad {
  background: linear-gradient(100deg, #f5f5f7 0%, #d7e9dc 35%, #30d158 100%) no-repeat;
  background-size: var(--gw, 100%) 100%; background-position: var(--gx, 0) 0;
  -webkit-background-clip: text; background-clip: text; color: transparent;
}

/* ---------- Magnetic CTA ----------
   translate = magnet (set per frame by JS, never transitioned); transform = press. */
.mag { will-change: translate; transition: transform 400ms var(--spring-snappy), background-color 200ms, opacity 200ms; }
.mag:active { transform: scale(.97); transition: transform 70ms ease-out, background-color 200ms, opacity 200ms; }
.mag-in { display: inline-flex; align-items: center; gap: inherit; pointer-events: none; }

/* ---------- Paper stack: /platform features, wide + tall screens only ---------- */
@media (min-width: 900px) and (min-height: 720px) {
  .stack { gap: 72px; }
  .stack > .feat {
    position: sticky; top: calc(92px + var(--i, 0) * 16px); align-self: start;
    padding: 40px; gap: 48px; border-radius: 28px; background: var(--surface);
    box-shadow: inset 0 0 0 1px var(--line), 0 -18px 50px -24px rgba(0,0,0,.9);
    transform-origin: 50% 0;
  }
  /* Resting tilt and drift of each sheet: never more than 1.5deg */
  .stack > .feat:nth-child(4n+1) { --tilt: -.7deg; --dx: -6px; }
  .stack > .feat:nth-child(4n+2) { --tilt: .9deg;  --dx: 8px; }
  .stack > .feat:nth-child(4n+3) { --tilt: -1.1deg; --dx: -4px; }
  .stack > .feat:nth-child(4n+4) { --tilt: 1.3deg; --dx: 6px; }

  /* Scroll-driven: the tilt lands while the sheet enters the viewport, tied to the scrollbar */
  .stack-sdt > .feat { animation: paper-land linear both; animation-timeline: view(); animation-range: entry 10% entry 100%; }
  @keyframes paper-land { from { rotate: 0deg; translate: 0 0; } to { rotate: var(--tilt); translate: var(--dx) 0; } }

  /* Fallback: IntersectionObserver adds .landed, the tilt settles on the gentle spring */
  .stack-io > .feat { transition: rotate 730ms var(--spring-gentle), translate 730ms var(--spring-gentle), opacity 700ms var(--ease), transform 700ms var(--ease); }
  .stack-io > .feat.landed, .stack-still > .feat { rotate: var(--tilt); translate: var(--dx) 0; }
}

@media (prefers-reduced-motion: reduce) {
  .js [data-split] { opacity: 1 !important; animation: none !important; }
  .mag, .mag-in { translate: none !important; }
}
