/* ==========================================================================
   NetrAI — Chromatic Waves hero field

   The OriginKit component `chromatic-waves` (js/effects/chromatic-waves.js) mounted
   behind every page's headline. This file is only the host layer, the palette
   tokens and the mask; everything that draws is in the port.

   WHICH VARIANT IS WHICH
   The component ships one palette, `["#FFFFFF"]` — white dots. That is the
   BLACK-BACKGROUND variant: on the light canvas white dots are invisible
   (measured: they vanish against #f5f5f7). The white-background variant needs
   dark dots. Rather than run the shipped palette in one theme and an inverted
   one in the other, both themes here run the same two-stop ramp — a neutral
   low stop for the sparse dots and the site's blue for the dense ones — which
   reads on either canvas and keeps the field inside the one-blue rule.

   WHY IT IS MASKED
   The field's dots grow with the noise field's luminance, so it has loud
   patches. Live headline type sits on top of it. The mask clears the middle
   of every host, where the copy is, and keeps the texture at the edges. Turn
   the mask off and the h1 loses contrast wherever a dense patch drifts under
   it — that is the whole reason it is here.

   COST
   One WebGL2 context per page, capped at 30 FPS by the component itself, and
   paused by the port whenever the hero scrolls out of view. Since it is always
   the topmost section, that means it stops as soon as you start reading.
   ========================================================================== */

:root {
  /* LIGHT: the brand blue on white, full strength at both stops.

     The first pass ramped a hairline neutral into a 42% blue, and on the
     #f5f5f7 canvas that read as white-on-white for most of the field — only
     the densest patches showed at all. Both stops are #0071e3 now, so the
     pattern is unambiguously the brand blue and the DENSITY does the shading:
     the shader already scales each dot's radius with the noise field, which is
     the variation that was being asked of the colour ramp. */
  --waves-dot-1: #0071e3;
  --waves-dot-2: #0071e3;

  /* the ground the pattern sits on — white, not the #f5f5f7 page canvas */
  --waves-bg: #ffffff;
}

[data-theme="dark"] {
  /* DARK is unchanged: a neutral low stop into Signal Blue, both held under
     full strength. On black a full-strength dot field is a headlight. */
  --waves-dot-1: rgba(72, 72, 74, 0.60);
  --waves-dot-2: rgba(41, 151, 255, 0.42);

  /* already the canvas colour, so this is a no-op — it exists so the light
     rule below has something to resolve to in both themes */
  --waves-bg: #000000;
}

/* --------------------------------------------------------------------------
   The host layer
   -------------------------------------------------------------------------- */

.waves-layer {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  /* the canvas writes straight alpha between the dots, so whatever surface
     the section already has shows through untouched */
  background: none;

  /* Clear the middle so the headline never fights a dense patch. Two axes:
     radial keeps the centre quiet, the linear fade stops the field colliding
     with the section's bottom hairline. */
  -webkit-mask-image:
    radial-gradient(115% 85% at 50% 42%, transparent 0%, transparent 32%, #000 76%),
    linear-gradient(to bottom, #000 0%, #000 72%, transparent 100%);
  mask-image:
    radial-gradient(115% 85% at 50% 42%, transparent 0%, transparent 32%, #000 76%),
    linear-gradient(to bottom, #000 0%, #000 72%, transparent 100%);
  -webkit-mask-composite: source-in;
  mask-composite: intersect;
}

/* --------------------------------------------------------------------------
   Hosts

   Every one of these is already `position: relative; overflow: hidden`, so the
   layer needs nothing but a stacking context above it for the copy.
   -------------------------------------------------------------------------- */

/* The ground.

   This goes on the SECTION, never on `.waves-layer` — the layer is masked, and
   a mask applies to an element's background as well as its content, so a
   background painted there would be cut away in the middle and the page canvas
   would show through as a pale hole exactly where the headline sits. */
.page-hero,
.hero-scene .hero-stage { background: var(--waves-bg); }

.page-hero > .hero-inner,
.page-hero > .eyebrow,
.page-hero > h1,
.page-hero > p { position: relative; z-index: 1; }

/* The homepage hero is the scroll scene: the layer belongs to the sticky
   stage, not to the 220vh section, or it would scroll away under the pinned
   headline instead of holding still behind it. */
.hero-scene .hero-stage > .waves-layer { z-index: 0; }
.hero-scene .hero-inner { z-index: 2; }
.hero-scene .hero-visual { z-index: 1; }

/* The homepage headline sits high in the stage rather than dead centre, so
   the quiet part of the mask moves up to match. */
.hero-scene .waves-layer {
  -webkit-mask-image:
    radial-gradient(100% 62% at 50% 34%, transparent 0%, transparent 30%, #000 74%),
    linear-gradient(to bottom, #000 0%, #000 78%, transparent 100%);
  mask-image:
    radial-gradient(100% 62% at 50% 34%, transparent 0%, transparent 30%, #000 74%),
    linear-gradient(to bottom, #000 0%, #000 78%, transparent 100%);
}

/* --------------------------------------------------------------------------
   Where it stands down
   -------------------------------------------------------------------------- */

/* On a phone the field is mostly mask and the context is the most expensive
   thing on the page. js/effects/waves-mounts.js does not mount below this width; the
   rule is here too so a layer left in the markup never reserves space. */
@media (max-width: 700px) {
  .waves-layer { display: none; }
}

/* Reduced motion keeps the field but the port freezes it — see DEVIATION 4 in
   js/effects/chromatic-waves.js. Nothing to do here. */


/* ==========================================================================
   Reduced motion
   The field is decorative. Under the preference the canvas holds its last
   frame rather than animating; js/effects/chromatic-waves.js already checks the
   query, this stops any CSS-driven drift on the mount itself.
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  .waves-layer,
  [data-waves] {
    animation: none !important;
    transition: none !important;
  }
}


/* --------------------------------------------------------------------------
   Text-heavy heroes need a bigger clear zone
   --------------------------------------------------------------------------
   The mask above was tuned against the homepage hero, where the only thing on
   top of the field is a headline sitting around 42% of the height. The inner
   pages use .page-hero, which stacks an eyebrow, an h1, a three-to-five line
   lead and a row of trust pills — so the copy runs well past the cleared
   radius and the lead paragraph ends up reading on top of dots at full
   density. On Pricing that paragraph is the sentence explaining the entire
   pricing model.

   Same two-axis approach, wider and taller: the transparent core reaches 52%
   before it starts ramping, and does not reach full strength until 88%, so
   the texture survives only at the outer edges where nothing is set over it.
   -------------------------------------------------------------------------- */
.page-hero .waves-layer {
  -webkit-mask-image:
    radial-gradient(135% 105% at 50% 46%, transparent 0%, transparent 52%, #000 88%),
    linear-gradient(to bottom, #000 0%, #000 68%, transparent 100%);
  mask-image:
    radial-gradient(135% 105% at 50% 46%, transparent 0%, transparent 52%, #000 88%),
    linear-gradient(to bottom, #000 0%, #000 68%, transparent 100%);
}

/* A narrow column has no "edge" left to decorate once the copy is clear of
   the field, so below the tablet breakpoint the layer is simply not drawn.
   js/effects/waves-mounts.js already refuses to mount under 700px; this covers the
   case where a wider viewport is resized down after mounting. */
@media (max-width: 700px) {
  .page-hero .waves-layer { display: none; }
}
