/* ============================================================
   motion.css — animation layer for ilkinaziz.com
   Everything is scoped behind .m-ready (added by motion.js) so
   content is never hidden if JS fails. Movement is disabled for
   visitors who prefer reduced motion; pointer effects are desktop-only.
   ============================================================ */

/* ---------- 1. scroll progress ---------- */
.m-progress {
  position: fixed; top: 0; left: 0; right: 0; height: 3px; z-index: 60;
  background: linear-gradient(90deg, var(--accent), var(--accent-2));
  transform: scaleX(0); transform-origin: 0 50%;
  will-change: transform; pointer-events: none;
}

/* ---------- 2. film grain ---------- */
.m-ready body::after {
  content: ""; position: fixed; inset: 0; z-index: 1; pointer-events: none;
  opacity: .028; mix-blend-mode: multiply;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)'/%3E%3C/svg%3E");
}
[data-theme="dark"] .m-ready body::after,
.m-ready[data-theme="dark"] body::after { opacity: .05; mix-blend-mode: screen; }

/* ---------- 3. hero word reveal ---------- */
.m-word {
  display: inline-block; overflow: hidden; vertical-align: top;
  padding: .14em .03em .2em; margin: -.14em -.03em -.2em;
}
.m-word-i {
  display: inline-block;
  transform: translateY(110%);
  transition: transform .95s cubic-bezier(.16, 1, .3, 1);
  will-change: transform;
}
.m-split-in .m-word-i { transform: translateY(0); }
.m-split-done .m-word-i { will-change: auto; }

/* hero block: motion.js drives the reveal, so cancel the site's block fade */
.m-ready #hero.reveal { opacity: 1; transform: none; transition: none; }

/* hero supporting lines rise after the headline */
.m-ready .hero__eyebrow,
.m-ready .hero__lede,
.m-ready .hero__actions,
.m-ready .hero__badges,
.m-ready .hero__marquee {
  opacity: 0; transform: translateY(18px);
  transition: opacity .8s ease, transform .8s cubic-bezier(.16, 1, .3, 1);
}
.m-ready .hero__eyebrow.m-in,
.m-ready .hero__lede.m-in,
.m-ready .hero__actions.m-in,
.m-ready .hero__badges.m-in,
.m-ready .hero__marquee.m-in { opacity: 1; transform: none; }

/* ---------- 4. cursor spotlight in the hero ---------- */
/* The layer is deliberately much larger than the hero's 1080px content box:
   if the glow's falloff reached the element edge you would see a hard border. */
.m-spot {
  position: absolute; z-index: 0; pointer-events: none;
  top: -80px; bottom: -360px; left: 50%; width: 100vw; transform: translateX(-50%);
  opacity: 0; transition: opacity .6s ease;
  background: radial-gradient(circle 300px at var(--mx, 50%) var(--my, 50%),
    rgba(255, 77, 46, .11), rgba(255, 210, 63, .05) 42%, rgba(255, 210, 63, 0) 72%);
}
.m-fine .hero:hover .m-spot { opacity: 1; }
.hero > *:not(.m-spot) { position: relative; z-index: 1; }

/* ---------- 5. section heading reveal ---------- */
.m-armed .section__head::before { width: 0; transition: width .9s cubic-bezier(.16, 1, .3, 1) .05s; }
.m-armed .section__head.m-in::before { width: 40px; }

/* A slow, soft fade reads calmer than a wipe — a clip-path reveal looks like a
   highlighter sweeping across the words. Driven from the parent so the observed
   element itself is never clipped or hidden. */
.m-armed .section__head .section__title,
.m-armed .contact .contact__title {
  opacity: 0;
  transform: translateY(12px);
  transition: opacity 1.8s ease, transform 1.8s cubic-bezier(.16, 1, .3, 1);
}
.m-armed .section__head.m-in .section__title,
.m-armed .contact.m-in .contact__title { opacity: 1; transform: none; }

/* the subtitle follows a beat later, same gentle fade */
.m-armed .section__head .section__sub {
  opacity: 0; transform: translateY(10px);
  transition: opacity 1.8s ease .18s, transform 1.8s cubic-bezier(.16, 1, .3, 1) .18s;
}
.m-armed .section__head.m-in .section__sub { opacity: 1; transform: none; }

