/* Steady download page: animations. Everything here is decoration: with reduced motion or no
   JavaScript, the page shows the finished state. */

/* ---------- Hero: the sun hops up the stairs ---------- */
.stairs { flex: 1 1 420px; min-width: 0; position: relative; height: auto; display: block; padding: 92px 0 0; margin: 0; border: 0; background: none; cursor: pointer; -webkit-tap-highlight-color: transparent; }
.stairs-svg { display: block; width: 100%; max-width: 580px; margin-left: auto; overflow: visible; }
.steps-body { fill: var(--pine); }
.tread { fill: var(--pine-mid); }
.step-labels text { fill: var(--white); font: 800 16px 'Manrope', system-ui, sans-serif; }
.sun-ball { fill: var(--sun); }
.rays line { stroke: var(--sun); stroke-width: 5; stroke-linecap: round; }
.rays { transform-box: view-box; transform-origin: 450px 38px; }
.sun-s { transform-box: fill-box; transform-origin: 50% 100%; }
/* After the last hop the sun rises off the top step, so its rays clear the step */
.sun-r { transform: translateY(-46px); }
.js .stairs:not(.play) .sun-r { opacity: 0; }
.js .stairs.play .sun-r { animation: rise 0.9s cubic-bezier(.2, .7, .3, 1) 3.55s both; }
@keyframes rise { from { transform: translateY(0); } to { transform: translateY(-46px); } }

.js .stairs.play .sun-x { animation: sun-x 3.2s linear 0.4s both; }
.js .stairs.play .sun-y { animation: sun-y 3.2s 0.4s both; }
.js .stairs.play .sun-s { animation: sun-s 3.2s 0.4s both; }
.js .stairs.play .tread { animation: tread 0.8s ease-out both; }
.js .stairs.play .t1 { animation-delay: 1.10s; }
.js .stairs.play .t2 { animation-delay: 1.62s; }
.js .stairs.play .t3 { animation-delay: 2.13s; }
.js .stairs.play .t4 { animation-delay: 2.64s; }
.js .stairs.play .t5 { animation-delay: 3.15s; }
.js .stairs.play .rays line { stroke-dasharray: 1 2; animation: draw 0.6s ease-out 3.95s both; }
.js .stairs.play .rays { animation: spin 40s linear 4.6s infinite; }

@keyframes sun-x {
  0%, 22% { transform: translateX(-400px); }
  38% { transform: translateX(-300px); }
  54% { transform: translateX(-200px); }
  70% { transform: translateX(-100px); }
  86%, 100% { transform: translateX(0); }
}
/* Down = speeding up (ease-in), up = slowing down (ease-out) */
@keyframes sun-y {
  0% { transform: translateY(-150px); opacity: 0; animation-timing-function: cubic-bezier(.55, 0, 1, .45); }
  5% { opacity: 1; }
  22% { transform: translateY(280px); animation-timing-function: cubic-bezier(0, .55, .45, 1); }
  30% { transform: translateY(150px); animation-timing-function: cubic-bezier(.55, 0, 1, .45); }
  38% { transform: translateY(210px); animation-timing-function: cubic-bezier(0, .55, .45, 1); }
  46% { transform: translateY(80px); animation-timing-function: cubic-bezier(.55, 0, 1, .45); }
  54% { transform: translateY(140px); animation-timing-function: cubic-bezier(0, .55, .45, 1); }
  62% { transform: translateY(10px); animation-timing-function: cubic-bezier(.55, 0, 1, .45); }
  70% { transform: translateY(70px); animation-timing-function: cubic-bezier(0, .55, .45, 1); }
  78% { transform: translateY(-60px); animation-timing-function: cubic-bezier(.55, 0, 1, .45); }
  86%, 100% { transform: translateY(0); opacity: 1; }
}
/* Stretch while falling, squash on each landing */
@keyframes sun-s {
  0%, 20% { transform: scale(.92, 1.1); }
  22% { transform: scale(1.22, .76); }
  26%, 34% { transform: scale(1, 1); }
  37% { transform: scale(.94, 1.07); }
  38% { transform: scale(1.18, .8); }
  42%, 50% { transform: scale(1, 1); }
  53% { transform: scale(.94, 1.07); }
  54% { transform: scale(1.18, .8); }
  58%, 66% { transform: scale(1, 1); }
  69% { transform: scale(.94, 1.07); }
  70% { transform: scale(1.18, .8); }
  74%, 82% { transform: scale(1, 1); }
  85% { transform: scale(.94, 1.07); }
  86% { transform: scale(1.24, .76); }
  91% { transform: scale(.97, 1.04); }
  95%, 100% { transform: scale(1, 1); }
}
@keyframes tread { 0% { fill: var(--pine-mid); } 12% { fill: var(--sun); } 100% { fill: var(--pine-mid); } }
/* Draw-on strokes have pathLength="1" and stroke-dasharray "1 2": at dashoffset 1 the gap hides the whole stroke.
   With a gap of only 1, the next dash would start exactly at the path's end, and a round cap paints it as a stray dot. */
