/* ═══════════════════════════════════════════════════════════
   animations.css  —  v2.0  (CINEMA GRADE)
   Apple · Stripe · Awwwards motion quality.

   ARCHITECTURE:
   1. Easing Custom Properties   — reusable cubic-beziers
   2. GPU Performance Hints      — will-change / translate3d
   3. Initial Hidden States      — GSAP animates FROM these
   4. Scroll Reveal States       — .is-revealed toggled by JS
   5. Floating / Idle Loops      — CSS fallback (GSAP overrides)
   6. Hover Micro-interactions   — CSS-only for instant feedback
   7. Scroll Progress Bar        — scaleX GPU-composited
   8. Parallax Layer Bases       — foundation for GSAP
   9. Word Split Animation       — title entrance helper
   10. Skeleton Loading States   — optional polish
   11. Reduced Motion Overrides  — accessibility required
   ═══════════════════════════════════════════════════════════ */

/* ─────────────────────────────────────────────
   1. EASING CUSTOM PROPERTIES
   Named bezier curves — use these everywhere.
   Matching GSAP easing for CSS transitions.
   ───────────────────────────────────────────── */
:root {
  --ease-out-expo:  cubic-bezier(0.16, 1, 0.3, 1);
  --ease-out-circ:  cubic-bezier(0, 0.55, 0.45, 1);
  --ease-out-quart: cubic-bezier(0.25, 1, 0.5, 1);
  --ease-out-back:  cubic-bezier(0.34, 1.56, 0.64, 1);
  --ease-in-out:    cubic-bezier(0.45, 0, 0.55, 1);
  --ease-in-expo:   cubic-bezier(0.7, 0, 0.84, 0);

  /* Duration scale */
  --dur-xs:   0.15s;
  --dur-sm:   0.3s;
  --dur-md:   0.6s;
  --dur-lg:   0.9s;
  --dur-xl:   1.2s;
  --dur-xxl:  1.6s;
}

/* ─────────────────────────────────────────────
   2. GPU PERFORMANCE HINTS
   Applied globally to all animated elements.
   will-change is set here as a default; GSAP
   overrides it surgically per-animation lifecycle.
   ───────────────────────────────────────────── */
.hero__profile-img,
.hero__name,
.hero__title,
.hero__description,
.hero__cta-group,
.hero__scroll-cue,
.hero__bg,
.hero__shapes,
.hero__content,
.ability-card,
.ability-card__icon,
.ability-card__bar-fill,
.project__content,
.project__mockups,
.mockup,
.mockup--phone,
.mockup--desktop,
.floating-mockup,
.project__float-el,
.mockup-halo,
.btn,
.nav,
.section-header,
.section-label,
.section-title,
.contact__content,
.scroll-progress,
.word,
.cursor-spotlight {
  will-change: transform, opacity;
  transform: translate3d(0, 0, 0);
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
}

/* ─────────────────────────────────────────────
   3. INITIAL HIDDEN STATES
   GSAP's entrance timelines animate FROM these.
   Must match GSAP fromTo start values exactly.
   ───────────────────────────────────────────── */

/* Hero — revealed by main.js entrance timeline */
.hero__bg           { opacity: 0; }
.hero__profile-img  { opacity: 0; transform: translate3d(0, 20px, 0) scale(0.9); }
.hero__title        { opacity: 0; transform: translate3d(0, 30px, 0); }
.hero__description  { opacity: 0; transform: translate3d(0, 25px, 0); }
.hero__cta-group    { opacity: 0; transform: translate3d(0, 20px, 0); }
.hero__scroll-cue   { opacity: 0; }

/* Nav entrance */
.nav                { opacity: 0; transform: translate3d(0, -20px, 0); }

/* Section elements — hidden before scroll reveal */
.section-label      { opacity: 0; transform: translate3d(0, 18px, 0); }
.section-title      { opacity: 0; transform: translate3d(0, 32px, 0); }
.section-header     { opacity: 0; transform: translate3d(0, 36px, 0); }

/* Ability cards */
.ability-card       { opacity: 0; transform: translate3d(0, 50px, 0) scale(0.93); }

/* Project elements */
.project__content   { opacity: 0; transform: translate3d(-45px, 20px, 0); }
.project__mockups   { opacity: 0; transform: translate3d(45px, 30px, 0); }

