/* Noircraft Lab 2026 - effects carried over from the live site (task 1.1 §B2). Classes fx-* are added by assets/js/fx.js
   from data-fx attributes; switches live in assets/js/fx.config.js. Parameters are the live site's (catalogue in the report)
   multiplied by --fx-scale (NC_FX.timing.scale, set on <html> by fx.js; 1.3 since 13.10, R-3) for reveal, fly-*, flap and type.
   Without JS nothing is hidden. With prefers-reduced-motion every effect is in its final state and nothing moves. */

/* reveal: blur-reveal (live: .nc-reveal) */
.fx-reveal { opacity: 0; transform: translateY(18px); filter: blur(10px); transition: opacity calc(.6s * var(--fx-scale, 1)) ease, transform calc(.6s * var(--fx-scale, 1)) ease, filter calc(.6s * var(--fx-scale, 1)) ease; transition-delay: calc(var(--fx-d, 0s) * var(--fx-scale, 1)); }
.fx-reveal.fx-in { opacity: 1; transform: none; filter: blur(0); }

/* fly-left / fly-right: side entry (live: .nc-reveal--left/--right, ncFlyIn 1.1s cubic-bezier(.22,.61,.36,1), -90/+90 px) */
.fx-fly-left, .fx-fly-right { opacity: 0; }
.fx-fly-left { --fx-fly: -90px; }
.fx-fly-right { --fx-fly: 90px; }
.fx-fly-left.fx-in, .fx-fly-right.fx-in { animation: ncFlyIn calc(1.1s * var(--fx-scale, 1)) cubic-bezier(.22, .61, .36, 1) calc(var(--fx-d, 0s) * var(--fx-scale, 1)) both; }
@keyframes ncFlyIn { from { opacity: 0; transform: translateX(var(--fx-fly, 0)); } to { opacity: 1; transform: none; } }
@media (max-width: 1023px) {
  /* one column: the cards rise from below instead of flying from the sides */
  .fx-fly-left.fx-in, .fx-fly-right.fx-in { animation-name: ncFlyUp; }
  @keyframes ncFlyUp { from { opacity: 0; transform: translateY(28px); } to { opacity: 1; transform: none; } }
}

/* flap: split-flap "flip-drop" (live: manifesto, .42s cubic-bezier(.2,.8,.2,1), opacity .3s, 26 ms per letter, perspective 900) */
.fx-flap { perspective: 900px; }
.fx-w { display: inline-block; white-space: nowrap; }
.fx-flap .fx-ch { display: inline-block; transform-origin: 50% 0; backface-visibility: hidden; }
.fx-flap.fx-armed .fx-ch { opacity: 0; transform: translateY(-.45em) rotateX(-92deg); }
.fx-flap.fx-armed.fx-in .fx-ch { opacity: 1; transform: translateY(0) rotateX(0); transition: transform calc(.42s * var(--fx-scale, 1)) cubic-bezier(.2, .8, .2, 1), opacity calc(.3s * var(--fx-scale, 1)) ease; transition-delay: calc(var(--i, 0) * 26ms * var(--fx-scale, 1)); }

/* type: typewriter on the Hero H1 (live: 40 ms per letter x scale, gold caret blinking 1 s steps; the caret is removed by fx.js with the last letter) */
.fx-type .fx-ch.is-off { visibility: hidden; }
.fx-caret { display: inline-block; width: 0; position: relative; vertical-align: text-top; }
.fx-caret::after { content: ""; position: absolute; left: 0; top: .18em; width: .06em; height: .74em; background: var(--gold); animation: fx-caret-blink 1s steps(1) infinite; }
@keyframes fx-caret-blink { 50% { opacity: 0; } }

/* lift: hover lift of a card (live: -7 px + drop shadow; Roman 13.10: 4 px like the service cards, shadow on the same scale) */
.fx-lift { transition: translate .4s cubic-bezier(.2, .7, .2, 1), filter .4s; }
.fx-lift:hover { translate: 0 -4px; filter: drop-shadow(0 24px 44px rgba(232,201,74,0.18)); }
/* reveal + lift on one element (the step cards): until the reveal has ended, its transition applies (opacity, transform, filter);
   fx.js adds fx-done at the end of the reveal, then the lift's transition takes over */
.fx-reveal.fx-lift:not(.fx-done) { transition: opacity calc(.6s * var(--fx-scale, 1)) ease, transform calc(.6s * var(--fx-scale, 1)) ease, filter calc(.6s * var(--fx-scale, 1)) ease; transition-delay: calc(var(--fx-d, 0s) * var(--fx-scale, 1)); }

/* glow-ring: cursor-proximity gold ring on the card border (live: glow-card.css v2.3, radius 200, 2 px ring) */
.fx-glow-ring { --mx: -9999; --my: -9999; --on: 0; }
.fx-glow-ring::after { content: ""; position: absolute; inset: 0; z-index: 2; border-radius: inherit; padding: 2px; pointer-events: none;
  background: radial-gradient(180px 180px at calc(var(--mx) * 1px) calc(var(--my) * 1px), rgba(232,201,74,calc(var(--on) * 1)) 0%, transparent 72%);
  background-repeat: no-repeat;
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0); -webkit-mask-composite: xor; mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0); mask-composite: exclude; }

/* title-parallax: section titles drift with the pointer (live: .section-title, 8 / 6 px) */
.fx-title-parallax { translate: calc(var(--ncgx, 0) * 8px) calc(var(--ncgy, 0) * 6px); will-change: translate; }

/* reduced motion: final state, no movement (also when JS marks html.fx-reduce) */
@media (prefers-reduced-motion: reduce) {
  .fx-reveal, .fx-fly-left, .fx-fly-right { opacity: 1; transform: none; filter: none; transition: none; animation: none; }
  .fx-flap.fx-armed .fx-ch { opacity: 1; transform: none; transition: none; }
  .fx-type .fx-ch.is-off { visibility: visible; }
  .fx-caret { display: none; }
  .fx-lift, .fx-reveal.fx-lift:not(.fx-done) { transition: none; }
  .fx-lift:hover { translate: none; filter: none; }
  .fx-glow-ring::after { display: none; }
  .fx-title-parallax { translate: none; }
}
html.fx-reduce .fx-reveal, html.fx-reduce .fx-fly-left, html.fx-reduce .fx-fly-right, html.fx-reduce .fx-reveal.fx-lift:not(.fx-done) { opacity: 1; transform: none; filter: none; transition: none; animation: none; }
@media (hover: none) { .fx-lift:hover { translate: none; filter: none; } }