@keyframes draw { from { stroke-dashoffset: 1; } to { stroke-dashoffset: 0; } }
@keyframes spin { to { transform: rotate(360deg); } }

/* ---------- Download button ---------- */
.dl-arrow { transform-box: fill-box; }
/* Not gated by .js (it's a hover effect, not a hidden state), so it needs its own reduced-motion guard */
@media (prefers-reduced-motion: no-preference) {
  .download:hover .dl-arrow, .pill:hover .dl-arrow { animation: nudge 0.9s ease-in-out infinite; }
}
@keyframes nudge { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(2.5px); } }

/* ---------- Install steps: each icon acts out its step ---------- */
.step-top { display: flex; align-items: center; justify-content: space-between; gap: 16px; max-width: 260px; }
.step-icon { width: 48px; height: 48px; fill: none; stroke: var(--pine); stroke-width: 3; stroke-linecap: round; stroke-linejoin: round; overflow: visible; }
.install li:nth-child(1) { --i: 0; } .install li:nth-child(2) { --i: 1; } .install li:nth-child(3) { --i: 2; } .install li:nth-child(4) { --i: 3; }
.install li { --d: calc(var(--i) * 0.35s); }
.i-toggle .track { fill: var(--white); transition: fill .3s; }
.i-toggle .knob { fill: var(--pine); stroke: none; }
.i-install .ring-bg { stroke: var(--pine-pale); }
.i-install .ring { transform: rotate(-90deg); transform-origin: 24px 24px; stroke-dasharray: 1 2; }
.i-install .tick { stroke-dasharray: 1 2; }
.i-open .app-bg { fill: var(--pine); stroke: none; }
.i-open .app-steps { fill: var(--white); stroke: none; }
.i-open .app-sun { fill: var(--sun); stroke: none; }
.i-open .app { transform-box: fill-box; transform-origin: 50% 50%; }
.i-toggle .knob { transform: translateX(18px); } /* finished state: switched on */
.i-toggle .track { fill: var(--pine-pale); }

.js .install li[data-reveal] { opacity: 0; transform: translateY(12px); transition: opacity .5s ease-out var(--d), transform .5s ease-out var(--d); }
.js .install li.in { opacity: 1; transform: none; }
.js .install li .i-download .arrow { opacity: 0; transform: translateY(-14px); }
.js .install li.in .i-download .arrow { animation: drop 0.9s cubic-bezier(.5, 0, .7, 1) calc(var(--d) + .3s) both; }
.js .install li.in .i-download .tray { animation: tray 0.9s ease-out calc(var(--d) + .3s) both; }
@keyframes drop { 0% { opacity: 0; transform: translateY(-14px); } 30% { opacity: 1; } 60% { transform: translateY(2px); } 75% { transform: translateY(-2px); } 100% { opacity: 1; transform: translateY(0); } }
@keyframes tray { 0%, 55% { transform: translateY(0); } 65% { transform: translateY(2.5px); } 100% { transform: translateY(0); } }
.js .install li .i-toggle .knob { transform: translateX(0); }
.js .install li .i-toggle .track { fill: var(--white); }
.js .install li.in .i-toggle .knob { animation: knob .5s cubic-bezier(.3, 1.4, .6, 1) calc(var(--d) + .5s) both; }
.js .install li.in .i-toggle .track { animation: track .5s ease-out calc(var(--d) + .5s) both; }
@keyframes knob { from { transform: translateX(0); } to { transform: translateX(18px); } }
@keyframes track { from { fill: var(--white); } to { fill: var(--pine-pale); } }
.js .install li .i-install .ring, .js .install li .i-install .tick { stroke-dashoffset: 1; }
.js .install li.in .i-install .ring { animation: draw 1s ease-in-out calc(var(--d) + .4s) both; }
.js .install li.in .i-install .tick { animation: draw .4s ease-out calc(var(--d) + 1.35s) both; }
.js .install li .i-open .app { transform: scale(.4); opacity: 0; }
.js .install li .i-open .app-sun { transform: scale(0); }
.js .install li.in .i-open .app { animation: pop .55s cubic-bezier(.3, 1.6, .5, 1) calc(var(--d) + .4s) both; }
.js .install li.in .i-open .app-sun { transform-box: fill-box; transform-origin: 50% 50%; animation: pop .4s cubic-bezier(.3, 1.8, .5, 1) calc(var(--d) + .85s) both; }
@keyframes pop { from { transform: scale(.4); opacity: 0; } to { transform: scale(1); opacity: 1; } }

/* ---------- Features: icons draw themselves ---------- */
.features > div:nth-child(1) { --i: 0; } .features > div:nth-child(2) { --i: 1; } .features > div:nth-child(3) { --i: 2; }
.features > div:nth-child(4) { --i: 3; } .features > div:nth-child(5) { --i: 4; } .features > div:nth-child(6) { --i: 5; }
.feat-icon { width: 34px; height: 34px; fill: none; stroke: var(--pine); stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; margin-bottom: 4px; }
.feat-icon * { stroke-dasharray: 1 2; stroke-dashoffset: 0; }
.js .features > div[data-reveal] .feat-icon * { stroke-dashoffset: 1; }
.js .features > div.in .feat-icon * { transition: stroke-dashoffset 1s ease-in-out calc(var(--i) * .12s); stroke-dashoffset: 0; }

