/* ============================================================
   92 — AMBIENT GLOW

   WHY

   Measured on the home page: of 17,825px of scroll, the hero
   carries 22% and the features panel 6% — the remaining 72%
   (12,860px across the marquee, the about block, the showcase,
   the demo grid and the footer) is one flat value, rgb(12,12,12),
   with no image or gradient anywhere in it.

   This lifts three points of that expanse off the floor. It does
   not introduce a colour: the hue is --grad-cta's own violet,
   which until now appeared only inside buttons. Spreading a trace
   of it into the page is what connects those buttons — and the
   about page, built on the same violet — to the rest of the site.

   THE THREE CONSTRAINTS THIS WAS BUILT UNDER

   1. QUIET. Violet-bloom-on-black is the default look of every
      agency site right now, and this site is more distinctive
      without it. If the glow is obvious, it is wrong.

   2. NO COLOUR BEHIND THE DEMO GRID. That section is 42% of the
      page and is a wall of 53 coloured screenshots. Ambient colour
      behind them fights the thumbnails and dirties both. It takes
      the dither below — which is colourless — and nothing else.

   3. DARK ONLY. The light theme does not have the problem this
      solves, and the same wash over rgb(247,249,250) reads as a
      stain rather than depth.

   PAINTED AS background-image, NOT A PSEUDO-ELEMENT

   Every target section sets an opaque background-color. A ::before
   at z-index -1 paints behind that colour and disappears; at
   z-index 0 it paints over the section's own non-positioned
   content. Both need the content re-stacked to work. A
   background-image has neither problem — it paints above the
   background-color and below all content, by definition.
   ============================================================ */

/* ============================================================
   THE DITHER, AND WHY IT IS EVERYWHERE

   A soft ramp on a near-black surface is the worst case for 8-bit
   colour. Simulated across the actual gradient before choosing a
   strength, counting the widest run of identical pixels along the
   centre line:

     dither amplitude    widest flat run
       none                  269 px      severe rings
       ±0.5 levels           235 px      still rings
       ±1.0 levels             3 px      gone
       ±2.5 levels             2 px      gone, but grainier

   So ±1 level is the floor that works and the ceiling worth
   paying. Anything less bands; anything more is visible grain for
   no gain.

   The tile itself was then measured rather than guessed — drawn to
   a canvas and sampled:

     grey  mean 128, sd 22.7
     alpha mean 127, sd 30.1
     composited over rgb(12,12,12) at full strength:
       mean lift +58 levels, sd 18.7

   At 5% that becomes sd 0.94 — the ±1 the simulation asked for —
   and a mean lift of +3 levels, which is where the important part
   comes in:

   THAT +3 IS WHY THE DITHER IS NOT SCOPED TO THE THREE GLOWS.

   A tile that lifts the surface from 12 to 15 applied only where
   the gradients are would draw a visible seam at every boundary
   between a glowing section and a plain one. Applied to every flat
   dark section it is uniform, so there is no edge anywhere — and a
   page floor of 15 rather than 12 is a mild version of exactly
   what this file was asked to do.

   The hero and the features panel are left out on purpose: neither
   is flat, so neither bands, and both already break the surface
   with their own media.
   ============================================================ */

:root {
  /* --grad-cta's violet, as channels so the alphas can compose. */
  --glow-rgb: 118 33 176;

  /* 5.5%: visible as depth, under the threshold where the colour
     announces itself. */
  --glow-a: 0.055;

  /* Monochrome fractal noise, tiled. Inline rather than a file: it
     is under a kilobyte, and a request for a texture this small
     costs more than it saves. `stitchTiles` makes the edges meet
     so the repeat is seamless, and the 0.05 opacity is the
     measured value above — changing it changes both the dither
     strength and the page floor, so change it knowingly. */
  --glow-noise:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n' color-interpolation-filters='sRGB'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)' opacity='0.05'/%3E%3C/svg%3E");
}

/* Guarded on `not light` rather than on `dark`, because the site
   sets no attribute at all in its default dark state — keying on
   [data-theme='dark'] would match nothing. */

/* ---- the dither, on every flat dark section ------------------ */
:root:not([data-theme='light']) .marquee,
:root:not([data-theme='light']) .about,
:root:not([data-theme='light']) .showcase,
:root:not([data-theme='light']) .demos,
:root:not([data-theme='light']) .footer {
  background-image: var(--glow-noise);
  background-repeat: repeat;
  background-size: 160px 160px;
}

/* ---- 1. the seam out of the hero -----------------------------
   The largest single drop on the page: four viewports of lit
   footage end and flat black begins. The glow sits at the top edge
   of the marquee and falls away downward, so it reads as light
   from the section above spilling over rather than as a shape.

   .marquee already clips its overflow, so the ellipse cannot
   escape into the sections on either side. */
:root:not([data-theme='light']) .marquee {
  background-image:
    var(--glow-noise),
    radial-gradient(120% 90% at 50% -10%,
      rgb(var(--glow-rgb) / var(--glow-a)) 0%,
      rgb(var(--glow-rgb) / calc(var(--glow-a) * 0.45)) 38%,
      transparent 72%);
  background-repeat: repeat, no-repeat;
  background-size: 160px 160px, cover;
}

/* ---- 2. the showcase ------------------------------------------
   Off-centre on purpose. Three glows down the same axis would read
   as a repeating motif; moving this one to the inline start keeps
   the page from feeling striped. */
:root:not([data-theme='light']) .showcase {
  background-image:
    var(--glow-noise),
    radial-gradient(90% 55% at 18% 12%,
      rgb(var(--glow-rgb) / var(--glow-a)) 0%,
      rgb(var(--glow-rgb) / calc(var(--glow-a) * 0.40)) 40%,
      transparent 70%);
  background-repeat: repeat, no-repeat;
  background-size: 160px 160px, cover;
}

/* ---- 3. the closing CTA ---------------------------------------
   The one place the violet is already at full strength, in the
   button itself. Here the glow has something to be the halo OF, so
   it is allowed to sit directly behind it and centred.

   This rule is also why about.html loads this file: the footer is
   the only glowing section the two pages share, and it is what
   keeps the about page's violet from arriving out of nowhere. */
:root:not([data-theme='light']) .footer {
  background-image:
    var(--glow-noise),
    radial-gradient(80% 70% at 50% 15%,
      rgb(var(--glow-rgb) / var(--glow-a)) 0%,
      rgb(var(--glow-rgb) / calc(var(--glow-a) * 0.42)) 42%,
      transparent 72%);
  background-repeat: repeat, no-repeat;
  background-size: 160px 160px, cover;
}

/* Reduced motion says nothing about colour, and nothing here
   animates, so the glow stays under that setting. */
