/* aiwithkian — animation utility layer
   Pure CSS, no deps. Pair with assets/anim.js for IntersectionObserver triggers.

   Progressive-enhancement pattern: walk-on elements default to fully visible.
   anim.js adds `js-anim` to <html> on init, which opts the page INTO the
   hidden-then-fade-in state. If JS fails, the page still renders all sections.
*/

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

:root {
  --anim-ease-out: cubic-bezier(0.22, 1, 0.36, 1);
  --anim-ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
  --anim-dur-fast: 280ms;
  --anim-dur-base: 520ms;
  --anim-dur-slow: 800ms;
}

/* ---------- Walk-on primitives — JS-OPT-IN ----------
   Default state: visible (no JS = no hidden content).
   When <html> has `.js-anim`, we apply the hidden start state and
   reveal via `.in-view` from the IntersectionObserver in anim.js.
*/

.anim-fade-up,
.anim-scale-in {
  /* default visible — see html.js-anim override below */
}

html.js-anim .anim-fade-up {
  opacity: 0;
  transform: translate3d(0, 24px, 0);
  transition: opacity var(--anim-dur-base) var(--anim-ease-out),
              transform var(--anim-dur-base) var(--anim-ease-out);
  will-change: opacity, transform;
}
html.js-anim .anim-fade-up.in-view {
  opacity: 1;
  transform: translate3d(0, 0, 0);
}

html.js-anim .anim-scale-in {
  opacity: 0;
  transform: scale(0.92);
  transition: opacity var(--anim-dur-base) var(--anim-ease-out),
              transform var(--anim-dur-base) var(--anim-ease-out);
  will-change: opacity, transform;
}
html.js-anim .anim-scale-in.in-view {
  opacity: 1;
  transform: scale(1);
}

@media (prefers-reduced-motion: reduce) {
  html.js-anim .anim-fade-up,
  html.js-anim .anim-scale-in {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }
}

/* ---------- Stagger helper: set --anim-delay inline or via :nth-child ---------- */

[data-anim][style*="--anim-delay"] {
  transition-delay: var(--anim-delay);
}

/* ---------- Arrow reveal (SVG line-draw) ---------- */

.cog-arrow {
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-dasharray: 200;
  stroke-dashoffset: 200;
}

.anim-arrow-reveal.in-view .cog-arrow,
.cog-arrow.in-view {
  animation: cog-arrow-draw 600ms var(--anim-ease-out) forwards;
}

@keyframes cog-arrow-draw {
  to { stroke-dashoffset: 0; }
}

/* ---------- Typing-effect cursor ---------- */

.anim-typing {
  display: inline;
  white-space: pre-wrap;
}
.anim-typing::after {
  content: '|';
  display: inline-block;
  margin-left: 2px;
  animation: cog-caret-blink 1s steps(1, end) infinite;
  color: currentColor;
  opacity: 0.85;
}
.anim-typing.is-done::after {
  animation: none;
  opacity: 0;
}

@keyframes cog-caret-blink {
  0%, 50% { opacity: 1; }
  51%, 100% { opacity: 0; }
}

/* ---------- Mouse-follow target ---------- */

[data-mouse-follow] {
  transition: transform 220ms var(--anim-ease-out);
  will-change: transform;
}

/* ---------- Subtle hover lift (used on cards/CTAs) ---------- */

.anim-lift {
  transition: transform 220ms var(--anim-ease-out),
              box-shadow 220ms var(--anim-ease-out);
}
.anim-lift:hover {
  transform: translate3d(0, -3px, 0);
}

/* ---------- ASCII drift scene — fixed-position page background ----------
   Per Defect 12: viewport-locked layer (position: fixed) that stays in
   place during scroll. ASCII art distributed vertically across the entire
   viewport (top/mid/low, left/right). Purely decorative.
*/

