@charset "UTF-8";
/*
 * PINNACLE TAX LAB — motion layer
 *
 * Loaded after style.css. Everything here is decoration: the page is complete
 * and readable with this file removed, with JavaScript off, and under
 * prefers-reduced-motion (section 9 switches all of it off).
 *
 *  1. Tokens
 *  2. Reveal variants (fail-open)
 *  3. Line & word reveals
 *  4. Parallax, tilt, magnetic
 *  5. Marquee
 *  6. Hero scene loops
 *  7. Section-specific motion
 *  8. Scroll-driven progress (progressive enhancement)
 *  9. Reduced motion
 */

/* ========================================================== 1. TOKENS === */

:root {
  --ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1);
  --dur: 0.85s;
  --dur-slow: 1.15s;

  /* Written per element by JS. */
  --i: 0;
  --stagger: 80ms;
  --parallax-y: 0px;
  --tilt-x: 0deg;
  --tilt-y: 0deg;
}

/* ================================================ 2. REVEAL VARIANTS === */

/*
 * FAIL-OPEN BY DESIGN.
 *
 * Nothing hides until JavaScript adds .will-reveal, which it does immediately
 * before observing. A blocked script, an error or an observer that never
 * fires all end the same way: the page renders fully visible, just without
 * the animation. Never write a rule here that hides content without the
 * .will-reveal gate.
 */

.will-reveal {
  opacity: 0;
  transition:
    opacity var(--dur) var(--ease-out-expo),
    transform var(--dur) var(--ease-out-expo),
    filter var(--dur) var(--ease-out-expo);
  transition-delay: calc(var(--delay, 0ms) + var(--i) * var(--stagger));
}

.will-reveal[data-reveal="up"]    { transform: translateY(32px); }
.will-reveal[data-reveal="down"]  { transform: translateY(-24px); }
.will-reveal[data-reveal="left"]  { transform: translateX(-40px); }
.will-reveal[data-reveal="right"] { transform: translateX(40px); }
.will-reveal[data-reveal="scale"] { transform: scale(0.92); }
.will-reveal[data-reveal="zoom"]  { transform: scale(1.06); }
.will-reveal[data-reveal="blur"]  { filter: blur(10px); transform: translateY(18px); }
.will-reveal[data-reveal="rise"]  { transform: translateY(64px) scale(0.97); }
.will-reveal[data-reveal="fade"]  { transform: none; }

.will-reveal[data-reveal="flip"] {
  transform: perspective(900px) rotateX(14deg) translateY(28px);
  transform-origin: top center;
}

.will-reveal[data-reveal="curtain"] {
  transform: scale(0.985);
  transition-duration: var(--dur-slow);
}

.will-reveal[data-reveal="draw"] {
  opacity: 1;
  transform: scaleX(0);
  transform-origin: left center;
}

/* Legacy hooks still carried by a few templates. */
.reveal.will-reveal { transform: translateY(24px); }
.reveal--left.will-reveal { transform: translateX(-28px); }
.reveal--right.will-reveal { transform: translateX(28px); }

.img-reveal.will-reveal {
  transform: scale(0.985);
}

/* Settled state — declared last so it wins over every variant above. */
.will-reveal.is-shown {
  opacity: 1;
  transform: none;
  filter: none;
}

[data-stagger] > * { --stagger: 90ms; }
[data-stagger="fast"] > * { --stagger: 50ms; }
[data-stagger="slow"] > * { --stagger: 140ms; }

/* ======================================== 3. LINE & WORD REVEALS ======== */

/*
 * data-reveal="lines": the heading is already split into .line > span in the
 * markup, so this works without the word-splitter. The heading itself stays
 * visible; each line slides up from behind its own mask.
 */
.line {
  display: block;
  overflow: hidden;
  padding-bottom: 0.1em;
  margin-bottom: -0.1em;
}

.line > span {
  display: inline-block;
}

.will-reveal[data-reveal="lines"] {
  opacity: 1;
  transform: none;
}