/* Reversed project layout */
.project__inner--reverse .project__content  { transform: translate3d(45px, 20px, 0); }
.project__inner--reverse .project__mockups  { transform: translate3d(-45px, 30px, 0); }

/* Individual mockup frames */
.mockup--phone    { opacity: 0; transform: translate3d(0, 44px, 0) scale(0.91) perspective(900px) rotateY(8deg); }
.mockup--desktop  { opacity: 0; transform: translate3d(0, 38px, 0) scale(0.93) perspective(900px) rotateY(-5deg); }

/* Project meta */
.project__number  { opacity: 0; transform: translate3d(0, 14px, 0); }
.project__type    { opacity: 0; transform: translate3d(10px, 0, 0); }
.project__title   { opacity: 0; transform: translate3d(0, 28px, 0); }
.project__description { opacity: 0; transform: translate3d(0, 20px, 0); }
.project__tags    { opacity: 0; transform: translate3d(0, 14px, 0); }
.btn--project     { opacity: 0; transform: translate3d(0, 10px, 0); }

/* Contact */
.contact__content       { opacity: 0; transform: translate3d(0, 40px, 0); }
.contact__title         { opacity: 0; transform: translate3d(0, 32px, 0); }
.contact__description   { opacity: 0; transform: translate3d(0, 28px, 0); }
.contact__socials       { opacity: 0; transform: translate3d(0, 24px, 0); }
.contact__social-link   { opacity: 0; transform: translate3d(0, 20px, 0) scale(0.85); }

/* Float elements — hidden until section is revealed */
.project__float-el      { opacity: 0; transform: translate3d(0, 18px, 0) scale(0.8); }

/* Word split — individual word spans */
.word                   { display: inline-block; opacity: 0; transform: translate3d(0, 40px, 0); }
.word-wrap              { display: inline-block; overflow: hidden; }

/* Skill bar */
.ability-card__bar-fill { width: 0%; }

/* ─────────────────────────────────────────────
   4. SCROLL REVEAL STATES
   .is-revealed toggled by ScrollTrigger.
   For most elements GSAP drives the animation;
   CSS transition is the fallback / complement.
   ───────────────────────────────────────────── */

/* Generic reveal */
[data-scroll-reveal].is-revealed {
  opacity: 1;
  transform: translate3d(0, 0, 0) scale(1);
  transition:
    opacity  var(--dur-lg) var(--ease-out-expo),
    transform var(--dur-lg) var(--ease-out-expo);
}

/* Section header */
.section-header.is-revealed,
.projects__header.is-revealed {
  opacity: 1;
  transform: translate3d(0, 0, 0);
  transition:
    opacity  var(--dur-xl) var(--ease-out-expo),
    transform var(--dur-xl) var(--ease-out-expo);
}

/* Label & title inherit from parent .is-revealed */
.is-revealed .section-label {
  opacity: 1;
  transform: translate3d(0, 0, 0);
  transition:
    opacity  var(--dur-md) var(--ease-out-expo),
    transform var(--dur-md) var(--ease-out-expo);
}

.is-revealed .section-title {
  opacity: 1;
  transform: translate3d(0, 0, 0);
  transition:
    opacity  var(--dur-lg) var(--ease-out-expo) 0.1s,
    transform var(--dur-lg) var(--ease-out-expo) 0.1s;
}

/* Ability cards */
.ability-card.is-revealed {
  opacity: 1;
  transform: translate3d(0, 0, 0) scale(1);
  transition:
    opacity  var(--dur-lg) var(--ease-out-expo),
    transform var(--dur-lg) var(--ease-out-expo),
    border-color var(--dur-sm) ease,
    box-shadow   var(--dur-sm) ease;
}

/* Stagger via attribute (CSS fallback when GSAP stagger not active) */
.ability-card[data-stagger="0"] { transition-delay: 0.00s; }
.ability-card[data-stagger="1"] { transition-delay: 0.10s; }
.ability-card[data-stagger="2"] { transition-delay: 0.20s; }
.ability-card[data-stagger="3"] { transition-delay: 0.30s; }
.ability-card[data-stagger="4"] { transition-delay: 0.40s; }
.ability-card[data-stagger="5"] { transition-delay: 0.50s; }