/* ---------- Privacy: the lock closes; the dots stay inside ---------- */
.privacy-head { flex: 1 1 320px; min-width: 0; display: flex; flex-direction: column; gap: 32px; }
.phone { width: 150px; height: auto; overflow: visible; }
.phone-body { fill: none; stroke: var(--pine-mid); stroke-width: 4; }
.phone-screen { fill: #163F35; }
.d { fill: var(--sun); opacity: .9; }
.d2, .d4 { fill: var(--pine-soft); }
.lock .shackle { fill: none; stroke: var(--white); stroke-width: 6; stroke-linecap: round; }
.lock .lock-body { fill: var(--white); }
.lock .keyhole { fill: var(--pine-deep); }
.js .phone .shackle { transform: translateY(-9px); }
.js .phone.in .shackle { transition: transform .35s cubic-bezier(.5, 0, .7, 1.6) .5s; transform: translateY(0); }
.js .phone.in .lock { transform-box: fill-box; transform-origin: 50% 100%; animation: thunk .3s ease-out .85s; }
@keyframes thunk { 50% { transform: scale(1.06, .94); } }
/* Each dot wanders around the screen and bounces off its edges (screen: x 42–158, y 26–252) */
.js .phone.in .d1 { animation: wander1 7s ease-in-out infinite alternate; }
.js .phone.in .d2 { animation: wander2 9s ease-in-out infinite alternate; }
.js .phone.in .d3 { animation: wander3 8s ease-in-out infinite alternate; }
.js .phone.in .d4 { animation: wander4 10s ease-in-out infinite alternate; }
.js .phone.in .d5 { animation: wander5 6s ease-in-out infinite alternate; }
@keyframes wander1 { 25% { transform: translate(78px, 40px); } 50% { transform: translate(20px, 150px); } 75% { transform: translate(-20px, 60px); } 100% { transform: translate(60px, 0); } }
@keyframes wander2 { 25% { transform: translate(-75px, 60px); } 50% { transform: translate(20px, 130px); } 75% { transform: translate(-30px, -60px); } 100% { transform: translate(-80px, 20px); } }
@keyframes wander3 { 25% { transform: translate(60px, -90px); } 50% { transform: translate(-30px, -160px); } 75% { transform: translate(60px, 40px); } 100% { transform: translate(-36px, -40px); } }
@keyframes wander4 { 25% { transform: translate(-80px, -40px); } 50% { transform: translate(15px, -175px); } 75% { transform: translate(-60px, -110px); } 100% { transform: translate(18px, 30px); } }
@keyframes wander5 { 25% { transform: translate(85px, -100px); } 50% { transform: translate(40px, 90px); } 75% { transform: translate(90px, -20px); } 100% { transform: translate(10px, 60px); } }

/* ---------- Changelog: the timeline draws down, dots pop in ---------- */
.changelog { position: relative; border-left: 0; }
.changelog::before { content: ''; position: absolute; left: 0; top: 4px; bottom: 4px; width: 2px; background: var(--pine-soft); transform-origin: top; }
.changelog li { position: relative; }
.changelog li::before { content: ''; position: absolute; left: -31px; top: 6px; width: 14px; height: 14px; border-radius: 50%; background: var(--pine); box-shadow: 0 0 0 4px var(--white); }
.changelog li:first-child::before { background: var(--sun); }
.js .changelog[data-reveal]::before { transform: scaleY(0); }
.js .changelog.in::before { transition: transform 1s ease-in-out; transform: scaleY(1); }
.js .changelog[data-reveal] li::before { transform: scale(0); }
.js .changelog.in li::before { transition: transform .4s cubic-bezier(.3, 1.6, .5, 1); transform: scale(1); }
.js .changelog.in li:nth-child(2)::before { transition-delay: .3s; } .js .changelog.in li:nth-child(3)::before { transition-delay: .6s; }
.js .changelog.in li:nth-child(4)::before { transition-delay: .9s; } .js .changelog.in li:nth-child(5)::before { transition-delay: 1.2s; }

@media (max-width: 520px) { .stairs { padding-top: 64px; } .phone { width: 120px; } }

/* ---------- Reduced motion: show everything finished and still ---------- */
@media (prefers-reduced-motion: reduce) {
  .js *, .js *::before, .js *::after { animation: none !important; transition: none !important; }
  .js [data-reveal], .js .install li[data-reveal] { opacity: 1 !important; transform: none !important; }
  .js .feat-icon *, .js .i-install .ring, .js .i-install .tick { stroke-dashoffset: 0 !important; }
  .js .install .i-download .arrow, .js .install .i-open .app, .js .install .i-open .app-sun { opacity: 1 !important; transform: none !important; }
  .js .install .i-toggle .knob { transform: translateX(18px) !important; }
  .js .phone .shackle { transform: none !important; }
  .js .changelog::before, .js .changelog li::before { transform: none !important; }
}