.will-reveal[data-reveal="lines"] .line > span {
  transform: translateY(108%) rotate(2deg);
  transform-origin: left bottom;
  transition: transform 1.05s var(--ease-out-expo);
  transition-delay: calc(var(--delay, 0ms) + var(--line, 0) * 110ms);
}

.will-reveal[data-reveal="lines"] .line:nth-child(2) { --line: 1; }
.will-reveal[data-reveal="lines"] .line:nth-child(3) { --line: 2; }
.will-reveal[data-reveal="lines"] .line:nth-child(4) { --line: 3; }
.will-reveal[data-reveal="lines"] .line:nth-child(5) { --line: 4; }

.will-reveal[data-reveal="lines"].is-shown .line > span {
  transform: none;
}

/* Word splitter output (data-split). */
.word {
  display: inline-block;
  overflow: hidden;
  vertical-align: top;
  padding-bottom: 0.08em;
  margin-bottom: -0.08em;
}

.word > span {
  display: inline-block;
  transform: translateY(110%);
  opacity: 0;
  transition:
    transform 0.9s var(--ease-out-expo),
    opacity 0.9s var(--ease-out-expo);
  transition-delay: calc(var(--delay, 0ms) + var(--i) * 55ms);
}

[data-split].is-shown .word > span {
  transform: none;
  opacity: 1;
}

/* The orange bar in a label grows in with its section. */
.will-reveal .meta__bar,
.will-reveal.meta .meta__bar {
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.7s var(--ease-out-expo) calc(var(--delay, 0ms) + 0.2s);
}

.will-reveal.is-shown .meta__bar,
.is-shown .will-reveal.is-shown .meta__bar {
  transform: scaleX(1);
}

/* ================================= 4. PARALLAX, TILT, MAGNETIC ========== */

.parallax-frame {
  position: relative;
  overflow: hidden;
}

/*
 * Sole owner of the framed image's transform. Reveals animate the figure,
 * never the <img>, so the two can never overwrite one another.
 */
.parallax-frame img {
  transform: translate3d(0, var(--parallax-y), 0) scale(1.14);
  will-change: transform;
}

[data-tilt] {
  transform: perspective(1000px) rotateX(var(--tilt-x)) rotateY(var(--tilt-y));
  transition: transform 0.5s var(--ease-smooth);
}

[data-tilt].is-tilting {
  transition: transform 0.12s linear;
}

[data-tilt]::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: radial-gradient(20rem circle at var(--px, 50%) var(--py, 50%), rgb(245 79 27 / 12%), transparent 45%);
  opacity: 0;
  transition: opacity 0.4s var(--ease-smooth);
  pointer-events: none;
}

[data-tilt]:hover::after {
  opacity: 1;
}

/* ========================================================= 5. MARQUEE === */

/*
 * JS duplicates the words once and then adds .is-ready; only then does the
 * track move, so a failed script leaves a still, complete row, never a gap.
 */
.marquee__track.is-ready {
  animation: marquee-scroll var(--marquee-duration, 40s) linear infinite;
}

.marquee__row--reverse .marquee__track.is-ready {
  animation-direction: reverse;
}

.marquee:hover .marquee__track {
  animation-play-state: paused;
}

@keyframes marquee-scroll {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(-50%, 0, 0); }
}

/* =================================================== 6. HERO SCENE ==== */

/* Floating objects use the `translate` property so they never fight the
   3D `transform` each layer already carries. */
@keyframes float-y {
  0%, 100% { translate: 0 0; }
  50%      { translate: 0 -14px; }
}

@keyframes float-y-soft {
  0%, 100% { translate: 0 0; }
  50%      { translate: 0 9px; }
}

.scene__cert {
  animation: float-y 7s ease-in-out infinite;
}

.scene__ledger {
  animation: float-y-soft 8s ease-in-out infinite;
}

.scene__orb {
  animation: float-y 6s ease-in-out infinite 0.8s;
}

.ledger i::after {
  transform-origin: left;
  animation: bar-grow 1.6s var(--ease-out-expo) both;
  animation-delay: calc(1s + var(--bar, 0) * 140ms);
}