/* Project columns */
.project__content.is-revealed {
  opacity: 1;
  transform: translate3d(0, 0, 0);
  transition:
    opacity  var(--dur-xl) var(--ease-out-expo),
    transform var(--dur-xl) var(--ease-out-expo);
}

.project__mockups.is-revealed {
  opacity: 1;
  transform: translate3d(0, 0, 0);
  transition:
    opacity  var(--dur-xl) var(--ease-out-expo) 0.12s,
    transform var(--dur-xl) var(--ease-out-expo) 0.12s;
}

/* Reversed layout — reset transform direction */
.project__inner--reverse .project__content.is-revealed,
.project__inner--reverse .project__mockups.is-revealed {
  transform: translate3d(0, 0, 0);
}

/* Mockup frames */
.mockup--phone.is-revealed,
.mockup--desktop.is-revealed {
  opacity: 1;
  transform: translate3d(0, 0, 0) scale(1) perspective(900px) rotateY(0deg);
  transition:
    opacity  var(--dur-xxl) var(--ease-out-expo),
    transform var(--dur-xxl) var(--ease-out-expo);
}

/* Overlay/secondary mockup delayed */
.mockup--overlay { transition-delay: 0.2s; }

/* Project meta — cascades within .is-revealed parent */
.is-revealed .project__number {
  opacity: 1; transform: translate3d(0, 0, 0);
  transition: opacity var(--dur-md) var(--ease-out-expo) 0.05s,
              transform var(--dur-md) var(--ease-out-expo) 0.05s;
}
.is-revealed .project__type {
  opacity: 1; transform: translate3d(0, 0, 0);
  transition: opacity var(--dur-md) var(--ease-out-expo) 0.10s,
              transform var(--dur-md) var(--ease-out-expo) 0.10s;
}
.is-revealed .project__title {
  opacity: 1; transform: translate3d(0, 0, 0);
  transition: opacity var(--dur-lg) var(--ease-out-expo) 0.15s,
              transform var(--dur-lg) var(--ease-out-expo) 0.15s;
}
.is-revealed .project__description {
  opacity: 1; transform: translate3d(0, 0, 0);
  transition: opacity var(--dur-lg) var(--ease-out-expo) 0.25s,
              transform var(--dur-lg) var(--ease-out-expo) 0.25s;
}
.is-revealed .project__tags {
  opacity: 1; transform: translate3d(0, 0, 0);
  transition: opacity var(--dur-md) var(--ease-out-expo) 0.35s,
              transform var(--dur-md) var(--ease-out-expo) 0.35s;
}
.is-revealed .btn--project {
  opacity: 1; transform: translate3d(0, 0, 0);
  transition: opacity var(--dur-md) var(--ease-out-expo) 0.45s,
              transform var(--dur-md) var(--ease-out-expo) 0.45s,
              gap 0.3s var(--ease-out-expo),
              border-color 0.3s ease,
              color 0.3s ease;
}

/* Float elements appear within revealed section */
.is-revealed .project__float-el {
  opacity: 1; transform: translate3d(0, 0, 0) scale(1);
  transition: opacity var(--dur-md) var(--ease-out-back) 0.3s,
              transform var(--dur-md) var(--ease-out-back) 0.3s;
}

/* Contact section */
.contact__content.is-revealed {
  opacity: 1; transform: translate3d(0, 0, 0);
  transition: opacity var(--dur-xl) var(--ease-out-expo),
              transform var(--dur-xl) var(--ease-out-expo);
}

/* Contact children — staggered delays */
.contact__content.is-revealed .section-label     { transition-delay: 0.00s; }
.contact__content.is-revealed .contact__title    { transition-delay: 0.11s; }
.contact__content.is-revealed .contact__description { transition-delay: 0.22s; }
.contact__content.is-revealed .btn--contact      { transition-delay: 0.33s; }
.contact__content.is-revealed .contact__socials  { transition-delay: 0.44s; }
.contact__content.is-revealed .contact__meta     { transition-delay: 0.55s; }

