/* ============================================================================
   signature_fx.css — SIGNATURE FX library.  sigfx-20260718

   Each vibe's signature motion, extracted as swappable per-element presets
   usable on ANY selected element of ANY vibe (Vibe Studio Effects panel →
   "Signature" groups). Home-vibe palettes are baked in on purpose — applying
   "Deco foil" means you get deco's gold, wherever you are.

   Three groups (mirrors vibe_fx_options() / the studio FXGROUPS table):
     .vfx-sigmo-*     signature MOTION loops  (glitch / flicker / wave / scan)
     .vfx-sigsheen-*  signature SHEENS        (gradient foil sweeps on text)
     .vfx-sighov-*    signature HOVERS        (each vibe's interactive feel)

   Rules of the file:
   - Self-contained: no var() without a literal fallback, every @keyframes
     carried here under an sg- prefix (never collides with vibe/hero_swaps
     keyframes), no ancestor scoping — single-class selectors only.
   - !important on contested props: these presets are an explicit promoter
     choice and must beat the home vibe's own descendant-scoped styling
     (.vibe-deco .dco-title etc. would otherwise out-specificity us).
   - Reduced-motion guard at the bottom mirrors every home vibe's own guard.
   - Persisted slot-keyed as sf:{} by assets/vibe_overlay.js, sanitized by
     lib/vibe_edits.php, replayed on the live event page by e.php.
   - Loaded in BOTH vibe_theme_preview.php (editor iframe) and e.php (public),
     mtime-versioned. Bump the SW CACHE_NAME on every change to this file.
   ============================================================================ */

/* ======================= GROUP 1 — SIGNATURE MOTION ======================= */

/* Substation glitch — chromatic RGB-split + neon glow + periodic skew jitter.
   Pure text-shadow (the substation source notes: no markup/pseudo needed). */