.ledger li:nth-child(2) i::after { --bar: 1; }
.ledger li:nth-child(3) i::after { --bar: 2; }
.ledger li:nth-child(4) i::after { --bar: 3; }

@keyframes bar-grow {
  from { transform: scaleX(0); }
  to   { transform: scaleX(1); }
}

.hero__capsule {
  animation: capsule-in 1.2s var(--ease-out-expo) 0.5s both;
}

@keyframes capsule-in {
  from { clip-path: inset(0 100% 0 0 round 999px); }
  to   { clip-path: inset(0 0 0 0 round 999px); }
}

/* ======================================== 7. SECTION-SPECIFIC MOTION === */

/* Why Pinnacle: the constellation draws itself, then the stars light up. */
.sky.will-reveal {
  opacity: 1;
  transform: none;
}

/* Dash lengths are in screen pixels (non-scaling stroke), and no line in
   the map is longer than 2000px. */
.sky.will-reveal .sky__lines line {
  stroke-dasharray: 2000;
  stroke-dashoffset: 2000;
  transition: stroke-dashoffset 1.3s var(--ease-out-expo);
  transition-delay: var(--d, 0ms);
}

.sky.will-reveal.is-shown .sky__lines line {
  stroke-dashoffset: 0;
}

.sky.will-reveal .star,
.sky.will-reveal .sky__hub {
  opacity: 0;
  scale: 0.6;
  transition: opacity 0.6s var(--ease-out-expo), scale 0.7s var(--ease-out-back);
  transition-delay: var(--delay, 200ms);
}

.sky.will-reveal.is-shown .star,
.sky.will-reveal.is-shown .sky__hub {
  opacity: 1;
  scale: 1;
}

/* Founder: the signature stroke draws under the name. */
.founder__stroke path {
  stroke-dasharray: 1;
  stroke-dashoffset: 0;
}

.will-reveal .founder__stroke path {
  stroke-dashoffset: 1;
  transition: stroke-dashoffset 1.4s var(--ease-out-expo) 0.7s;
}

.will-reveal.is-shown .founder__stroke path {
  stroke-dashoffset: 0;
}

/* The orange disc behind the founder drifts slowly. */
.founder__disc {
  animation: float-y 9s ease-in-out infinite;
}

/* Stats: counters tick with a small pulse as they land. */
.counting {
  animation: count-pulse 0.5s var(--ease-smooth);
}

@keyframes count-pulse {
  50% { opacity: 0.7; }
}

/* ============================ 8. SCROLL-DRIVEN (PROGRESSIVE) ========== */

@supports (animation-timeline: scroll()) {
  .nav__rail {
    animation: rail-progress linear both;
    animation-timeline: scroll(root block);
    transition: none;
  }

  @keyframes rail-progress {
    from { transform: scaleX(0); }
    to   { transform: scaleX(1); }
  }
}

/* ================================================ 9. REDUCED MOTION === */

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  /*
   * Everything above is decoration. Switch it all off and settle every
   * element into its final state — nothing here may hide content.
   */
  *,
  *::before,
  *::after {
    animation: none !important;
    transition-duration: 0.001ms !important;
    transition-delay: 0ms !important;
    scroll-behavior: auto !important;
  }

  .will-reveal,
  [data-reveal],
  .sky.will-reveal .star,
  .sky.will-reveal .sky__hub {
    opacity: 1 !important;
    transform: none !important;
    filter: none !important;
    scale: none !important;
  }

  .line > span,
  .word > span {
    transform: none !important;
    opacity: 1 !important;
  }

  .sky__lines line,
  .founder__stroke path {
    stroke-dashoffset: 0 !important;
  }

  .meta__bar {
    transform: none !important;
  }

  .parallax-frame img {
    transform: none !important;
  }

  [data-tilt],
  [data-magnetic],
  .scene__stage {
    transform: none !important;
  }

  [data-tilt]::after {
    display: none;
  }

  .marquee__track {
    flex-wrap: wrap;
    width: 100%;
    transform: none !important;
  }

  .xpreview,
  .cursor {
    display: none !important;
  }
}
