/* Site-wide motion for drdaveps.com. Everything here is hidden only while JS is alive
   (.js on <html>), so a broken script degrades to a fully visible page. */
:root{
  --ease-out:cubic-bezier(0.23,1,0.32,1);
  --ease-in-out:cubic-bezier(0.77,0,0.175,1);
}

/* ---- Reading progress, every page ---- */
#scroll-progress{position:fixed;inset:0 0 auto 0;height:3px;z-index:60;pointer-events:none;
  background:linear-gradient(90deg,#9E72B6,#CBA64F 60%,#F5ECD2);transform-origin:0 50%;transform:scaleX(0)}

/* ---- Scroll reveals (fire once). Uses the individual `translate` property so it
   composes with Tailwind's rotate/scale utilities instead of overwriting them. ---- */
.js [data-reveal]{opacity:0;translate:0 28px;
  transition:opacity .7s var(--ease-out),translate .7s var(--ease-out);transition-delay:var(--rd,0ms)}
.js [data-reveal="fade"]{translate:none}
.js [data-reveal].in{opacity:1;translate:none}

/* Section-heading marks pop in when their heading arrives */
.js h2[data-reveal] > .h2-mark{scale:.6;rotate:-25deg;opacity:0;
  transition:scale .8s var(--ease-out) .12s,rotate .8s var(--ease-out) .12s,opacity .5s ease .12s}
.js h2[data-reveal].in > .h2-mark{scale:1;rotate:0deg;opacity:1}
/* gold rule beside headings draws out from the left */
.js h2[data-reveal] > span.h-px{transform-origin:0 50%;scale:0 1;transition:scale .9s var(--ease-out) .1s}
.js h2[data-reveal].in > span.h-px{scale:1 1}

/* Parallax targets get their offset from motion.js via `translate` */
[data-parallax],[data-zoom]{will-change:translate}
[data-zoom]{will-change:scale}

/* ================= The Ascent: pinned winged-brain set piece ================= */
.ascend{position:relative;background:#1A0C24;color:#F8F4FA;isolation:isolate}
.js .ascend{height:260vh}
.ascend-pin{position:relative;min-height:100svh;display:flex;align-items:center;overflow:hidden}
.js .ascend-pin{position:sticky;top:0;height:100svh}
/* starfield: two drifting dot layers, pure CSS */
.ascend-stars,.ascend-stars::after{position:absolute;inset:-20% 0;pointer-events:none;
  background-image:radial-gradient(1.2px 1.2px at 20% 30%,#fff8,transparent),radial-gradient(1px 1px at 70% 60%,#fff6,transparent),
  radial-gradient(1.4px 1.4px at 40% 80%,#EBD9A8aa,transparent),radial-gradient(1px 1px at 85% 15%,#fff7,transparent),
  radial-gradient(1px 1px at 10% 70%,#C2A3D2aa,transparent),radial-gradient(1.3px 1.3px at 55% 25%,#fff6,transparent);
  background-size:340px 340px;opacity:.7}
.ascend-stars::after{content:"";inset:0;background-size:520px 520px;opacity:.5;translate:0 calc(var(--p,1) * -60px)}
.ascend-stars{translate:0 calc(var(--p,1) * -120px)}

/* progress phases, all derived from --p (0..1) which motion.js sets on .ascend-stage.
   ponytail: ~45 SVG children read --p from the stage; fine at this size, move to
   per-element writes if the graphic ever grows into the hundreds. */
.ascend-stage{--p:1;
  --p1:clamp(0,var(--p)/.28,1);
  --p2:clamp(0,(var(--p) - .2)/.38,1);
  --p3:clamp(0,(var(--p) - .45)/.33,1);
  --p4:clamp(0,(var(--p) - .7)/.2,1)}
.ascend-svg{display:block;width:100%;height:auto;overflow:visible}
.as-line{stroke:#C2A3D2;stroke-width:2.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:1 1;stroke-dashoffset:calc(1 - var(--p2))}
.as-outline{stroke:#E6D5EE;stroke-width:2.8}
.as-node{fill:#FFF8E6;opacity:var(--p2)}
.as-staff,.as-snake{stroke-dasharray:1 1;stroke-dashoffset:calc(1 - var(--p1))}
.as-pulse{stroke-dasharray:.08 .92;stroke-dashoffset:calc(1 - var(--p1));opacity:calc(var(--p1) * (1 - var(--p2)))}
.as-feather{--pf:clamp(0,(var(--p3) - var(--d))/.55,1);transform-origin:0 0;
  transform:rotate(calc(var(--a) * var(--pf) + 84deg * (1 - var(--pf))));opacity:calc(.15 + var(--pf) * .85)}
.as-wings{opacity:clamp(0,var(--p3) * 4,1);transform-box:view-box;transform-origin:300px 220px}
.as-aura{opacity:calc(.25 + var(--p4) * .75)}
.as-crown{opacity:var(--p4)}
.as-flow{stroke-dasharray:.06 .94;opacity:0}

/* Once fully risen it keeps breathing: energy climbs the staff, wings and crown pulse */
@keyframes as-flow{from{stroke-dashoffset:1}to{stroke-dashoffset:0}}
@keyframes as-breathe{0%,100%{scale:1}50%{scale:1.025}}
@keyframes as-glow{0%,100%{opacity:.82}50%{opacity:1}}
.ascend-stage.lit .as-flow{opacity:1;animation:as-flow 2.6s linear infinite}
.ascend-stage.lit .as-wings{animation:as-breathe 5s ease-in-out infinite}
.ascend-stage.lit .as-brain{animation:as-glow 4s ease-in-out infinite}

/* the three words light up with the drawing */
.js .ascend-word{opacity:.22;translate:0 10px;transition:opacity .5s var(--ease-out),translate .5s var(--ease-out),color .5s ease}
.js .ascend-word.on{opacity:1;translate:none}
.ascend-word.on .ascend-dot{background:#CBA64F;box-shadow:0 0 0 6px rgba(203,166,79,.18)}
.ascend-dot{transition:background .5s ease,box-shadow .5s ease}
.js .ascend-final{opacity:0;translate:0 16px;transition:opacity .7s var(--ease-out),translate .7s var(--ease-out)}
.js .ascend-final.on{opacity:1;translate:none}

@media (max-width:640px){
  .js .ascend{height:230vh}
  .as-line{stroke-width:2.6}
}
/* Stacked layout (phones, tablets): the stage is taller than the screen, so pinning it at the
   very top hid the brain under the sticky header. It now pins with the brain plus Body, Mind and
   Spirit centred in the space below the header; on short phones the brain's top sits 12px under
   the header and Spirit waits below. motion.js measures --hdr, --asc-t (brain top in the pin)
   and --asc-h (brain top to the end of Spirit). */
@media (max-width:1023px) and (prefers-reduced-motion:no-preference){
  .js .ascend-pin{height:auto;min-height:0;
    top:max(calc(var(--hdr,0px) + 12px - var(--asc-t,0px)),
            calc((100svh + var(--hdr,0px)) / 2 - var(--asc-t,0px) - var(--asc-h,0px) / 2))}
}

@media (prefers-reduced-motion:reduce){
  .js .ascend{height:auto}
  .js .ascend-pin{position:relative;height:auto;min-height:100svh}
  .js [data-reveal]{translate:none;transition:opacity .4s ease}
  .js .ascend-word,.js .ascend-final{opacity:1;translate:none}
  .ascend-stars,.ascend-stars::after{translate:none}
}

/* ================= Native feel on phones (mobile-native) ================= */
html{-webkit-tap-highlight-color:transparent}
a,button,summary,[role="button"]{touch-action:manipulation}
/* iOS zooms into any input under 16px and never zooms back out */
@media (pointer:coarse){input,textarea,select{font-size:16px!important}}
/* press feedback lands on touch-down, not on release */
a.rounded-full,button.rounded-full,button[type="submit"]{transition-property:background-color,color,border-color,box-shadow,scale;transition-duration:.15s}
a.rounded-full:active,button.rounded-full:active,button[type="submit"]:active{scale:.97}
