/* ====== Motion layer (animations, reveals, hover states) ====== */

/* Scroll reveal */
.reveal {
  opacity: 0;
  transform: translateY(28px);
  transition: opacity .9s cubic-bezier(.16,1,.3,1), transform .9s cubic-bezier(.16,1,.3,1);
}

/* ===== Boot → site entrance (orchestrated first-screen reveal) =========
   When the boot log finishes AND React has painted, <body> gets .booted and
   the splash fades. At that moment the whole first screen ASSEMBLES itself:
   the nav pill drops in, the side rail's icons cascade in from the left, and
   the hero pieces rise + sharpen one after another. Only runs when motion is
   allowed; reduced-motion users just see the finished screen instantly.

   NOTE: .navbar and .rail are positioned with transform (translateX/Y), so we
   animate their INNER pieces (.nav-pill, .rail a/.line) — never the positioned
   container — to avoid fighting their centering. */
@media (prefers-reduced-motion: no-preference) {
  /* hidden until the assemble begins */
  body:not(.booted) .navbar .nav-pill,
  body:not(.booted) .rail a,
  body:not(.booted) .rail .line,
  body:not(.booted) .hero-version,
  body:not(.booted) .hero-eyebrow,
  body:not(.booted) .hero-title .ht-line,
  body:not(.booted) .hero-body,
  body:not(.booted) .hero-cta,
  body:not(.booted) .hero-right,
  body:not(.booted) .hero-scroll { opacity: 0; }

  /* cascade — each piece animates in with a staggered delay */
  body.booted .navbar .nav-pill            { animation: introDrop .72s cubic-bezier(.16,1,.3,1) both; animation-delay: .12s; }
  body.booted .rail a                       { animation: introSlideL .7s cubic-bezier(.16,1,.3,1) both; }
  body.booted .rail a:nth-child(1)          { animation-delay: .26s; }
  body.booted .rail a:nth-child(2)          { animation-delay: .33s; }
  body.booted .rail a:nth-child(3)          { animation-delay: .40s; }
  body.booted .rail a:nth-child(4)          { animation-delay: .47s; }
  body.booted .rail .line                   { animation: introSlideL .7s cubic-bezier(.16,1,.3,1) both; animation-delay: .54s; }
  body.booted .hero-version                 { animation: introFade .7s ease both; animation-delay: .30s; }
  body.booted .hero-eyebrow                 { animation: introRise .8s cubic-bezier(.16,1,.3,1) both; animation-delay: .34s; }
  body.booted .hero-title .ht-line:nth-child(1) { animation: introRise .85s cubic-bezier(.16,1,.3,1) both; animation-delay: .44s; }
  body.booted .hero-title .ht-line:nth-child(2) { animation: introRise .85s cubic-bezier(.16,1,.3,1) both; animation-delay: .56s; }
  body.booted .hero-body                    { animation: introRise .85s cubic-bezier(.16,1,.3,1) both; animation-delay: .70s; }
  body.booted .hero-cta                     { animation: introRise .85s cubic-bezier(.16,1,.3,1) both; animation-delay: .84s; }
  body.booted .hero-right                   { animation: introRiseScale .9s cubic-bezier(.16,1,.3,1) both; animation-delay: .50s; }
  body.booted .hero-scroll                  { animation: introFade .9s ease both; animation-delay: 1.05s; }
}

@keyframes introDrop {
  from { opacity: 0; transform: translateY(-22px); }
  to   { opacity: 1; transform: translateY(0); }
}
@keyframes introSlideL {
  from { opacity: 0; transform: translateX(-16px); }
  to   { opacity: 1; transform: translateX(0); }
}
@keyframes introRise {
  from { opacity: 0; transform: translateY(22px); filter: blur(6px); }
  to   { opacity: 1; transform: translateY(0);   filter: blur(0); }
}
@keyframes introRiseScale {
  from { opacity: 0; transform: translateY(26px) scale(.985); filter: blur(8px); }
  to   { opacity: 1; transform: translateY(0)   scale(1);     filter: blur(0); }
}
@keyframes introFade {
  from { opacity: 0; }
  to   { opacity: 1; }
}

.reveal.revealed { opacity: 1; transform: translateY(0); }
.reveal.section-title { transform: translateY(40px); }
.reveal.project-card { transform: translateY(36px) scale(.98); }
.reveal.project-card.revealed { transform: translateY(0) scale(1); }
.reveal.timeline-item { transform: translateX(-20px); }
.reveal.timeline-item.revealed { transform: translateX(0); }