/* ---------- 6. staggered card entrances ---------- */
.m-armed .m-stagger {
  opacity: 0; transform: translateY(28px) scale(.975);
  transition: opacity .75s ease, transform .75s cubic-bezier(.16, 1, .3, 1);
}
.m-armed .m-stagger.m-in { opacity: 1; transform: none; }

/* ---------- 7. 3D tilt cards ---------- */
.m-fine .m-tilt { position: relative; transform-style: preserve-3d; }
.m-fine .m-tilt.m-tilting { transition: transform .1s linear, border-color .3s; }
.m-sheen {
  position: absolute; inset: 0; border-radius: inherit; pointer-events: none;
  opacity: 0; transition: opacity .35s ease;
  background: radial-gradient(circle 240px at var(--sx, 50%) var(--sy, 50%),
    rgba(255, 255, 255, .55), transparent 68%);
  mix-blend-mode: soft-light;
}
[data-theme="dark"] .m-sheen {
  background: radial-gradient(circle 240px at var(--sx, 50%) var(--sy, 50%),
    rgba(255, 255, 255, .1), transparent 68%);
  mix-blend-mode: screen;
}
.m-fine .m-tilt:hover .m-sheen { opacity: 1; }

/* ---------- 8. timeline accent bars ---------- */
.m-armed .timeline__item { position: relative; overflow: hidden; }
.m-armed .timeline__item::before {
  content: ""; position: absolute; left: 0; top: 1.6rem; bottom: 1.6rem; width: 3px;
  border-radius: 0 3px 3px 0;
  background: linear-gradient(180deg, var(--accent), var(--accent-2));
  transform: scaleY(0); transform-origin: 50% 0;
  transition: transform 1s cubic-bezier(.16, 1, .3, 1);
}
.m-armed .timeline__item.m-in::before { transform: scaleY(1); }

/* ---------- 9. magnetic buttons ---------- */
.m-fine .m-mag { transition: transform .45s cubic-bezier(.16, 1, .3, 1), background .25s, color .25s; }
.m-fine .m-mag.m-mag-on { transition: transform .12s ease-out, background .25s, color .25s; }

/* ---------- 10. portrait parallax ---------- */
.m-ready .about__photo img { will-change: transform; }

/* ---------- 11. theme switch circular wipe ---------- */
@media (prefers-reduced-motion: no-preference) {
  html.m-vt::view-transition-old(root) { animation: none; z-index: 1; }
  html.m-vt::view-transition-new(root) { animation: m-circle .6s cubic-bezier(.3, 0, .2, 1); z-index: 2; }
}
@keyframes m-circle {
  from { clip-path: circle(0 at var(--vtx, 50%) var(--vty, 50%)); }
  to   { clip-path: circle(160% at var(--vtx, 50%) var(--vty, 50%)); }
}

/* ---------- 12. reduced motion: keep it calm ---------- */
@media (prefers-reduced-motion: reduce) {
  .m-progress { display: none; }
  .m-ready body::after { display: none; }
  .m-word, .m-word-i { overflow: visible; transform: none !important; transition: none !important;
    padding: 0; margin: 0; }
  .m-ready .hero__eyebrow, .m-ready .hero__lede, .m-ready .hero__actions,
  .m-ready .hero__badges, .m-ready .hero__marquee,
  .m-armed .m-stagger { opacity: 1 !important; transform: none !important; transition: none !important; }
  .m-armed .section__head .section__title, .m-armed .contact .contact__title,
  .m-armed .section__head .section__sub {
    opacity: 1 !important; transform: none !important; transition: none !important; }
  .m-armed .section__head::before { width: 40px !important; transition: none !important; }
  .m-armed .timeline__item::before { transform: scaleY(1) !important; transition: none !important; }
  .m-spot, .m-sheen { display: none; }
}

/* ---------- 13. animated page-to-page navigation ---------- */
@keyframes m-pageOut { to { opacity: 0; transform: translateY(-8px); } }
@keyframes m-pageIn { from { opacity: 0; transform: translateY(16px); } }
@media (prefers-reduced-motion: reduce) {
  html::view-transition-old(root), html::view-transition-new(root) { animation: none !important; }
}

