/*
  RYMVI generative background — flowing contour-wave pattern.
  Pure CSS + inline SVG (no raster images). One geometry, reused everywhere:
  colour, strength and motion come entirely from CSS custom properties, so
  every theme (dark / blue / light) and every placement (hero / subtle)
  renders from the same markup injected by assets/js/background.js.

  Usage:
    <div class="rymvi-bg rymvi-bg--hero"   data-rymvi-bg="hero"   aria-hidden="true"></div>
    <div class="rymvi-bg rymvi-bg--subtle" data-rymvi-bg="subtle" aria-hidden="true"></div>

  Per-instance overrides (inline, no CSS edit needed):
    style="--rymvi-bg-opacity:.4"
*/

/*
  body becomes the stacking-context root so that a z-index:-1 fixed layer
  paints ABOVE the body's own background but BELOW every normal (static)
  descendant — headers, sections, cards, text. That's what lets the subtle
  variant sit behind the whole site without a wrapper per page: any element
  with its own opaque background (a card, .section-soft, the footer)
  naturally occludes the pattern, no extra markup required.
*/
body { position: relative; }

.rymvi-bg {
  --rymvi-bg-opacity: 1; /* placement-level ceiling, overridable per-instance */
  position: fixed;
  inset: 0;
  z-index: -1;
  overflow: hidden;
  pointer-events: none;
  opacity: var(--rymvi-bg-opacity);
  contain: strict;
}

.rymvi-bg svg {
  display: block;
  width: 100%;
  height: 100%;
  /* theme master knob: dark = strongest, light = a quiet wash */
  opacity: var(--wave-opacity, 1);
}

/* Per-role strength, all theme-driven so a single SVG re-themes for free */
.rymvi-wave-glow { opacity: var(--wave-glow-opacity, .5); }
.rymvi-wave-line { opacity: var(--wave-line-opacity, .55); }
.rymvi-wave-accent { opacity: calc(var(--wave-line-opacity, .55) * .6); }
.rymvi-wave-node { opacity: var(--wave-node-opacity, .55); }

/*
  Gradient-stop colors are intentionally NOT set here. WebKit/Safari does
  not reliably resolve var() for stop-color on SVG <stop> elements via
  EITHER an inline style attribute or a stylesheet class rule — it
  silently falls back to black. background.js reads the resolved
  --wave-* values in JS instead and writes literal stop-color attributes,
  which is safe in every browser since it never asks any engine to
  compute a CSS custom property inside an SVG gradient. Do not add a
  stop-color rule for .rymvi-stop-* back here — a real stylesheet rule
  would win the cascade over the JS-set attribute and reintroduce the
  same bug it failed to fix once already.
*/
.rymvi-stop-fade { stop-opacity: 0; }

/* ---- Hero-strength variant --------------------------------------------
   Scoped to one section (not the viewport) so it can be the loud, premium
   moment behind a hero without following the user down the page. */
.rymvi-bg--hero {
  --rymvi-bg-opacity: 1;
  position: absolute;
}

.rymvi-bg-host {
  /* z-index:0 (not just position:relative) is required so this element
     forms its own stacking context — otherwise the -1 z-index on
     .rymvi-bg--hero below gets hoisted to the page root, where this
     element's own opaque background (painted later, as normal in-flow
     content) would cover the pattern completely. */
  position: relative;
  z-index: 0;
  overflow: hidden;
  background: var(--bg);
}

.rymvi-bg-host > :not(.rymvi-bg) {
  position: relative;
  z-index: 1;
}

/* ---- Subtle page-background variant -----------------------------------
   A calm, fixed ambient wash. Sits behind body copy at low strength; any
   section with its own opaque surface (cards, .section-soft, footer)
   naturally paints over it, so dense content stays clutter-free. */
.rymvi-bg--subtle {
  --rymvi-bg-opacity: .55;
}

/* ---- Extremely slow ambient drift --------------------------------------
   Off entirely unless the user has no motion preference set. */
@media (prefers-reduced-motion: no-preference) {
  .rymvi-drift-a { animation: rymvi-drift-a 150s ease-in-out infinite alternate; }
  .rymvi-drift-b { animation: rymvi-drift-b 190s ease-in-out infinite alternate; }
  .rymvi-drift-c { animation: rymvi-drift-c 170s ease-in-out infinite alternate; }
  .rymvi-wave-node { animation: rymvi-pulse 16s ease-in-out infinite; }
}

@keyframes rymvi-drift-a {
  from { transform: translate3d(-1.1%, -.3%, 0); }
  to   { transform: translate3d(1.1%, .3%, 0); }
}
@keyframes rymvi-drift-b {
  from { transform: translate3d(1%, .5%, 0); }
  to   { transform: translate3d(-1%, -.5%, 0); }
}
@keyframes rymvi-drift-c {
  from { transform: translate3d(-.7%, .4%, 0); }
  to   { transform: translate3d(.7%, -.4%, 0); }
}
@keyframes rymvi-pulse {
  0%, 100% { opacity: .8; }
  50% { opacity: 1; }
}

/* Narrow / tall viewports: the wave art is authored wide (16:10) and
   "slices" to cover, which zooms in on portrait phones. Ease the strength
   back slightly there so it reads as texture, not a wall of neon. */
@media (max-width: 640px) {
  .rymvi-bg { --rymvi-bg-opacity: calc(var(--rymvi-bg-opacity, 1) * .8); }
}