.vfx-sigmo-subglitch {
  text-shadow: 0.028em 0 0 color-mix(in srgb, var(--vfx-glow, #ff2a78) 75%, transparent), -0.028em 0 0 color-mix(in srgb, var(--vfx-glow, #00f0ff) 75%, transparent), 0 0 18px color-mix(in srgb, var(--vfx-glow, #00ff9d) 55%, transparent) !important;
  animation: sg-subglitch 3.8s steps(1) infinite !important;
  will-change: transform, text-shadow;
}
@keyframes sg-subglitch {
  0%, 90%, 100% {
    text-shadow: 0.028em 0 0 color-mix(in srgb, var(--vfx-glow, #ff2a78) 75%, transparent), -0.028em 0 0 color-mix(in srgb, var(--vfx-glow, #00f0ff) 75%, transparent), 0 0 18px color-mix(in srgb, var(--vfx-glow, #00ff9d) 55%, transparent);
    transform: translate(0, 0) skewX(0);
  }
  91% { text-shadow: -0.06em 0 0 color-mix(in srgb, var(--vfx-glow, #ff2a78) 95%, transparent), 0.06em 0 0 color-mix(in srgb, var(--vfx-glow, #00f0ff) 95%, transparent), 0 0 30px color-mix(in srgb, var(--vfx-glow, #00ff9d) 85%, transparent); transform: translate(3px,-1px) skewX(-3deg); }
  93% { text-shadow: 0.07em 0 0 color-mix(in srgb, var(--vfx-glow, #ff2a78) 95%, transparent), -0.07em 0 0 color-mix(in srgb, var(--vfx-glow, #00f0ff) 95%, transparent), 0 0 30px color-mix(in srgb, var(--vfx-glow, #00ff9d) 85%, transparent); transform: translate(-3px, 1px) skewX(2deg); }
  95% { transform: translate(2px, 0) skewX(0); }
  97% { transform: translate(-1px, 0); }
}

/* Berlin chromatic glitch — cyan/magenta ghost-split bursts + jitter.
   Text-shadow implementation of berlin's ::before/::after glitch (the pseudo
   mechanism needs attr(data-text) and can't survive the persistence pipeline;
   this reads the same on screen and works on any element). */
.vfx-sigmo-blnglitch {
  animation: sg-blnglitch 3.2s steps(2) infinite !important;
  will-change: transform, text-shadow;
}
@keyframes sg-blnglitch {
  0%, 88%, 100% {
    text-shadow: 0 0 24px color-mix(in srgb, var(--vfx-glow, #37e6ff) 50%, transparent), 0 0 60px color-mix(in srgb, var(--vfx-glow, #37e6ff) 25%, transparent);
    transform: translate(0,0);
  }
  90% { text-shadow: -4px 2px 0 color-mix(in srgb, var(--vfx-glow, #37e6ff) 90%, transparent), 4px -2px 0 color-mix(in srgb, var(--vfx-glow, #ff2fb0) 85%, transparent), 0 0 24px color-mix(in srgb, var(--vfx-glow, #37e6ff) 50%, transparent); transform: translate(-2px,1px); }
  93% { text-shadow: 3px -2px 0 color-mix(in srgb, var(--vfx-glow, #37e6ff) 90%, transparent), -3px 2px 0 color-mix(in srgb, var(--vfx-glow, #ff2fb0) 85%, transparent), 0 0 24px color-mix(in srgb, var(--vfx-glow, #37e6ff) 50%, transparent); transform: translate(2px,-1px); }
  96% { text-shadow: 0 0 24px color-mix(in srgb, var(--vfx-glow, #37e6ff) 50%, transparent), 0 0 60px color-mix(in srgb, var(--vfx-glow, #37e6ff) 25%, transparent); transform: translate(0,0); }
}

/* Berlin jitter — hard position snaps, steps(1). */
.vfx-sigmo-blnjitter { animation: sg-blnjitter 5.5s steps(1) infinite !important; }
@keyframes sg-blnjitter { 0%,96%,100% { transform: translate(0,0); } 97% { transform: translate(-2px,1px); } 98% { transform: translate(2px,-1px); } }

/* Berlin flicker — hard steps(1) brightness drop, like a dying fluorescent. */
.vfx-sigmo-blnflicker { animation: sg-blnflicker 6s steps(1) infinite !important; }
@keyframes sg-blnflicker { 0%,97%,100% { opacity: 1; } 98% { opacity: 0.55; } 99% { opacity: 0.85; } }

/* Sub Bass RGB split — static purple/cyan chromatic shadow. No motion, pure attitude. */
.vfx-sigmo-rgbsplit {
  text-shadow: -2px 0 0 color-mix(in srgb, var(--vfx-glow, #a855f7) 85%, transparent), 2px 0 0 color-mix(in srgb, var(--vfx-glow, #22d3ee) 75%, transparent) !important;
}

/* Acid wave — slow skew sway, straight off the acid title. */
.vfx-sigmo-acidwave { animation: sg-acidwave 4s ease-in-out infinite !important; }
@keyframes sg-acidwave { 0%,100% { transform: skewX(0deg); } 25% { transform: skewX(-3deg); } 75% { transform: skewX(3deg); } }

/* Candle flicker — warm brightness/opacity flutter (candlelight + supper),
   de-positioned for generic use (home version bakes a translateX(-50%)). */
.vfx-sigmo-candle { animation: sg-candle 2.6s ease-in-out infinite !important; }
@keyframes sg-candle {
  0%,100% { opacity: .82; filter: brightness(.96); }
  30%     { opacity: 1;   filter: brightness(1.06); }
  60%     { opacity: .88; filter: brightness(.99); }
}

/* Gold twinkle — soft opacity shimmer (noir stars / supper dividers). */
.vfx-sigmo-twinkle { animation: sg-twinkle 3.2s ease-in-out infinite !important; }
@keyframes sg-twinkle { 0%,100% { opacity: .45; } 50% { opacity: 1; } }

/* Stub scan — a barcode-style light sweep across the element (overlay layer).
   Known edge: elements whose vibe already uses ::after get that layer replaced. */
.vfx-sigmo-stubscan { position: relative !important; }
.vc-bi.vfx-sigmo-stubscan { position: absolute !important; } /* stubfix-20260720: board items are position:absolute (centered); the blanket relative override dropped them into normal flow (top-left). The ::after uses position:absolute;inset:0, so it still anchors to the absolute host — the scan sweep is unaffected. */
.vfx-sigmo-stubscan::after {
  content: "" !important; position: absolute !important; inset: 0 !important; pointer-events: none !important;
  background: linear-gradient(90deg, transparent, rgba(255,255,255,.45), transparent) !important;
  background-size: 220% 100% !important;
  animation: sg-stubscan 2.6s linear infinite !important;
}
@keyframes sg-stubscan { 0% { background-position: 160% 0; } 100% { background-position: -60% 0; } }

/* ======================= GROUP 2 — SIGNATURE SHEENS ======================= */
/* Gradient foil sweeps clipped to the text. These REPLACE the element's text
   colour with the home vibe's foil — that's the point. Shared sweep keyframes. */
@keyframes sg-foil220 { to { background-position: 220% center; } }
@keyframes sg-foil240 { to { background-position: 240% center; } }

.vfx-sigsheen-deco, .vfx-sigsheen-disco, .vfx-sigsheen-eternal, .vfx-sigsheen-supper,
.vfx-sigsheen-velvet, .vfx-sigsheen-noir, .vfx-sigsheen-launch, .vfx-sigsheen-summit {
  -webkit-background-clip: text !important; background-clip: text !important;
  color: transparent !important; -webkit-text-fill-color: transparent !important;
  background-size: 220% auto !important;
}

/* sheenfix-20260718: gradient-text FX applied to a CONTAINER (section frames are
   slot elements) made every DESCENDANT inherit transparent ink — the whole ticket
   box went blank (Shock's "big blue rectangle": berlin's cyan button, invisible
   text). Children keep their own colors; the foil still paints the container's
   direct text. Covers the old rainbow/gradflow loops too (same clip technique). */
.vfx-sigsheen-deco *, .vfx-sigsheen-disco *, .vfx-sigsheen-eternal *, .vfx-sigsheen-supper *,
.vfx-sigsheen-velvet *, .vfx-sigsheen-noir *, .vfx-sigsheen-launch *, .vfx-sigsheen-summit *,
.vfx-loop-rainbow *, .vfx-loop-gradflow * {
  -webkit-text-fill-color: currentColor !important;
}

/* sheenfix2-20260718: gradient-text FX on a CONTAINER + a descendant that
   TRANSFORMS on hover (berlin's lineup rows slide 6px) makes Chromium repaint
   that descendant's text in the background-clip mask at the container's
   top-left — a gold ghost of the hovered name over the section kicker (Shock's
   lineup bug, berlin-only because only berlin's rows transform on hover).
   Suppress descendant hover transforms inside gradient-text containers; the
   sheen and every other hover style stay. */
.vfx-sigsheen-deco :hover, .vfx-sigsheen-disco :hover, .vfx-sigsheen-eternal :hover,
.vfx-sigsheen-supper :hover, .vfx-sigsheen-velvet :hover, .vfx-sigsheen-noir :hover,
.vfx-sigsheen-launch :hover, .vfx-sigsheen-summit :hover,
.vfx-loop-rainbow :hover, .vfx-loop-gradflow :hover {
  transform: none !important;
}

/* Deco — antique gold foil. */
.vfx-sigsheen-deco {
  background-image: linear-gradient(100deg, #9a7f34, #f4e3a6 45%, #d9b95c 60%, #9a7f34) !important;
  animation: sg-foil220 9s linear infinite !important;
}
/* Discotheque — gold→white→pink shimmer with the gold glow. */
.vfx-sigsheen-disco {
  background-image: linear-gradient(100deg, #f5c451, #fff3cf 40%, #ff4fa3 60%, #f5c451) !important;
  filter: drop-shadow(0 4px 24px color-mix(in srgb, var(--vfx-glow, #f5c451) 40%, transparent)) !important;
  animation: sg-foil220 7s linear infinite !important;
}
/* Eternal — soft champagne foil. */
.vfx-sigsheen-eternal {
  background-image: linear-gradient(100deg, #9c7c31, #eacd82 45%, #c8a24a 60%, #9c7c31) !important;
  animation: sg-foil220 9s linear infinite !important;
}
/* Supper — engraved menu-gold foil (dark troughs). */
.vfx-sigsheen-supper {
  background-image: linear-gradient(100deg, #b08a3e 0%, #7a5f27 30%, #e6c877 50%, #7a5f27 70%, #b08a3e 100%) !important;
  animation: sg-foil220 9s linear infinite !important;
}
/* Velvet — warm champagne sheen. */
.vfx-sigsheen-velvet {
  background-image: linear-gradient(100deg, #b8943f, #fff4d8 45%, #e6c98a 60%, #b8943f) !important;
  animation: sg-foil220 8s linear infinite !important;
}
/* Noir — old-Hollywood gold sheen. */
.vfx-sigsheen-noir {
  background-image: linear-gradient(100deg, #9a7d20, #f3e2a3 45%, #d4af37 60%, #9a7d20) !important;
  animation: sg-foil220 6.5s linear infinite !important;
}
/* Launch — violet→cyan→pink tech flow. */
.vfx-sigsheen-launch {
  background-image: linear-gradient(100deg, #7c5cff, #22d3ee 45%, #ff5ca8 75%, #7c5cff) !important;
  background-size: 240% auto !important;
  animation: sg-foil240 7s linear infinite !important;
}
/* Summit — corporate blue flow. */
.vfx-sigsheen-summit {
  background-image: linear-gradient(100deg, #2f6df6, #6ea0ff 50%, #2f6df6) !important;
  animation: sg-foil220 3.5s linear infinite !important;
}

/* ======================= GROUP 3 — SIGNATURE HOVERS ======================= */

/* Junglist tilt-punch — the zine paste-up: shove up-left, hard cyan offset slab. */
.vfx-sighov-junglist { transition: transform .2s, box-shadow .2s, filter .2s !important; }
.vfx-sighov-junglist:hover {
  transform: translate(-2px,-2px) rotate(-0.5deg) !important;
  box-shadow: 8px 8px 0 var(--vfx-glow, var(--event-accent-2, #00ffff)) !important;
  filter: brightness(1.08) !important;
}

/* Headliner lift-glow — scale + lift into the amber marquee wash. */
.vfx-sighov-headliner { transition: transform .25s, box-shadow .25s !important; }
.vfx-sighov-headliner:hover {
  transform: scale(1.012) translateY(-3px) !important;
  box-shadow: 0 36px 90px -22px color-mix(in srgb, var(--vfx-glow, #fbbf24) 55%, transparent), 0 0 60px -8px color-mix(in srgb, var(--vfx-glow, #f59e0b) 30%, transparent) !important;
}

/* Sub Bass glow — lift into the purple/cyan bass wash. */
.vfx-sighov-subbass { transition: transform .2s, box-shadow .2s, filter .2s !important; }
.vfx-sighov-subbass:hover {
  transform: translateY(-2px) !important;
  box-shadow: 0 0 32px -8px color-mix(in srgb, var(--vfx-glow, #a855f7) 80%, transparent), 0 0 18px -10px color-mix(in srgb, var(--vfx-glow, #22d3ee) 60%, transparent) !important;
  filter: brightness(1.06) !important;
}

/* Substation glow — lift into the neon-green wash. */
.vfx-sighov-substation { transition: transform .2s, box-shadow .2s !important; }
.vfx-sighov-substation:hover {
  transform: translateY(-2px) !important;
  box-shadow: 0 0 28px -8px var(--vfx-glow, var(--event-accent, #00ff9d)) !important;
}

/* Berlin panel-lift — lift into the dual cyan/magenta glow. */
.vfx-sighov-berlin { transition: transform .2s, box-shadow .2s !important; }
.vfx-sighov-berlin:hover {
  transform: translateY(-4px) !important;
  box-shadow: 0 12px 40px -8px color-mix(in srgb, var(--vfx-glow, #37e6ff) 45%, transparent), 0 0 40px color-mix(in srgb, var(--vfx-glow, #ff2fb0) 20%, transparent) !important;
}

/* Berlin slide — index-row shove-right with the inset accent bar. */
.vfx-sighov-blnslide { transition: transform .18s, box-shadow .18s, background-color .18s !important; }
.vfx-sighov-blnslide:hover {
  transform: translateX(6px) !important;
  box-shadow: inset 3px 0 0 var(--vfx-glow, var(--event-accent, #37e6ff)), 0 0 22px color-mix(in srgb, var(--vfx-glow, #37e6ff) 15%, transparent) !important;
  background-color: color-mix(in srgb, var(--vfx-glow, #37e6ff) 7%, transparent) !important;
}

/* DnB press — presses DOWN like a rubber stamp, shadow collapses. */
.vfx-sighov-dnbpress { transition: transform .12s, box-shadow .12s !important; }
.vfx-sighov-dnbpress:hover {
  transform: translate(2px,2px) !important;
  box-shadow: 2px 3px 0 rgba(20,19,15,.7) !important;
}

/* DnB settle — sits slightly askew, straightens when touched (scrapbook).
   Known edge: the base tilt yields to an editor-moved element's inline transform. */
.vfx-sighov-dnbsettle { transform: rotate(-1.2deg); transition: transform .2s !important; }
.vfx-sighov-dnbsettle:hover { transform: rotate(0deg) !important; }

/* ========================= BACKDROP LAYER BASE ============================ */
/* bdpublish2-20260718: the .vc-bg layer classes are defined in custom.css, which
   public VIBE pages do not load (only custom-renderer pages and the editor iframe
   do). The replayed backdrop span was landing unstyled on live pages — classes on,
   zero CSS. These two rules make the layer real everywhere this sheet loads.
   Identical values to custom.css:22/177, so double-loading in the editor is a
   harmless no-op. The replay sets z-index:-1 inline (wins over the 0 here). */
.vc-bg { position: fixed; inset: 0; z-index: 0; pointer-events: none; overflow: hidden; }
.vc-bg--image { background: var(--vc-bg-image) center/cover no-repeat; }

/* ======================= BACKDROP-ACTIVE OVERRIDES ======================== */
/* bgswapfix3-20260718: the backdrop layer sits at z:-1 (under all content, over
   the body background). Two vibes paint their background on an OPAQUE full-bleed
   layer ABOVE z:-1, which swallowed the backdrop (Shock's sweep, 2026-07-18:
   only these 2 of 25 misbehave — dnb's board is body::before at z:0, supper's
   candlelit table is a fixed .sup-table div at z:0). When a backdrop image is
   active the editor stamps body.vc-has-backdrop and these layers yield.
   NOTE for the publish wiring: whatever replays backdrops on the live page must
   stamp the same class. */
body.vc-has-backdrop.vibe-dnb::before { background: none !important; }
body.vc-has-backdrop .sup-table { display: none !important; }

/* ============================ REDUCED MOTION ============================== */
@media (prefers-reduced-motion: reduce) {
  [class*="vfx-sigmo-"], [class*="vfx-sigsheen-"] { animation: none !important; }
  .vfx-sigmo-stubscan::after { animation: none !important; display: none !important; }
  [class*="vfx-sighov-"], [class*="vfx-sighov-"]:hover { transition: none !important; }
}

/* =============================================================================
   bgfxcss-20260718 — BG EFFECT rules for PUBLIC vibe pages.
   Same trap as bdpublish2: real vibe pages never load custom.css, so the
   .vc-bg--<effect> classes replayed by vibe_overlay.js had NO styling — the
   effect layer landed unpainted (publish receipt caught it: payload stored
   bd:{img,fx,op} perfectly, live page showed nothing). Faithful copies from
   custom.css; --vc-accent vars are set inline on the layer by the replay.
   ============================================================================= */
.vc-bg--solid { display: none; }
.vc-bg--dim { background: #000; } /* bgdim-20260718: black dim mask — opacity set inline by the slider/replay */
.vc-bg--gradient { background:
  linear-gradient(155deg,
    color-mix(in srgb, var(--vc-accent) 24%, var(--vc-bg)) 0%,
    var(--vc-bg) 52%,
    color-mix(in srgb, var(--vc-accent2) 22%, var(--vc-bg)) 100%); }
.vc-bg--spotlight { background:
  radial-gradient(32vmax 30vmax at 50% 4%, color-mix(in srgb, var(--vc-accent) 45%, transparent), transparent 58%),
  radial-gradient(130vmax 110vmax at 50% 46%, transparent 30%, color-mix(in srgb, #000 52%, transparent) 100%); }
.vc-bg--aurora { inset: -30vmax; opacity: .9; background:
  radial-gradient(46vmax 30vmax at 18% 20%, color-mix(in srgb, var(--vc-accent) 52%, transparent), transparent 60%),
  radial-gradient(40vmax 30vmax at 84% 28%, color-mix(in srgb, var(--vc-accent2) 48%, transparent), transparent 60%),
  radial-gradient(52vmax 38vmax at 56% 92%, color-mix(in srgb, var(--vc-accent) 34%, transparent), transparent 62%);
  filter: blur(42px) saturate(1.15); animation: vc-drift 20s ease-in-out infinite alternate; }
.vc-bg--mesh { inset: -20vmax; opacity: .85; background:
  radial-gradient(28vmax 28vmax at 14% 18%, color-mix(in srgb, var(--vc-accent) 58%, transparent), transparent 55%),
  radial-gradient(26vmax 26vmax at 82% 14%, color-mix(in srgb, var(--vc-accent2) 52%, transparent), transparent 55%),
  radial-gradient(32vmax 32vmax at 78% 82%, color-mix(in srgb, var(--vc-accent) 46%, transparent), transparent 55%),
  radial-gradient(26vmax 26vmax at 18% 86%, color-mix(in srgb, var(--vc-accent2) 44%, transparent), transparent 55%);
  filter: blur(34px); animation: vc-drift 24s ease-in-out infinite alternate; }
.vc-bg--grain { background:
  radial-gradient(80vmax 60vmax at 50% -8%, color-mix(in srgb, var(--vc-accent) 15%, transparent), transparent 60%); }
.vc-bg--grain::after { content: ""; position: absolute; inset: 0; opacity: .55; mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='2'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='.5'/%3E%3C/svg%3E"); }
.vc-bg--mirrorball { inset: -20vmax; opacity: .7;
  background:
    radial-gradient(circle at 50% 50%, color-mix(in srgb, var(--vc-accent) 75%, transparent) 0 1.6px, transparent 2.6px) 0 0/30px 30px,
    radial-gradient(circle at 50% 50%, color-mix(in srgb, var(--vc-accent2) 65%, transparent) 0 1.6px, transparent 2.6px) 15px 15px/30px 30px,
    radial-gradient(circle at 50% 50%, color-mix(in srgb, #fff 55%, transparent) 0 1px, transparent 2px) 8px 22px/64px 64px;
  animation: vc-twinkle 5s ease-in-out infinite, vc-spin 90s linear infinite; }
.vc-bg--sunburst { inset: -20vmax; opacity: .3;
  background: repeating-conic-gradient(from 0deg at 50% 30%, color-mix(in srgb, var(--vc-accent) 62%, transparent) 0 3deg, transparent 3deg 11deg);
  -webkit-mask-image: radial-gradient(closest-side at 50% 30%, #000 8%, transparent 64%);
          mask-image: radial-gradient(closest-side at 50% 30%, #000 8%, transparent 64%);
  animation: vc-spin 120s linear infinite; }
.vc-bg--rays { inset: -10vmax; opacity: .42;
  background: repeating-linear-gradient(98deg,
    transparent 0 6vmax,
    color-mix(in srgb, var(--vc-accent) 32%, transparent) 6vmax 6.7vmax,
    transparent 6.7vmax 13vmax,
    color-mix(in srgb, var(--vc-accent2) 24%, transparent) 13vmax 13.5vmax,
    transparent 13.5vmax 20vmax);
  -webkit-mask-image: linear-gradient(178deg, #000 0%, rgba(0,0,0,.4) 45%, transparent 78%);
          mask-image: linear-gradient(178deg, #000 0%, rgba(0,0,0,.4) 45%, transparent 78%);
  filter: blur(1.5px); }
@keyframes vc-drift { 0% { transform: translate3d(0,0,0) scale(1); } 100% { transform: translate3d(0,-3%,0) scale(1.08); } }
@keyframes vc-twinkle { 0%, 100% { opacity: .45; } 50% { opacity: .8; } }
@keyframes vc-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
  .vc-bg--aurora, .vc-bg--mesh, .vc-bg--mirrorball, .vc-bg--sunburst { animation: none; }
}

/* =============================================================================
   TEXTURES — textures-20260718 (Shock-approved design: material SURFACES).
   Backdrops are images, effects are light, patterns are geometry — textures are
   the material the page feels printed on. One dedicated fixed layer above the
   content (#vfxTexLayer, z:3 like the DnB grain decor — a surface finish sits
   over everything), pointer-events none, one texture at a time, intensity via
   inline opacity (slider). All CSS/SVG-generated, no assets. Blend modes chosen
   to read on BOTH dark and light vibes (paired dark+light marks or overlay).
   ============================================================================= */
.vc-texture { position: fixed; inset: 0; z-index: 3; pointer-events: none; }

/* Film grain — dense animated noise, the 16mm look. */
.vc-texture--grain { inset: -8%; opacity: .5; mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='3'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='.6'/%3E%3C/svg%3E");
  animation: vtx-grain .5s steps(4) infinite; }

/* Halftone dots — print-press dot screen, dark + light dots so it reads everywhere. */
.vc-texture--halftone { opacity: .35; mix-blend-mode: overlay;
  background-image: radial-gradient(circle, rgba(0,0,0,.9) 0 1.2px, transparent 1.7px),
                    radial-gradient(circle, rgba(255,255,255,.55) 0 1px, transparent 1.5px);
  background-size: 6px 6px, 6px 6px; background-position: 0 0, 3px 3px; }

/* Canvas weave — fine two-direction thread. */
.vc-texture--canvas { opacity: .35; mix-blend-mode: overlay;
  background-image: repeating-linear-gradient(0deg, rgba(255,255,255,.10) 0 1px, transparent 1px 3px),
                    repeating-linear-gradient(90deg, rgba(0,0,0,.14) 0 1px, transparent 1px 3px); }

/* Worn paper — soft mottling + a warm age tint. */
.vc-texture--paper { opacity: .4; mix-blend-mode: soft-light;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='300' height='300'%3E%3Cfilter id='p'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.045' numOctaves='5'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23p)' opacity='.85'/%3E%3C/svg%3E"),
                    linear-gradient(120deg, rgba(255,244,214,.35), rgba(122,92,44,.25)); }

/* Concrete — coarse mineral noise. */
.vc-texture--concrete { opacity: .35; mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='260' height='260'%3E%3Cfilter id='c'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.12' numOctaves='4'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23c)' opacity='.7'/%3E%3C/svg%3E"); }

/* VHS static — jittering horizontal noise bands. */
.vc-texture--vhs { opacity: .3; mix-blend-mode: screen;
  background-image: repeating-linear-gradient(0deg, rgba(255,255,255,.09) 0 1px, transparent 1px 3px),
                    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='120'%3E%3Cfilter id='v'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.03 .8' numOctaves='2'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23v)' opacity='.55'/%3E%3C/svg%3E");
  animation: vtx-vhs .4s steps(3) infinite; }

/* CRT scanlines — clean dark line raster. */
.vc-texture--scanline { opacity: .4; mix-blend-mode: overlay;
  background-image: repeating-linear-gradient(0deg, rgba(0,0,0,.6) 0 1px, transparent 1px 3px); }

/* Newsprint — xerox dot screen + toner speckle. */
.vc-texture--newsprint { opacity: .35; mix-blend-mode: overlay;
  background-image: radial-gradient(circle, rgba(0,0,0,.8) 0 .8px, transparent 1.2px),
                    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='x'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.5' numOctaves='2'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23x)' opacity='.4'/%3E%3C/svg%3E");
  background-size: 4px 4px, 160px 160px; }

/* Brushed foil — fine metal striations + a slow travelling sheen. */
.vc-texture--foil { opacity: .3; mix-blend-mode: overlay;
  background-image: repeating-linear-gradient(92deg, rgba(255,255,255,.16) 0 2px, rgba(0,0,0,.12) 2px 5px, rgba(255,255,255,.05) 5px 9px),
                    linear-gradient(100deg, transparent 20%, rgba(255,255,255,.3) 50%, transparent 80%);
  background-size: auto, 260% auto; animation: vtx-sheen 8s linear infinite; }

/* Plastic wrap — drifting specular highlights. */
/* wraptune-20260719 (weakest of the 10 at Shock's eyeball pass): the old two soft
   sheens read as nothing. Now CELLOPHANE — six sharp crease highlights at varied
   angles and tile sizes, drifting in different directions, so the crinkle structure
   shifts like plastic wrap catching light. */
.vc-texture--wrap { opacity: .35; mix-blend-mode: screen;
  background-image:
    linear-gradient(115deg, transparent 40%, rgba(255,255,255,.5) 44%, rgba(255,255,255,.06) 46%, transparent 52%),
    linear-gradient(295deg, transparent 42%, rgba(255,255,255,.38) 47%, transparent 53%),
    linear-gradient(23deg,  transparent 48%, rgba(255,255,255,.28) 50%, transparent 52.5%),
    linear-gradient(158deg, transparent 31%, rgba(255,255,255,.22) 33%, transparent 35%),
    linear-gradient(203deg, transparent 63%, rgba(255,255,255,.3) 65.5%, transparent 68%),
    linear-gradient(78deg,  transparent 18%, rgba(255,255,255,.16) 20%, transparent 23%);
  background-size: 280% 280%, 300% 300%, 220% 220%, 240% 240%, 260% 260%, 320% 320%;
  animation: vtx-wrap 14s ease-in-out infinite alternate; }

@keyframes vtx-grain { 0%{transform:translate(0,0)} 25%{transform:translate(-2%,1%)} 50%{transform:translate(1%,-2%)} 75%{transform:translate(-1%,2%)} 100%{transform:translate(2%,-1%)} }
@keyframes vtx-vhs { 0%{background-position:0 0,0 0} 50%{background-position:0 1px,9px 0} 100%{background-position:0 -1px,-7px 0} }
@keyframes vtx-sheen { to { background-position: 0 0, 260% center; } }
@keyframes vtx-wrap { from{background-position:0% 0%,100% 100%,0% 100%,100% 0%,50% 0%,0% 50%} to{background-position:100% 100%,0% 0%,100% 0%,0% 100%,50% 100%,100% 50%} } /* wraptune-20260719 */
@media (prefers-reduced-motion: reduce) { .vc-texture { animation: none !important; } }

/* =====================================================================
   PATTERNS PUBLISH + MATRIX RAIN — patterns2-20260719
   .vc-pattern: the transparent full-page geometry overlay. It stacks like
   .vc-texture (fixed, above the vibe's own fixed z:0 cover layers, below
   textures at z:3) — the old z:-1 layer was BURIED under opaque vibe
   layers (dnb board::before) and invisible; z:0 painted over static text.
   Keyframes live here so published pages animate them (they only existed
   inside the editor engine before — patterns never replayed live).
   ===================================================================== */
.vc-pattern { position: fixed; inset: 0; z-index: 2; pointer-events: none; }
@keyframes vcPatSpin { to { transform: rotate(360deg); } }
@keyframes vcPatPulse { 0%,100% { transform: scale(1); } 50% { transform: scale(1.06); } }
@keyframes vcPatFxPulse { 0%,100% { transform: scale(1); } 50% { transform: scale(1.05); } }
@keyframes vcPatFxBreathe { 0%,100% { transform: scale(1); } 50% { transform: scale(1.09); } }
@keyframes vcPatFxDrift { 0% { background-position: center, 0 0; } 50% { background-position: center, 50px 40px; } 100% { background-position: center, 0 0; } }
@keyframes vcPatFxFlicker { 0%,100% { opacity: var(--pop, .18); } 42% { opacity: calc(var(--pop, .18) * .3); } 58% { opacity: var(--pop, .18); } }

/* Alien code — laser-etched glyph rain. matrixglyph-20260719 (Shock: "alien
   code… like the code you see in a red laser on dmt" — laser red = pick #ff0033
   in the effect Color picker; paints entirely with var(--vc-accent)). The rune
   glyphs are an SVG tile used as a MASK (static shape); the colorable falling
   gradient streaks light them up as they pass — same seamless-loop math as
   Matrix rain (travel distance = exact multiple of each layer's tile height). */
.vc-bg--aliencode { opacity: .6;
  background-image:
    linear-gradient(180deg, color-mix(in srgb, var(--vc-accent) 14%, transparent) 0%, color-mix(in srgb, var(--vc-accent) 44%, transparent) 58%, color-mix(in srgb, var(--vc-accent) 72%, #fff) 93%, color-mix(in srgb, var(--vc-accent) 14%, transparent) 100%),
    linear-gradient(180deg, color-mix(in srgb, var(--vc-accent) 10%, transparent) 0%, color-mix(in srgb, var(--vc-accent) 32%, transparent) 52%, color-mix(in srgb, var(--vc-accent) 62%, transparent) 92%, color-mix(in srgb, var(--vc-accent) 10%, transparent) 100%),
    linear-gradient(180deg, color-mix(in srgb, var(--vc-accent) 7%, transparent) 0%, color-mix(in srgb, var(--vc-accent) 22%, transparent) 56%, color-mix(in srgb, var(--vc-accent) 46%, transparent) 94%, color-mix(in srgb, var(--vc-accent) 7%, transparent) 100%);
  background-repeat: repeat;
  background-size: 29px 260px, 41px 180px, 53px 340px;
  background-position: 0 0, 11px 0, 27px 0;
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='105' height='154' viewBox='0 0 105 154'%3E%3Cdefs%3E%3Cpath id='g0' d='M0 0H7M3.5 0V9M1 9H6'/%3E%3Cpath id='g1' d='M0 0L7 4.5L0 9M3 4.5H7'/%3E%3Cpath id='g2' d='M3.5 0L7 3L5 9H2L0 3Z'/%3E%3Cpath id='g3' d='M0 4.5H7M3.5 0V2M3.5 7V9M1 1.5L6 7.5'/%3E%3Cpath id='g4' d='M0 0V9M3 2H7M3 7H7M7 2V7'/%3E%3Cpath id='g5' d='M0 9L3.5 0L7 9M2 6H5M3.5 6V9'/%3E%3Cpath id='g6' d='M1 0H6L3.5 4L6 9H1'/%3E%3Cpath id='g7' d='M1 1H2.4M4.6 1H6M2.8 4.5H4.2M1 8H2.4M4.6 8H6'/%3E%3Cpath id='g8' d='M0 2H7M0 2V7H7V2M2 4.5H5'/%3E%3Cpath id='g9' d='M3.5 0V9M0 3L7 6M7 3L0 6'/%3E%3C/defs%3E%3Cg fill='none' stroke='%23fff' stroke-width='1.4' stroke-linecap='square'%3E%3Cuse href='%23g0' x='3.5' y='1'/%3E%3Cuse href='%23g3' x='3.5' y='12'/%3E%3Cuse href='%23g7' x='3.5' y='23'/%3E%3Cuse href='%23g1' x='3.5' y='34'/%3E%3Cuse href='%23g4' x='3.5' y='56'/%3E%3Cuse href='%23g9' x='3.5' y='67'/%3E%3Cuse href='%23g2' x='3.5' y='78'/%3E%3Cuse href='%23g6' x='3.5' y='100'/%3E%3Cuse href='%23g8' x='3.5' y='111'/%3E%3Cuse href='%23g5' x='3.5' y='122'/%3E%3Cuse href='%23g3' x='3.5' y='133'/%3E%3Cuse href='%23g0' x='3.5' y='144'/%3E%3Cuse href='%23g5' x='24.5' y='1'/%3E%3Cuse href='%23g2' x='24.5' y='23'/%3E%3Cuse href='%23g8' x='24.5' y='34'/%3E%3Cuse href='%23g4' x='24.5' y='45'/%3E%3Cuse href='%23g0' x='24.5' y='56'/%3E%3Cuse href='%23g7' x='24.5' y='78'/%3E%3Cuse href='%23g3' x='24.5' y='89'/%3E%3Cuse href='%23g9' x='24.5' y='100'/%3E%3Cuse href='%23g1' x='24.5' y='111'/%3E%3Cuse href='%23g6' x='24.5' y='133'/%3E%3Cuse href='%23g2' x='24.5' y='144'/%3E%3Cuse href='%23g9' x='45.5' y='1'/%3E%3Cuse href='%23g4' x='45.5' y='12'/%3E%3Cuse href='%23g6' x='45.5' y='34'/%3E%3Cuse href='%23g1' x='45.5' y='45'/%3E%3Cuse href='%23g8' x='45.5' y='56'/%3E%3Cuse href='%23g3' x='45.5' y='67'/%3E%3Cuse href='%23g0' x='45.5' y='89'/%3E%3Cuse href='%23g2' x='45.5' y='100'/%3E%3Cuse href='%23g7' x='45.5' y='111'/%3E%3Cuse href='%23g5' x='45.5' y='122'/%3E%3Cuse href='%23g8' x='45.5' y='144'/%3E%3Cuse href='%23g2' x='66.5' y='1'/%3E%3Cuse href='%23g7' x='66.5' y='12'/%3E%3Cuse href='%23g5' x='66.5' y='23'/%3E%3Cuse href='%23g9' x='66.5' y='45'/%3E%3Cuse href='%23g3' x='66.5' y='56'/%3E%3Cuse href='%23g6' x='66.5' y='67'/%3E%3Cuse href='%23g0' x='66.5' y='78'/%3E%3Cuse href='%23g4' x='66.5' y='89'/%3E%3Cuse href='%23g8' x='66.5' y='111'/%3E%3Cuse href='%23g1' x='66.5' y='122'/%3E%3Cuse href='%23g7' x='66.5' y='133'/%3E%3Cuse href='%23g8' x='87.5' y='12'/%3E%3Cuse href='%23g0' x='87.5' y='23'/%3E%3Cuse href='%23g4' x='87.5' y='34'/%3E%3Cuse href='%23g6' x='87.5' y='45'/%3E%3Cuse href='%23g1' x='87.5' y='67'/%3E%3Cuse href='%23g5' x='87.5' y='78'/%3E%3Cuse href='%23g9' x='87.5' y='89'/%3E%3Cuse href='%23g3' x='87.5' y='100'/%3E%3Cuse href='%23g2' x='87.5' y='122'/%3E%3Cuse href='%23g4' x='87.5' y='133'/%3E%3Cuse href='%23g7' x='87.5' y='144'/%3E%3C/g%3E%3C/svg%3E");
          mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='105' height='154' viewBox='0 0 105 154'%3E%3Cdefs%3E%3Cpath id='g0' d='M0 0H7M3.5 0V9M1 9H6'/%3E%3Cpath id='g1' d='M0 0L7 4.5L0 9M3 4.5H7'/%3E%3Cpath id='g2' d='M3.5 0L7 3L5 9H2L0 3Z'/%3E%3Cpath id='g3' d='M0 4.5H7M3.5 0V2M3.5 7V9M1 1.5L6 7.5'/%3E%3Cpath id='g4' d='M0 0V9M3 2H7M3 7H7M7 2V7'/%3E%3Cpath id='g5' d='M0 9L3.5 0L7 9M2 6H5M3.5 6V9'/%3E%3Cpath id='g6' d='M1 0H6L3.5 4L6 9H1'/%3E%3Cpath id='g7' d='M1 1H2.4M4.6 1H6M2.8 4.5H4.2M1 8H2.4M4.6 8H6'/%3E%3Cpath id='g8' d='M0 2H7M0 2V7H7V2M2 4.5H5'/%3E%3Cpath id='g9' d='M3.5 0V9M0 3L7 6M7 3L0 6'/%3E%3C/defs%3E%3Cg fill='none' stroke='%23fff' stroke-width='1.4' stroke-linecap='square'%3E%3Cuse href='%23g0' x='3.5' y='1'/%3E%3Cuse href='%23g3' x='3.5' y='12'/%3E%3Cuse href='%23g7' x='3.5' y='23'/%3E%3Cuse href='%23g1' x='3.5' y='34'/%3E%3Cuse href='%23g4' x='3.5' y='56'/%3E%3Cuse href='%23g9' x='3.5' y='67'/%3E%3Cuse href='%23g2' x='3.5' y='78'/%3E%3Cuse href='%23g6' x='3.5' y='100'/%3E%3Cuse href='%23g8' x='3.5' y='111'/%3E%3Cuse href='%23g5' x='3.5' y='122'/%3E%3Cuse href='%23g3' x='3.5' y='133'/%3E%3Cuse href='%23g0' x='3.5' y='144'/%3E%3Cuse href='%23g5' x='24.5' y='1'/%3E%3Cuse href='%23g2' x='24.5' y='23'/%3E%3Cuse href='%23g8' x='24.5' y='34'/%3E%3Cuse href='%23g4' x='24.5' y='45'/%3E%3Cuse href='%23g0' x='24.5' y='56'/%3E%3Cuse href='%23g7' x='24.5' y='78'/%3E%3Cuse href='%23g3' x='24.5' y='89'/%3E%3Cuse href='%23g9' x='24.5' y='100'/%3E%3Cuse href='%23g1' x='24.5' y='111'/%3E%3Cuse href='%23g6' x='24.5' y='133'/%3E%3Cuse href='%23g2' x='24.5' y='144'/%3E%3Cuse href='%23g9' x='45.5' y='1'/%3E%3Cuse href='%23g4' x='45.5' y='12'/%3E%3Cuse href='%23g6' x='45.5' y='34'/%3E%3Cuse href='%23g1' x='45.5' y='45'/%3E%3Cuse href='%23g8' x='45.5' y='56'/%3E%3Cuse href='%23g3' x='45.5' y='67'/%3E%3Cuse href='%23g0' x='45.5' y='89'/%3E%3Cuse href='%23g2' x='45.5' y='100'/%3E%3Cuse href='%23g7' x='45.5' y='111'/%3E%3Cuse href='%23g5' x='45.5' y='122'/%3E%3Cuse href='%23g8' x='45.5' y='144'/%3E%3Cuse href='%23g2' x='66.5' y='1'/%3E%3Cuse href='%23g7' x='66.5' y='12'/%3E%3Cuse href='%23g5' x='66.5' y='23'/%3E%3Cuse href='%23g9' x='66.5' y='45'/%3E%3Cuse href='%23g3' x='66.5' y='56'/%3E%3Cuse href='%23g6' x='66.5' y='67'/%3E%3Cuse href='%23g0' x='66.5' y='78'/%3E%3Cuse href='%23g4' x='66.5' y='89'/%3E%3Cuse href='%23g8' x='66.5' y='111'/%3E%3Cuse href='%23g1' x='66.5' y='122'/%3E%3Cuse href='%23g7' x='66.5' y='133'/%3E%3Cuse href='%23g8' x='87.5' y='12'/%3E%3Cuse href='%23g0' x='87.5' y='23'/%3E%3Cuse href='%23g4' x='87.5' y='34'/%3E%3Cuse href='%23g6' x='87.5' y='45'/%3E%3Cuse href='%23g1' x='87.5' y='67'/%3E%3Cuse href='%23g5' x='87.5' y='78'/%3E%3Cuse href='%23g9' x='87.5' y='89'/%3E%3Cuse href='%23g3' x='87.5' y='100'/%3E%3Cuse href='%23g2' x='87.5' y='122'/%3E%3Cuse href='%23g4' x='87.5' y='133'/%3E%3Cuse href='%23g7' x='87.5' y='144'/%3E%3C/g%3E%3C/svg%3E");
  -webkit-mask-repeat: repeat;
          mask-repeat: repeat;
  -webkit-mask-size: 105px 154px;
          mask-size: 105px 154px;
  animation: vc-acode 12s linear infinite; }
/* acodeflow-20260719 (Shock: "flow in one motion like a waterfall all the way down
   the page… delete the matrix rain"): the glyph MASK falls too — the whole rune
   field trickles down continuously, light waves flowing through at near-matched
   speeds (gentle parallax, no gaps, no glitch stepping). Every travel distance is
   an exact multiple of its tile height → seamless loop. Matrix rain removed. */
@keyframes vc-acode {
  from { background-position: 0 0, 11px 0, 27px 0; -webkit-mask-position: 0 0; mask-position: 0 0; }
  to   { background-position: 0 260px, 11px 360px, 27px 340px; -webkit-mask-position: 0 308px; mask-position: 0 308px; } }

@media (prefers-reduced-motion: reduce) {
  .vc-pattern, .vc-bg--aliencode { animation: none !important; }
}

/* glowvar-20260719: every preset glow stop above now reads var(--vfx-glow, <original>) — recolorable per-element from the Effects panel; untouched presets render pixel-identical. dnbpress press-ink excluded (not a glow). 36 stops converted. */