.contact__content.is-revealed .contact__title,
.contact__content.is-revealed .contact__description,
.contact__content.is-revealed .btn--contact,
.contact__content.is-revealed .contact__socials,
.contact__content.is-revealed .contact__meta {
  opacity: 1;
  transform: translate3d(0, 0, 0);
  transition:
    opacity  var(--dur-lg) var(--ease-out-expo),
    transform var(--dur-lg) var(--ease-out-expo);
}

/* ─────────────────────────────────────────────
   5. FLOATING / IDLE LOOP ANIMATIONS
   CSS keyframes as fallback.
   GSAP overrides these with better control.
   ───────────────────────────────────────────── */

/* Floating mockup animations handled by GSAP after scroll into view */
.floating-mockup { animation: none; }
.project__float-el--1 { animation: none; }
.project__float-el--2 { animation: none; }
.project__float-el--3 { animation: none; }

@keyframes float-detail-1 {
  0%, 100% { transform: translate3d(0, 0px, 0);     opacity: 0.45; }
  50%       { transform: translate3d(5px, -11px, 0); opacity: 0.80; }
}

@keyframes float-detail-2 {
  0%, 100% { transform: translate3d(0, 0px, 0);       opacity: 0.35; }
  50%       { transform: translate3d(-7px, -9px, 0);   opacity: 0.70; }
}

/* Background shape drifts — hero atmosphere */
@keyframes shape-drift-1 {
  0%, 100% { transform: translate3d(0, 0, 0) scale(1); }
  33%       { transform: translate3d(22px, -16px, 0) scale(1.03); }
  66%       { transform: translate3d(-11px, 11px, 0) scale(0.97); }
}
@keyframes shape-drift-2 {
  0%, 100% { transform: translate3d(0, 0, 0); }
  50%       { transform: translate3d(-28px, 22px, 0); }
}
@keyframes shape-drift-3 {
  0%, 100% { transform: translate3d(0, 0, 0) scale(1);    opacity: 0.40; }
  50%       { transform: translate3d(16px, -22px, 0) scale(1.06); opacity: 0.65; }
}
@keyframes shape-drift-4 {
  0%, 100% { transform: translate3d(0, 0, 0) rotate(0deg); }
  50%       { transform: translate3d(18px, -12px, 0) rotate(8deg); }
}

/* Shape animations disabled — shapes have no fill so animation is wasted CPU */
.shape--1 { animation: none; }
.shape--2 { animation: none; }
.shape--3 { animation: none; }
.shape--4 { animation: shape-rotate 30s linear infinite; } /* keep the ring rotation, it's cheap */

/* Scroll cue bounce */
@keyframes scroll-cue-bounce {
  0%, 100% { transform: translate3d(-50%, 0, 0); }
  50%       { transform: translate3d(-50%, 8px, 0); }
}
.hero__scroll-line {
  animation: scroll-cue-bounce 2s ease-in-out infinite;
}

/* ─────────────────────────────────────────────
   6. HOVER MICRO-INTERACTIONS
   CSS-only — instant feedback before GSAP fires.
   ───────────────────────────────────────────── */

/* Ability card hover */
@media (hover: hover) and (pointer: fine) {
  .ability-card {
    transition:
      opacity  var(--dur-lg) var(--ease-out-expo),
      transform var(--dur-lg) var(--ease-out-expo),
      border-color var(--dur-sm) ease,
      box-shadow   0.4s ease;
  }

  /* Profile rings on hover */
  .hero__profile-wrap:hover .hero__profile-ring {
    border-color: rgba(243, 231, 217, 0.14);
    box-shadow: 0 0 42px rgba(243, 231, 217, 0.08);
    transition:
      border-color 0.55s ease,
      box-shadow   0.55s ease;
  }

  /* Button glow on hover */
  .btn--primary:hover,
  .btn--contact:hover {
    transition:
      transform  var(--dur-sm) var(--ease-out-back),
      box-shadow var(--dur-sm) ease;
  }

  /* Nav link indicator */
  .nav__link::after {
    content: '';
    position: absolute;
    bottom: -2px;
    left: 0;
    width: 100%;
    height: 1px;
    background: currentColor;
    transform: scaleX(0);
    transform-origin: right center;
    transition: transform 0.35s var(--ease-out-expo);
  }

  .nav__link:hover::after,
  .nav__link--active::after {
    transform: scaleX(1);
    transform-origin: left center;
  }
}