/* Split text */
[data-split] .ch {
  display: inline-block;
  opacity: 0;
  transform: translateY(60%) rotate(6deg);
  transition: opacity .8s cubic-bezier(.16,1,.3,1), transform .8s cubic-bezier(.16,1,.3,1);
}
[data-split].revealed .ch,
.revealed[data-split] .ch {
  opacity: 1;
  transform: translateY(0) rotate(0);
}

/* Magnetic transitions */
.btn, .nav-pill a, .chip, .project-card .actions a {
  transition: transform .35s cubic-bezier(.16,1,.3,1), background .25s, color .25s, border-color .25s;
}

/* Tilt cards — smooth return */
.project-card, .about .pic, .contact-card, .terminal {
  transition: transform .6s cubic-bezier(.16,1,.3,1), border-color .3s, box-shadow .35s;
  transform-style: preserve-3d;
}

/* Card sheen following cursor (uses --mx/--my set by tilt JS) */
.project-card::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: radial-gradient(360px 240px at var(--mx, 50%) var(--my, 50%), #ece4d014, transparent 70%);
  pointer-events: none;
  opacity: 0;
  transition: opacity .35s;
  z-index: 1;
}
.project-card:hover::after { opacity: 1; }
.project-card .info, .project-card .visual { position: relative; z-index: 2; }

/* Animated underline on nav links */
.nav-links a {
  position: relative;
  overflow: hidden;
}
.nav-links a::before {
  content: "";
  position: absolute;
  left: 14px; right: 14px;
  bottom: 6px;
  height: 1px;
  background: var(--ink);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform .4s cubic-bezier(.16,1,.3,1);
}
.nav-links a:hover::before,
.nav-links a.active::before { transform: scaleX(1); }
.nav-links a span.label-clone {
  display: inline-block;
  transition: transform .35s cubic-bezier(.16,1,.3,1);
}

/* Glow ring on focus / active section */
.nav-links a.active {
  background: linear-gradient(180deg, #ffffff14, #ffffff06) !important;
  color: var(--ink) !important;
  box-shadow: 0 0 0 1px var(--line-strong), 0 0 24px #3eff9a18;
}

/* Buttons — sliding ink fill */
.btn {
  position: relative;
  overflow: hidden;
  isolation: isolate;
}
.btn::before {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--ink);
  transform: translateY(101%);
  transition: transform .45s cubic-bezier(.16,1,.3,1);
  z-index: -1;
}
.btn:hover::before { transform: translateY(0); }
.btn:hover { color: var(--bg); border-color: var(--ink); }
.btn.primary::before { background: var(--green); }
.btn.primary:hover { background: var(--green); color: var(--bg); }

/* Chip pop on hover */
.chip {
  transition: transform .3s cubic-bezier(.16,1,.3,1), background .25s, color .25s, border-color .25s;
}
.chip:hover {
  transform: translateY(-2px);
  border-color: var(--green-dim);
  color: var(--green);
  background: #3eff9a0a;
}

/* About stats — count-up style entry */
.about-stats .stat .n {
  display: inline-block;
  background: linear-gradient(180deg, var(--ink), #ece4d088);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  transition: transform .6s cubic-bezier(.16,1,.3,1);
}
.about-stats.revealed .stat .n { transform: translateY(0); }

/* Timeline dots — pulse on the active 'now' */
.timeline-item.now::before {
  animation: pulseDot 2s ease-in-out infinite;
}
@keyframes pulseDot {
  0%, 100% { box-shadow: 0 0 0 0 var(--green), 0 0 14px var(--green); }
  50%      { box-shadow: 0 0 0 8px #3eff9a00, 0 0 20px var(--green); }
}

/* Subtle floating drift on the about pic */
.about .pic {
  animation: floatY 8s ease-in-out infinite;
}
@keyframes floatY {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-6px); }
}

/* Section title subtle gradient sweep */
h2.section-title {
  background: linear-gradient(100deg, var(--ink) 30%, var(--green) 50%, var(--ink) 70%);
  background-size: 200% 100%;
  background-position: 100% 50%;
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  transition: background-position 1.6s cubic-bezier(.16,1,.3,1);
}
h2.section-title.revealed { background-position: 0% 50%; }

