/* =====================================================================
   fx.css — dynamic animations & interactions
   Uses the site's own colours (var(--green) = teal in Data Science,
   orange in the AI Generalist view), so nothing about the palette changes.
   Everything here is switched off for "reduce motion" users and touch-only
   effects are skipped on phones.
===================================================================== */

/* ---------- scroll progress bar ---------- */
.fx-progress {
    position: fixed;
    top: 0; left: 0;
    z-index: 10001;
    height: 2px;
    width: 100%;
    background: var(--green);
    transform-origin: 0 50%;
    transform: scaleX(0);
    box-shadow: 0 0 10px var(--green);
    pointer-events: none;
}

/* ---------- hero particle network ---------- */
.fx-network {
    position: absolute;
    inset: 0;
    z-index: 1;               /* above the dark overlay, below the text */
    width: 100%;
    height: 100%;
    pointer-events: none;
    opacity: 0;
    transition: opacity 1.2s ease;
}
.fx-network.is-on { opacity: 1; }

/* ---------- typewriter caret on the hero headline ---------- */
.fx-typing::after {
    content: "";
    display: inline-block;
    width: 0.08em;
    height: 0.9em;
    margin-left: 0.08em;
    vertical-align: -0.08em;
    background: var(--green);
    animation: fxCaret 0.9s steps(1) infinite;
}
.fx-typed::after { animation: fxCaret 0.9s steps(1) 4 forwards; }
@keyframes fxCaret { 50% { opacity: 0; } }

/* ---------- custom cursor (mouse only) ---------- */
.fx-cursor,
.fx-cursor-dot {
    position: fixed;
    top: 0; left: 0;
    z-index: 10002;
    pointer-events: none;
    border-radius: 50%;
    will-change: transform;
}
.fx-cursor {
    width: 36px; height: 36px;
    margin: -18px 0 0 -18px;
    border: 1.5px solid var(--green);
    opacity: 0;
    display: grid;
    place-items: center;
    transition: width 0.3s, height 0.3s, margin 0.3s, background-color 0.3s, opacity 0.3s, border-color 0.3s;
}
.fx-cursor-dot {
    width: 6px; height: 6px;
    margin: -3px 0 0 -3px;
    background: var(--green);
    opacity: 0;
    transition: opacity 0.3s, transform 0.08s;
}
.fx-cursor.is-visible, .fx-cursor-dot.is-visible { opacity: 1; }
.fx-cursor.is-hover {
    width: 60px; height: 60px;
    margin: -30px 0 0 -30px;
    background: var(--green-tint);
}
.fx-cursor.is-label {
    width: 84px; height: 84px;
    margin: -42px 0 0 -42px;
    background: var(--green);
    border-color: var(--green);
}
.fx-cursor__label {
    font-family: var(--font-mono, monospace);
    font-size: 12px;
    font-weight: 600;
    color: var(--navy);
    opacity: 0;
    transition: opacity 0.2s;
}
.fx-cursor.is-label .fx-cursor__label { opacity: 1; }
.fx-cursor.is-down { transform: scale(0.85); }

/* ---------- spotlight + tilt cards ---------- */
.fx-tilt {
    transform-style: preserve-3d;
    will-change: transform;
}
.fx-spot { position: relative; isolation: isolate; }
.fx-spot::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;              /* above the card background, below its content */
    border-radius: inherit;
    pointer-events: none;
    background: radial-gradient(420px circle at var(--mx, 50%) var(--my, 50%), var(--green-tint), transparent 45%);
    opacity: 0;
    transition: opacity 0.35s;
}
.fx-spot:hover::before { opacity: 1; }

/* glare on tilted images */
.fx-glare { position: relative; overflow: hidden; }
.fx-glare::after {
    content: "";
    position: absolute;
    inset: 0;
    pointer-events: none;
    background: radial-gradient(500px circle at var(--mx, 50%) var(--my, 0%), rgba(255, 255, 255, 0.18), transparent 40%);
    opacity: 0;
    transition: opacity 0.4s;
    z-index: 3;
}
.fx-glare:hover::after { opacity: 1; }

/* ---------- click ripple on buttons ---------- */
.fx-ripple-host { position: relative; overflow: hidden; }
.fx-ripple {
    position: absolute;
    border-radius: 50%;
    background: var(--green);
    opacity: 0.35;
    transform: scale(0);
    animation: fxRipple 0.65s ease-out forwards;
    pointer-events: none;
}
@keyframes fxRipple { to { transform: scale(1); opacity: 0; } }

/* ---------- section heading decode + underline draw ---------- */
.section-heading.fx-decoding { color: var(--lightest-slate); }
.section-heading::after { transform-origin: 0 50%; }
.section-heading.fx-line::after { animation: fxLine 1s cubic-bezier(0.22, 1, 0.36, 1) both; }
@keyframes fxLine { from { transform: scaleX(0); } to { transform: scaleX(1); } }

/* ---------- staggered list reveals ---------- */
.fx-stagger > * {
    opacity: 0;
    transform: translateY(14px);
    transition: opacity 0.5s ease, transform 0.5s ease;
}
.fx-stagger.is-in > * { opacity: 1; transform: none; }


/* ---------- back to top ---------- */
.fx-top {
    position: fixed;
    right: 96px;              /* clear of the vertical email line on the right */
    bottom: 32px;
    z-index: 900;
    width: 50px; height: 50px;
    border: 0;
    padding: 0;
    border-radius: 50%;
    background: var(--light-navy);
    color: var(--green);
    cursor: pointer;
    display: grid;
    place-items: center;
    opacity: 0;
    transform: translateY(16px) scale(0.9);
    pointer-events: none;
    transition: opacity 0.35s, transform 0.35s, box-shadow 0.3s;
    box-shadow: 0 10px 30px -15px var(--navy-shadow, rgba(2, 12, 27, 0.7));
}
.fx-top.is-shown { opacity: 1; transform: none; pointer-events: auto; }
.fx-top:hover { box-shadow: 0 0 0 4px var(--green-tint), 0 10px 30px -10px var(--green); }
.fx-top svg.fx-top__ring { position: absolute; inset: 0; width: 100%; height: 100%; transform: rotate(-90deg); }
.fx-top__ring circle { fill: none; stroke-width: 2; }
.fx-top__track { stroke: var(--lightest-navy); }
.fx-top__bar { stroke: var(--green); stroke-linecap: round; transition: stroke-dashoffset 0.1s linear; }
.fx-top__arrow { position: relative; width: 18px; height: 18px; transition: transform 0.3s; }
.fx-top:hover .fx-top__arrow { transform: translateY(-3px); }

/* the hidden admin dot sits bottom-right; move back-to-top clear of it */
@media (max-width: 768px) {
    .fx-top { right: 16px; bottom: 18px; width: 46px; height: 46px; }
}

/* ---------- hero name: letters lift on hover (desktop) ---------- */
.fx-letters { display: inline-block; }
.fx-letters span {
    display: inline-block;
    transition: transform 0.35s cubic-bezier(0.34, 1.56, 0.64, 1), color 0.3s;
}
.fx-letters span:hover { transform: translateY(-10px) rotate(-4deg); color: var(--green); }

/* ---------- reduce motion ---------- */
@media (prefers-reduced-motion: reduce) {
    .fx-network, .fx-cursor, .fx-cursor-dot, .fx-progress { display: none !important; }
    .fx-stagger > * { opacity: 1; transform: none; transition: none; }
    .fx-typing::after, .fx-typed::after { animation: none; display: none; }
    .section-heading.fx-line::after { animation: none; }
    .fx-letters span:hover { transform: none; }
}
