/* ============================================================
   FX — the atmosphere layer that sits behind every page.

   Three things live in here, all of them decorative and all of
   them ignored by screen readers:

     1. the topographic contour field   (canvas, drawn by fx.js)
     2. the two undulating side rails   (canvas, drawn by fx.js)
     3. a blueprint grid, accent bloom and vignette (pure CSS)

   Nothing in this layer takes clicks. If you ever want the site
   flat and quiet, delete the <div class="fx"> block from the
   HTML and this whole file — everything else keeps working.
   ============================================================ */

.fx {
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  overflow: hidden;
  contain: layout paint;
}

/* ---------- 1. topographic contours ---------- */

.fx__topo {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  opacity: 0.85;
}

/* ---------- 2. side rails ---------- */

/* Full-height strips pinned to each edge. fx.js draws the contour
   spines into them; they swell while you are moving between
   projects and settle once you arrive.

   The strip is about twice as wide as the rail looks, because the
   inner half is swing room. The mask is what makes that usable: a
   wave reaching in toward the content dissolves instead of being
   clipped at a hard edge, and one that reaches far enough simply
   passes behind the panel. */
.fx__rail {
  position: absolute;
  top: 0;
  bottom: 0;
  width: var(--rail);
  height: 100%;
}
.fx__rail--l {
  left: 0;
  -webkit-mask-image: linear-gradient(to right, #000 50%, transparent 100%);
  mask-image: linear-gradient(to right, #000 50%, transparent 100%);
}
.fx__rail--r {
  right: 0;
  -webkit-mask-image: linear-gradient(to left, #000 50%, transparent 100%);
  mask-image: linear-gradient(to left, #000 50%, transparent 100%);
}

/* ---------- 3. CSS atmosphere ---------- */

/* Faint blueprint grid — the thing that makes it read as a tool
   rather than a poster. Two gradients, no images. */
.fx__grid {
  position: absolute;
  inset: -1px;
  background-image:
    linear-gradient(to right,  rgba(150, 175, 210, 0.1) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(150, 175, 210, 0.1) 1px, transparent 1px);
  background-size: 72px 72px;
  -webkit-mask-image: radial-gradient(ellipse 80% 70% at 50% 45%, #000 15%, transparent 80%);
  mask-image: radial-gradient(ellipse 80% 70% at 50% 45%, #000 15%, transparent 80%);
}

/* The accent bloom. Its colour follows the project you are on. */
.fx__glow {
  position: absolute;
  left: 50%;
  top: 46%;
  width: min(120vw, 1500px);
  aspect-ratio: 1.6;
  translate: -50% -50%;
  background:
    radial-gradient(ellipse at 28% 40%,
      color-mix(in srgb, var(--accent) 30%, transparent) 0%, transparent 58%),
    radial-gradient(ellipse at 76% 66%,
      color-mix(in srgb, var(--pop) 12%, transparent) 0%, transparent 52%);
  filter: blur(80px) saturate(150%);
  opacity: 0.5;
  transition: background 0.9s var(--ease);
  will-change: transform;
  animation: fx-breathe 30s ease-in-out infinite;
}

@keyframes fx-breathe {
  0%, 100% { transform: translate3d(-2%, 0, 0) scale(1); }
  50%      { transform: translate3d(3%, -3%, 0) scale(1.1); }
}

/* Corner darkening, so the middle of the screen stays the brightest
   thing on it. */
.fx__vignette {
  position: absolute;
  inset: 0;
  background:
    radial-gradient(ellipse 120% 95% at 50% 45%, transparent 42%, var(--bg-deep) 100%),
    linear-gradient(to bottom, rgba(0,0,0,0.45), transparent 22%, transparent 76%, rgba(0,0,0,0.55));
}

/* A single very slow scanline drifting down the page. Barely visible
   and that is the point — it keeps the screen feeling alive. */
.fx__scan {
  position: absolute;
  left: 0; right: 0;
  height: 40vh;
  background: linear-gradient(to bottom,
    transparent,
    color-mix(in srgb, var(--accent) 5%, transparent) 55%,
    transparent);
  opacity: 0.6;
  animation: fx-scan 18s linear infinite;
}

@keyframes fx-scan {
  0%   { transform: translateY(-45vh); }
  100% { transform: translateY(105vh); }
}

/* ---------- narrow screens ---------- */

/* Only the side rails go on a phone, because they need horizontal room that
   is not there. Everything else stays: the contour field is most of what
   makes the page look like itself, and a modern phone draws it comfortably.
   The rail canvases collapse to zero width here, and fx.js skips drawing
   into them, so they cost nothing while hidden. */
@media (max-width: 860px) {
  .fx__rail { display: none; }
  .fx__grid { background-size: 48px 48px; opacity: 0.28; }
}

/* ---------- calm version ---------- */

@media (prefers-reduced-motion: reduce) {
  .fx__scan { display: none; }
  .fx__glow { animation: none; opacity: 0.35; }
  .fx__topo { opacity: 0.6; }
}