.ascii-scene {
  position: fixed;
  inset: 0;
  pointer-events: none;
  overflow: hidden;
  z-index: 0;
  font-family: "VT323", "Geist Mono", monospace;
  color: var(--text-subtle);
  line-height: 1.0;
  user-select: none;
}
.ascii-scene pre {
  position: absolute;
  margin: 0;
  font-size: 14px;
  white-space: pre;
  overflow: hidden !important;
  pointer-events: none;
  scrollbar-width: none; /* Firefox */
  background: transparent;
  border: 0;
  opacity: 0.42;
}
.ascii-scene pre::-webkit-scrollbar { display: none; } /* Chrome/Safari */

/* Council 7: 13 decorative elements distributed across the viewport with
   varied drift speeds (15-50s range — was 35-60s) so the scene reads as
   alive instead of dead. Staggered negative delays keep them out of sync.
   Position grid: top rows 4-18vh, mid 32-50vh, low 62-82vh; left/right
   alternated to spread visual weight. */
.ascii-sun       { top:  4vh; right: 3vw; opacity: 0.55;
                   animation: asciiDriftSlow 14s ease-in-out -2s infinite alternate; }
.ascii-cloud-1   { top:  8vh; left:  4vw;
                   animation: asciiDriftMid 11s linear -7s infinite alternate; }
.ascii-cloud-2   { top: 18vh; right: 8vw;
                   animation: asciiDriftFast 9s linear -12s infinite alternate-reverse; }
.ascii-cloud-3   { top: 32vh; left:  3vw;
                   animation: asciiDriftMid 12s ease-in-out -4s infinite alternate; }
.ascii-cloud-4   { top: 50vh; right: 4vw;
                   animation: asciiDriftFast 10s linear -15s infinite alternate-reverse; }
.ascii-moon      { bottom: 12vh; left: 6vw; opacity: 0.40;
                   animation: asciiDriftSlow 25s ease-in-out -10s infinite alternate; }
.ascii-star      { top: 12vh; left: 38vw; opacity: 0.55; font-size: 18px;
                   animation: asciiTwinkle 1.2s ease-in-out infinite; }
.ascii-star-2    { top: 28vh; left: 64vw; opacity: 0.50; font-size: 18px;
                   animation: asciiTwinkle 1.7s ease-in-out -1s infinite; }
.ascii-bird      { top: 22vh; left: 20vw;
                   animation: asciiDriftFast 7s ease-in-out -3s infinite alternate; }
.ascii-tree      { top: 62vh; right: 4vw; opacity: 0.32;
                   animation: asciiDriftSlow 17s ease-in-out -22s infinite alternate-reverse; }
.ascii-mountains { top: 78vh; left:  4vw; opacity: 0.30;
                   /* static — mountains don't drift */ }
.ascii-plane     { top: 38vh; left: -28vw;
                   animation: asciiPlane 11s linear 2s infinite; }
.ascii-ground    { bottom: 4vh; left: 50%; opacity: 0.28;
                   animation: asciiGroundDrift 20s ease-in-out -8s infinite alternate; }

/* D38: bottom-middle + bottom-right fill — Kian flagged those quadrants as
   sparse. Six new elements clustered in 45-90vw / 62-90vh zone. */
.ascii-house       { top: 84vh; left: 48vw; opacity: 0.30; font-size: 13px; }
.ascii-tree-2      { top: 78vh; left: 80vw; opacity: 0.30; font-size: 13px;
                     animation: asciiDriftSlow 19s ease-in-out -6s infinite alternate; }
.ascii-bird-flock  { top: 70vh; left: 55vw; opacity: 0.45;
                     animation: asciiDriftFast 8s linear -2s infinite alternate; }
.ascii-cloud-bot-1 { top: 62vh; left: 75vw; opacity: 0.40;
                     animation: asciiDriftMid 11s linear -9s infinite alternate-reverse; }
.ascii-kite        { top: 74vh; left: 45vw; opacity: 0.45; font-size: 14px;
                     animation: asciiDriftMid 10s ease-in-out -3s infinite alternate; }