/* Contact button — ripple press effect */
.btn--contact {
  position: relative;
  overflow: hidden;
}

.btn--contact::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: rgba(255, 255, 255, 0.10);
  transform: scale(0);
  opacity: 0;
  pointer-events: none;
  transition:
    transform 0.45s var(--ease-out-expo),
    opacity   0.45s ease;
}

.btn--contact:active::after {
  transform: scale(1);
  opacity: 1;
  transition-duration: 0.08s;
}

/* Project link arrow slide */
.btn--project .btn__arrow {
  display: inline-block;
  transition: transform 0.3s var(--ease-out-expo);
}

@media (hover: hover) and (pointer: fine) {
  .btn--project:hover .btn__arrow {
    transform: translate3d(5px, 0, 0);
  }
}

/* ─────────────────────────────────────────────
   7. SCROLL PROGRESS BAR
   scaleX is GPU-composited — no paint triggered.
   GSAP uses scaleX; CSS provides the base style.
   ───────────────────────────────────────────── */
.scroll-progress {
  position:         fixed;
  top:              0;
  left:             0;
  height:           2px;
  width:            100%;                /* full width — scaleX controls progress */
  transform:        scaleX(0);
  transform-origin: left center;
  background:       linear-gradient(
    90deg,
    var(--color-accent, #f3e7d9)  0%,
    rgba(84, 67, 73, 0.45)        100%
  );
  z-index:          calc(var(--z-nav, 100) + 10);
}

/* ─────────────────────────────────────────────
   8. NAV ANIMATIONS
   ───────────────────────────────────────────── */
.nav.is-visible {
  opacity: 1;
  transform: translate3d(0, 0, 0);
  transition:
    opacity  var(--dur-lg) var(--ease-out-expo),
    transform var(--dur-lg) var(--ease-out-expo);
}

/* Hide on scroll down */
.nav.nav--hidden {
  transform: translate3d(0, -100%, 0);
  transition: transform 0.38s var(--ease-in-out);
}

/* Show on scroll up */
.nav.nav--visible {
  transform: translate3d(0, 0, 0);
  transition: transform 0.42s var(--ease-out-expo);
}

/* Active link indicator */
.nav__indicator {
  transform: scaleX(0);
  transform-origin: left center;
  opacity: 0;
  transition:
    transform 0.35s var(--ease-out-expo),
    opacity   0.35s ease;
}

/* ─────────────────────────────────────────────
   9. WORD SPLIT — TITLE ENTRANCE
   GSAP animates .word spans individually.
   CSS provides the base layer/overflow clipping.
   ───────────────────────────────────────────── */
.word-wrap {
  display: inline-block;
  overflow: hidden;
  line-height: inherit;
  vertical-align: bottom;
}

.word {
  display: inline-block;
  transform-origin: bottom center;
  opacity: 0;
  transform: translate3d(0, 40px, 0);
}

.word.is-visible {
  opacity: 1;
  transform: translate3d(0, 0, 0);
  transition:
    opacity  var(--dur-lg) var(--ease-out-expo),
    transform var(--dur-lg) var(--ease-out-expo);
}

/* ─────────────────────────────────────────────
   10. PARALLAX LAYER BASES
   GSAP inlines transform; these are default states.
   ───────────────────────────────────────────── */
.parallax-layer,
[data-speed] {
  will-change: transform;
  transform: translate3d(0, 0, 0);
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
}

/* ─────────────────────────────────────────────
   11. SKILL BAR FILL
   Width transition fired by .is-animating class.
   GSAP also drives this directly — CSS is fallback.
   ───────────────────────────────────────────── */
.ability-card__bar-fill {
  width:      0%;
  transition: width 0s;  /* disabled until JS triggers */
}

.ability-card__bar-fill.is-animating {
  transition: width 1.4s var(--ease-out-expo);
}

/* ─────────────────────────────────────────────
   12. HERO EXIT — is-exiting CLASS FALLBACK
   CSS handles this when GSAP scrub isn't active
   (e.g., quick scroll on low-end devices).
   ───────────────────────────────────────────── */
.hero.is-exiting .hero__content {
  transform: translate3d(0, -40px, 0) scale(0.97);
  opacity: 0.3;
  transition:
    transform 0.55s var(--ease-in-out),
    opacity   0.55s ease;
}

/* ─────────────────────────────────────────────
   13. MOBILE MENU LINK STAGGER
   ───────────────────────────────────────────── */
.nav__mobile-menu .nav__mobile-link {
  opacity: 0;
  transform: translate3d(0, 22px, 0);
  transition:
    opacity  0.5s var(--ease-out-expo),
    transform 0.5s var(--ease-out-expo),
    color    0.2s ease;
}

.nav__mobile-menu.is-open .nav__mobile-link:nth-child(1) { transition-delay: 0.08s; }
.nav__mobile-menu.is-open .nav__mobile-link:nth-child(2) { transition-delay: 0.16s; }
.nav__mobile-menu.is-open .nav__mobile-link:nth-child(3) { transition-delay: 0.24s; }
.nav__mobile-menu.is-open .nav__mobile-link:nth-child(4) { transition-delay: 0.32s; }

.nav__mobile-menu.is-open .nav__mobile-link {
  opacity: 1;
  transform: translate3d(0, 0, 0);
}

/* ─────────────────────────────────────────────
   14. PROJECT TRANSITION CURTAINS
   Scene-change dividers between projects.
   ───────────────────────────────────────────── */
.project-transition {
  position: relative;
  z-index:  10;
  overflow: hidden;
}

.transition__curtain--top,
.transition__curtain--bottom {
  will-change: transform, opacity;
  transition:
    transform 0.85s var(--ease-out-expo),
    opacity   0.85s ease;
}

/* Project divider line — scaleX entrance */
.project__divider {
  transform:        scaleX(0);
  transform-origin: left center;
  opacity:          0;
  transition:
    transform 1.1s var(--ease-out-expo),
    opacity   1.1s ease;
}

.project__divider.is-revealed {
  transform: scaleX(1);
  opacity:   1;
}

/* ─────────────────────────────────────────────
   15. CURSOR SPOTLIGHT
   Dynamically injected by parallaxEffects.js.
   Base styles defined here.
   ───────────────────────────────────────────── */
.cursor-spotlight {
  position:       absolute;
  inset:          0;
  pointer-events: none;
  z-index:        1;
  opacity:        0;
  background: radial-gradient(
    600px circle at var(--spotlight-x, 50%) var(--spotlight-y, 50%),
    rgba(255, 255, 255, 0.04) 0%,
    transparent 70%
  );
  transition: opacity 0.4s ease;
}

/* ─────────────────────────────────────────────
   16. PREFERS-REDUCED-MOTION
   Accessibility override — kill ALL motion.
   Elements jump to final state immediately.
   ───────────────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {

  /* Kill CSS keyframe animations */
  .floating-mockup,
  .project__float-el--1,
  .project__float-el--2,
  .project__float-el--3,
  .shape--1,
  .shape--2,
  .shape--3,
  .shape--4,
  .hero__scroll-line,
  .noise-overlay,
  .mockup-halo,
  .cursor-spotlight {
    animation: none !important;
    transition: none !important;
  }

  /* Reveal all initially-hidden elements immediately */
  .hero__bg,
  .hero__profile-img,
  .hero__title,
  .hero__description,
  .hero__cta-group,
  .hero__scroll-cue,
  .hero__profile-wrap,
  .hero__content,
  .hero__shapes,
  .nav,
  .ability-card,
  .project__content,
  .project__mockups,
  .project__inner--reverse .project__content,
  .project__inner--reverse .project__mockups,
  .mockup--phone,
  .mockup--desktop,
  .section-header,
  .section-label,
  .section-title,
  .projects__header,
  .contact__content,
  .contact__title,
  .contact__description,
  .contact__socials,
  .contact__social-link,
  .contact__meta,
  [data-scroll-reveal],
  .project__number,
  .project__type,
  .project__title,
  .project__description,
  .project__tags,
  .btn--project,
  .project__float-el,
  .project__divider,
  .word,
  .nav__mobile-menu .nav__mobile-link {
    opacity:    1 !important;
    transform:  none !important;
    transition: none !important;
  }

  /* Skill bars jump to final width */
  .ability-card__bar-fill {
    transition: none !important;
  }
}
