/* ============================================================
   Ink & Intuition — SHARED ambient module: rising soft-glow particles
   Structural CSS only. Palette, opacity, sizing and edge fades are all
   per-instance and are set inline by js/ambient/metaballs.js, because they
   differ per section (see that file's own comment block for why). This
   stylesheet only owns the parts that never change: positioning, clipping
   and the base particle shape.

   REPLACED 2026-08-08: this used to blur a shared container with an SVG
   filter and snap the blurred edges back to hard ones with a feColorMatrix
   ramp, so overlapping circles fused into one blob shape (an actual
   metaball merge). That forced a full-region filter re-rasterise every
   frame and measured as way too heavy on real hardware, so it is gone.
   Each particle now gets its OWN soft circular glow from a plain
   radial-gradient background, set inline per particle in the JS (it needs
   that particle's own colour), so there is no shared filter and no
   per-frame filter cost at all -- only `transform` changes frame to frame,
   which the browser can composite cheaply. Ported from
   tmp/briefs/ref-metaballs.md Section A (a React/TS reference Daniel
   supplied as flavour only, never vendored).

   Any section can adopt this: give it an empty
   `<div class="ambient-metaballs" aria-hidden="true"></div>` positioned
   wherever the ambient layer should sit (absolutely, inset over the field it
   belongs to) and call:

     window.II.ambient.metaballs.mount(el, { colors: [...], fieldOpacity, ... });

   See the JS file's top comment for the full options list. Nothing here
   assumes CTA; CTA's own tuning lives in css/sections/cta.css and
   js/sections/cta.js, not in this shared file.
   ============================================================ */

.ambient-metaballs {
  position: absolute;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
}

/* The particle layer. No filter of any kind lives here since the
   2026-08-08 change (see the file header) -- just an edge mask and an
   opacity, both set inline per instance because they differ per section. */
.ambient-metaballs__field {
  position: absolute;
  inset: 0;
}

/* Reduced motion holds a handful of particles at fixed, still positions (see
   the JS). This is a plain still frame, so nothing here needs a
   prefers-reduced-motion override of its own -- the JS never starts a loop
   in that mode, which is what actually stops the animation. */
.ambient-metaballs__particle {
  position: absolute;
  top: 0;
  left: 0;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  /* Belt and braces alongside the JS's own `radial-gradient(circle
     farthest-side, ...)`: the gradient already fades to transparent at
     this box's own edge, so this clip should never visibly bite, but it is
     a free backstop against a stretched (non-square) particle box leaving
     gradient corners exposed. */
  overflow: hidden;
  /* Positioned via transform, not left/top, every tick: compositor-friendly
     and consistent with how the rest of this codebase moves ambient layers
     (see --atmos-drift's own note in tokens.css). */
  will-change: transform;
}

@media (forced-colors: active) {
  /* Decoration only; forced-colours mode gives real content its own
     guaranteed contrast without this layer's help. */
  .ambient-metaballs { display: none; }
}