.ascii-car         { top: 88vh; left: 85vw; opacity: 0.32; font-size: 13px;
                     animation: asciiDriftFast 9s linear -5s infinite alternate-reverse; }

@keyframes asciiDriftSlow {
  from { transform: translateX(-30px); }
  to   { transform: translateX(30px); }
}
@keyframes asciiDriftMid {
  from { transform: translateX(-50px); }
  to   { transform: translateX(50px); }
}
@keyframes asciiDriftFast {
  from { transform: translateX(-70px); }
  to   { transform: translateX(70px); }
}
@keyframes asciiTwinkle {
  0%, 100% { opacity: 0.25; }
  50%      { opacity: 0.85; }
}
@keyframes asciiGroundDrift {
  from { transform: translateX(calc(-50% - 20px)); }
  to   { transform: translateX(calc(-50% + 20px)); }
}
@keyframes asciiPlane {
  0%   { transform: translateX(0); }
  100% { transform: translateX(160vw); }
}

/* Mobile: keep ASCII visible (Kian: "mobile is very important"), but
   reduce to 5 anchor elements (sun, 2 clouds, moon, mountains) at edges.
   Hide the rest to avoid clutter on small screens. font-size: 10px. */
@media (max-width: 640px) {
  .ascii-scene pre { font-size: 10px; opacity: 0.42; }
  .ascii-cloud-3,
  .ascii-cloud-4,
  .ascii-star,
  .ascii-star-2,
  .ascii-bird,
  .ascii-tree,
  .ascii-plane,
  .ascii-ground,
  .ascii-house,
  .ascii-tree-2,
  .ascii-bird-flock,
  .ascii-cloud-bot-1,
  .ascii-kite,
  .ascii-car { display: none; }
  .ascii-sun       { top: 1vh; right: 0; opacity: 0.55; }
  .ascii-cloud-1   { top: 14vh; left: 0; }
  .ascii-cloud-2   { top: 38vh; right: 0; }
  .ascii-moon      { bottom: 18vh; left: 0; opacity: 0.45; }
  .ascii-mountains { top: auto; bottom: 6vh; left: 0; opacity: 0.30; }
}

@media (prefers-reduced-motion: reduce) {
  .ascii-scene pre { animation: none !important; }
}

/* ---------- D36 perf hints — scroll-animated elements only ----------
   `will-change` is a contract with the browser to promote the element to
   its own GPU layer. It only helps if applied SPARINGLY — sticking it on
   every element actually hurts perf because each layer eats memory and
   compositor cost. We apply it ONLY to the elements that GSAP scroll-
   animates: hero text, the two card grids, and the drifting ASCII art.

   `backface-visibility: hidden` + `transform: translateZ(0)` are extra
   GPU-layer hints for older Safari/iOS where will-change alone isn't
   enough. `contain` lets the browser skip layout/paint outside these
   boxes — large win for the ASCII scene which covers the viewport.
*/

.linktree__item,
.expect__item,
.hero__eyebrow,
.hero__headline,
.hero__tagline,
.hero__meeting,
.signup,
.ascii-scene .ascii-cloud-1,
.ascii-scene .ascii-cloud-2,
.ascii-scene .ascii-cloud-3 {
  will-change: transform, opacity;
  backface-visibility: hidden;
  transform: translateZ(0);
}

.ascii-scene { contain: layout paint; }
.linktree__item,
.expect__item { contain: layout style; }

@media (prefers-reduced-motion: reduce) {
  .linktree__item,
  .expect__item,
  .hero__eyebrow,
  .hero__headline,
  .hero__tagline,
  .hero__meeting,
  .signup,
  .ascii-scene .ascii-cloud-1,
  .ascii-scene .ascii-cloud-2,
  .ascii-scene .ascii-cloud-3 {
    will-change: auto;
  }
}