/* Terminal: subtle scanline + glow pulse */
.terminal {
  position: relative;
}
.terminal::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: repeating-linear-gradient(0deg, transparent 0 2px, #ffffff04 2px 3px);
  pointer-events: none;
  mix-blend-mode: overlay;
  opacity: 0.6;
}
.terminal {
  box-shadow:
    0 1px 0 #ffffff10 inset,
    0 30px 80px -20px #00000099,
    0 0 0 1px #3eff9a10,
    0 0 60px #3eff9a08;
  animation: termGlow 5s ease-in-out infinite;
}
@keyframes termGlow {
  0%, 100% { box-shadow: 0 1px 0 #ffffff10 inset, 0 30px 80px -20px #00000099, 0 0 0 1px #3eff9a10, 0 0 60px #3eff9a08; }
  50%      { box-shadow: 0 1px 0 #ffffff10 inset, 0 30px 80px -20px #00000099, 0 0 0 1px #3eff9a25, 0 0 80px #3eff9a18; }
}

/* Tech stage — ambient floor glow */
.tech-stage::after {
  content: "";
  position: absolute;
  bottom: -40%;
  left: 50%;
  transform: translateX(-50%);
  width: 70%;
  aspect-ratio: 2/1;
  border-radius: 50%;
  background: radial-gradient(closest-side, #3eff9a18, transparent 70%);
  filter: blur(20px);
  pointer-events: none;
}

/* Tech icons — entry stagger + hover lift */
.tech-icon {
  transition:
    transform .9s cubic-bezier(.16,1,.3,1),
    opacity .55s,
    border-color .25s,
    background .25s,
    color .25s;
}
.tech-stage.blast .tech-icon:hover {
  transform: translate(var(--tx), var(--ty)) scale(1.7) !important;
  background: linear-gradient(180deg, #3eff9a14, #3eff9a04);
  border-color: var(--green);
  box-shadow: 0 12px 32px -4px #3eff9a30, 0 0 0 1px #3eff9a40;
  z-index: 12;
}

/* Project visuals — hover plays them */
.project-card:hover .v-ocr .laser { animation-duration: 1.6s; }
.project-card:hover .v-face .bracket { transform: translate(-50%, -50%) scale(1.06); transition: transform .6s cubic-bezier(.16,1,.3,1); }
.project-card:hover .v-claw circle[fill="#3eff9a"] { filter: drop-shadow(0 0 8px var(--green)); }

/* Footer mini — gentle bob */
.footer-mini.shown { animation: bobUp .9s cubic-bezier(.16,1,.3,1); }
@keyframes bobUp {
  0% { transform: translateX(-50%) translateY(120%); opacity: 0; }
  60% { transform: translateX(-50%) translateY(-6px); opacity: 1; }
  100% { transform: translateX(-50%) translateY(0); opacity: 1; }
}

/* Cursor: smooth state morph */
.orb { transition: width .35s cubic-bezier(.16,1,.3,1), height .35s cubic-bezier(.16,1,.3,1), margin .35s, background .25s, border-width .35s, border-color .35s, box-shadow .35s; }

/* Hero caption letters cascade */
.hero-h .line { display: block; overflow: hidden; }
.hero-h .line .ch {
  display: inline-block;
  transform: translateY(110%);
  transition: transform .8s cubic-bezier(.16,1,.3,1);
}
.hero-caption.in .hero-h .line .ch { transform: translateY(0); }

/* Eyebrows: type-in line */
.eyebrow {
  position: relative;
  padding-left: 44px;
}
.eyebrow .dot {
  margin-right: 0;
  position: absolute;
  left: 28px; top: 50%;
  transform: translateY(-50%);
}
.eyebrow::before {
  content: "";
  position: absolute;
  left: 0; top: 50%;
  width: 24px; height: 1px;
  background: var(--line-strong);
  transform-origin: left;
  transform: scaleX(0);
  transition: transform .8s cubic-bezier(.16,1,.3,1) .1s;
}
.eyebrow.revealed::before { transform: scaleX(1); }

/* Bigger ambient grid breath */
body::before { animation: gridDrift 24s linear infinite; }
@keyframes gridDrift {
  from { background-position: 0 0, 0 0; }
  to   { background-position: 64px 64px, 64px 64px; }
}

/* Aurora wash drift */
body::after {
  animation: auroraDrift 18s ease-in-out infinite alternate;
}
@keyframes auroraDrift {
  0%   { background-position: 80% 10%, 10% 80%; }
  100% { background-position: 60% 30%, 30% 70%; }
}

/* Smooth focus ring */
*:focus-visible { outline: 2px solid var(--green); outline-offset: 4px; border-radius: 6px; }

/* VCR effect on bold/em across body — flickering CRT type */
b, strong, em, .vcr {
  font-family: var(--font-vcr);
  font-weight: 400;
  font-style: normal;
  letter-spacing: 0.02em;
  color: var(--ink);
  text-shadow:
    0 0 1px #ece4d088,
    0 0 6px #ece4d044,
    1px 0 0 #ff6a6a18,
   -1px 0 0 #3eff9a18;
  animation: vcrFlicker 5s steps(2, end) infinite;
  position: relative;
}
em {
  color: var(--green);
  text-shadow: 0 0 8px var(--green-dim);
}
@keyframes vcrFlicker {
  0%, 100% { opacity: 1; filter: none; }
  3% { opacity: 0.85; filter: blur(0.4px); }
  6% { opacity: 1; }
  48% { opacity: 1; }
  50% { opacity: 0.92; transform: translateX(0.5px); }
  52% { opacity: 1; transform: translateX(0); }
  93% { opacity: 0.96; }
}

/* protect places where em/strong shouldn't be VCR'd */
.btn em, .btn strong, .nav-pill em, .nav-pill strong,
.term-out em, .term-out strong { font-family: inherit; text-shadow: none; animation: none; color: inherit; letter-spacing: normal; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}

/* ===== Motion blur ==================================================
   A short DIRECTIONAL blur during transitions so movement reads as a smooth
   sweep rather than a hard cut. Deliberately NOT applied to the 3D-tilt
   elements (.project-card / .tw3-tile / .pic / .contact-card) — a resting
   filter flattens preserve-3d and would kill their tilt. */

/* Projects: blur trails off as the inner window slides in */
.proj-window {
  animation-name: projInBlur;
  will-change: opacity, transform, filter;
}
@keyframes projInBlur {
  0%   { opacity: 0; transform: translate3d(26px, 0, 0); filter: blur(5px); }
  45%  { filter: blur(1.4px); }
  100% { opacity: 1; transform: translate3d(0, 0, 0); filter: blur(0); }
}

/* Certifications: motion-blur the full-travel slide. The blur peaks mid-travel
   and resolves sharp, so the sweep reads as smooth motion smear rather than
   two hard-edged cards passing. */
.cv3-card.enter[data-dir="1"]  { animation-name: cv3EnterNextBlur; will-change: transform, filter; }
.cv3-card.enter[data-dir="-1"] { animation-name: cv3EnterPrevBlur; will-change: transform, filter; }
.cv3-card.exit[data-dir="1"]   { animation-name: cv3ExitNextBlur;  will-change: transform, filter; }
.cv3-card.exit[data-dir="-1"]  { animation-name: cv3ExitPrevBlur;  will-change: transform, filter; }
@keyframes cv3EnterNextBlur { 0% { transform: translateX(100%);  filter: blur(6px); } 50% { filter: blur(2.5px); } 100% { transform: translateX(0); filter: blur(0); } }
@keyframes cv3ExitNextBlur  { 0% { transform: translateX(0); filter: blur(0); } 50% { filter: blur(2.5px); } 100% { transform: translateX(-100%); filter: blur(6px); } }
@keyframes cv3EnterPrevBlur { 0% { transform: translateX(-100%); filter: blur(6px); } 50% { filter: blur(2.5px); } 100% { transform: translateX(0); filter: blur(0); } }
@keyframes cv3ExitPrevBlur  { 0% { transform: translateX(0); filter: blur(0); } 50% { filter: blur(2.5px); } 100% { transform: translateX(100%); filter: blur(6px); } }

/* Scroll reveals: a hair of defocus that sharpens as content rises into
   place. Excludes the 3D-tilt cards (see note above). */
.reveal:not(.project-card):not(.pic):not(.contact-card) {
  filter: blur(5px);
  transition:
    opacity .9s cubic-bezier(.16,1,.3,1),
    transform .9s cubic-bezier(.16,1,.3,1),
    filter .65s cubic-bezier(.16,1,.3,1);
}
.reveal.revealed:not(.project-card):not(.pic):not(.contact-card) {
  filter: blur(0);
}

@media (prefers-reduced-motion: reduce) {
  .proj-window, .cv3-card.enter, .cv3-card.exit,
  .reveal:not(.project-card):not(.pic):not(.contact-card) { filter: none !important; }
}


/* ===== Cursor trail / nebula / stars / hero marquee / CRT ===== */
.cursor-trail { position: fixed; inset: 0; pointer-events: none; z-index: 9998; }
.trail-p {
  position: absolute;
  width: 4px; height: 4px;
  margin-left: -2px; margin-top: -2px;
  border-radius: 50%;
  background: var(--green);
  box-shadow: 0 0 8px var(--green);
  opacity: .9;
  animation: trailFade .65s cubic-bezier(.2,.8,.2,1) forwards;
}
@keyframes trailFade {
  0% { opacity: .9; transform: scale(1); }
  100% { opacity: 0; transform: scale(0.2); }
}

.nebula { position: fixed; inset: -10%; z-index: 0; pointer-events: none; filter: blur(80px) saturate(140%); opacity: 0.55; }
.nebula .blob { position: absolute; width: 520px; height: 520px; border-radius: 50%; mix-blend-mode: screen; }
.nebula .b1 { background: radial-gradient(closest-side, #3eff9a55, transparent 70%); top: -10%; left: -8%; animation: blobA 22s ease-in-out infinite alternate; }
.nebula .b2 { background: radial-gradient(closest-side, #7b6dff44, transparent 70%); top: 20%; right: -10%; animation: blobB 28s ease-in-out infinite alternate; }
.nebula .b3 { background: radial-gradient(closest-side, #ece4d033, transparent 70%); bottom: -15%; left: 30%; animation: blobC 32s ease-in-out infinite alternate; }
.nebula .b4 { background: radial-gradient(closest-side, #ff6ec722, transparent 70%); top: 60%; left: -5%; width: 380px; height: 380px; animation: blobA 26s ease-in-out infinite alternate-reverse; }
@keyframes blobA { 0% { transform: translate(0,0) scale(1); } 100% { transform: translate(120px, 80px) scale(1.2); } }
@keyframes blobB { 0% { transform: translate(0,0) scale(1.1); } 100% { transform: translate(-160px, 100px) scale(.9); } }
@keyframes blobC { 0% { transform: translate(0,0) scale(.9); } 100% { transform: translate(80px, -120px) scale(1.15); } }

.stars { position: fixed; inset: 0; z-index: 0; pointer-events: none;
  background-image:
    radial-gradient(1px 1px at 13% 22%, #ece4d088, transparent 50%),
    radial-gradient(1px 1px at 47% 78%, #ece4d066, transparent 50%),
    radial-gradient(1.5px 1.5px at 81% 12%, #3eff9a99, transparent 50%),
    radial-gradient(1px 1px at 28% 64%, #ece4d066, transparent 50%),
    radial-gradient(1px 1px at 92% 88%, #ece4d099, transparent 50%),
    radial-gradient(1px 1px at 60% 30%, #3eff9a99, transparent 50%),
    radial-gradient(1px 1px at 8% 88%, #ece4d066, transparent 50%),
    radial-gradient(1px 1px at 70% 56%, #ece4d099, transparent 50%);
  animation: starTwinkle 4s ease-in-out infinite;
}
@keyframes starTwinkle { 0%, 100% { opacity: .8; } 50% { opacity: .4; } }

.hero-marquee {
  position: absolute; top: 12%; left: -10%; right: -10%;
  font-family: var(--font-vcr);
  font-size: clamp(80px, 13vw, 220px);
  line-height: 1; letter-spacing: -0.02em;
  white-space: nowrap;
  color: transparent;
  -webkit-text-stroke: 1px #ece4d018;
  pointer-events: none; user-select: none; z-index: 0;
  animation: marquee 28s linear infinite;
}
.hero-marquee.row2 { top: auto; bottom: 6%; animation-direction: reverse; animation-duration: 36s; opacity: .6; }
@keyframes marquee { from { transform: translateX(0); } to { transform: translateX(-50%); } }

.hero-particles { position: absolute; inset: 0; pointer-events: none; z-index: 1; }
.hero-particles span {
  position: absolute; width: 3px; height: 3px; border-radius: 50%;
  background: var(--ink); opacity: .4;
  animation: floatDrift 12s linear infinite;
}
.hero-particles span:nth-child(3n) { background: var(--green); box-shadow: 0 0 8px var(--green); opacity: .6; }
@keyframes floatDrift {
  0% { transform: translate(0,0); opacity: 0; }
  10% { opacity: .6; }
  90% { opacity: .4; }
  100% { transform: translate(40px, -120px); opacity: 0; }
}

.crt-scan { position: fixed; inset: 0; z-index: 2; pointer-events: none;
  background: repeating-linear-gradient(0deg, transparent 0 2px, #00000022 2px 3px);
  mix-blend-mode: multiply; opacity: 0.4; }
.crt-vignette { position: fixed; inset: 0; z-index: 2; pointer-events: none;
  background: radial-gradient(ellipse 100% 80% at 50% 50%, transparent 50%, #000a 100%); }
