/* ==========================================================================
   CONNECT — Snake-to-QR animation layer (Nokia-retro reveal).
   ---------------------------------------------------------------------------
   Replaces the static <img> QR with a two-layer stack inside the scan card:
     (1) a <canvas> where the snakes crawl in from the edges and lay down the
         black QR modules — pixel-square, retro, brand-coloured heads.
     (2) the REAL vector qr-linkedin.svg on top, hidden until the snakes finish,
         then cross-faded in. The crisp, scannable final QR is therefore the
         genuine vector (never a rasterised canvas, never a video) — scanability
         hangs on the SVG, exactly the locked 49x49 matrix.
   Offline-safe (no CDN), deterministic (seeded), reduced-motion -> instant QR.
   The dark modules sit on the off-white scan card = high contrast = scannable.
   ========================================================================== */

/* the stack: canvas + final svg occupy the same 320x320 box the <img> used.
   square box, no smoothing on the canvas -> hard retro pixels. */
.nc-snakeqr {
  position: relative;
  width: 320px;
  height: 320px;
  /* off-white paper showing through the quiet zone, same token as the card */
  background: var(--c-paper-200);
}

/* the snake playfield — drawn 1:1, scaled by the card. crisp pixels. */
.nc-snakeqr__canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  image-rendering: pixelated;          /* keep modules square if up-scaled */
  image-rendering: crisp-edges;
}

/* the genuine vector QR — the scannable end state. Hidden until armed-done. */
.nc-snakeqr__final {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  opacity: 0;
  transition: opacity 320ms var(--ease-out);
  pointer-events: none;
}

/* when the sequence has finished (or reduced-motion / no-JS), the real SVG is
   shown and the canvas is hidden underneath it. Driven by data-state on the
   stack: "snaking" = canvas live, "done" = vector shown. */
.nc-snakeqr[data-snake-state="done"] .nc-snakeqr__final { opacity: 1; }
.nc-snakeqr[data-snake-state="done"] .nc-snakeqr__canvas { opacity: 0; }
.nc-snakeqr__canvas { transition: opacity 200ms var(--ease-out); }

/* No-JS / reduced-motion safety net: if JS never runs, the <noscript>-style
   fallback is the SVG shown outright. We default the stack to "done" in markup
   so a dead-JS deck still shows a scannable QR; JS flips it to "snaking" only
   when it actually arms an animated run. */

/* Reduced motion: CSS alone forces the vector visible + canvas gone, even if
   the data-state never changes (belt and braces with the JS guard). */
@media (prefers-reduced-motion: reduce) {
  .nc-snakeqr__final { opacity: 1 !important; transition: none; }
  .nc-snakeqr__canvas { opacity: 0 !important; }
}
