/* ============================================================
   cadence — textures
   Two drop-in utility classes. CSS-first, no JS.
   Rule of the brand: flat material, honestly lit — no gradients,
   glow or shadow. Both textures below are MATERIAL (paper) or
   SYSTEMIC (the beat), never atmospheric.
   COLOUR IS NOT SET HERE. These read the current surface's tokens
   (from base.css: --dot, --rule-beat, --grain-blend, --grain-mult),
   so a texture auto-tunes to whatever `.base-*` surface it sits on.
   USAGE (pair with a surface class)
     <section class="base-light grain">       paper fibre on light
     <section class="base-dark grain beat">    both, on dark (auto-flips)
     <section class="base-moss beat">          beat texture on moss
   Each texture is a pseudo-element behind the content:
     .grain -> ::before      .beat -> ::after
   so both can live on the same element at once. Content must sit
   above them — handled by the `> *` rule. The host uses
   `isolation:isolate` so blend modes never leak to the page.
   KNOBS (set inline or per-section; defaults shown)
     --grain      0..1   grain strength         (default .5  — "mid")
     --beat-tex   0..1   beat texture strength   (default .4  — "faint")
     --beat       size   the beat unit           (inherits system; 26px fallback)
   e.g.  <section class="base-light grain" style="--grain:.35">  // calmer for text
   ============================================================ */
/* shared host + content stacking ---------------------------------- */
.grain,
.beat{ position:relative; isolation:isolate; }
.grain > *,
.beat  > *{ position:relative; z-index:1; }
/* ---- .grain : paper fibre --------------------------------------- *
   Monochrome fractal noise (feTurbulence), tiled. Not a gradient —
   it's stock/material. Blend mode + strength come from the surface:
   light surfaces multiply (bone → paper); dark/colour surfaces screen
   at half strength (reads as ink tooth, not mud). Default .5 = "mid".
   Drop --grain toward .3 behind long body copy.                      */
.grain::before{
  content:"";
  position:absolute; inset:0; z-index:0; pointer-events:none;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size:200px 200px;
  mix-blend-mode:var(--grain-blend, multiply);        /* from the surface */
  opacity:calc(var(--grain, .5) * var(--grain-mult, 1));
}
/* ---- .beat : the measure made visible --------------------------- *
   Two layers: dots on the beat (a dot pattern — same technique as the
   brand's own band tile) and hairline baseline rules every beat.
   Faint by default so it reads as structure, not decoration. Dot and
   rule colours come from the surface (--dot, --rule-beat); size tracks
   the beat unit, so it stays true to the grid.                        */
.beat::after{
  content:"";
  position:absolute; inset:0; z-index:0; pointer-events:none;
  opacity:var(--beat-tex, .4);
  background-image:
    radial-gradient(var(--dot, #c1a87e) .09em, transparent .1em),
    repeating-linear-gradient(
      to bottom,
      transparent 0,
      transparent calc(var(--beat, 26px) - 1px),
      var(--rule-beat, rgba(193,168,126,.45)) calc(var(--beat, 26px) - 1px),
      var(--rule-beat, rgba(193,168,126,.45)) var(--beat, 26px)
    );
  background-size:
    var(--beat, 26px) var(--beat, 26px),   /* dot cell = one beat */
    100% var(--beat, 26px);                /* rule pitch = one beat */
}
/* ---- notes -------------------------------------------------------
   • Decorative only: both are pseudo-elements with pointer-events:none,
     invisible to assistive tech, and never affect layout.
   • Contrast: grain multiply darkens the surface a touch — keep --grain
     ≤ .5 behind body text so contrast holds. Reserve higher values
     (.7+) for a single hero moment, not running surfaces.
   • No motion, so nothing to gate under prefers-reduced-motion.
   • Perf: one 200px tiling SVG for grain; pure CSS backgrounds for beat.
     Cheap. Safe to apply per-section.
   • Press/ink (deboss) stays OFF these classes — it is reserved for the
     seal, the one place the brand is allowed a light source.
   ------------------------------------------------------------------ */