/* ---------- 14. page loader: monogram in a progress ring ----------
   Part of every page's static HTML and visible from the FIRST PAINT, so the
   browser never shows the empty skeleton or the previous page for a frame.
   JS uncovers it once the content has rendered; the CSS animation below is a
   failsafe so it can never stick. */
.m-load {
  position: fixed; inset: 0; z-index: 500; display: grid; place-items: center;
  background: rgba(251, 251, 250, .96); backdrop-filter: blur(6px);
  opacity: 1; visibility: visible;
  transition: opacity .34s ease, visibility .34s;
  animation: m-loadFail 0s linear 3.2s forwards;
}
[data-theme="dark"] .m-load { background: rgba(12, 12, 16, .96); }
.m-load.off { opacity: 0; visibility: hidden; animation: none; }
@keyframes m-loadFail { to { opacity: 0; visibility: hidden; } }

/* a card moving To do -> Doing -> Done.
   Column tints are absolute rather than theme vars: --bg-2 sits too close to
   the overlay background in both themes and the board vanished. */
.m-kb {
  position: relative; width: 104px; height: 72px; display: flex; gap: 7px;
  animation: m-kbFloat 2.4s ease-in-out infinite;
}
.m-kb__col {
  width: 30px; border-radius: 6px; position: relative;
  background: rgba(0, 0, 0, .045); border: 1px solid rgba(0, 0, 0, .13);
}
[data-theme="dark"] .m-kb__col {
  background: rgba(255, 255, 255, .05); border-color: rgba(255, 255, 255, .15);
}
.m-kb__col::before {            /* column header */
  content: ""; position: absolute; left: 6px; right: 6px; top: 6px; height: 2px;
  border-radius: 2px; background: rgba(0, 0, 0, .22);
}
[data-theme="dark"] .m-kb__col::before { background: rgba(255, 255, 255, .26); }
.m-kb__col::after {             /* a card already sitting in the column */
  content: ""; position: absolute; left: 5px; right: 5px; height: 8px;
  border-radius: 3px; background: rgba(0, 0, 0, .16);
}
[data-theme="dark"] .m-kb__col::after { background: rgba(255, 255, 255, .18); }
.m-kb__col:nth-child(1)::after { top: 16px; }
.m-kb__col:nth-child(2)::after { top: 28px; }
.m-kb__col:nth-child(3)::after { top: 16px; }
.m-kb__card {
  position: absolute; top: 42px; left: 6px; width: 18px; height: 11px;
  border-radius: 3px; background: linear-gradient(90deg, var(--accent), var(--accent-2));
  box-shadow: 0 4px 12px rgba(255, 77, 46, .45);
  animation: m-kbMove .9s cubic-bezier(.4, 0, .18, 1) infinite;
}
/* The hops are front-loaded on purpose. The overlay is only guaranteed to be
   on screen for MIN_COVER (460ms), and the animation restarts with each
   arriving page — so both hops have to be done inside that window or the card
   just sits in the first column and the board looks broken.
   Timings at .9s: lands in col2 at 198ms, in col3 at 450ms. */
@keyframes m-kbMove {
  0%   { transform: translate(0, 0) scale(.88);    opacity: 0; }
  4%   { transform: translate(0, 0) scale(1);      opacity: 1; }
  8%   { transform: translate(0, 0); }
  15%  { transform: translate(18px, -9px); }
  22%  { transform: translate(37px, 0); }
  36%  { transform: translate(37px, 0); }
  43%  { transform: translate(55px, -9px); }
  50%  { transform: translate(74px, 0); }
  86%  { transform: translate(74px, 0) scale(1);   opacity: 1; }
  100% { transform: translate(74px, 0) scale(.88); opacity: 0; }
}
@keyframes m-kbFloat {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-4px); }
}
@media (prefers-reduced-motion: reduce) {
  .m-kb { animation: none; }
  .m-kb__card { animation: none; transform: translate(74px, 0); }   /* parked in Done */
  .m-load { transition: opacity .01s; backdrop-filter: none; }
}
.m-load.m-instant{transition:none}

/* ---------- Insights: reveal animation switched off entirely ---------- */
.m-armed #insights .section__title,
.m-armed #insights .section__sub {
  opacity: 1 !important; transform: none !important; transition: none !important;
}
.m-armed #insights .section__head::before { width: 40px !important; transition: none !important; }
